From 7117dc601f98401c46d7cc03d0aaf3c3437e59a5 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 17 Aug 2023 09:39:35 +0200 Subject: [PATCH 001/100] packaging-nix: Update nix flake Signed-off-by: Philipp Jungkamp --- packaging/nix/ethercat.nix | 29 +++++++++++++++++++++++++++++ packaging/nix/flake.lock | 35 ++++++++++++++++++++++++++--------- packaging/nix/flake.nix | 15 ++++++++++++--- packaging/nix/villas.nix | 13 ++++++++++++- 4 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 packaging/nix/ethercat.nix diff --git a/packaging/nix/ethercat.nix b/packaging/nix/ethercat.nix new file mode 100644 index 000000000..eacaf9151 --- /dev/null +++ b/packaging/nix/ethercat.nix @@ -0,0 +1,29 @@ +{ + autoconf, + automake, + cmake, + lib, + libtool, + pkg-config, + stdenv, + src, +}: +stdenv.mkDerivation { + pname = "ethercat"; + version = "villas"; + src = src; + separateDebugInfo = true; + nativeBuildInputs = [autoconf automake libtool pkg-config]; + preConfigure = '' + bash ./bootstrap + ''; + configureFlags = [ + "--enable-userlib=yes" + "--enable-kernel=no" + ]; + meta = with lib; { + description = "IgH EtherCAT Master for Linux"; + homepage = "https://etherlab.org/master"; + license = licenses.gpl2Only; + }; +} diff --git a/packaging/nix/flake.lock b/packaging/nix/flake.lock index 574abd6e2..91713f0fc 100644 --- a/packaging/nix/flake.lock +++ b/packaging/nix/flake.lock @@ -16,20 +16,36 @@ "type": "github" } }, + "ethercat": { + "flake": false, + "locked": { + "lastModified": 1689851599, + "narHash": "sha256-r829UW4ziY+QUxqjb2j2Bo+xJeUNWn6WiSRK3Gly2Zo=", + "owner": "etherlab.org", + "repo": "ethercat", + "rev": "c8a512ac077f2ab51bb072bfbef1a687f9f1c090", + "type": "gitlab" + }, + "original": { + "owner": "etherlab.org", + "ref": "stable-1.5", + "repo": "ethercat", + "type": "gitlab" + } + }, "fpga": { "flake": false, "locked": { - "lastModified": 1686871446, - "narHash": "sha256-pRFFr72NVge4UgwBvc8gYygnvOHghTSUGI+JtqpRlxo=", - "ref": "refs/heads/villas-node", - "rev": "ce8612379de62f50a52e172fe8eaee924d5d8822", - "revCount": 481, + "lastModified": 1690302379, + "narHash": "sha256-u2u4CUffhA9jxtuk4HokqlmyDQGNz4+LOEJ5Z9DhedU=", + "ref": "refs/heads/master", + "rev": "1cac3fafde6ef3098a145f9d5d936a2dc6b7d7c0", + "revCount": 532, "submodules": true, "type": "git", "url": "https://github.com/VILLASframework/fpga.git" }, "original": { - "ref": "refs/heads/villas-node", "submodules": true, "type": "git", "url": "https://github.com/VILLASframework/fpga.git" @@ -90,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1687354544, - "narHash": "sha256-1Xu+QzyA10AiY21i27Zu9bqQAaxXBacNKbGUA9OZy7Y=", + "lastModified": 1692254348, + "narHash": "sha256-CyRMA7Rap1X65k4p/uoaLXhbnn+PZvwxNHSeLuiQ9ss=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "876181e3ae452cc6186486f6f7300a8a6de237cb", + "rev": "5353604b0affde24dcd75e59d0d22342b1758cfb", "type": "github" }, "original": { @@ -107,6 +123,7 @@ "root": { "inputs": { "common": "common", + "ethercat": "ethercat", "fpga": "fpga", "lib60870": "lib60870", "libdatachannel": "libdatachannel", diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index 1c7f4f0a1..2f87bb4c2 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -12,11 +12,15 @@ fpga = { type = "git"; url = "https://github.com/VILLASframework/fpga.git"; - ref = "refs/heads/villas-node"; submodules = true; flake = false; }; + ethercat = { + url = "gitlab:etherlab.org/ethercat/stable-1.5"; + flake = false; + }; + lib60870 = { url = "github:mz-automation/lib60870/v2.3.2"; flake = false; @@ -71,7 +75,8 @@ self.overlays.minimal ]; }) - .pkgsCross.${crossSystem}; + .pkgsCross + .${crossSystem}; # build villas and its dependencies for the specified `pkgs` packagesWith = pkgs: rec { @@ -91,6 +96,10 @@ withAllNodes = true; }; + ethercat = pkgs.callPackage ./ethercat.nix { + src = inputs.ethercat; + }; + lib60870 = pkgs.callPackage ./lib60870.nix { src = inputs.lib60870; }; @@ -131,7 +140,7 @@ pkgs = pkgsFor system; shellHook = ''[ -z "$PS1" ] || exec "$SHELL"''; hardeningDisable = ["all"]; - packages = with pkgs; [bashInteractive criterion bc jq]; + packages = with pkgs; [bashInteractive bc boxfort criterion jq libffi libgit2 pcre]; in rec { default = full; diff --git a/packaging/nix/villas.nix b/packaging/nix/villas.nix index 711793fab..a3de2c3e8 100644 --- a/packaging/nix/villas.nix +++ b/packaging/nix/villas.nix @@ -7,17 +7,23 @@ withAllFormats ? false, withAllHooks ? false, withAllNodes ? false, + # extras withExtraConfig ? withAllExtras, withExtraGraphviz ? withAllExtras, + # formats withFormatProtobuf ? withAllFormats, + # hooks withHookLua ? withAllHooks, + # nodes withNodeAmqp ? withAllNodes, withNodeComedi ? withAllNodes, withNodeFpga ? withAllNodes, + withNodeEthercat ? withAllNodes, withNodeIec60870 ? withAllNodes, withNodeIec61850 ? withAllNodes, withNodeInfiniband ? withAllNodes, withNodeKafka ? withAllNodes, + withNodeModbus ? withAllNodes, withNodeMqtt ? withAllNodes, withNodeNanomsg ? withAllNodes, withNodeRedis ? withAllNodes, @@ -42,12 +48,14 @@ comedilib, curl, czmq, + ethercat, gnugrep, jansson, lib60870, libconfig, libdatachannel, libiec61850, + libmodbus, libnl, libre, libsodium, @@ -73,7 +81,8 @@ stdenv.mkDerivation { pname = "villas"; outputs = ["out" "dev"]; separateDebugInfo = true; - cmakeFlags = [] + cmakeFlags = + [] ++ lib.optionals (!withGpl) ["-DWITHOUT_GPL=ON"] ++ lib.optionals withFormatProtobuf ["-DCMAKE_FIND_ROOT_PATH=${protobufcBuildBuild}/bin"]; postPatch = '' @@ -116,10 +125,12 @@ stdenv.mkDerivation { ++ lib.optionals withHookLua [lua] ++ lib.optionals withNodeAmqp [rabbitmq-c] ++ lib.optionals withNodeComedi [comedilib] + ++ lib.optionals withNodeEthercat [ethercat] ++ lib.optionals withNodeIec60870 [lib60870] ++ lib.optionals withNodeIec61850 [libiec61850] ++ lib.optionals withNodeInfiniband [rdma-core] ++ lib.optionals withNodeKafka [rdkafka] + ++ lib.optionals withNodeModbus [libmodbus] ++ lib.optionals withNodeMqtt [mosquitto] ++ lib.optionals withNodeNanomsg [nanomsg] ++ lib.optionals withNodeRedis [redis-plus-plus] From 9c94b3105797125461deefb6f7303f217f156e4c Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 22 Aug 2023 16:13:12 +0200 Subject: [PATCH 002/100] packaging-nix: Add debug info to dependencies in devShells Signed-off-by: Philipp Jungkamp --- packaging/nix/flake.nix | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index 2f87bb4c2..916271de6 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -47,6 +47,12 @@ } @ inputs: let inherit (nixpkgs) lib; + # add separateDebugInfo to a derivation + addSeparateDebugInfo = d: + d.overrideAttrs { + separateDebugInfo = true; + }; + # supported systems for native compilation supportedSystems = ["x86_64-linux" "aarch64-linux"]; @@ -63,21 +69,28 @@ pkgsFor = system: import nixpkgs { inherit system; - overlays = [self.overlays.default]; + overlays = with self.overlays; [default]; }; # initialize nixpkgs for cross-compiling from `system` to `crossSystem` crossPkgsFor = system: crossSystem: (import nixpkgs { inherit system; - overlays = [ - self.overlays.default - self.overlays.minimal + overlays = with self.overlays; [ + default + minimal ]; }) .pkgsCross .${crossSystem}; + # initialize development nixpkgs for the specified `system` + devPkgsFor = system: + import nixpkgs { + inherit system; + overlays = with self.overlays; [default debug]; + }; + # build villas and its dependencies for the specified `pkgs` packagesWith = pkgs: rec { default = villas; @@ -128,6 +141,10 @@ # standard flake attribute allowing you to add the villas packages to your nixpkgs overlays = { default = final: prev: packagesWith final; + debug = final: prev: { + jansson = addSeparateDebugInfo prev.jansson; + libmodbus = addSeparateDebugInfo prev.libmodbus; + }; minimal = final: prev: { mosquitto = prev.mosquitto.override {systemd = final.systemdMinimal;}; rdma-core = prev.rdma-core.override {udev = final.systemdMinimal;}; @@ -137,7 +154,7 @@ # standard flake attribute for defining developer environments devShells = forSupportedSystems ( system: let - pkgs = pkgsFor system; + pkgs = devPkgsFor system; shellHook = ''[ -z "$PS1" ] || exec "$SHELL"''; hardeningDisable = ["all"]; packages = with pkgs; [bashInteractive bc boxfort criterion jq libffi libgit2 pcre]; From 82272fc7e6cabe7cdf1617c6489b2199705f8b7f Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 22 Aug 2023 16:10:22 +0200 Subject: [PATCH 003/100] api: web: Do proper shutdown if startup was interrupted Signed-off-by: Philipp Jungkamp --- include/villas/web.hpp | 6 ++++-- lib/api.cpp | 3 ++- lib/web.cpp | 5 +++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/villas/web.hpp b/include/villas/web.hpp index 12a372056..2129fa738 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -24,9 +24,9 @@ namespace node { /* Forward declarations */ class Api; -class Web { +class Web final { -protected: +private: enum State state; Logger logger; @@ -55,6 +55,8 @@ public: */ Web(Api *a = nullptr); + ~Web(); + void start(); void stop(); diff --git a/lib/api.cpp b/lib/api.cpp index 4a1c01317..289e9e457 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -33,7 +33,8 @@ Api::Api(SuperNode *sn) : Api::~Api() { - assert(state != State::STARTED); + if (state == State::STARTED) + stop(); } void Api::start() diff --git a/lib/web.cpp b/lib/web.cpp index c4bc4db67..d81acd317 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -185,6 +185,11 @@ Web::Web(Api *a) : lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); } +Web::~Web() { + if(state == State::STARTED) + stop(); +} + int Web::parse(json_t *json) { int ret, enabled = 1; From 391bff5993a49ac45584846d6d64eed55d3ebb14 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:59:22 +0200 Subject: [PATCH 004/100] web: Fix code-style Co-authored-by: Steffen Vogel Signed-off-by: Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> --- lib/web.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/web.cpp b/lib/web.cpp index d81acd317..f96f79850 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -185,8 +185,9 @@ Web::Web(Api *a) : lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); } -Web::~Web() { - if(state == State::STARTED) +Web::~Web() +{ + if (state == State::STARTED) stop(); } From 53848f534548d7304ce514aeede85df2ee04f8f4 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:01:02 +0200 Subject: [PATCH 005/100] packaging-nix: Fix code-style and capitalization Co-authored-by: Steffen Vogel Signed-off-by: Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> --- packaging/nix/flake.nix | 8 ++++---- packaging/nix/villas.nix | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index 916271de6..b8c8dad38 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -47,7 +47,7 @@ } @ inputs: let inherit (nixpkgs) lib; - # add separateDebugInfo to a derivation + # Add separateDebugInfo to a derivation addSeparateDebugInfo = d: d.overrideAttrs { separateDebugInfo = true; @@ -72,7 +72,7 @@ overlays = with self.overlays; [default]; }; - # initialize nixpkgs for cross-compiling from `system` to `crossSystem` + # Initialize nixpkgs for cross-compiling from `system` to `crossSystem` crossPkgsFor = system: crossSystem: (import nixpkgs { inherit system; @@ -84,14 +84,14 @@ .pkgsCross .${crossSystem}; - # initialize development nixpkgs for the specified `system` + # Initialize development nixpkgs for the specified `system` devPkgsFor = system: import nixpkgs { inherit system; overlays = with self.overlays; [default debug]; }; - # build villas and its dependencies for the specified `pkgs` + # Build villas and its dependencies for the specified `pkgs` packagesWith = pkgs: rec { default = villas; diff --git a/packaging/nix/villas.nix b/packaging/nix/villas.nix index a3de2c3e8..0973436df 100644 --- a/packaging/nix/villas.nix +++ b/packaging/nix/villas.nix @@ -7,14 +7,14 @@ withAllFormats ? false, withAllHooks ? false, withAllNodes ? false, - # extras + # Extra features withExtraConfig ? withAllExtras, withExtraGraphviz ? withAllExtras, - # formats + # Format-types withFormatProtobuf ? withAllFormats, - # hooks + # Hook-types withHookLua ? withAllHooks, - # nodes + # Node-types withNodeAmqp ? withAllNodes, withNodeComedi ? withAllNodes, withNodeFpga ? withAllNodes, From 5aacd5f49ed749a3d6f4a4ec4090ceb70ce56e41 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 22 Aug 2023 16:11:32 +0200 Subject: [PATCH 006/100] node-modbus: Add initial modbus support Signed-off-by: Philipp Jungkamp --- CMakeLists.txt | 3 + etc/examples/nodes/modbus.conf | 67 +++ include/villas/nodes/modbus.hpp | 290 ++++++++++ lib/nodes/CMakeLists.txt | 5 + lib/nodes/modbus.cpp | 913 ++++++++++++++++++++++++++++++++ 5 files changed, 1278 insertions(+) create mode 100644 etc/examples/nodes/modbus.conf create mode 100644 include/villas/nodes/modbus.hpp create mode 100644 lib/nodes/modbus.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0e4e2f48..7fffdec13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ pkg_check_modules(LIBIEC61850 IMPORTED_TARGET libiec61850>=1.5.0) pkg_check_modules(LIB60870 IMPORTED_TARGET lib60870>=2.3.1) pkg_check_modules(LIBCONFIG IMPORTED_TARGET libconfig>=1.4.9) pkg_check_modules(MOSQUITTO IMPORTED_TARGET libmosquitto>=1.6.9) +pkg_check_modules(MODBUS IMPORTED_TARGET libmodbus>=3.1.0) pkg_check_modules(RDKAFKA IMPORTED_TARGET rdkafka>=1.5.0) pkg_check_modules(HIREDIS IMPORTED_TARGET hiredis>=1.0.0) pkg_check_modules(REDISPP IMPORTED_TARGET redis++>=1.2.0) @@ -201,6 +202,7 @@ cmake_dependent_option(WITH_NODE_INFINIBAND "Build with infiniband node-type" cmake_dependent_option(WITH_NODE_INFLUXDB "Build with influxdb node-type" "${WITH_DEFAULTS}" "" OFF) cmake_dependent_option(WITH_NODE_KAFKA "Build with kafka node-type" "${WITH_DEFAULTS}" "RDKAFKA_FOUND" OFF) cmake_dependent_option(WITH_NODE_LOOPBACK "Build with loopback node-type" "${WITH_DEFAULTS}" "" OFF) +cmake_dependent_option(WITH_NODE_MODBUS "Build with modbus node-type" "${WITH_DEFAULTS}" "MODBUS_FOUND" OFF) cmake_dependent_option(WITH_NODE_MQTT "Build with mqtt node-type" "${WITH_DEFAULTS}" "MOSQUITTO_FOUND" OFF) cmake_dependent_option(WITH_NODE_NANOMSG "Build with nanomsg node-type" "${WITH_DEFAULTS}" "NANOMSG_FOUND" OFF) cmake_dependent_option(WITH_NODE_NGSI "Build with ngsi node-type" "${WITH_DEFAULTS}" "" OFF) @@ -311,6 +313,7 @@ add_feature_info(NODE_INFINIBAND WITH_NODE_INFINIBAND "Build with add_feature_info(NODE_INFLUXDB WITH_NODE_INFLUXDB "Build with influxdb node-type") add_feature_info(NODE_KAFKA WITH_NODE_KAFKA "Build with kafka node-type") add_feature_info(NODE_LOOPBACK WITH_NODE_LOOPBACK "Build with loopback node-type") +add_feature_info(NODE_MODBUS WITH_NODE_MODBUS "Build with modbus node-type") add_feature_info(NODE_MQTT WITH_NODE_MQTT "Build with mqtt node-type") add_feature_info(NODE_NANOMSG WITH_NODE_NANOMSG "Build with nanomsg node-type") add_feature_info(NODE_NGSI WITH_NODE_NGSI "Build with ngsi node-type") diff --git a/etc/examples/nodes/modbus.conf b/etc/examples/nodes/modbus.conf new file mode 100644 index 000000000..f83434954 --- /dev/null +++ b/etc/examples/nodes/modbus.conf @@ -0,0 +1,67 @@ +nodes = { + modbus_node = { + type = "modbus" + + transport = "tcp" # "tcp" + response_timeout = 1.0 # in seconds + + # For transport = tcp + remote = "127.0.0.1" + port = 1502 + + # For transport = rtu + device = "/dev/ttyS0" + baudrate = 9600 + parity = "none" # "even" "odd" + data_bits = 5 # 6 7 8 + stop_bits = 1 # 2 + + # Modbus device / unit ID + # this is optional for TCP + unit = 1 + rate = 10 # in Hz + + in = { + signals = ( + { + type = "float" + address = 0x50 + }, + { + type = "boolean" + address = 0x54 + bit = 1 + }, + { + type = "float" + address = 0x52 + integer_registers = 1 + scale = 10 + offset = 2 + }, + { + type = "boolean" + address = 0x54 + bit = 0 + }, + { + type = "float" + address = 0x01 + scale = 2 + offset = 10 + } + ) + } + + out = { + signals = ( + { + type = "float" + address = 0x01 + scale = 2 + offset = 10 + } + ) + } + } +} diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp new file mode 100644 index 000000000..f56205bab --- /dev/null +++ b/include/villas/nodes/modbus.hpp @@ -0,0 +1,290 @@ +/** A Modbus node-type supporting RTU and TCP based transports. + * + * @author Philipp Jungkamp + * @copyright 2023, OPAL-RT Germany GmbH + * @license Apache 2.0 + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace villas { +namespace node { +namespace modbus { + +using modbus_addr_t = uint16_t; +using modbus_addrdiff_t = int32_t; + +enum class Parity : char { + None = 'N', + Even = 'E', + Odd = 'O', +}; + +enum class Endianess : char { + Big, + Little, +}; + +// The settings for an RTU modbus connection. +struct Rtu { + std::string device; + Parity parity; + int baudrate; + int data_bits; + int stop_bits; + unsigned char unit; + + static + Rtu parse(json_t *json); +}; + +// The settings for an TCP MODBUS connection. +struct Tcp { + std::string remote; + uint16_t port; + std::optional unit; + + static + Tcp parse(json_t *json); +}; + +// Forward declaration. +class RegisterMappingSingle; + +// A merged block of mappings. +using RegisterMappingBlock = std::vector; + +// Either a single mapping or a merged block of mappings. +using RegisterMapping = std::variant; + +// Swap the two bytes of a 16 bit integer. +uint16_t byteswap(uint16_t i); + +// The start of a single register mapping. +modbus_addr_t blockBegin(RegisterMappingSingle const &single); + +// The start of a block of register mappings. +modbus_addr_t blockBegin(RegisterMappingBlock const &block); + +// The start of either a single or a block of register mappings. +modbus_addr_t blockBegin(RegisterMapping const &mapping); + +// The end of a single register mapping. +modbus_addr_t blockEnd(RegisterMappingSingle const &single); + +// The end of a block of register mappings. +modbus_addr_t blockEnd(RegisterMappingBlock const &block); + +// The end of either a single or a block of register mappings. +modbus_addr_t blockEnd(RegisterMapping const &mapping); + +// The number of mapped registers in a single register mapping. +modbus_addr_t mappedRegisters(RegisterMappingSingle const &single); + +// The number of mapped registers in a block of register mappings. +modbus_addr_t mappedRegisters(RegisterMappingBlock const &block); + +// The number of mapped registers in either a single or a block of register mappings. +modbus_addr_t mappedRegisters(RegisterMapping const &mapping); + +// The distance between two blocks. +modbus_addrdiff_t blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs); + +// Whether there are overlapping bit mappings between lhs and rhs. +bool hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs); + +// The compare the addresses of two mappings. +bool compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs); + +// Parse an Endianess from a null terminated string. +Endianess parseEndianess(char const *str); + +// Parse an Parity from a null terminated string. +Parity parseParity(char const *str); + +// The mapping from a register to a signal. +class RegisterMappingSingle { +public: + inline static constexpr + size_t MAX_REGISTERS = sizeof(int64_t) / sizeof(int16_t); + + struct IntegerToInteger { + Endianess word_endianess; + Endianess byte_endianess; + modbus_addr_t num_registers; + + int64_t read(uint16_t const *registers) const; + void write(int64_t i, uint16_t *registers) const; + }; + + struct IntegerToFloat { + IntegerToInteger integer_conversion; + double offset; + double scale; + + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; + + struct FloatToFloat { + Endianess word_endianess; + Endianess byte_endianess; + double offset; + double scale; + + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; + + struct BitToBool { + uint8_t bit; + + bool read(uint16_t reg) const; + }; + + // Conversion rule for registers. + // + // - IntegerToInteger means merging multiple registers. + // - FloatToFloat converts from IEEE float to float. + // - IntegerToFloat converts registers to integer, casts to float + // and then applies offset and scale to produce a float. + // - BitToBool takes a single bit from a registers and reports it as a boolean. + std::variant conversion; + + RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address); + + unsigned int signal_index; + modbus_addr_t address; + + static + RegisterMappingSingle parse(unsigned int index, Signal::Ptr signal, json_t *json); + + SignalData read(uint16_t const *registers, modbus_addr_t length) const; + void write(SignalData data, uint16_t *registers, modbus_addr_t length) const; + + modbus_addr_t num_registers() const; +}; + +class ModbusNode final : public Node { +private: + // The maximum size of a RegisterMappingBlock created during mergeMappings. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + modbus_addr_t max_block_size; + + // The minimum block usage of a RegisterMappingBlock created during mergeMappings. + // The usage of a block is defined as the ration of registers used in mappings to the size of the block. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + float min_block_usage; + + // The type of connection settings used to initialize the modbus_context. + std::variant connection_settings; + + // The rate used for periodically querying the modbus device registers. + double rate; + + // The timeout in seconds when waiting for a response from a modbus slave/server. + double response_timeout; + + // Mappings used to create the input signals from the read registers. + std::vector in_mappings; + + // Number of in signals. + unsigned int num_in_signals; + + // Mappings used to create the input signals from the read registers. + std::vector out_mappings; + + // Number of out signals. + unsigned int num_out_signals; + + // The interval in seconds for trying to reconnect on connection loss. + double reconnect_interval; + + std::vector read_buffer; + std::vector write_buffer; + modbus_t *modbus_context; + Task read_task; + std::atomic reconnecting; + + bool isReconnecting(); + void reconnect(); + + static + void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs); + + static + void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs); + + bool tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs); + + void mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance); + + unsigned int parseMappings(std::vector &mappings, json_t *json); + + int readMapping(RegisterMappingSingle const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + + int readMapping(RegisterMappingBlock const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + + int readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + + int readBlock(RegisterMapping const &mapping, SignalData *signals, size_t num_signals); + + virtual + int _read(struct Sample *smps[], unsigned int cnt); + + int writeMapping(RegisterMappingSingle const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); + int writeMapping(RegisterMappingBlock const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); + int writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); + int writeBlock(RegisterMapping const &mapping, SignalData const *signals, size_t num_signals); + + virtual + int _write(struct Sample *smps[], unsigned int cnt); + +public: + ModbusNode(const uuid_t &id = {}, const std::string &name = ""); + + virtual + ~ModbusNode(); + + virtual + int prepare(); + + virtual + int parse(json_t *json); + + virtual + int check(); + + virtual + int start(); + + virtual + int stop(); + + virtual + std::vector getPollFDs(); + + virtual + const std::string & getDetails(); +}; + +} /* namespace modbus */ +} /* namespace node */ +} /* namespace villas */ diff --git a/lib/nodes/CMakeLists.txt b/lib/nodes/CMakeLists.txt index 064bb6ded..04c4719fd 100644 --- a/lib/nodes/CMakeLists.txt +++ b/lib/nodes/CMakeLists.txt @@ -79,6 +79,11 @@ if(WITH_NODE_OPAL) list(APPEND LIBRARIES ${OPAL_LIBRARIES}) endif() +if(WITH_NODE_MODBUS) + list(APPEND NODE_SRC modbus.cpp) + list(APPEND LIBRARIES PkgConfig::MODBUS) +endif() + # Enable nanomsg node type when libnanomsg is available if(WITH_NODE_NANOMSG) list(APPEND NODE_SRC nanomsg.cpp) diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp new file mode 100644 index 000000000..6b3f04250 --- /dev/null +++ b/lib/nodes/modbus.cpp @@ -0,0 +1,913 @@ +/** A Modbus node-type supporting RTU and TCP transports. + * + * The modbus communication using the libmodbus library is fairly simple. + * + * 1. Create a modbus_t modbus_context from the connection_settings. + * 2. Call modbus_connect to create a connection to a server. + * 3. Use modbus_read_registers/modbus_write_registers to read/write values. + * + * The complicated part is the configuration parsing, especially the mapping + * from signals to registers. We try to group as many registers as we can + * together to query them using a single modbus command. The general idea is: + * + * 1. Create a simple mapping for all signal specifications in the parse() function. + * 2. Sort all mappings by the range of registers the need. + * 3. Merge mappings that sit next to each other into larger groups until either ... + * - ... the group is larger than "max_block_size". + * - ... the ration of needed registers to queried registers falls below + * "min_block_usage". So we cap the amount of unecessary data transmitted. + * + * The merging process is further complicated by the possibility to map bits from + * a register to their own signals. We don't generally want to allow mapping the + * same register multiple times, except for the case of bit mappings. + * + * While a general overlap between any two mappings is considered an error, the + * case of overlapping bit mappings is detected by hasOverlappingBitMapping and + * handled in blockDistance and compareBlockAddress. + * + * - The special case in compareBlockAddress makes bit mappings of the same register + * reside next to each other after sorting the mappings. + * - The special case in blockDistance makes causes the bit mappings to be grouped + * first, before any adjacent registers. + * + * @author Philipp Jungkamp + * @copyright 2023, OPAL-RT Germany GmbH + * @license Apache 2.0 + *********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace villas; +using namespace villas::node; +using namespace villas::node::modbus; +using namespace villas::utils; + +int64_t RegisterMappingSingle::IntegerToInteger::read(uint16_t const *registers) const +{ + int64_t integer = 0; + auto ptr = word_endianess == Endianess::Big ? registers + num_registers - 1 : registers; + + for (size_t i = 0; i < num_registers; ++i) { + integer <<= sizeof(uint16_t) * 8; + + if (byte_endianess == Endianess::Big) + integer |= (int64_t) *ptr; + else + integer |= (int64_t) byteswap(*ptr); + + if (word_endianess == Endianess::Big) + --ptr; + else + ++ptr; + } + + return integer; +} + +void RegisterMappingSingle::IntegerToInteger::write(int64_t integer, uint16_t *registers) const +{ + auto ptr = word_endianess == Endianess::Big ? registers : registers + num_registers - 1; + + for (size_t i = 0; i < num_registers; ++i) { + if (byte_endianess == Endianess::Big) + *ptr = (uint16_t) integer; + else + *ptr = byteswap((uint16_t) integer); + + if (word_endianess == Endianess::Big) + ++ptr; + else + --ptr; + + integer >>= sizeof(uint16_t) * 8; + } +} + +double RegisterMappingSingle::IntegerToFloat::read(uint16_t const *registers) const +{ + int64_t integer = integer_conversion.read(registers); + + return integer * scale + offset; +} + +void RegisterMappingSingle::IntegerToFloat::write(double d, uint16_t *registers) const +{ + int64_t integer = (d - offset) / scale; + + integer_conversion.write(integer, registers); +} + +double RegisterMappingSingle::FloatToFloat::read(uint16_t const *registers) const +{ + static_assert(sizeof(float) == sizeof(uint32_t)); + + auto const conversion = IntegerToInteger { + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; + + union { + uint32_t i; + float f; + } value; + + value.i = (uint32_t) conversion.read(registers); + + return value.f * scale + offset; +} + +void RegisterMappingSingle::FloatToFloat::write(double d, uint16_t *registers) const +{ + static_assert(sizeof(float) == sizeof(uint32_t)); + + auto const conversion = IntegerToInteger { + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; + + union { + uint32_t i; + float f; + } value; + + value.f = (d - offset) / scale; + + conversion.write((int64_t) value.i, registers); +} + +bool RegisterMappingSingle::BitToBool::read(uint16_t reg) const +{ + return (reg >> bit) & 1; +} + +RegisterMappingSingle::RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address) : + conversion(IntegerToInteger { + .word_endianess = Endianess::Big, + .byte_endianess = Endianess::Big, + .num_registers = 1, + }), + signal_index(signal_index), + address(address) +{ } + +SignalData RegisterMappingSingle::read(uint16_t const *registers, modbus_addr_t length) const +{ + SignalData data; + + if (num_registers() != length) + throw RuntimeError { "reading from invalid register range" }; + + if (auto i2i = std::get_if(&conversion)) + data.i = i2i->read(registers); + else if (auto i2f = std::get_if(&conversion)) + data.f = i2f->read(registers); + else if (auto f2f = std::get_if(&conversion)) + data.f = f2f->read(registers); + else if (auto b2b = std::get_if(&conversion)) + data.b = b2b->read(*registers); + else + throw RuntimeError { "read unsupported" }; + + return data; +} + +void RegisterMappingSingle::write(SignalData data, uint16_t *registers, modbus_addr_t length) const +{ + if (num_registers() != length) + throw RuntimeError { "writing to invalid register range" }; + + if (auto i2i = std::get_if(&conversion)) + i2i->write(data.i, registers); + else if (auto i2f = std::get_if(&conversion)) + i2f->write(data.f, registers); + else if (auto f2f = std::get_if(&conversion)) + f2f->write(data.f, registers); + else + throw RuntimeError { "write unsupported" }; +} + +modbus_addr_t RegisterMappingSingle::num_registers() const +{ + if (auto i2i = std::get_if(&conversion)) + return i2i->num_registers; + + if (auto i2f = std::get_if(&conversion)) + return i2f->integer_conversion.num_registers; + + if (std::holds_alternative(conversion)) + return 2; + + if (std::holds_alternative(conversion)) + return 1; + + throw RuntimeError { "unreachable" }; +} + +uint16_t modbus::byteswap(uint16_t i) +{ + uint8_t low = (i & 0x00FF); + uint8_t high = (i & 0xFF00) >> 8; + return (low << 8) | high; +} + +modbus_addr_t modbus::blockBegin(RegisterMappingSingle const &single) +{ + return single.address; +} + +modbus_addr_t modbus::blockBegin(RegisterMappingBlock const &block) +{ + assert(!block.empty()); + return blockBegin(block.front()); +} + +modbus_addr_t modbus::blockBegin(RegisterMapping const &mapping) +{ + return std::visit([](auto &v){ + return blockBegin(v); + }, mapping); +} + +modbus_addr_t modbus::blockEnd(RegisterMappingSingle const &single) +{ + return single.address + single.num_registers(); +} + +modbus_addr_t modbus::blockEnd(RegisterMappingBlock const &block) +{ + assert(!block.empty()); + return blockEnd(block.back()); +} + +modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) +{ + return std::visit([](auto &v){ + return blockEnd(v); + }, mapping); +} + + +modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) +{ + return single.num_registers(); +} + +modbus_addr_t modbus::mappedRegisters(RegisterMappingBlock const &block) +{ + auto mapped = 0; + + modbus_addr_t last_address = -1; + for (auto &single : block) { + if (single.address != last_address) + mapped += single.num_registers(); + + last_address = single.address; + } + + return mapped; +} + +modbus_addr_t modbus::mappedRegisters(RegisterMapping const &mapping) +{ + return std::visit([](auto &v){ + return mappedRegisters(v); + }, mapping); +} + +modbus_addrdiff_t modbus::blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs) +{ + if (blockBegin(rhs) >= blockEnd(lhs)) + return (modbus_addrdiff_t) blockBegin(rhs) - blockEnd(lhs); + + if (blockBegin(lhs) >= blockEnd(rhs)) + return (modbus_addrdiff_t) blockBegin(lhs) - blockEnd(rhs); + + if (hasOverlappingBitMapping(lhs, rhs)) + return -1; + + throw RuntimeError { "overlapping mappings" }; +} + +bool modbus::hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs) +{ + // Only check if there is exactly 1 register of overlap. + if (blockEnd(lhs) - blockBegin(rhs) != 1 && blockEnd(rhs) - blockBegin(lhs) != 1) + return false; + + // Assume that lhs is at a lower address than rhs. + if (blockBegin(rhs) < blockBegin(lhs) || blockEnd(rhs) < blockEnd(lhs)) + return hasOverlappingBitMapping(rhs, lhs); + + // Get the last mapping from the lhs block. + RegisterMappingSingle const *lhs_back = nullptr; + if (auto single = std::get_if(&lhs)) + lhs_back = single; + else if (auto block = std::get_if(&lhs)) + lhs_back = &block->back(); + else + return false; + + // We are only interested in bit mappings. + if (!std::holds_alternative(lhs_back->conversion)) + return false; + + // Get the first mapping from the rhs block. + RegisterMappingSingle const *rhs_front = nullptr; + if (auto single = std::get_if(&rhs)) + rhs_front = single; + else if (auto block = std::get_if(&rhs)) + rhs_front = &block->front(); + else + return false; + + // We are only interested in bit mappings. + if (!std::holds_alternative(rhs_front->conversion)) + return false; + + // The last register of lhs and the first register of rhs overlap and are both bit mappings. + return true; +} + +bool modbus::compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs) +{ + if (blockBegin(rhs) >= blockEnd(lhs)) + return true; + + if (blockBegin(lhs) >= blockEnd(rhs)) + return false; + + if (hasOverlappingBitMapping(lhs, rhs)) + return false; + + throw RuntimeError { "overlapping mappings" }; +} + +bool ModbusNode::isReconnecting() +{ + return reconnecting.load(); +} + +void ModbusNode::reconnect() +{ + if (reconnecting.exchange(true)) + return; + + logger->error("No connection to the Modbus server. Reconnecting..."); + + std::thread([this](){ + auto start = std::chrono::steady_clock::now(); + + if (modbus_connect(modbus_context) == -1) { + logger->error("reconnect failure: ", modbus_strerror(errno)); + std::this_thread::sleep_until(start + std::chrono::duration(reconnect_interval)); + } + + reconnecting.store(false); + }).detach(); +} + +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs) +{ + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock { *lhs_single }; + + auto &block = std::get(lhs); + block.reserve(blockEnd(rhs) - blockBegin(lhs)); + std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(block)); +} + +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs) +{ + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock { *lhs_single }; + + auto &block = std::get(lhs); + block.push_back(rhs); +} + +bool ModbusNode::tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs) +{ + auto block_size = blockEnd(rhs) - blockBegin(lhs); + + if (block_size >= max_block_size) + return false; + + auto block_usage = (mappedRegisters(lhs) + mappedRegisters(rhs)) / (float) block_size; + + if (block_usage < min_block_usage) + return false; + + std::visit([&lhs](auto const &rhs){ + mergeMappingInplace(lhs, rhs); + }, rhs); + + return true; +} + +void ModbusNode::mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance) +{ + if (std::size(mappings) < 2) + return; + + // Sort all mappings by their block address. + std::sort(std::begin(mappings), std::end(mappings), compareBlockAddress); + + // Calculate the distances. (number of unused registers inbetween mappings) + auto distances = std::vector(); + distances.reserve(std::size(mappings)); + for (size_t i = 1; i < std::size(mappings); i++) + distances.push_back(blockDistance(mappings[i-1], mappings[i])); + + for (;;) { + // Try to group the mappings closest to each other first. + auto min_distance = std::min_element(std::begin(distances), std::end(distances)); + + // The closest distance is too far to merge, abort the merging process. + if (min_distance == std::end(distances) || *min_distance >= max_block_distance) + break; + + // Find the mappings to the left and right of the minimum distance. + auto i = std::distance(std::begin(distances), min_distance); + auto left_mapping = std::next(std::begin(mappings), i); + auto right_mapping = std::next(std::begin(mappings), i+1); + + if (tryMergeMappingInplace(*left_mapping, *right_mapping)) { + // Remove the right mapping and the distance + // if it could be merged into the left mapping. + mappings.erase(right_mapping); + distances.erase(min_distance); + } else { + // Set the distance to a value, so that it won't be retried. + *min_distance = max_block_distance; + } + } +} + +int ModbusNode::readBlock(RegisterMapping const &mapping, SignalData *data, size_t size) +{ + if (isReconnecting()) + return -1; + + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; + + read_buffer.resize(block_size); + + if (modbus_read_registers(modbus_context, address, block_size, read_buffer.data()) == -1) { + logger->error("read registers failure: ", modbus_strerror(errno)); + + reconnect(); + + return -1; + } + + return readMapping(mapping, read_buffer.data(), read_buffer.size(), data, size); +} + +int ModbusNode::readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) +{ + return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ + return readMapping(mapping, registers, num_registers, signals, num_signals); + }, mapping); +} + +int ModbusNode::readMapping(RegisterMappingSingle const &single, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) +{ + auto signal_data = single.read(registers, num_registers); + + assert(single.signal_index < num_signals); + signals[single.signal_index] = signal_data; + + return 0; +} + +int ModbusNode::readMapping(RegisterMappingBlock const &block, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) +{ + auto begin_block = blockBegin(block); + + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); + + assert(end_single - begin_block <= num_registers); + if (auto ret = readMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; +} + +int ModbusNode::_read(struct Sample *smps[], unsigned cnt) +{ + read_task.wait(); + + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; + smp->flags |= (int) SampleFlags::HAS_DATA; + + for (auto &mapping : in_mappings) { + smp->length = num_in_signals; + assert(smp->length <= smp->capacity); + if (auto ret = readBlock(mapping, smp->data, smp->length)) + return ret; + } + } + + return cnt; +} + +int ModbusNode::writeBlock(RegisterMapping const &mapping, SignalData const *data, size_t size) +{ + if (isReconnecting()) + return -1; + + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; + + write_buffer.resize(block_size); + + if (auto ret = writeMapping(mapping, write_buffer.data(), write_buffer.size(), data, size)) + return ret; + + if (modbus_write_registers(modbus_context, address, block_size, write_buffer.data()) == -1) { + logger->error("write registers failure: ", modbus_strerror(errno)); + + reconnect(); + + return -1; + } + + return 0; +} + +int ModbusNode::writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) +{ + return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ + return writeMapping(mapping, registers, num_registers, signals, num_signals); + }, mapping); +} + +int ModbusNode::writeMapping(RegisterMappingSingle const &single, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) +{ + assert(single.signal_index < num_signals); + single.write(signals[single.signal_index], registers, num_registers); + + return 0; +} + +int ModbusNode::writeMapping(RegisterMappingBlock const &block, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) +{ + auto begin_block = blockBegin(block); + + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); + + assert(end_single - begin_block <= num_registers); + if (auto ret = writeMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; +} + +int ModbusNode::_write(struct Sample *smps[], unsigned cnt) +{ + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; + + for (auto &mapping : out_mappings) { + assert(smp->length == num_out_signals); + if (auto ret = writeBlock(mapping, smp->data, smp->length)) + return ret; + } + } + + return cnt; +} + +ModbusNode::ModbusNode(const uuid_t &id, const std::string &name) : + Node(id, name), + max_block_size(32), + min_block_usage(0.25), + connection_settings(), + rate(-1), + response_timeout(1), + in_mappings{}, + num_in_signals(0), + out_mappings{}, + num_out_signals(0), + reconnect_interval(10), + read_buffer{}, + write_buffer{}, + modbus_context(nullptr), + read_task(), + reconnecting(false) +{ } + +ModbusNode::~ModbusNode() +{ + if (modbus_context) + modbus_free(modbus_context); +} + +int ModbusNode::prepare() +{ + mergeMappings(in_mappings, max_block_size - 2); + mergeMappings(out_mappings, 0); + + if (in.enabled) { + read_task.setRate(rate); + + logger->info("Making {} Modbus calls for each read", in_mappings.size()); + } + + if (out.enabled) + logger->info("Making {} Modbus calls for each write", out_mappings.size()); + + assert(!std::holds_alternative(connection_settings)); + + if (auto tcp = std::get_if(&connection_settings)) { + modbus_context = modbus_new_tcp(tcp->remote.c_str(), tcp->port); + + if (tcp->unit) + modbus_set_slave(modbus_context, *tcp->unit); + } + + if (auto rtu = std::get_if(&connection_settings)) { + modbus_context = modbus_new_rtu( + rtu->device.c_str(), + rtu->baudrate, + static_cast(rtu->parity), + rtu->data_bits, + rtu->stop_bits); + + modbus_set_slave(modbus_context, rtu->unit); + } + + auto response_timeout_secs = (uint32_t) response_timeout; + auto response_timeout_usecs = (uint32_t) (response_timeout - (double) response_timeout_secs); + modbus_set_response_timeout(modbus_context, response_timeout_secs, response_timeout_usecs); + + return Node::prepare(); +} + +Endianess modbus::parseEndianess(char const *str) +{ + if (!strcmp(str, "little")) + return Endianess::Little; + + if (!strcmp(str, "big")) + return Endianess::Big; + + throw RuntimeError { "invalid endianess" }; +} + +Parity modbus::parseParity(char const *str) +{ + if (!strcmp(str, "none")) + return Parity::None; + + if (!strcmp(str, "even")) + return Parity::Even; + + if (!strcmp(str, "odd")) + return Parity::Odd; + + throw RuntimeError { "invalid parity" }; +} + +Rtu Rtu::parse(json_t* json) +{ + char const *device = nullptr; + char const *parity_str = nullptr; + int baudrate = -1; + int data_bits = -1; + int stop_bits = -1; + + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: i, s: i, s: i }", + "device", &device, + "parity", &parity_str, + "baudrate", &baudrate, + "data_bits", &data_bits, + "stop_bits", &stop_bits + ); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-rtu"); + + Parity parity = parseParity(parity_str); + + return Rtu { device, parity, baudrate, data_bits, stop_bits }; +} + +Tcp Tcp::parse(json_t* json) +{ + char const *remote = nullptr; + int port = 502; + int unit_int = -1; + + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: i, s?: i }", + "remote", &remote, + "port", &port, + "unit", &unit_int + ); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-tcp"); + + std::optional unit = unit_int >= 0 ? std::optional(unit_int) : std::nullopt; + + return Tcp { + .remote = remote, + .port = (uint16_t) port, + .unit = unit, + }; +} + +RegisterMappingSingle RegisterMappingSingle::parse(unsigned int index, Signal::Ptr signal, json_t *json) +{ + int address = -1; + int bit = -1; + int integer_registers = -1; + char const *word_endianess_str = nullptr; + char const *byte_endianess_str = nullptr; + double offset = 0.0; + double scale = 1.0; + + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: i, s?: i, s?: s, s?: s, s?: F, s?: F }", + "address", &address, + "bit", &bit, + "integer_registers", &integer_registers, + "word_endianess", &word_endianess_str, + "byte_endianess", &byte_endianess_str, + "offset", &offset, + "scale", &scale + ); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-signal"); + + if (integer_registers != -1 && (integer_registers <= 0 || (size_t) integer_registers > MAX_REGISTERS)) + throw RuntimeError { "unsupported register block size" }; + + Endianess word_endianess = Endianess::Big; + if (word_endianess_str) + word_endianess = parseEndianess(word_endianess_str); + + Endianess byte_endianess = Endianess::Big; + if (byte_endianess_str) + byte_endianess = parseEndianess(byte_endianess_str); + + auto mapping = RegisterMappingSingle { index, (modbus_addr_t) address }; + if (signal->type == SignalType::FLOAT) { + if (integer_registers == -1) { + mapping.conversion = FloatToFloat { + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .offset = offset, + .scale = scale, + }; + } else { + auto integer_conversion = IntegerToInteger { + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t) integer_registers, + }; + + mapping.conversion = IntegerToFloat { + .integer_conversion = integer_conversion, + .offset = offset, + .scale = scale, + }; + } + + return mapping; + } else if (signal->type == SignalType::INTEGER) { + if (integer_registers == -1) + integer_registers = 1; + + mapping.conversion = IntegerToInteger { + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t) integer_registers, + }; + } else if (signal->type == SignalType::BOOLEAN) { + if (bit < 0 || bit > 15) + throw RuntimeError { "mappings from bit to bool must be in the range 0 to 16" }; + + mapping.conversion = BitToBool { + .bit = (uint8_t) bit, + }; + } else { + throw RuntimeError { "unsupported signal type" }; + } + + return mapping; +} + +unsigned int ModbusNode::parseMappings(std::vector &mappings, json_t *json) +{ + assert(json_is_array(json)); + + size_t i; + json_t *signal_json; + auto signals = getInputSignals(false); + + json_array_foreach (json, i, signal_json) { + auto signal = signals->getByIndex(i); + + mappings.push_back(RegisterMappingSingle::parse(i, signal, signal_json)); + } + + return json_array_size(json); +} + +int ModbusNode::parse(json_t *json) +{ + if(auto ret = Node::parse(json)) + return ret; + + json_error_t err; + char const * transport = nullptr; + json_t *in_json = nullptr; + json_t *out_json = nullptr; + + if (json_unpack_ex(json, &err, 0, "{ s: s, s?: F, s?: F, s?: i, s?: i, s?: F, s?: o, s?: o }", + "transport", &transport, + "response_timeout", &response_timeout, + "reconnect_interval", &reconnect_interval, + "min_block_usage", &min_block_usage, + "max_block_size", &max_block_size, + "rate", &rate, + "in", &in_json, + "out", &out_json + )) + throw ConfigError(json, err, "node-config-node-modbus"); + + if (in.enabled && rate < 0) + throw RuntimeError { "missing polling rate for Modbus reads" }; + + if (!strcmp(transport, "rtu")) + connection_settings = Rtu::parse(json); + else if (!strcmp(transport, "tcp")) + connection_settings = Tcp::parse(json); + else + throw ConfigError(json, err, "node-config-node-modbus-transport"); + + json_t *signals_json; + + if (in_json && (signals_json = json_object_get(in_json, "signals"))) + num_in_signals = parseMappings(in_mappings, signals_json); + + if (out_json && (signals_json = json_object_get(out_json, "signals"))) + num_out_signals = parseMappings(out_mappings, signals_json); + + return 0; +} + +int ModbusNode::check() +{ + return Node::check(); +} + +int ModbusNode::start() +{ + if (modbus_connect(modbus_context) == -1) + throw RuntimeError { "connection failure: {}", modbus_strerror(errno) }; + + return Node::start(); +} + +int ModbusNode::stop() +{ + modbus_close(modbus_context); + + return Node::stop(); +} + +std::vector ModbusNode::getPollFDs() +{ + return { read_task.getFD() }; +} + +const std::string & ModbusNode::getDetails() +{ + details = fmt::format(""); + return details; +} + +static char name[] = "modbus"; +static char description[] = "read and write Modbus registers as a client"; +static NodePlugin p; From 893aeaa12e140b61f54e6f4d6b528c5c88858e6c Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 22 Aug 2023 16:21:22 +0200 Subject: [PATCH 007/100] packaging: Add libmodbus to Distro Dockerfiles Signed-off-by: Philipp Jungkamp --- packaging/docker/Dockerfile.debian | 3 ++- packaging/docker/Dockerfile.debian-multiarch | 6 ++++-- packaging/docker/Dockerfile.fedora | 3 ++- packaging/docker/Dockerfile.rocky | 3 ++- packaging/docker/Dockerfile.ubuntu | 3 ++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index f6ad41769..7798d0ef6 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -50,7 +50,8 @@ RUN apt-get update && \ libspdlog-dev \ liblua5.3-dev \ libhiredis-dev \ - libnice-dev + libnice-dev \ + libmodbus-dev # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index 6564bd1c7..e16bfe55d 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -58,7 +58,8 @@ RUN apt-get update && \ libusb-1.0-0-dev:${ARCH} \ libre-dev:${ARCH} \ liblua5.3-dev:${ARCH} \ - libhiredis-dev:${ARCH} + libhiredis-dev:${ARCH} \ + libmodbus-dev:${ARCH} # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ @@ -153,7 +154,8 @@ RUN apt-get update && \ libusb-1.0-0:${ARCH} \ libre0:${ARCH} \ liblua5.3-0:${ARCH} \ - libhiredis0.14:${ARCH} && \ + libhiredis0.14:${ARCH} \ + libmodbus5:${ARCH} && \ rm -rf /var/lib/apt/lists/* COPY --from=builder ${PREFIX} ${PREFIX} diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index e48548e91..9753dc5f4 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -64,7 +64,8 @@ RUN dnf -y install \ libusb-devel \ lua-devel \ hiredis-devel \ - libnice-devel + libnice-devel \ + libmodbus-devel # Add local and 64-bit locations to linker paths RUN echo /usr/local/lib >> /etc/ld.so.conf && \ diff --git a/packaging/docker/Dockerfile.rocky b/packaging/docker/Dockerfile.rocky index ea0fd1212..329376923 100644 --- a/packaging/docker/Dockerfile.rocky +++ b/packaging/docker/Dockerfile.rocky @@ -47,7 +47,8 @@ RUN dnf -y install \ libusb1-devel \ lua-devel \ hiredis-devel \ - libnice-devel + libnice-devel \ + libmodbus-devel # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 870e76a0c..07bc6b807 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -52,7 +52,8 @@ RUN apt-get update && \ libspdlog-dev \ liblua5.3-dev \ libhiredis-dev \ - libnice-dev + libnice-dev \ + libmodbus-dev # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ From f229d042d4bbc90eaf77e8b6cceca8d0e18662f7 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 23 Aug 2023 11:44:08 +0200 Subject: [PATCH 008/100] node-modbus: Fix code-style Signed-off-by: Philipp Jungkamp --- lib/nodes/modbus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 6b3f04250..08b3a453d 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -836,7 +836,7 @@ unsigned int ModbusNode::parseMappings(std::vector &mappings, j int ModbusNode::parse(json_t *json) { - if(auto ret = Node::parse(json)) + if (auto ret = Node::parse(json)) return ret; json_error_t err; From 132fe1c92da9d3a653cf54a82edd6b4482d5c8eb Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 23 Aug 2023 11:46:33 +0200 Subject: [PATCH 009/100] node-modbus: Add comments to the modbus node example configuration Signed-off-by: Philipp Jungkamp --- etc/examples/nodes/modbus.conf | 156 +++++++++++++++++++++++++++------ 1 file changed, 127 insertions(+), 29 deletions(-) diff --git a/etc/examples/nodes/modbus.conf b/etc/examples/nodes/modbus.conf index f83434954..c1b3952df 100644 --- a/etc/examples/nodes/modbus.conf +++ b/etc/examples/nodes/modbus.conf @@ -2,65 +2,163 @@ nodes = { modbus_node = { type = "modbus" - transport = "tcp" # "tcp" - response_timeout = 1.0 # in seconds + # Required transport type. Can be either "rtu" or "tcp" + transport = "tcp" - # For transport = tcp + # Optional timeout in seconds when waiting for responses from a modbus server. + # Default is 1.0. + response_timeout = 1.0 + + + # + # Settings for transport = "tcp". + # + + # Required remote IP address. remote = "127.0.0.1" - port = 1502 - # For transport = rtu + # Optional remote port. + # Default is 502. + port = 502 + + + # + # Settings for transport = "rtu" + # + + # Required device file. device = "/dev/ttyS0" - baudrate = 9600 - parity = "none" # "even" "odd" - data_bits = 5 # 6 7 8 - stop_bits = 1 # 2 - # Modbus device / unit ID - # this is optional for TCP + # Required baudrate. + baudrate = 9600 + + # Required parity. One of "none", "even" and "odd" + parity = "none" + + # Required data bits. One of 5, 6, 7, 8 + data_bits = 5 + + # Required stop bits. One of 1, 2 + stop_bits = 1 + + # The modbus unit ID. + # Required for transport = "rtu". + # Optional for transport = "tcp". unit = 1 - rate = 10 # in Hz + + # Optional polling rate for the modbus remote reads. + # Defaults to 10. + rate = 10 in = { signals = ( + # A 32-bit IEEE 754 floating point value. + # This spans 2 registers. { + # Required type = "float". type = "float" + + # Required address of the lowest register. address = 0x50 - }, - { - type = "boolean" - address = 0x54 - bit = 1 - }, - { - type = "float" - address = 0x52 - integer_registers = 1 + + # Optional endianess for joining the 2 16-bit registers into a 32-bit value. + # Defaults to "big". + word_endianess = "big" + + # Optional endianess for the 2 bytes within a register. + # Defaults to "big". + byte_endianess = "big" + + # Optional scale that should be applied to the integer value. + # Defaults to 1. scale = 10 + + # Optional offset that should be applied to the integer value after scaling. + # Defaults to 0. offset = 2 }, + # A single bit within a register as a boolean value. { + # Required type = "boolean". type = "boolean" + + # Required address of the register. address = 0x54 + + # Required bit within the register. + # Starting at 0. bit = 0 }, + # An integer value. + # This may span multiple registers. { + # Required type = "integer". + type = "integer" + + # Required address of the lowest register. + address = 0x52 + + # Optional number of registers that should be joined to form the value. + # Defaults to 1. + integer_registers = 1 + + # Optional endianess for joining the 16-bit registers into a 32-bit value. + # Defaults to "big". + word_endianess = "big" + + # Optional endianess for the 2 bytes within a register. + # Defaults to "big". + byte_endianess = "big" + }, + # An float value created by reading an integer and applying an optional offset and scale. + # This may span multiple registers. + { + # Required type = "float". type = "float" - address = 0x01 - scale = 2 - offset = 10 + + # Required address of the lowest register. + address = 0x52 + + # Required number of registers that should be joined to form the value. + # A "float" value without the "integer_registers" settings is considered an IEEE 754 float, spanning 2 registers. + integer_registers = 1 + + # Optional endianess for joining the 16-bit registers into a 32-bit value. + # Defaults to "big". + word_endianess = "big" + + # Optional endianess for the 2 bytes within a register. + # Defaults to "big". + byte_endianess = "big" + + # Optional scale that should be applied to the integer value. + # Defaults to 1. + scale = 10 + + # Optional offset that should be applied to the integer value after scaling. + # Defaults to 0. + offset = 2 } ) } out = { signals = ( + # All register mappings described for "in" except for "boolean" are supported in the "out" signals. { type = "float" - address = 0x01 - scale = 2 - offset = 10 - } + address = 0x50 + + # Scale and offset a applied as attributes of the register that is written to. + # This means the value written to "register" for a "signal" with "offset" and "scale" will be: + # + # register = (signal - offset) / scale + # + # It is fairly common to specify a scale and offset for modbus registers in a device manual. + # You should be able to plug those values into this configuration without conversion. + scale = 10 + offset = 2 + }, ) } } From a95c4af822e0de355b7487532bf4bd51ec1297ab Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 23 Aug 2023 14:38:06 +0200 Subject: [PATCH 010/100] node-modbus: Add details and improve description Signed-off-by: Philipp Jungkamp --- lib/nodes/modbus.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 08b3a453d..f169dbdfe 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -904,10 +904,28 @@ std::vector ModbusNode::getPollFDs() const std::string & ModbusNode::getDetails() { - details = fmt::format(""); + if (details.empty()) { + if (auto tcp = std::get_if(&connection_settings)) { + details = fmt::format("transport=tcp, remote={}, port={}", tcp->remote, tcp->port); + + if (tcp->unit) + details.append(fmt::format(", unit={}", *tcp->unit)); + } + + if (auto rtu = std::get_if(&connection_settings)) { + details = fmt::format("transport=rtu, device={}, baudrate={}, parity={}, data_bits={}, stop_bits={}, unit={}", + rtu->device.c_str(), + rtu->baudrate, + static_cast(rtu->parity), + rtu->data_bits, + rtu->stop_bits, + rtu->unit); + } + } + return details; } static char name[] = "modbus"; -static char description[] = "read and write Modbus registers as a client"; +static char description[] = "Read and write Modbus registers"; static NodePlugin p; From 2a82e7b388268af9d0753969dfc006dc22a6052c Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 23 Aug 2023 14:43:42 +0200 Subject: [PATCH 011/100] node-modbus: Improve _read and _write loop Signed-off-by: Philipp Jungkamp --- lib/nodes/modbus.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index f169dbdfe..090d3a1b1 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -514,11 +514,12 @@ int ModbusNode::_read(struct Sample *smps[], unsigned cnt) for (unsigned int i = 0; i < cnt; ++i) { auto smp = smps[i]; + smp->length = num_in_signals; smp->flags |= (int) SampleFlags::HAS_DATA; + assert(smp->length <= smp->capacity); + for (auto &mapping : in_mappings) { - smp->length = num_in_signals; - assert(smp->length <= smp->capacity); if (auto ret = readBlock(mapping, smp->data, smp->length)) return ret; } @@ -587,8 +588,9 @@ int ModbusNode::_write(struct Sample *smps[], unsigned cnt) for (unsigned int i = 0; i < cnt; ++i) { auto smp = smps[i]; + assert(smp->length == num_out_signals); + for (auto &mapping : out_mappings) { - assert(smp->length == num_out_signals); if (auto ret = writeBlock(mapping, smp->data, smp->length)) return ret; } From 65cb2d612be341fd1896a843a17601b679f9264c Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 24 Aug 2023 10:09:16 +0200 Subject: [PATCH 012/100] doc: Add OpenAPI specification for modbus node-type Signed-off-by: Philipp Jungkamp --- .../components/schemas/config/node_obj.yaml | 1 + .../schemas/config/nodes/_modbus.yaml | 3 + .../schemas/config/nodes/modbus.yaml | 108 ++++++++++++++++++ .../config/nodes/signals/modbus_signal.yaml | 45 ++++++++ 4 files changed, 157 insertions(+) create mode 100644 doc/openapi/components/schemas/config/nodes/_modbus.yaml create mode 100644 doc/openapi/components/schemas/config/nodes/modbus.yaml create mode 100644 doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml diff --git a/doc/openapi/components/schemas/config/node_obj.yaml b/doc/openapi/components/schemas/config/node_obj.yaml index 43729e15b..dfe8cd92e 100644 --- a/doc/openapi/components/schemas/config/node_obj.yaml +++ b/doc/openapi/components/schemas/config/node_obj.yaml @@ -34,6 +34,7 @@ discriminator: influxdb: nodes/_influxdb.yaml kafka: nodes/_kafka.yaml loopback: nodes/_loopback.yaml + modbus: nodes/_modbus.yaml mqtt: nodes/_mqtt.yaml nanomsg: nodes/_nanomsg.yaml ngsi: nodes/_ngsi.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_modbus.yaml b/doc/openapi/components/schemas/config/nodes/_modbus.yaml new file mode 100644 index 000000000..2ecbc813d --- /dev/null +++ b/doc/openapi/components/schemas/config/nodes/_modbus.yaml @@ -0,0 +1,3 @@ +allOf: +- $ref: ../node_obj.yaml +- $ref: modbus.yaml diff --git a/doc/openapi/components/schemas/config/nodes/modbus.yaml b/doc/openapi/components/schemas/config/nodes/modbus.yaml new file mode 100644 index 000000000..4c1a8efc9 --- /dev/null +++ b/doc/openapi/components/schemas/config/nodes/modbus.yaml @@ -0,0 +1,108 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +--- + +allOf: +- type: object + anyOf: + - required: [transport, remote] + properties: + + transport: + type: string + enum: + - tcp + + remote: + type: string + description: The hostname or IP of the modbus TCP device. + example: example.com + + port: + type: integer + description: The port number of the modbus TCP device. + default: 1883 + + unit: + type: integer + description: The addressed unit used for serial communication. This is optional for TCP. + minimum: 0 + maximum: 65535 + example: 1 + + - required: [transport, device, baudrate, parity, data_bits, stop_bits, unit] + properties: + + transport: + type: string + enum: + - rtu + + device: + type: string + description: Path to the serial device file. + example: /dev/ttyS0 + + baudrate: + type: integer + description: The baudrate used for serial communication. + example: 9600 + + parity: + type: string + enum: + - none + - even + - odd + description: The parity used for serial communication. + example: none + + data_bits: + type: integer + description: The data bits used for serial communication. + minimum: 5 + maximum: 8 + example: 5 + + stop_bits: + type: integer + description: The stop bits used for serial communication. + minimum: 1 + maximum: 2 + example: 5 + + unit: + type: integer + description: The addressed unit used for serial communication. This is optional for TCP. + minimum: 0 + maximum: 65535 + example: 1 + + properties: + + response_timeout: + type: number + description: The timeout in seconds when waiting for responses from a modbus server. + example: 1.0 + + rate: + type: number + description: The rate at which modbus device registers are queried for changes. + example: 1.0 + + in: + type: object + properties: + signals: + type: array + items: + $ref: ./signals/modbus_signal.yaml + + out: + type: object + properties: + signals: + type: array + items: + $ref: ./signals/modbus_signal.yaml + +- $ref: ../node.yaml diff --git a/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml new file mode 100644 index 000000000..ae1861603 --- /dev/null +++ b/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml @@ -0,0 +1,45 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +--- + +allOf: +- type: object + required: [type, address] + properties: + + address: + type: integer + description: The modbus register address. + + word_endianess: + type: string + enum: + - big + - little + description: The ordering of two modbus registers joined together to form a larger number. + default: "big" + + byte_endianess: + type: string + enum: + - big + - little + description: The ordering of the bytes within a modbus register. + default: "big" + + scale: + type: number + description: The scale of the register's value. + default: 1.0 + + offset: + type: number + description: The offset of the register's value. + default: 0.0 + + bit: + type: integer + description: The bit index within a register. + minimum: 0 + maximum: 15 + +- $ref: ../../signal.yaml From ad6bd0ecf7c9883d9881708a90319d87db4a41c9 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 13:12:24 +0200 Subject: [PATCH 013/100] node-file: Don't truncate files Signed-off-by: Philipp Jungkamp --- lib/nodes/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index c398c92db..631cd02f8 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -262,7 +262,7 @@ int villas::node::file_start(NodeCompat *n) f->formatter->start(n->getInputSignals(false)); /* Open file */ - f->stream_out = fopen(f->uri, "w+"); + f->stream_out = fopen(f->uri, "a+"); if (!f->stream_out) return -1; From b9bad1219d69b0e601342ba5c81e4c712a71d286 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 18:04:42 +0200 Subject: [PATCH 014/100] tests: Fix multiplexing test assuming implicit truncate Signed-off-by: Philipp Jungkamp --- tests/integration/node-multiplexing.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/node-multiplexing.sh b/tests/integration/node-multiplexing.sh index 6f2b84bbd..53d7720b8 100755 --- a/tests/integration/node-multiplexing.sh +++ b/tests/integration/node-multiplexing.sh @@ -119,4 +119,6 @@ villas node config.json villas compare output.dat expect_${MODE}.dat +rm output.dat + done From 7a84a6494f26fd3ae6bb2083ecb90e4b68a5bae6 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Aug 2023 18:01:03 +0200 Subject: [PATCH 015/100] deps: Harmonize URL suffixes Signed-off-by: Steffen Vogel --- packaging/deps.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packaging/deps.sh b/packaging/deps.sh index aad2ed70d..c0c8f57d8 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -92,7 +92,7 @@ pushd ${TMPDIR} >/dev/null if ! pkg-config "criterion >= 2.4.1" && \ [ "${ARCH}" == "x86_64" ] && \ should_build "criterion" "for unit tests"; then - git clone ${GIT_OPTS} --branch v2.3.3 --recursive https://github.com/Snaipe/Criterion + git clone ${GIT_OPTS} --branch v2.3.3 --recursive https://github.com/Snaipe/Criterion.git mkdir -p Criterion/build pushd Criterion/build cmake ${CMAKE_OPTS} .. @@ -103,7 +103,7 @@ fi # Build & Install libjansson if ! pkg-config "jansson >= 2.13" && \ should_build "jansson" "for configuration parsing" "required"; then - git clone ${GIT_OPTS} --branch v2.14 https://github.com/akheron/jansson + git clone ${GIT_OPTS} --branch v2.14 https://github.com/akheron/jansson.git pushd jansson autoreconf -i ./configure ${CONFIGURE_OPTS} @@ -129,7 +129,7 @@ fi # Build & Install mosquitto if ! pkg-config "libmosquitto >= 1.4.15" && \ should_build "mosquitto" "for the MQTT node-type"; then - git clone ${GIT_OPTS} --branch v2.0.15 https://github.com/eclipse/mosquitto + git clone ${GIT_OPTS} --branch v2.0.15 https://github.com/eclipse/mosquitto.git mkdir -p mosquitto/build pushd mosquitto/build cmake -DWITH_BROKER=OFF \ @@ -144,7 +144,7 @@ fi # Build & Install rabbitmq-c if ! pkg-config "librabbitmq >= 0.13.0" && \ should_build "rabbitmq" "for the AMQP node and VILLAScontroller"; then - git clone ${GIT_OPTS} --branch v0.11.0 https://github.com/alanxz/rabbitmq-c + git clone ${GIT_OPTS} --branch v0.11.0 https://github.com/alanxz/rabbitmq-c.git mkdir -p rabbitmq-c/build pushd rabbitmq-c/build cmake ${CMAKE_OPTS} .. @@ -155,7 +155,7 @@ fi # Build & Install libzmq if ! pkg-config "libzmq >= 2.2.0" && \ should_build "zmq" "for the zeromq node-type"; then - git clone ${GIT_OPTS} --branch v4.3.4 https://github.com/zeromq/libzmq + git clone ${GIT_OPTS} --branch v4.3.4 https://github.com/zeromq/libzmq.git mkdir -p libzmq/build pushd libzmq/build cmake -DWITH_PERF_TOOL=OFF \ @@ -180,7 +180,7 @@ fi # Build & Install libiec61850 if ! pkg-config "libiec61850 >= 1.5.0" && \ should_build "iec61850" "for the iec61850 node-type"; then - git clone ${GIT_OPTS} --branch v1.5.1 https://github.com/mz-automation/libiec61850 + git clone ${GIT_OPTS} --branch v1.5.1 https://github.com/mz-automation/libiec61850.git mkdir -p libiec61850/build pushd libiec61850/build cmake -DBUILD_EXAMPLES=OFF \ @@ -206,7 +206,7 @@ fi # Build & Install librdkafka if ! pkg-config "rdkafka >= 1.5.0" && \ should_build "rdkafka" "for the kafka node-type"; then - git clone ${GIT_OPTS} --branch v2.0.1 https://github.com/edenhill/librdkafka + git clone ${GIT_OPTS} --branch v2.0.1 https://github.com/edenhill/librdkafka.git mkdir -p librdkafka/build pushd librdkafka/build cmake -DRDKAFKA_BUILD_TESTS=OFF \ @@ -232,7 +232,7 @@ fi # Build & Install uldaq if ! pkg-config "libuldaq >= 1.2.0" && \ should_build "uldaq" "for the uldaq node-type"; then - git clone ${GIT_OPTS} --branch v1.2.1 https://github.com/mccdaq/uldaq + git clone ${GIT_OPTS} --branch v1.2.1 https://github.com/mccdaq/uldaq.git pushd uldaq autoreconf -i ./configure \ @@ -246,7 +246,7 @@ fi if ! ( pkg-config "libnl-3.0 >= 3.2.25" && \ pkg-config "libnl-route-3.0 >= 3.2.25" \ ) && should_build "libnl" "for network emulation"; then - git clone ${GIT_OPTS} --branch libnl3_7_0 https://github.com/thom311/libnl + git clone ${GIT_OPTS} --branch libnl3_7_0 https://github.com/thom311/libnl.git pushd libnl autoreconf -i ./configure \ @@ -259,7 +259,7 @@ fi # Build & Install libconfig if ! pkg-config "libconfig >= 1.4.9" && \ should_build "libconfig" "for libconfig configuration syntax"; then - git clone ${GIT_OPTS} --branch v1.7.3 https://github.com/hyperrealm/libconfig + git clone ${GIT_OPTS} --branch v1.7.3 https://github.com/hyperrealm/libconfig.git pushd libconfig autoreconf -i ./configure ${CONFIGURE_OPTS} \ @@ -381,7 +381,7 @@ fi # Build & Install libwebsockets if ! pkg-config "libwebsockets >= 4.3.0" && \ should_build "libwebsockets" "for the websocket node and VILLASweb" "required"; then - git clone ${GIT_OPTS} --branch v4.3-stable https://github.com/warmcat/libwebsockets + git clone ${GIT_OPTS} --branch v4.3-stable https://github.com/warmcat/libwebsockets.git mkdir -p libwebsockets/build pushd libwebsockets/build cmake -DLWS_WITH_IPV6=ON \ @@ -395,7 +395,7 @@ fi # Build & Install libdatachannel if ! cmake --find-package -DNAME=LibDataChannel -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST >/dev/null 2>/dev/null && \ should_build "libdatachannel" "for the webrtc node-type"; then - git clone ${GIT_OPTS} --recursive --branch v0.18.4 https://github.com/paullouisageneau/libdatachannel + git clone ${GIT_OPTS} --recursive --branch v0.18.4 https://github.com/paullouisageneau/libdatachannel.git mkdir -p libdatachannel/build pushd libdatachannel/build From 7453681ebd8b2187bc07a50fca4294a6cf620283 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Aug 2023 18:24:59 +0200 Subject: [PATCH 016/100] deps: Fix interactive mode Signed-off-by: Steffen Vogel --- packaging/deps.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/deps.sh b/packaging/deps.sh index c0c8f57d8..90cb80bd0 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -40,7 +40,8 @@ should_build() { if [[ -z "${DEPS_NONINTERACTIVE+x}" ]] && [[ -t 1 ]]; then echo - case "$(read -p "Do you wan't to install '${id}' into '${PREFIX}'? This is used ${use}. (y/N)")" in + read -p "Do you wan't to install '${id}' into '${PREFIX}'? This is used ${use}. (y/N) " + case "${REPLY}" in y | Y) echo "Installing '${id}'" return 0 From 950b8a929db70b7bb35328057ec0778e1c745f97 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Aug 2023 18:26:20 +0200 Subject: [PATCH 017/100] deps: Install libmodbus Signed-off-by: Steffen Vogel --- packaging/deps.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packaging/deps.sh b/packaging/deps.sh index 90cb80bd0..cf77f6dfd 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -413,6 +413,18 @@ if ! cmake --find-package -DNAME=LibDataChannel -DCOMPILER_ID=GNU -DLANGUAGE=CXX popd fi +# Build & Install libmodbus +if ! pkg-config "libmodbus >= 3.1.0" && \ + should_build "libmodbus" "for the modbus node-type"; then + git clone ${GIT_OPTS} --recursive --branch v3.1.10 https://github.com/stephane/libmodbus.git + mkdir -p libmodbus/build + pushd libmodbus + autoreconf -i + ./configure ${CONFIGURE_OPTS} + make ${MAKE_OPTS} install + popd +fi + popd >/dev/null rm -rf ${TMPDIR} From 932ee22472510a6fc6c4a4b96d80d074f6858339 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Aug 2023 18:27:19 +0200 Subject: [PATCH 018/100] modbus: Expose socket descriptor to netem emulation Signed-off-by: Steffen Vogel --- include/villas/nodes/modbus.hpp | 3 +++ lib/nodes/modbus.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index f56205bab..3bccbf703 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -281,6 +281,9 @@ public: virtual std::vector getPollFDs(); + virtual + std::vector getNetemFDs(); + virtual const std::string & getDetails(); }; diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 090d3a1b1..d74486177 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -904,6 +904,17 @@ std::vector ModbusNode::getPollFDs() return { read_task.getFD() }; } +std::vector ModbusNode::getNetemFDs() +{ + if (modbus_context != nullptr && std::holds_alternative(connection_settings)) { + return { + modbus_get_socket(modbus_context) + }; + } + + return { }; +} + const std::string & ModbusNode::getDetails() { if (details.empty()) { From 4b433e20fd367fedbbcb53bec82f982a5a02c886 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 28 Aug 2023 09:30:23 +0200 Subject: [PATCH 019/100] Fix include order Signed-off-by: Steffen Vogel --- include/villas/nodes/modbus.hpp | 18 +++++++++--------- lib/nodes/modbus.cpp | 9 ++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index 3bccbf703..c7df327cb 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -7,15 +7,6 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include - #include #include #include @@ -24,6 +15,15 @@ #include #include +#include + +#include +#include +#include +#include +#include +#include + namespace villas { namespace node { namespace modbus { diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index d74486177..5d3987d1f 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -35,6 +35,11 @@ * @license Apache 2.0 *********************************************************************************/ +#include +#include + +#include + #include #include #include @@ -42,9 +47,7 @@ #include #include #include -#include -#include -#include + using namespace villas; using namespace villas::node; From bde15823483a8b870fb82a179611d3a0213f0c15 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 12:50:53 +0200 Subject: [PATCH 020/100] hook-reorder-ts: Add hook to fix reordered samples Signed-off-by: Philipp Jungkamp --- lib/hooks/CMakeLists.txt | 1 + lib/hooks/reorder_ts.cpp | 168 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 lib/hooks/reorder_ts.cpp diff --git a/lib/hooks/CMakeLists.txt b/lib/hooks/CMakeLists.txt index 153331488..ed2f1e0f7 100644 --- a/lib/hooks/CMakeLists.txt +++ b/lib/hooks/CMakeLists.txt @@ -25,6 +25,7 @@ set(HOOK_SRC pmu_ipdft.cpp pps_ts.cpp print.cpp + reorder_ts.cpp restart.cpp rms.cpp round.cpp diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp new file mode 100644 index 000000000..ca593038f --- /dev/null +++ b/lib/hooks/reorder_ts.cpp @@ -0,0 +1,168 @@ +/** Reorder samples hook. + * + * @author Philipp Jungkamp + * @copyright 2023, OPAL-RT Germany GmbH + * @license Apache 2.0 + *********************************************************************************/ + +#include +#include +#include +#include + +#include +#include + +namespace villas { +namespace node { + +class ReorderTsHook : public Hook { + +protected: + std::vector window; + std::size_t window_size; + Sample *buffer; + + bool compareTimestamp(Sample *lhs, Sample *rhs) { + auto lhs_ts = lhs->ts.origin; + auto rhs_ts = rhs->ts.origin; + + if (lhs_ts.tv_sec < rhs_ts.tv_sec) + return true; + + if (lhs_ts.tv_sec == rhs_ts.tv_sec && lhs_ts.tv_nsec < rhs_ts.tv_nsec) + return true; + + return false; + } + + void swapSample(Sample *lhs, Sample *rhs) { + if (buffer) { + sample_copy(buffer, lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } else { + buffer = sample_clone(lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } + } + +public: + ReorderTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : + Hook(p, n, fl, prio, en), + window{}, + window_size(16), + buffer(nullptr) + { } + + virtual void parse(json_t *json) + { + assert(state != State::STARTED); + + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s?: i }", + "window", &window_size + ); + if (ret) + throw ConfigError(json, err, "node-config-hook-reorder-ts"); + + state = State::PARSED; + } + + virtual void start() + { + assert(state == State::PREPARED || state == State::STOPPED); + + window.reserve(window_size); + + state = State::STARTED; + } + + virtual void stop() + { + assert(state == State::STARTED); + + for (auto sample : window) + sample_free(sample); + + if (buffer) + sample_free(buffer); + + window.clear(); + + state = State::STOPPED; + } + + virtual Hook::Reason process(Sample *sample) + { + assert(state == State::STARTED); + assert(sample); + + if (window.empty()) { + window.push_back(sample_clone(sample)); + + logger->info("window.size={}/{}", window.size(), window_size); + + return Hook::Reason::SKIP_SAMPLE; + } + + for (std::size_t i = window.size() - 1;; i--) { + if (!compareTimestamp(sample, window[i])) { + if (i != window.size() - 1) { + logger->warn("Fixing reordered Sample"); + sample_dump(logger, sample); + } + + if (window.size() == window_size) { + // The front sample will be returned. + Sample *window_sample = window.front(); + // Move all elements before the index of insertion towards the front. + std::memmove(&window[0], &window[1], i * sizeof(decltype(window)::value_type)); + // Store the new sample at the correct index. + window[i] = window_sample; + // Swap the contents of the front sample with the processed sample. + swapSample(window_sample, sample); + + return Hook::Reason::OK; + } else { + // Increase the vector size by 1. + window.push_back(nullptr); + // Move all elements from the index of insertion onwards towards the back. + std::memmove(&window[i + 2], &window[i + 1], (window.size() - i - 2) * sizeof(decltype(window)::value_type)); + // Store the new sample at the correct index. + window[i + 1] = sample_clone(sample); + + logger->info("window.size={}/{}", window.size(), window_size); + + return Hook::Reason::SKIP_SAMPLE; + } + } + + if (!i) break; + } + + logger->error("Could not reorder Sample"); + sample_dump(logger, sample); + + return Hook::Reason::SKIP_SAMPLE; + } + + virtual void restart() + { + assert(state == State::STARTED); + + for (auto sample : window) + sample_free(sample); + + window.clear(); + } +}; + +/* Register hook */ +static char n[] = "reorder_ts"; +static char d[] = "Reorder messages by their timestamp"; +static HookPlugin p; + +} /* namespace node */ +} /* namespace villas */ From aa3e08ae64b4d95e81c3e1085d10957108c4a0ca Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 13:21:34 +0200 Subject: [PATCH 021/100] hook-reorder-ts: Add example for 'reorder_ts' hook Signed-off-by: Philipp Jungkamp --- etc/examples/hooks/reorder_ts.conf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 etc/examples/hooks/reorder_ts.conf diff --git a/etc/examples/hooks/reorder_ts.conf b/etc/examples/hooks/reorder_ts.conf new file mode 100644 index 000000000..fa16d1361 --- /dev/null +++ b/etc/examples/hooks/reorder_ts.conf @@ -0,0 +1,16 @@ +@include "hook-nodes.conf" + +paths = ( + { + in = "signal_node" + out = "file_node" + + hooks = ( + { + type = "reorder_ts" + + window = 10 + } + ) + } +) From 26887f00ff20e4f500355b4722afb849a13094d2 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 17:55:12 +0200 Subject: [PATCH 022/100] hook-reorder-ts: Fix code-style Signed-off-by: Philipp Jungkamp --- etc/examples/hooks/reorder_ts.conf | 2 +- lib/hooks/reorder_ts.cpp | 71 +++++++++++++----------------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/etc/examples/hooks/reorder_ts.conf b/etc/examples/hooks/reorder_ts.conf index fa16d1361..7d639f744 100644 --- a/etc/examples/hooks/reorder_ts.conf +++ b/etc/examples/hooks/reorder_ts.conf @@ -9,7 +9,7 @@ paths = ( { type = "reorder_ts" - window = 10 + window_size = 10 } ) } diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index ca593038f..ebd4cd8b4 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -9,9 +9,11 @@ #include #include #include +#include #include #include +#include namespace villas { namespace node { @@ -23,19 +25,6 @@ protected: std::size_t window_size; Sample *buffer; - bool compareTimestamp(Sample *lhs, Sample *rhs) { - auto lhs_ts = lhs->ts.origin; - auto rhs_ts = rhs->ts.origin; - - if (lhs_ts.tv_sec < rhs_ts.tv_sec) - return true; - - if (lhs_ts.tv_sec == rhs_ts.tv_sec && lhs_ts.tv_nsec < rhs_ts.tv_nsec) - return true; - - return false; - } - void swapSample(Sample *lhs, Sample *rhs) { if (buffer) { sample_copy(buffer, lhs); @@ -56,13 +45,14 @@ public: buffer(nullptr) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { assert(state != State::STARTED); json_error_t err; int ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "window", &window_size + "window_size", &window_size ); if (ret) throw ConfigError(json, err, "node-config-hook-reorder-ts"); @@ -70,7 +60,8 @@ public: state = State::PARSED; } - virtual void start() + virtual + void start() { assert(state == State::PREPARED || state == State::STOPPED); @@ -79,7 +70,8 @@ public: state = State::STARTED; } - virtual void stop() + virtual + void stop() { assert(state == State::STARTED); @@ -94,61 +86,60 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(Sample *sample) + virtual + Hook::Reason process(Sample *smp) { assert(state == State::STARTED); - assert(sample); + assert(smp); if (window.empty()) { - window.push_back(sample_clone(sample)); + window.push_back(sample_clone(smp)); - logger->info("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); return Hook::Reason::SKIP_SAMPLE; } for (std::size_t i = window.size() - 1;; i--) { - if (!compareTimestamp(sample, window[i])) { - if (i != window.size() - 1) { + if (time_cmp(&smp->ts.origin, &window[i]->ts.origin) >= 0) { + if (i != window.size() - 1) logger->warn("Fixing reordered Sample"); - sample_dump(logger, sample); - } if (window.size() == window_size) { - // The front sample will be returned. Sample *window_sample = window.front(); - // Move all elements before the index of insertion towards the front. - std::memmove(&window[0], &window[1], i * sizeof(decltype(window)::value_type)); - // Store the new sample at the correct index. + std::copy( + ++std::begin(window), + std::next(std::begin(window), i + 1), + std::begin(window)); window[i] = window_sample; - // Swap the contents of the front sample with the processed sample. - swapSample(window_sample, sample); + swapSample(window_sample, smp); return Hook::Reason::OK; } else { - // Increase the vector size by 1. window.push_back(nullptr); - // Move all elements from the index of insertion onwards towards the back. - std::memmove(&window[i + 2], &window[i + 1], (window.size() - i - 2) * sizeof(decltype(window)::value_type)); - // Store the new sample at the correct index. - window[i + 1] = sample_clone(sample); + std::copy_backward( + std::next(std::begin(window), i + 1), + --std::end(window), + std::end(window)); + window[i + 1] = sample_clone(smp); - logger->info("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); return Hook::Reason::SKIP_SAMPLE; } } - if (!i) break; + if (!i) + break; } logger->error("Could not reorder Sample"); - sample_dump(logger, sample); return Hook::Reason::SKIP_SAMPLE; } - virtual void restart() + virtual + void restart() { assert(state == State::STARTED); From 636dee213c63e1b90b5a763ab6cf9a554a525845 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Aug 2023 18:32:10 +0200 Subject: [PATCH 023/100] Fix code-style Signed-off-by: Steffen Vogel --- lib/hooks/reorder_ts.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index ebd4cd8b4..53fff9bd2 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -25,7 +25,8 @@ protected: std::size_t window_size; Sample *buffer; - void swapSample(Sample *lhs, Sample *rhs) { + void swapSample(Sample *lhs, Sample *rhs) + { if (buffer) { sample_copy(buffer, lhs); sample_copy(lhs, rhs); From f03579df2fe44b49413904b87047be703013bb54 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 29 Aug 2023 13:32:57 +0200 Subject: [PATCH 024/100] hook-reorder-ts: Add OpenAPI specification Signed-off-by: Philipp Jungkamp --- .../components/schemas/config/hook_obj.yaml | 1 + .../schemas/config/hooks/_reorder_ts.yaml | 3 +++ .../schemas/config/hooks/reorder_ts.yaml | 14 ++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml create mode 100644 doc/openapi/components/schemas/config/hooks/reorder_ts.yaml diff --git a/doc/openapi/components/schemas/config/hook_obj.yaml b/doc/openapi/components/schemas/config/hook_obj.yaml index 240e23f44..81d1cd117 100644 --- a/doc/openapi/components/schemas/config/hook_obj.yaml +++ b/doc/openapi/components/schemas/config/hook_obj.yaml @@ -30,6 +30,7 @@ discriminator: pmu_dft: hooks/_pmu_dft.yaml pps_ts: hooks/_pps_ts.yaml print: hooks/_print.yaml + reorder_ts: hooks/_reorder_ts.yaml restart: hooks/_restart.yaml rms: hooks/_rms.yaml round: hooks/_round.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml b/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml new file mode 100644 index 000000000..a562b1945 --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml @@ -0,0 +1,3 @@ +allOf: +- $ref: ../hook_obj.yaml +- $ref: reorder_ts.yaml diff --git a/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml b/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml new file mode 100644 index 000000000..7d284700f --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +--- + +allOf: +- type: object + properties: + window_size: + description: | + The size of the window in which samples will be reordered. + This also represents the latency in number of samples introduced by this hook. + type: integer + default: 16 + +- $ref: ../hook.yaml From 78727be952dc5898765f7bfe1e19e2324d041618 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 28 Aug 2023 09:34:02 +0200 Subject: [PATCH 025/100] Use C++ style comments Signed-off-by: Steffen Vogel --- clients/shmem/villas-shmem.cpp | 6 +++--- include/villas/api.hpp | 6 +++--- include/villas/api/request.hpp | 6 +++--- include/villas/api/requests/node.hpp | 6 +++--- include/villas/api/requests/path.hpp | 6 +++--- include/villas/api/requests/universal.hpp | 6 +++--- include/villas/api/response.hpp | 6 +++--- include/villas/api/session.hpp | 6 +++--- include/villas/api/universal.hpp | 8 ++++---- include/villas/capabilities.hpp | 2 +- include/villas/config_class.hpp | 4 ++-- include/villas/config_helper.hpp | 4 ++-- include/villas/dumper.hpp | 4 ++-- include/villas/format.hpp | 4 ++-- include/villas/formats/column.hpp | 4 ++-- include/villas/formats/iotagent_ul.hpp | 4 ++-- include/villas/formats/json.hpp | 4 ++-- include/villas/formats/json_edgeflex.hpp | 4 ++-- include/villas/formats/json_kafka.hpp | 4 ++-- include/villas/formats/json_reserve.hpp | 4 ++-- include/villas/formats/line.hpp | 4 ++-- include/villas/formats/msg.hpp | 4 ++-- include/villas/formats/msg_format.hpp | 4 ++-- include/villas/formats/opal_asyncip.hpp | 4 ++-- include/villas/formats/protobuf.hpp | 4 ++-- include/villas/formats/raw.hpp | 4 ++-- include/villas/formats/value.hpp | 4 ++-- include/villas/formats/villas_binary.hpp | 4 ++-- include/villas/formats/villas_human.hpp | 4 ++-- include/villas/hook.hpp | 4 ++-- include/villas/hook_list.hpp | 4 ++-- include/villas/hooks/decimate.hpp | 4 ++-- include/villas/hooks/limit_rate.hpp | 4 ++-- include/villas/hooks/lua.hpp | 4 ++-- include/villas/hooks/pmu.hpp | 4 ++-- include/villas/kernel/if.hpp | 4 ++-- include/villas/kernel/nl.hpp | 6 +++--- include/villas/kernel/tc.hpp | 6 +++--- include/villas/kernel/tc_netem.hpp | 6 +++--- include/villas/log_opal_sink.hpp | 4 ++-- include/villas/mapping.hpp | 4 ++-- include/villas/mapping_list.hpp | 4 ++-- include/villas/memory/ib.h | 6 +++--- include/villas/node.hpp | 4 ++-- include/villas/node/exceptions.hpp | 4 ++-- include/villas/node/memory.hpp | 6 +++--- include/villas/node/memory_type.hpp | 6 +++--- include/villas/node_compat.hpp | 4 ++-- include/villas/node_compat_type.hpp | 4 ++-- include/villas/node_direction.hpp | 4 ++-- include/villas/node_list.hpp | 4 ++-- include/villas/nodes/amqp.hpp | 4 ++-- include/villas/nodes/api.hpp | 4 ++-- include/villas/nodes/can.hpp | 4 ++-- include/villas/nodes/comedi.hpp | 4 ++-- include/villas/nodes/ethercat.hpp | 4 ++-- include/villas/nodes/example.hpp | 4 ++-- include/villas/nodes/exec.hpp | 4 ++-- include/villas/nodes/file.hpp | 4 ++-- include/villas/nodes/fpga.hpp | 4 ++-- include/villas/nodes/iec60870.hpp | 4 ++-- include/villas/nodes/iec61850.hpp | 4 ++-- include/villas/nodes/iec61850_goose.hpp | 4 ++-- include/villas/nodes/iec61850_sv.hpp | 4 ++-- include/villas/nodes/infiniband.hpp | 4 ++-- include/villas/nodes/influxdb.hpp | 4 ++-- include/villas/nodes/kafka.hpp | 4 ++-- include/villas/nodes/loopback.hpp | 4 ++-- include/villas/nodes/loopback_internal.hpp | 4 ++-- include/villas/nodes/modbus.hpp | 6 +++--- include/villas/nodes/mqtt.hpp | 4 ++-- include/villas/nodes/nanomsg.hpp | 4 ++-- include/villas/nodes/ngsi.hpp | 4 ++-- include/villas/nodes/opal.hpp | 4 ++-- include/villas/nodes/redis.hpp | 4 ++-- include/villas/nodes/redis_helpers.hpp | 6 +++--- include/villas/nodes/rtp.hpp | 4 ++-- include/villas/nodes/shmem.hpp | 4 ++-- include/villas/nodes/signal.hpp | 4 ++-- include/villas/nodes/signal_old.hpp | 4 ++-- include/villas/nodes/socket.hpp | 4 ++-- include/villas/nodes/stats.hpp | 4 ++-- include/villas/nodes/temper.hpp | 4 ++-- include/villas/nodes/test_rtt.hpp | 4 ++-- include/villas/nodes/uldaq.hpp | 4 ++-- include/villas/nodes/webrtc.hpp | 4 ++-- include/villas/nodes/webrtc/peer_connection.hpp | 6 +++--- include/villas/nodes/webrtc/signaling_client.hpp | 6 +++--- include/villas/nodes/webrtc/signaling_message.hpp | 6 +++--- include/villas/nodes/websocket.hpp | 4 ++-- include/villas/nodes/zeromq.hpp | 4 ++-- include/villas/path.hpp | 4 ++-- include/villas/path_destination.hpp | 4 ++-- include/villas/path_list.hpp | 4 ++-- include/villas/path_source.hpp | 4 ++-- include/villas/pool.hpp | 4 ++-- include/villas/queue.h | 4 ++-- include/villas/queue.hpp | 2 +- include/villas/queue_signalled.h | 4 ++-- include/villas/queue_signalled.hpp | 2 +- include/villas/sample.hpp | 4 ++-- include/villas/shmem.hpp | 4 ++-- include/villas/signal.hpp | 4 ++-- include/villas/signal_data.hpp | 4 ++-- include/villas/signal_list.hpp | 4 ++-- include/villas/signal_type.hpp | 4 ++-- include/villas/socket_addr.hpp | 4 ++-- include/villas/stats.hpp | 2 +- include/villas/super_node.hpp | 4 ++-- include/villas/usb.hpp | 4 ++-- include/villas/web.hpp | 4 ++-- lib/api/requests/capabiltities.cpp | 6 +++--- lib/api/requests/config.cpp | 6 +++--- lib/api/requests/graph.cpp | 6 +++--- lib/api/requests/node_action.cpp | 6 +++--- lib/api/requests/node_file.cpp | 6 +++--- lib/api/requests/node_info.cpp | 6 +++--- lib/api/requests/node_stats.cpp | 6 +++--- lib/api/requests/node_stats_reset.cpp | 6 +++--- lib/api/requests/nodes.cpp | 6 +++--- lib/api/requests/path_action.cpp | 6 +++--- lib/api/requests/path_info.cpp | 6 +++--- lib/api/requests/paths.cpp | 6 +++--- lib/api/requests/restart.cpp | 6 +++--- lib/api/requests/shutdown.cpp | 6 +++--- lib/api/requests/status.cpp | 6 +++--- lib/api/requests/universal/channel.cpp | 8 ++++---- lib/api/requests/universal/channels.cpp | 8 ++++---- lib/api/requests/universal/info.cpp | 8 ++++---- lib/api/requests/universal/status.cpp | 8 ++++---- lib/hooks/average.cpp | 4 ++-- lib/hooks/cast.cpp | 4 ++-- lib/hooks/decimate.cpp | 4 ++-- lib/hooks/dp.cpp | 4 ++-- lib/hooks/drop.cpp | 4 ++-- lib/hooks/dump.cpp | 4 ++-- lib/hooks/ebm.cpp | 4 ++-- lib/hooks/fix.cpp | 4 ++-- lib/hooks/gate.cpp | 4 ++-- lib/hooks/jitter_calc.cpp | 4 ++-- lib/hooks/limit_rate.cpp | 4 ++-- lib/hooks/limit_value.cpp | 4 ++-- lib/hooks/lua.cpp | 4 ++-- lib/hooks/ma.cpp | 4 ++-- lib/hooks/pmu.cpp | 4 ++-- lib/hooks/pmu_dft.cpp | 6 +++--- lib/hooks/pmu_ipdft.cpp | 4 ++-- lib/hooks/power.cpp | 4 ++-- lib/hooks/pps_ts.cpp | 4 ++-- lib/hooks/print.cpp | 4 ++-- lib/hooks/restart.cpp | 4 ++-- lib/hooks/rms.cpp | 4 ++-- lib/hooks/round.cpp | 4 ++-- lib/hooks/scale.cpp | 4 ++-- lib/hooks/shift_seq.cpp | 4 ++-- lib/hooks/shift_ts.cpp | 4 ++-- lib/hooks/skip_first.cpp | 4 ++-- lib/hooks/stats.cpp | 4 ++-- lib/hooks/ts.cpp | 4 ++-- plugins/example_hook.cpp | 4 ++-- src/villas-compare.cpp | 6 +++--- src/villas-conf2json.cpp | 6 +++--- src/villas-convert.cpp | 6 +++--- src/villas-graph.cpp | 6 +++--- src/villas-hook.cpp | 6 +++--- src/villas-pipe.cpp | 6 +++--- src/villas-relay.cpp | 6 +++--- src/villas-relay.hpp | 6 +++--- src/villas-signal.cpp | 6 +++--- src/villas-test-config.cpp | 6 +++--- src/villas-test-rtt.cpp | 6 +++--- src/villas-zmq-keygen.cpp | 6 +++--- 172 files changed, 397 insertions(+), 397 deletions(-) diff --git a/clients/shmem/villas-shmem.cpp b/clients/shmem/villas-shmem.cpp index 877b833f7..345b5ca4f 100644 --- a/clients/shmem/villas-shmem.cpp +++ b/clients/shmem/villas-shmem.cpp @@ -117,9 +117,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/include/villas/api.hpp b/include/villas/api.hpp index bbb32680f..fc8da99de 100644 --- a/include/villas/api.hpp +++ b/include/villas/api.hpp @@ -73,7 +73,7 @@ public: InvalidMethod(Request *req); }; -} /* namespace api */ +} // namespace api /* Forward declarations */ class SuperNode; @@ -113,5 +113,5 @@ public: villas::QueueSignalled pending; /**< A queue of api_sessions which have pending requests. */ }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index ac962d26b..5f3b3b29a 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -179,6 +179,6 @@ public: } }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/requests/node.hpp b/include/villas/api/requests/node.hpp index 71cb40708..e8672f770 100644 --- a/include/villas/api/requests/node.hpp +++ b/include/villas/api/requests/node.hpp @@ -30,6 +30,6 @@ public: prepare(); }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/requests/path.hpp b/include/villas/api/requests/path.hpp index c3d05528e..9868cd0ce 100644 --- a/include/villas/api/requests/path.hpp +++ b/include/villas/api/requests/path.hpp @@ -28,6 +28,6 @@ public: prepare(); }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/requests/universal.hpp b/include/villas/api/requests/universal.hpp index 25be3940e..cc12d2ba6 100644 --- a/include/villas/api/requests/universal.hpp +++ b/include/villas/api/requests/universal.hpp @@ -31,6 +31,6 @@ public: prepare(); }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/response.hpp b/include/villas/api/response.hpp index ac9c6434b..79afd3be9 100644 --- a/include/villas/api/response.hpp +++ b/include/villas/api/response.hpp @@ -95,6 +95,6 @@ public: } }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index 5c0aa7c77..b62ec896c 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -102,6 +102,6 @@ public: methodToString(Method meth); }; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/api/universal.hpp b/include/villas/api/universal.hpp index 00e4500cc..fb13678ed 100644 --- a/include/villas/api/universal.hpp +++ b/include/villas/api/universal.hpp @@ -51,7 +51,7 @@ public: void parse(json_t *json, bool readable, bool writable); }; -} /* namespace universal */ -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace universal +} // namespace api +} // namespace node +} // namespace villas diff --git a/include/villas/capabilities.hpp b/include/villas/capabilities.hpp index c7e54d51c..195f3c5f3 100644 --- a/include/villas/capabilities.hpp +++ b/include/villas/capabilities.hpp @@ -14,5 +14,5 @@ namespace node { json_t * getCapabilities(); -} /* namespace node */ +} // namespace node } /* namepace vilals */ diff --git a/include/villas/config_class.hpp b/include/villas/config_class.hpp index 567f75dc9..f49563655 100644 --- a/include/villas/config_class.hpp +++ b/include/villas/config_class.hpp @@ -87,5 +87,5 @@ public: json_t * load(const std::string &u, bool resolveIncludes = true, bool resolveEnvVars = true); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index 17bb6e73b..ae66b2811 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -40,5 +40,5 @@ int json_object_extend(json_t *orig, json_t *merge); json_t * json_load_cli(int argc, const char *argv[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/dumper.hpp b/include/villas/dumper.hpp index 35e0cda9b..762814230 100644 --- a/include/villas/dumper.hpp +++ b/include/villas/dumper.hpp @@ -39,5 +39,5 @@ public: void writeDataBinary(unsigned len, double *yData, double *xData = nullptr); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 901836c34..8cafd277b 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -193,5 +193,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/column.hpp b/include/villas/formats/column.hpp index 585f9a930..5449a5d16 100644 --- a/include/villas/formats/column.hpp +++ b/include/villas/formats/column.hpp @@ -66,5 +66,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/iotagent_ul.hpp b/include/villas/formats/iotagent_ul.hpp index bb56b52f3..547ff40f3 100644 --- a/include/villas/formats/iotagent_ul.hpp +++ b/include/villas/formats/iotagent_ul.hpp @@ -28,5 +28,5 @@ public: using Format::Format; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 8fc0ccf66..40cbb9e56 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -56,5 +56,5 @@ public: void parse(json_t *json); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/json_edgeflex.hpp b/include/villas/formats/json_edgeflex.hpp index df5c7c331..8a22c714d 100644 --- a/include/villas/formats/json_edgeflex.hpp +++ b/include/villas/formats/json_edgeflex.hpp @@ -24,5 +24,5 @@ public: using JsonFormat::JsonFormat; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/json_kafka.hpp b/include/villas/formats/json_kafka.hpp index 6876d79d3..236388465 100644 --- a/include/villas/formats/json_kafka.hpp +++ b/include/villas/formats/json_kafka.hpp @@ -32,5 +32,5 @@ public: void parse(json_t *json); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/json_reserve.hpp b/include/villas/formats/json_reserve.hpp index 4e236309b..7800a0419 100644 --- a/include/villas/formats/json_reserve.hpp +++ b/include/villas/formats/json_reserve.hpp @@ -24,5 +24,5 @@ public: using JsonFormat::JsonFormat; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index 30a19ef8e..54a4df2f1 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -87,5 +87,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/msg.hpp b/include/villas/formats/msg.hpp index 62b120420..dc9c6e795 100644 --- a/include/villas/formats/msg.hpp +++ b/include/villas/formats/msg.hpp @@ -48,5 +48,5 @@ int msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalLis /** Copy fields form \p smp into \p msg. */ int msg_from_sample(struct Message *msg, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 6ee6e1e9d..64ed1e4b1 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -70,5 +70,5 @@ struct Message } data[]; } __attribute__((packed)); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/opal_asyncip.hpp b/include/villas/formats/opal_asyncip.hpp index d154b74c2..d74593923 100644 --- a/include/villas/formats/opal_asyncip.hpp +++ b/include/villas/formats/opal_asyncip.hpp @@ -74,5 +74,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index e3b8d91c4..cac4f68c9 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -35,5 +35,5 @@ public: int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/raw.hpp b/include/villas/formats/raw.hpp index 95d06b356..c4e0201c0 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -66,5 +66,5 @@ public: { } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 83763090f..4cc1e902a 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -26,5 +26,5 @@ public: int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/villas_binary.hpp b/include/villas/formats/villas_binary.hpp index 81146ad8f..520e1a84b 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -81,5 +81,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index 58e97899c..bf99a6475 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -30,5 +30,5 @@ public: void header(FILE *f, const SignalList::Ptr sigs); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 233d13386..3624b3d20 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -307,5 +307,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index 2ed1c7c9e..70d23eba7 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -64,5 +64,5 @@ public: json_t * toJson() const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hooks/decimate.hpp b/include/villas/hooks/decimate.hpp index 35251767a..d5f1c8a17 100644 --- a/include/villas/hooks/decimate.hpp +++ b/include/villas/hooks/decimate.hpp @@ -49,6 +49,6 @@ public: Hook::Reason process(struct Sample *smp); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hooks/limit_rate.hpp b/include/villas/hooks/limit_rate.hpp index 9e443c9ba..92b08ad99 100644 --- a/include/villas/hooks/limit_rate.hpp +++ b/include/villas/hooks/limit_rate.hpp @@ -42,5 +42,5 @@ public: virtual Hook::Reason process(struct Sample *smp); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hooks/lua.hpp b/include/villas/hooks/lua.hpp index 2a5672ab5..49de8b140 100644 --- a/include/villas/hooks/lua.hpp +++ b/include/villas/hooks/lua.hpp @@ -129,5 +129,5 @@ public: }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/hooks/pmu.hpp b/include/villas/hooks/pmu.hpp index 30b1ea5a5..088f52381 100644 --- a/include/villas/hooks/pmu.hpp +++ b/include/villas/hooks/pmu.hpp @@ -84,5 +84,5 @@ public: Phasor estimatePhasor(dsp::CosineWindow *window, Phasor lastPhasor); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index 48ac20dd1..0fdcb1bf4 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -115,5 +115,5 @@ public: } }; -} /* namespace kernel */ -} /* namespace villas */ +} // namespace kernel +} // namespace villas diff --git a/include/villas/kernel/nl.hpp b/include/villas/kernel/nl.hpp index c2c83c50e..ca4fcbda6 100644 --- a/include/villas/kernel/nl.hpp +++ b/include/villas/kernel/nl.hpp @@ -41,6 +41,6 @@ struct nl_sock * init(); /** Close and free global netlink socket. */ void shutdown(); -} /* namespace nl */ -} /* namespace kernel */ -} /* namespace villas */ +} // namespace nl +} // namespace kernel +} // namespace villas diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index 0a51053c4..55adcab83 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -61,6 +61,6 @@ int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, int ba */ int mark(Interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark); -} /* namespace tc */ -} /* namespace kernel */ -} /* namespace villas */ +} // namespace tc +} // namespace kernel +} // namespace villas diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index 0559c3e89..dea2d776c 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -59,6 +59,6 @@ int netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent int netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json); -} /* namespace tc */ -} /* namespace kernel */ -} /* namespace villas */ +} // namespace tc +} // namespace kernel +} // namespace villas diff --git a/include/villas/log_opal_sink.hpp b/include/villas/log_opal_sink.hpp index 1826e1546..9cd390c79 100644 --- a/include/villas/log_opal_sink.hpp +++ b/include/villas/log_opal_sink.hpp @@ -54,5 +54,5 @@ using OpalSink_mt = OpalSink; using OpalSink_st = OpalSink; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/mapping.hpp b/include/villas/mapping.hpp index df1c1494f..c760325e9 100644 --- a/include/villas/mapping.hpp +++ b/include/villas/mapping.hpp @@ -106,5 +106,5 @@ public: Signal::Ptr toSignal(unsigned index) const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/mapping_list.hpp b/include/villas/mapping_list.hpp index b21695a2c..e6e480ddb 100644 --- a/include/villas/mapping_list.hpp +++ b/include/villas/mapping_list.hpp @@ -28,5 +28,5 @@ public: int update(const MappingEntry::Ptr me, struct Sample *remapped, const struct Sample *original); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/memory/ib.h b/include/villas/memory/ib.h index 23d15779f..164b6640d 100644 --- a/include/villas/memory/ib.h +++ b/include/villas/memory/ib.h @@ -21,6 +21,6 @@ struct IB { struct ibv_mr * ib_get_mr(void *ptr); -} /* namespace memory */ -} /* namespace node */ -} /* namespace villas */ +} // namespace memory +} // namespace node +} // namespace villas diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 8cec6db01..a69ab1eab 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -481,5 +481,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/node/exceptions.hpp b/include/villas/node/exceptions.hpp index 2225ab9af..4f72e828d 100644 --- a/include/villas/node/exceptions.hpp +++ b/include/villas/node/exceptions.hpp @@ -71,5 +71,5 @@ public: { } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index c7a0db721..930cda757 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -71,6 +71,6 @@ int free(void *ptr); struct Allocation * get_allocation(void *ptr); -} /* namespace memory */ -} /* namespace node */ -} /* namespace villas */ +} // namespace memory +} // namespace node +} // namespace villas diff --git a/include/villas/node/memory_type.hpp b/include/villas/node/memory_type.hpp index 98f6ef587..0756b885e 100644 --- a/include/villas/node/memory_type.hpp +++ b/include/villas/node/memory_type.hpp @@ -53,6 +53,6 @@ struct Type * managed(void *ptr, size_t len); int mmap_init(int hugepages) __attribute__ ((warn_unused_result)); -} /* namespace memory */ -} /* namespace node */ -} /* namespace villas */ +} // namespace memory +} // namespace node +} // namespace villas diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index b1d40c78f..4c8b13333 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -202,5 +202,5 @@ public: int stop(); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index b962d68a6..4535b28f7 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -220,5 +220,5 @@ public: struct memory::Type * (*memory_type)(NodeCompat *n, struct memory::Type *parent); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp index 053374d4c..54b87d518 100644 --- a/include/villas/node_direction.hpp +++ b/include/villas/node_direction.hpp @@ -61,5 +61,5 @@ public: unsigned getSignalsMaxCount() const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index 52c05d16d..51d95f954 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -45,5 +45,5 @@ public: json_t * toJson() const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index 8ea42a03d..e928cc5ef 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -67,5 +67,5 @@ int amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/api.hpp b/include/villas/nodes/api.hpp index ecbf75682..79ce3f4e2 100644 --- a/include/villas/nodes/api.hpp +++ b/include/villas/nodes/api.hpp @@ -51,5 +51,5 @@ protected: int _write(struct Sample *smps[], unsigned cnt); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index 5b3d0839a..0c382da04 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -60,5 +60,5 @@ int can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int can_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index a5bc3eb7b..c09a8970a 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -78,5 +78,5 @@ int comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 43169955d..3de4a57d0 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -91,5 +91,5 @@ int ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index 005bb2b24..5afbe6e9f 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -93,5 +93,5 @@ public: }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/exec.hpp b/include/villas/nodes/exec.hpp index af8a07c88..6f666cdd7 100644 --- a/include/villas/nodes/exec.hpp +++ b/include/villas/nodes/exec.hpp @@ -72,5 +72,5 @@ public: std::vector getPollFDs(); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index 01bc952ec..72dd1bf4b 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -73,5 +73,5 @@ int file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index b76aa784e..79edaf907 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -113,5 +113,5 @@ public: int start(SuperNode *sn); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/iec60870.hpp b/include/villas/nodes/iec60870.hpp index f245c29da..e487f2040 100644 --- a/include/villas/nodes/iec60870.hpp +++ b/include/villas/nodes/iec60870.hpp @@ -187,5 +187,5 @@ public: }; } /* namespace iec60870 */ -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index 002b6e9d0..786744129 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -101,5 +101,5 @@ int iec61850_receiver_destroy(struct iec61850_receiver *r); const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/iec61850_goose.hpp b/include/villas/nodes/iec61850_goose.hpp index 4f60fb99e..c11770b4e 100644 --- a/include/villas/nodes/iec61850_goose.hpp +++ b/include/villas/nodes/iec61850_goose.hpp @@ -255,5 +255,5 @@ public: }; } /* namespace iec61850 */ -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index 6be13f043..51c7ef121 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -79,5 +79,5 @@ int iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) int iec61850_sv_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index 26445fc39..0678b37a5 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -111,5 +111,5 @@ int ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/influxdb.hpp b/include/villas/nodes/influxdb.hpp index a31174ab2..91e66e6bf 100644 --- a/include/villas/nodes/influxdb.hpp +++ b/include/villas/nodes/influxdb.hpp @@ -37,5 +37,5 @@ int influxdb_close(NodeCompat *n); int influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/kafka.hpp b/include/villas/nodes/kafka.hpp index 3c25b5150..a7bffb9c6 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -80,5 +80,5 @@ int kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/loopback.hpp b/include/villas/nodes/loopback.hpp index 2395b8aad..7813e24e4 100644 --- a/include/villas/nodes/loopback.hpp +++ b/include/villas/nodes/loopback.hpp @@ -50,5 +50,5 @@ public: int parse(json_t *json); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index cecf511c7..ff38604e2 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -75,5 +75,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index c7df327cb..b5472602d 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -288,6 +288,6 @@ public: const std::string & getDetails(); }; -} /* namespace modbus */ -} /* namespace node */ -} /* namespace villas */ +} // namespace modbus +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 9d683070e..0e5ba87e0 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -80,5 +80,5 @@ int mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index 9f0f8abf6..b280a690a 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -53,5 +53,5 @@ int nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/ngsi.hpp b/include/villas/nodes/ngsi.hpp index 33b037076..3202e7382 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -74,5 +74,5 @@ int ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int ngsi_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index 9e8541b74..ba09adac5 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -52,5 +52,5 @@ int opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index 56744877b..d2cbd0181 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -120,5 +120,5 @@ int redis_poll_fds(NodeCompat *n, int fds[]); int redis_netem_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index d35018ed5..be967972c 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -63,7 +63,7 @@ struct hash } }; -} /* namespace std */ +} // namespace std namespace sw { namespace redis { @@ -166,8 +166,8 @@ OStream &operator<<(OStream &os, const ConnectionOptions &o) return os; } -} /* namespace redis */ -} /* namespace sw */ +} // namespace redis +} // namespace sw template OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index f8a7c2e35..1f3c96372 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -109,5 +109,5 @@ int rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/shmem.hpp b/include/villas/nodes/shmem.hpp index 29da87c40..ae94d446b 100644 --- a/include/villas/nodes/shmem.hpp +++ b/include/villas/nodes/shmem.hpp @@ -44,5 +44,5 @@ int shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/signal.hpp b/include/villas/nodes/signal.hpp index 222be861a..f63dcc328 100644 --- a/include/villas/nodes/signal.hpp +++ b/include/villas/nodes/signal.hpp @@ -103,5 +103,5 @@ public: std::vector getPollFDs(); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/signal_old.hpp b/include/villas/nodes/signal_old.hpp index d00cdf423..c0200cf0d 100644 --- a/include/villas/nodes/signal_old.hpp +++ b/include/villas/nodes/signal_old.hpp @@ -73,5 +73,5 @@ int signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int signal_node_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index d0305ede1..f4fc53539 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -71,5 +71,5 @@ int socket_parse(NodeCompat *n, json_t *json); char * socket_print(NodeCompat *n); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/stats.hpp b/include/villas/nodes/stats.hpp index 7a1538bb9..9b9c45b7b 100644 --- a/include/villas/nodes/stats.hpp +++ b/include/villas/nodes/stats.hpp @@ -62,5 +62,5 @@ int stats_node_signal_parse(struct stats_node_signal *s, json_t *json); int stats_node_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index e86f35efd..9224b3540 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -147,5 +147,5 @@ int temper_poll_fds(NodeCompat *n, int fds[]); int temper_netem_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/test_rtt.hpp b/include/villas/nodes/test_rtt.hpp index 0986ba8b7..0e357f090 100644 --- a/include/villas/nodes/test_rtt.hpp +++ b/include/villas/nodes/test_rtt.hpp @@ -68,5 +68,5 @@ int test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int test_rtt_poll_fds(NodeCompat *n, int fds[]); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/uldaq.hpp b/include/villas/nodes/uldaq.hpp index 8c06d53ba..8378844ca 100644 --- a/include/villas/nodes/uldaq.hpp +++ b/include/villas/nodes/uldaq.hpp @@ -72,5 +72,5 @@ int uldaq_stop(NodeCompat *n); int uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp index be853494b..3d7593fd1 100644 --- a/include/villas/nodes/webrtc.hpp +++ b/include/villas/nodes/webrtc.hpp @@ -117,5 +117,5 @@ public: }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index bdf374a01..ebbfd42e7 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -90,7 +90,7 @@ protected: void onDataChannelMessage(rtc::binary msg); }; -} /* namespace webrtc */ -} /* namespace node */ -} /* namespace villas */ +} // namespace webrtc +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/webrtc/signaling_client.hpp b/include/villas/nodes/webrtc/signaling_client.hpp index 970d466ba..13e09eccd 100644 --- a/include/villas/nodes/webrtc/signaling_client.hpp +++ b/include/villas/nodes/webrtc/signaling_client.hpp @@ -113,7 +113,7 @@ public: } }; -} /* namespace webrtc */ -} /* namespace node */ -} /* namespace villas */ +} // namespace webrtc +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/webrtc/signaling_message.hpp b/include/villas/nodes/webrtc/signaling_message.hpp index c2e797783..b0d651691 100644 --- a/include/villas/nodes/webrtc/signaling_message.hpp +++ b/include/villas/nodes/webrtc/signaling_message.hpp @@ -57,6 +57,6 @@ struct SignalingMessage { std::string toString() const; }; -} /* namespace webrtc */ -} /* namespace node */ -} /* namespace villas */ +} // namespace webrtc +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index 06501759c..7a3d74017 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -126,5 +126,5 @@ int websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/zeromq.hpp b/include/villas/nodes/zeromq.hpp index ad3990916..40de65a29 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -83,5 +83,5 @@ int zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); int zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 9d67fc5b2..3f84f2ac3 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -197,5 +197,5 @@ public: json_t * toJson() const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/path_destination.hpp b/include/villas/path_destination.hpp index 97d513484..9239c3a00 100644 --- a/include/villas/path_destination.hpp +++ b/include/villas/path_destination.hpp @@ -55,5 +55,5 @@ public: using PathDestinationList = std::vector; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 9f7366be4..220c8ebce 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -30,5 +30,5 @@ public: json_t * toJson() const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp index 2ea7a0f4f..ea7da31c7 100644 --- a/include/villas/path_source.hpp +++ b/include/villas/path_source.hpp @@ -100,5 +100,5 @@ public: -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/pool.hpp b/include/villas/pool.hpp index 46f4dea31..41932a395 100644 --- a/include/villas/pool.hpp +++ b/include/villas/pool.hpp @@ -66,5 +66,5 @@ void * pool_get(struct Pool *p); /** Release a memory block back to the pool. */ int pool_put(struct Pool *p, void *buf); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/queue.h b/include/villas/queue.h index a1512ffe4..7906628ed 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -113,5 +113,5 @@ int queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt); */ int queue_close(struct CQueue *q); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index 3e0e15678..3e783b40d 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -47,4 +47,4 @@ public: }; -} /* namespace villas */ +} // namespace villas diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index ba04f4483..6a50ce5a8 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -67,5 +67,5 @@ int queue_signalled_close(struct CQueueSignalled *qs) __attribute__ ((warn_unuse /** Returns a file descriptor which can be used with poll / select to wait for new data */ int queue_signalled_fd(struct CQueueSignalled *qs); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/queue_signalled.hpp b/include/villas/queue_signalled.hpp index fffee36a7..a343181cf 100644 --- a/include/villas/queue_signalled.hpp +++ b/include/villas/queue_signalled.hpp @@ -43,4 +43,4 @@ public: } }; -} /* namespace villas */ +} // namespace villas diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index b52d9ab66..4964476e0 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -129,5 +129,5 @@ enum SignalType sample_format(const struct Sample *s, unsigned idx); void sample_data_insert(struct Sample *smp, const union SignalData *src, size_t offset, size_t len); void sample_data_remove(struct Sample *smp, size_t offset, size_t len); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/shmem.hpp b/include/villas/shmem.hpp index 2a6d7d87e..ebeefe0a3 100644 --- a/include/villas/shmem.hpp +++ b/include/villas/shmem.hpp @@ -105,5 +105,5 @@ int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned * per struct Sample. */ size_t shmem_total_size(int queuelen, int samplelen); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/signal.hpp b/include/villas/signal.hpp index 962b833d5..e654431ea 100644 --- a/include/villas/signal.hpp +++ b/include/villas/signal.hpp @@ -50,5 +50,5 @@ public: bool isNext(const Signal &sig); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/signal_data.hpp b/include/villas/signal_data.hpp index 3aef644e4..be6c91169 100644 --- a/include/villas/signal_data.hpp +++ b/include/villas/signal_data.hpp @@ -65,5 +65,5 @@ union SignalData { std::string toString(enum SignalType type, int precision = 5) const; }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/signal_list.hpp b/include/villas/signal_list.hpp index 22322e2a2..77f34b06e 100644 --- a/include/villas/signal_list.hpp +++ b/include/villas/signal_list.hpp @@ -50,5 +50,5 @@ public: Signal::Ptr getByIndex(unsigned idx); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/signal_type.hpp b/include/villas/signal_type.hpp index a037aa2d8..e606eba8f 100644 --- a/include/villas/signal_type.hpp +++ b/include/villas/signal_type.hpp @@ -29,5 +29,5 @@ std::string signalTypeToString(enum SignalType fmt); enum SignalType signalTypeDetect(const std::string &val); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index 7d0bb8a49..f7312e987 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -71,5 +71,5 @@ int socket_parse_address(const char *str, struct sockaddr *sa, enum SocketLayer int socket_compare_addr(struct sockaddr *x, struct sockaddr *y); -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/stats.hpp b/include/villas/stats.hpp index f57948002..18d0671cb 100644 --- a/include/villas/stats.hpp +++ b/include/villas/stats.hpp @@ -123,4 +123,4 @@ public: static std::vector columns; }; -} /* namespace villas */ +} // namespace villas diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index 806e1bc81..7711420e4 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -194,5 +194,5 @@ public: ~SuperNode(); }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/include/villas/usb.hpp b/include/villas/usb.hpp index ffa72b170..9ff70e184 100644 --- a/include/villas/usb.hpp +++ b/include/villas/usb.hpp @@ -108,5 +108,5 @@ struct libusb_context * get_context(); void detach(struct libusb_device_handle *hdl, int iface); -} /* namespace usb */ -} /* namespace villas */ +} // namespace usb +} // namespace villas diff --git a/include/villas/web.hpp b/include/villas/web.hpp index 2129fa738..64f43dc45 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -95,5 +95,5 @@ public: } }; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index 81bb14852..cf0a494c2 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -38,6 +38,6 @@ static char r[] = "/capabilities"; static char d[] = "get capabiltities and details about this VILLASnode instance"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index 41fb1a0fc..c341402ac 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -43,6 +43,6 @@ static char r[] = "/config"; static char d[] = "get configuration of this VILLASnode instance"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/graph.cpp b/lib/api/requests/graph.cpp index 9513accf7..963a00292 100644 --- a/lib/api/requests/graph.cpp +++ b/lib/api/requests/graph.cpp @@ -113,7 +113,7 @@ static char r[] = "/graph\\.([a-z]+)"; static char d[] = "get graph representation of configuration"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index 8df3fc01f..eff4b24dc 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -71,6 +71,6 @@ static char d5[] = "restart a node"; static RequestPlugin, n5, r5, d5> p5; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 67503fa17..2ecc6c661 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -54,6 +54,6 @@ static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/file(?:/([^/]+))?"; static char d[] = "control instances of 'file' node-type"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index d99f22374..9b31b8170 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -51,6 +51,6 @@ static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")"; static char d[] = "retrieve info of a node"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index 55d38092e..086ba4d10 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -46,6 +46,6 @@ static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/stats"; static char d[] = "get internal statistics counters"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index 57c3017c9..889d68dde 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -48,6 +48,6 @@ static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/stats/reset"; static char d[] = "reset internal statistics counters"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index bc4c563c1..167d3c866 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -44,6 +44,6 @@ static char r[] = "/nodes"; static char d[] = "retrieve list of all known nodes"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 296a36b2c..30cb7957e 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -52,6 +52,6 @@ static char d2[] = "stop a path"; static RequestPlugin, n2, r2, d2> p2; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index 36c709264..ad3f8549f 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -42,6 +42,6 @@ static char r[] = "/path/(" RE_UUID ")"; static char d[] = "retrieve info of a path"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index f38aba7e7..7ee255641 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -44,6 +44,6 @@ static char r[] = "/paths"; static char d[] = "retrieve list of all paths with details"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 29a150fd3..2fa383ede 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -124,7 +124,7 @@ static char r[] = "/restart"; static char d[] = "restart VILLASnode with new configuration"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index 6ffb8890b..60b24b3d2 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -40,6 +40,6 @@ static char r[] = "/shutdown"; static char d[] = "quit VILLASnode"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index 83925d20a..74be93763 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -114,7 +114,7 @@ static char r[] = "/status"; static char d[] = "get status and statistics of web server"; static RequestPlugin p; -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/universal/channel.cpp b/lib/api/requests/universal/channel.cpp index 060a1ebea..d8b1a971b 100644 --- a/lib/api/requests/universal/channel.cpp +++ b/lib/api/requests/universal/channel.cpp @@ -157,7 +157,7 @@ static char r[] = "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|e static char d[] = "retrieve or send samples via universal data-exchange API"; static RequestPlugin p; -} /* namespace universal */ -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace universal +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/universal/channels.cpp b/lib/api/requests/universal/channels.cpp index e835a0bba..576a9216f 100644 --- a/lib/api/requests/universal/channels.cpp +++ b/lib/api/requests/universal/channels.cpp @@ -54,7 +54,7 @@ static char r[] = "/universal/(" RE_NODE_NAME ")/channels"; static char d[] = "get channels of universal data-exchange API node"; static RequestPlugin p; -} /* namespace universal */ -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace universal +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/universal/info.cpp b/lib/api/requests/universal/info.cpp index 053207bce..efbc46023 100644 --- a/lib/api/requests/universal/info.cpp +++ b/lib/api/requests/universal/info.cpp @@ -47,7 +47,7 @@ static char r[] = "/universal/(" RE_NODE_NAME ")/info"; static char d[] = "get infos of universal data-exchange API"; static RequestPlugin p; -} /* namespace universal */ -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace universal +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/api/requests/universal/status.cpp b/lib/api/requests/universal/status.cpp index 0270cbad3..222681e4c 100644 --- a/lib/api/requests/universal/status.cpp +++ b/lib/api/requests/universal/status.cpp @@ -41,7 +41,7 @@ static char r[] = "/universal/(" RE_NODE_NAME ")/status"; static char d[] = "get status of universal data-exchange API"; static RequestPlugin p; -} /* namespace universal */ -} /* namespace api */ -} /* namespace node */ -} /* namespace villas */ +} // namespace universal +} // namespace api +} // namespace node +} // namespace villas diff --git a/lib/hooks/average.cpp b/lib/hooks/average.cpp index 5a517a29b..db8d6bd6f 100644 --- a/lib/hooks/average.cpp +++ b/lib/hooks/average.cpp @@ -103,5 +103,5 @@ static char n[] = "average"; static char d[] = "Calculate average over some signals"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/cast.cpp b/lib/hooks/cast.cpp index 73e41ff6a..6dfe0179f 100644 --- a/lib/hooks/cast.cpp +++ b/lib/hooks/cast.cpp @@ -105,6 +105,6 @@ static char n[] = "cast"; static char d[] = "Cast signals types"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/decimate.cpp b/lib/hooks/decimate.cpp index 9bea7d24d..e6c397400 100644 --- a/lib/hooks/decimate.cpp +++ b/lib/hooks/decimate.cpp @@ -57,5 +57,5 @@ static char n[] = "decimate"; static char d[] = "Downsamping by integer factor"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/dp.cpp b/lib/hooks/dp.cpp index c7d0b42b6..010c77f24 100644 --- a/lib/hooks/dp.cpp +++ b/lib/hooks/dp.cpp @@ -297,5 +297,5 @@ static char n[] = "dp"; static char d[] = "Transform to/from dynamic phasor domain"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/drop.cpp b/lib/hooks/drop.cpp index 89bd594de..0ea53ca65 100644 --- a/lib/hooks/drop.cpp +++ b/lib/hooks/drop.cpp @@ -80,5 +80,5 @@ static char n[] = "drop"; static char d[] = "Drop messages with reordered sequence numbers"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/dump.cpp b/lib/hooks/dump.cpp index c8b3ebcdb..4571707eb 100644 --- a/lib/hooks/dump.cpp +++ b/lib/hooks/dump.cpp @@ -31,5 +31,5 @@ static char n[] = "dump"; static char d[] = "Dump data to stdout"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/ebm.cpp b/lib/hooks/ebm.cpp index 2eda91353..f2d054f40 100644 --- a/lib/hooks/ebm.cpp +++ b/lib/hooks/ebm.cpp @@ -109,5 +109,5 @@ static char n[] = "ebm"; static char d[] = "Energy-based Metric"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/fix.cpp b/lib/hooks/fix.cpp index 5d9f6affd..5e50ffc60 100644 --- a/lib/hooks/fix.cpp +++ b/lib/hooks/fix.cpp @@ -50,6 +50,6 @@ static char n[] = "fix"; static char d[] = "Fix received data by adding missing fields"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/gate.cpp b/lib/hooks/gate.cpp index b4ed6e651..cd4ae43b1 100644 --- a/lib/hooks/gate.cpp +++ b/lib/hooks/gate.cpp @@ -155,5 +155,5 @@ static char n[] = "gate"; static char d[] = "Skip samples only if an enable signal is under a specified threshold"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/jitter_calc.cpp b/lib/hooks/jitter_calc.cpp index efbff88b0..d32b047c2 100644 --- a/lib/hooks/jitter_calc.cpp +++ b/lib/hooks/jitter_calc.cpp @@ -97,5 +97,5 @@ static char n[] = "jitter_calc"; static char d[] = "Calc jitter, mean and variance of GPS vs NTP TS"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/limit_rate.cpp b/lib/hooks/limit_rate.cpp index ef45704a9..e07fe7909 100644 --- a/lib/hooks/limit_rate.cpp +++ b/lib/hooks/limit_rate.cpp @@ -81,5 +81,5 @@ static char n[] = "limit_rate"; static char d[] = "Limit sending rate"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/limit_value.cpp b/lib/hooks/limit_value.cpp index 0a66d61e7..7b23512b1 100644 --- a/lib/hooks/limit_value.cpp +++ b/lib/hooks/limit_value.cpp @@ -89,5 +89,5 @@ static char n[] = "limit_value"; static char d[] = "Limit signal values"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index eddce457c..d75392cd2 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -773,5 +773,5 @@ static char n[] = "lua"; static char d[] = "Implement hook functions or expressions in Lua"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/ma.cpp b/lib/hooks/ma.cpp index f877b631d..baf507f21 100644 --- a/lib/hooks/ma.cpp +++ b/lib/hooks/ma.cpp @@ -105,5 +105,5 @@ static char n[] = "ma"; static char d[] = "A simple moving average filter over a fixed number of past samples"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/pmu.cpp b/lib/hooks/pmu.cpp index f5915aadb..491b6f004 100644 --- a/lib/hooks/pmu.cpp +++ b/lib/hooks/pmu.cpp @@ -247,5 +247,5 @@ static char n[] = "pmu"; static char d[] = "This hook estimates a phsor"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/pmu_dft.cpp b/lib/hooks/pmu_dft.cpp index 086b1f21a..a5c0118bf 100644 --- a/lib/hooks/pmu_dft.cpp +++ b/lib/hooks/pmu_dft.cpp @@ -168,7 +168,7 @@ public: phasorPhase(dumperPrefix + "phasorPhase"), phasorAmplitude(dumperPrefix + "phasorAmplitude"), phasorFreq(dumperPrefix + "phasorFreq"), -#endif +#endif angleUnitFactor(1), phaseOffset(0.0), frequencyOffset(0.0), @@ -671,5 +671,5 @@ static char n[] = "pmu_dft"; static char d[] = "This hook calculates the dft on a window"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/pmu_ipdft.cpp b/lib/hooks/pmu_ipdft.cpp index a235634f2..99a3a8c44 100644 --- a/lib/hooks/pmu_ipdft.cpp +++ b/lib/hooks/pmu_ipdft.cpp @@ -154,5 +154,5 @@ static char n[] = "ip-dft-pmu"; static char d[] = "This hook calculates a phasor based on ipDFT"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/power.cpp b/lib/hooks/power.cpp index f1540c746..414fe5b49 100644 --- a/lib/hooks/power.cpp +++ b/lib/hooks/power.cpp @@ -331,5 +331,5 @@ static char n[] = "power"; static char d[] = "This hook calculates the Active and Reactive Power for a given signal "; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/pps_ts.cpp b/lib/hooks/pps_ts.cpp index 6bf969e12..b2541e37c 100644 --- a/lib/hooks/pps_ts.cpp +++ b/lib/hooks/pps_ts.cpp @@ -224,5 +224,5 @@ static char n[] = "pps_ts"; static char d[] = "Timestamp samples based GPS PPS signal"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/print.cpp b/lib/hooks/print.cpp index 7467cb29f..e93de76e0 100644 --- a/lib/hooks/print.cpp +++ b/lib/hooks/print.cpp @@ -136,6 +136,6 @@ static char n[] = "print"; static char d[] = "Print the message to stdout or a file"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/restart.cpp b/lib/hooks/restart.cpp index 4ec1f6fca..5aad7d077 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -77,5 +77,5 @@ static char n[] = "restart"; static char d[] = "Call restart hooks for current node"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/rms.cpp b/lib/hooks/rms.cpp index 993d4d8fc..f33efbaea 100644 --- a/lib/hooks/rms.cpp +++ b/lib/hooks/rms.cpp @@ -114,5 +114,5 @@ static char n[] = "rms"; static char d[] = "This hook calculates the root-mean-square (RMS) on a window"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/round.cpp b/lib/hooks/round.cpp index 825e7b3ee..49ea6f2f0 100644 --- a/lib/hooks/round.cpp +++ b/lib/hooks/round.cpp @@ -72,5 +72,5 @@ static char n[] = "round"; static char d[] = "Round signals to a set number of digits"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/scale.cpp b/lib/hooks/scale.cpp index 06e99564f..d9daa6c3c 100644 --- a/lib/hooks/scale.cpp +++ b/lib/hooks/scale.cpp @@ -80,5 +80,5 @@ static char n[] = "scale"; static char d[] = "Scale signals by a factor and add offset"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/shift_seq.cpp b/lib/hooks/shift_seq.cpp index 90e4c046a..a56797b88 100644 --- a/lib/hooks/shift_seq.cpp +++ b/lib/hooks/shift_seq.cpp @@ -53,5 +53,5 @@ static char n[] = "shift_seq"; static char d[] = "Shift sequence number of samples"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/shift_ts.cpp b/lib/hooks/shift_ts.cpp index f0ffa2235..55b6e2f69 100644 --- a/lib/hooks/shift_ts.cpp +++ b/lib/hooks/shift_ts.cpp @@ -91,5 +91,5 @@ static char n[] = "shift_ts"; static char d[] = "Shift timestamps of samples"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/skip_first.cpp b/lib/hooks/skip_first.cpp index 1994e6ce2..4bff92e76 100644 --- a/lib/hooks/skip_first.cpp +++ b/lib/hooks/skip_first.cpp @@ -126,5 +126,5 @@ static char n[] = "skip_first"; static char d[] = "Skip the first samples"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/stats.cpp b/lib/hooks/stats.cpp index 4e17c458e..801c1784b 100644 --- a/lib/hooks/stats.cpp +++ b/lib/hooks/stats.cpp @@ -263,6 +263,6 @@ static char n[] = "stats"; static char d[] = "Collect statistics for the current node"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/hooks/ts.cpp b/lib/hooks/ts.cpp index 659287771..bfe8ec548 100644 --- a/lib/hooks/ts.cpp +++ b/lib/hooks/ts.cpp @@ -32,5 +32,5 @@ static char n[] = "ts"; static char d[] = "Overwrite origin timestamp of samples with receive timestamp"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/plugins/example_hook.cpp b/plugins/example_hook.cpp index eada31936..fc96abdeb 100644 --- a/plugins/example_hook.cpp +++ b/plugins/example_hook.cpp @@ -27,5 +27,5 @@ static char n[] = "example"; static char d[] = "This is just a simple example hook"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/src/villas-compare.cpp b/src/villas-compare.cpp index 7aff485bc..7006f946b 100644 --- a/src/villas-compare.cpp +++ b/src/villas-compare.cpp @@ -266,9 +266,9 @@ out: for (auto side : sides) } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-conf2json.cpp b/src/villas-conf2json.cpp index d21fd3e90..a0e3d4cac 100644 --- a/src/villas-conf2json.cpp +++ b/src/villas-conf2json.cpp @@ -78,9 +78,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index 610bd6e11..aa9969895 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -161,9 +161,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index 8b833e175..ffd4a29fe 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -126,9 +126,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index b5ef0501a..30c1797dd 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -310,9 +310,9 @@ stop: sent = output->print(stdout, smps, send); } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index 822caf22d..9e8d6db76 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -510,9 +510,9 @@ check: if (optarg == endptr) }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index a4436fe20..6f107de1b 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -513,9 +513,9 @@ const lws_http_mount Relay::mount = { .basic_auth_login_file = nullptr, }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index ad3037384..3b8fd6000 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -155,6 +155,6 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index ef0baaa21..2b8b24708 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -314,9 +314,9 @@ out: sample_decref(t); } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-test-config.cpp b/src/villas-test-config.cpp index 4d82c2b6f..538a5688a 100644 --- a/src/villas-test-config.cpp +++ b/src/villas-test-config.cpp @@ -106,9 +106,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-test-rtt.cpp b/src/villas-test-rtt.cpp index 3b84c718e..da66d6bb2 100644 --- a/src/villas-test-rtt.cpp +++ b/src/villas-test-rtt.cpp @@ -238,9 +238,9 @@ check: if (optarg == endptr) } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { diff --git a/src/villas-zmq-keygen.cpp b/src/villas-zmq-keygen.cpp index 262f6b391..7f7cda8a1 100644 --- a/src/villas-zmq-keygen.cpp +++ b/src/villas-zmq-keygen.cpp @@ -73,9 +73,9 @@ protected: } }; -} /* namespace tools */ -} /* namespace node */ -} /* namespace villas */ +} // namespace tools +} // namespace node +} // namespace villas int main(int argc, char *argv[]) { From 0735eb0f89c976ba8db7abeae7814060fb5dfe3c Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 31 Aug 2023 11:25:01 +0200 Subject: [PATCH 026/100] Make project REUSE compliant And various other cleanups and harmonizations Signed-off-by: Steffen Vogel --- .devcontainer/devcontainer.json | 3 + .dockerignore | 3 + .editorconfig | 2 + .envrc | 2 + .gitignore | 3 + .gitlab-ci.yml | 18 +- .gitmodules | 3 + .reuse/dep5 | 12 + CHANGELOG.md | 5 + CMakeLists.txt | 7 +- CODEOWNERS | 3 + CONTRIBUTING.md | 7 +- COPYING.md | 194 -------------- LICENSE | 73 ++++++ LICENSES/Apache-2.0.txt | 73 ++++++ LICENSES/BSD-1-Clause.txt | 7 + LICENSES/BSD-2-Clause.txt | 9 + LICENSES/LGPL-2.1-only.txt | 175 +++++++++++++ README.md | 9 +- clients/CMakeLists.txt | 7 +- clients/hypersim/README.md | 5 + clients/hypersim/model/ucm_node.def | 3 + clients/matlab/README.md | 5 + clients/matlab/receiver.m | 8 +- clients/matlab/villas.conf | 3 + clients/opal/.gitignore | 5 +- clients/opal/.project | 4 + clients/opal/CMakeLists.txt | 7 +- clients/opal/models/send_receive/.gitignore | 3 + clients/opal/models/send_receive/Makefile.mk | 7 +- .../opal/models/send_receive/include/config.h | 19 +- .../opal/models/send_receive/include/msg.h | 17 +- .../models/send_receive/include/msg_format.h | 67 +++-- .../opal/models/send_receive/include/socket.h | 19 +- .../opal/models/send_receive/include/utils.h | 17 +- .../opal/models/send_receive/send_receive.llm | 2 + .../opal/models/send_receive/send_receive.mdl | 2 + .../models/send_receive/send_receive.probe | 2 + clients/opal/models/send_receive/src/compat.c | 11 +- clients/opal/models/send_receive/src/main.asv | 7 +- clients/opal/models/send_receive/src/main.c | 71 ++--- clients/opal/models/send_receive/src/msg.c | 10 +- clients/opal/models/send_receive/src/socket.c | 38 +-- clients/opal/models/send_receive/src/utils.c | 16 +- clients/opal/villas_udp.llp | 4 + clients/python/client.py | 3 + clients/shmem/CMakeLists.txt | 7 +- clients/shmem/villas-shmem.cpp | 10 +- ...las_typhoon_ethernet_variable_exchange.tse | 3 + cmake/FindEtherlab.cmake | 9 +- cmake/FindIBVerbs.cmake | 7 +- cmake/FindOpal.cmake | 7 +- cmake/FindRDMACM.cmake | 7 +- cmake/FindSymbol.cmake | 7 +- cmake/VILLASnodePackaging.cmake | 9 +- cmake/config/Coverage.cmake | 7 +- cmake/config/Debug.cmake | 7 +- cmake/config/Profiling.cmake | 7 +- cmake/config/Release.cmake | 7 +- cmake/toolchains/debian-arm64.cmake | 3 + cmake/toolchains/debian-armhf.cmake | 3 + common | 2 +- doc/.gitignore | 3 + doc/.redocly.yaml | 4 + doc/CMakeLists.txt | 9 +- doc/Doxyfile.in | 4 +- doc/index.html | 4 + doc/openapi-relay.yaml | 2 + doc/openapi/README.md | 13 - doc/openapi/components/README.md | 14 - .../components/parameters/node-uuid-name.yaml | 3 + .../components/parameters/node-uuid.yaml | 3 + .../components/parameters/path-uuid.yaml | 3 + doc/openapi/components/schemas/config.yaml | 3 +- .../components/schemas/config/format.yaml | 3 +- .../components/schemas/config/format_obj.yaml | 3 +- .../schemas/config/format_spec.yaml | 3 +- .../schemas/config/formats/_csv.yaml | 4 + .../schemas/config/formats/_gtnet.yaml | 4 + .../schemas/config/formats/_iotagent_ul.yaml | 4 + .../schemas/config/formats/_json.yaml | 4 + .../config/formats/_json_edgeflex.yaml | 4 + .../schemas/config/formats/_json_kafka.yaml | 4 + .../schemas/config/formats/_json_reserve.yaml | 4 + .../schemas/config/formats/_opal_asyncip.yaml | 4 + .../schemas/config/formats/_protobuf.yaml | 4 + .../schemas/config/formats/_raw.yaml | 4 + .../schemas/config/formats/_tsv.yaml | 4 + .../schemas/config/formats/_value.yaml | 4 + .../config/formats/_villas_binary.yaml | 4 + .../schemas/config/formats/_villas_human.yaml | 4 + .../schemas/config/formats/_villas_web.yaml | 4 + .../schemas/config/formats/column.yaml | 3 +- .../schemas/config/formats/csv.yaml | 3 +- .../schemas/config/formats/gtnet.yaml | 3 +- .../schemas/config/formats/iotagent_ul.yaml | 3 +- .../schemas/config/formats/json.yaml | 3 +- .../schemas/config/formats/json_edgeflex.yaml | 3 +- .../schemas/config/formats/json_kafka.yaml | 3 +- .../schemas/config/formats/json_reserve.yaml | 3 +- .../schemas/config/formats/line.yaml | 3 +- .../schemas/config/formats/opal_asyncip.yaml | 3 +- .../schemas/config/formats/protobuf.yaml | 3 +- .../schemas/config/formats/raw.yaml | 3 +- .../schemas/config/formats/tsv.yaml | 3 +- .../schemas/config/formats/value.yaml | 3 +- .../schemas/config/formats/villas_binary.yaml | 3 +- .../schemas/config/formats/villas_human.yaml | 3 +- .../schemas/config/formats/villas_web.yaml | 3 +- .../components/schemas/config/global.yaml | 3 +- .../components/schemas/config/hook.yaml | 4 +- .../components/schemas/config/hook_list.yaml | 3 +- .../components/schemas/config/hook_multi.yaml | 3 +- .../components/schemas/config/hook_obj.yaml | 3 +- .../schemas/config/hook_single.yaml | 3 +- .../components/schemas/config/hook_spec.yaml | 3 +- .../schemas/config/hooks/_average.yaml | 4 + .../schemas/config/hooks/_cast.yaml | 4 + .../schemas/config/hooks/_decimate.yaml | 4 + .../components/schemas/config/hooks/_dp.yaml | 3 + .../schemas/config/hooks/_drop.yaml | 4 + .../schemas/config/hooks/_dump.yaml | 4 + .../components/schemas/config/hooks/_ebm.yaml | 4 + .../components/schemas/config/hooks/_fix.yaml | 4 + .../schemas/config/hooks/_gate.yaml | 3 + .../schemas/config/hooks/_jitter_calc.yaml | 4 + .../schemas/config/hooks/_limit_rate.yaml | 4 + .../schemas/config/hooks/_limit_value.yaml | 4 + .../components/schemas/config/hooks/_lua.yaml | 4 + .../components/schemas/config/hooks/_ma.yaml | 4 + .../schemas/config/hooks/_pmu_dft.yaml | 4 + .../schemas/config/hooks/_pps_ts.yaml | 4 + .../schemas/config/hooks/_print.yaml | 4 + .../schemas/config/hooks/_restart.yaml | 4 + .../components/schemas/config/hooks/_rms.yaml | 4 + .../schemas/config/hooks/_round.yaml | 4 + .../schemas/config/hooks/_scale.yaml | 4 + .../schemas/config/hooks/_shift_seq.yaml | 4 + .../schemas/config/hooks/_shift_ts.yaml | 4 + .../schemas/config/hooks/_skip_first.yaml | 4 + .../schemas/config/hooks/_stats.yaml | 4 + .../components/schemas/config/hooks/_ts.yaml | 4 + .../schemas/config/hooks/average.yaml | 3 +- .../components/schemas/config/hooks/cast.yaml | 3 +- .../schemas/config/hooks/decimate.yaml | 3 +- .../components/schemas/config/hooks/dp.yaml | 3 +- .../components/schemas/config/hooks/drop.yaml | 3 +- .../components/schemas/config/hooks/dump.yaml | 3 +- .../components/schemas/config/hooks/ebm.yaml | 3 +- .../components/schemas/config/hooks/fix.yaml | 3 +- .../components/schemas/config/hooks/gate.yaml | 3 +- .../schemas/config/hooks/jitter_calc.yaml | 3 +- .../schemas/config/hooks/limit_rate.yaml | 3 +- .../schemas/config/hooks/limit_value.yaml | 3 +- .../components/schemas/config/hooks/lua.yaml | 3 +- .../components/schemas/config/hooks/ma.yaml | 3 +- .../schemas/config/hooks/pmu_dft.yaml | 3 +- .../schemas/config/hooks/pps_ts.yaml | 3 +- .../schemas/config/hooks/print.yaml | 3 +- .../schemas/config/hooks/restart.yaml | 3 +- .../components/schemas/config/hooks/rms.yaml | 3 +- .../schemas/config/hooks/round.yaml | 3 +- .../schemas/config/hooks/scale.yaml | 3 +- .../schemas/config/hooks/shift_seq.yaml | 3 +- .../schemas/config/hooks/shift_ts.yaml | 3 +- .../schemas/config/hooks/skip_first.yaml | 3 +- .../schemas/config/hooks/stats.yaml | 3 +- .../components/schemas/config/hooks/ts.yaml | 3 +- .../components/schemas/config/http.yaml | 3 +- .../components/schemas/config/logging.yaml | 3 +- .../components/schemas/config/netem.yaml | 4 +- .../components/schemas/config/node.yaml | 3 +- .../components/schemas/config/node_obj.yaml | 3 +- .../schemas/config/node_signals.yaml | 3 +- .../schemas/config/nodes/_amqp.yaml | 4 + .../components/schemas/config/nodes/_api.yaml | 4 + .../components/schemas/config/nodes/_can.yaml | 4 + .../schemas/config/nodes/_comedi.yaml | 4 + .../schemas/config/nodes/_ethercat.yaml | 4 + .../schemas/config/nodes/_example.yaml | 4 + .../schemas/config/nodes/_exec.yaml | 4 + .../schemas/config/nodes/_file.yaml | 4 + .../schemas/config/nodes/_fpga.yaml | 4 + .../schemas/config/nodes/_iec60870-5-104.yaml | 4 + .../schemas/config/nodes/_iec61850-8-1.yaml | 4 + .../schemas/config/nodes/_iec61850-9-2.yaml | 4 + .../schemas/config/nodes/_infiniband.yaml | 4 + .../schemas/config/nodes/_influxdb.yaml | 4 + .../schemas/config/nodes/_kafka.yaml | 4 + .../schemas/config/nodes/_loopback.yaml | 4 + .../schemas/config/nodes/_modbus.yaml | 4 + .../schemas/config/nodes/_mqtt.yaml | 4 + .../schemas/config/nodes/_nanomsg.yaml | 4 + .../schemas/config/nodes/_ngsi.yaml | 4 + .../schemas/config/nodes/_opal.yaml | 4 + .../schemas/config/nodes/_redis.yaml | 4 + .../components/schemas/config/nodes/_rtp.yaml | 4 + .../schemas/config/nodes/_shmem.yaml | 4 + .../schemas/config/nodes/_signal_node.yaml | 4 + .../schemas/config/nodes/_signal_v2_node.yaml | 4 + .../schemas/config/nodes/_socket.yaml | 4 + .../schemas/config/nodes/_stats_node.yaml | 4 + .../schemas/config/nodes/_temper.yaml | 4 + .../schemas/config/nodes/_test_rtt.yaml | 4 + .../schemas/config/nodes/_uldaq.yaml | 4 + .../schemas/config/nodes/_webrtc.yaml | 4 + .../schemas/config/nodes/_websocket.yaml | 4 + .../schemas/config/nodes/_zeromq.yaml | 4 + .../components/schemas/config/nodes/amqp.yaml | 3 +- .../components/schemas/config/nodes/api.yaml | 3 +- .../components/schemas/config/nodes/can.yaml | 3 +- .../schemas/config/nodes/comedi.yaml | 3 +- .../schemas/config/nodes/ethercat.yaml | 3 +- .../schemas/config/nodes/example.yaml | 3 +- .../components/schemas/config/nodes/exec.yaml | 3 +- .../components/schemas/config/nodes/file.yaml | 3 +- .../components/schemas/config/nodes/fpga.yaml | 3 +- .../schemas/config/nodes/iec60870-5-104.yaml | 3 +- .../schemas/config/nodes/iec61850-8-1.yaml | 3 +- .../schemas/config/nodes/iec61850-9-2.yaml | 3 +- .../schemas/config/nodes/infiniband.yaml | 3 +- .../schemas/config/nodes/influxdb.yaml | 3 +- .../schemas/config/nodes/kafka.yaml | 3 +- .../schemas/config/nodes/loopback.yaml | 3 +- .../schemas/config/nodes/modbus.yaml | 3 +- .../components/schemas/config/nodes/mqtt.yaml | 3 +- .../schemas/config/nodes/nanomsg.yaml | 3 +- .../components/schemas/config/nodes/ngsi.yaml | 3 +- .../components/schemas/config/nodes/opal.yaml | 3 +- .../schemas/config/nodes/redis.yaml | 3 +- .../components/schemas/config/nodes/rtp.yaml | 3 +- .../schemas/config/nodes/shmem.yaml | 3 +- .../schemas/config/nodes/signal_node.yaml | 3 +- .../schemas/config/nodes/signal_v2_node.yaml | 3 +- .../config/nodes/signals/api_signal.yaml | 3 +- .../config/nodes/signals/can_signal.yaml | 3 +- .../config/nodes/signals/comedi_signal.yaml | 3 +- .../config/nodes/signals/iec60870_signal.yaml | 3 +- .../nodes/signals/iec61850_goose_data.yaml | 3 +- .../iec61850_goose_publisher_data.yaml | 3 +- .../iec61850_goose_subscriber_signal.yaml | 3 +- .../config/nodes/signals/iec61850_signal.yaml | 3 +- .../config/nodes/signals/modbus_signal.yaml | 3 +- .../nodes/signals/signal_v2_signal.yaml | 3 +- .../config/nodes/signals/stats_signal.yaml | 3 +- .../config/nodes/signals/uldaq_signal.yaml | 4 +- .../schemas/config/nodes/socket.yaml | 3 +- .../schemas/config/nodes/stats_node.yaml | 3 +- .../schemas/config/nodes/temper.yaml | 3 +- .../schemas/config/nodes/test_rtt.yaml | 3 +- .../schemas/config/nodes/uldaq.yaml | 3 +- .../schemas/config/nodes/webrtc.yaml | 3 +- .../schemas/config/nodes/websocket.yaml | 3 +- .../schemas/config/nodes/zeromq.yaml | 3 +- .../components/schemas/config/path.yaml | 3 +- .../components/schemas/config/signal.yaml | 3 +- .../schemas/config/signal_list.yaml | 3 +- .../components/schemas/formats/edgeflex.yaml | 3 +- .../components/schemas/formats/igor.yaml | 3 +- .../components/schemas/formats/sogno-old.yaml | 3 +- .../components/schemas/formats/sogno.yaml | 3 +- doc/openapi/openapi.yaml | 2 + doc/openapi/paths/README.md | 105 -------- doc/openapi/paths/capabilities.yaml | 3 + doc/openapi/paths/config.yaml | 3 + doc/openapi/paths/graph.{format}.yaml | 3 + .../paths/node/node@{uuid-or-name}.yaml | 3 + .../node/node@{uuid-or-name}@file@rewind.yaml | 3 + .../node/node@{uuid-or-name}@file@seek.yaml | 3 + .../paths/node/node@{uuid-or-name}@pause.yaml | 3 + .../node/node@{uuid-or-name}@restart.yaml | 3 + .../node/node@{uuid-or-name}@resume.yaml | 3 + .../paths/node/node@{uuid-or-name}@start.yaml | 3 + .../paths/node/node@{uuid-or-name}@stats.yaml | 3 + .../node/node@{uuid-or-name}@stats@reset.yaml | 3 + .../paths/node/node@{uuid-or-name}@stop.yaml | 3 + doc/openapi/paths/nodes.yaml | 3 + doc/openapi/paths/path/path@{uuid}.yaml | 3 + doc/openapi/paths/path/path@{uuid}@start.yaml | 3 + doc/openapi/paths/path/path@{uuid}@stop.yaml | 3 + doc/openapi/paths/paths.yaml | 3 + doc/openapi/paths/restart.yaml | 3 + doc/openapi/paths/shutdown.yaml | 3 + doc/openapi/paths/status.yaml | 3 + doc/theme/header.html | 6 +- doc/theme/layout.xml | 4 + doc/theme/style.css | 5 + etc/CMakeLists.txt | 7 +- etc/WSCC_9bus_MV.conf | 3 + etc/eric-lab.conf | 10 +- etc/examples/api.conf | 3 + etc/examples/example.conf | 27 +- etc/examples/formats/csv.conf | 3 + etc/examples/formats/gtnet.conf | 3 + etc/examples/formats/iotagent_ul.conf | 3 + etc/examples/formats/json-edgeflex.conf | 3 + etc/examples/formats/json-kafka.conf | 3 + etc/examples/formats/json-reserve.conf | 3 + etc/examples/formats/json.conf | 3 + etc/examples/formats/opal-asyncip.conf | 3 + etc/examples/formats/protobuf.conf | 3 + etc/examples/formats/raw.conf | 3 + etc/examples/formats/tsv.conf | 3 + etc/examples/formats/value.conf | 3 + etc/examples/formats/villas-binary.conf | 3 + etc/examples/formats/villas-human.conf | 3 + etc/examples/formats/villas-web.conf | 3 + etc/examples/global.conf | 21 +- etc/examples/hooks/average.conf | 3 + etc/examples/hooks/cast.conf | 3 + etc/examples/hooks/decimate.conf | 3 + etc/examples/hooks/dp.conf | 3 + etc/examples/hooks/dump.conf | 3 + etc/examples/hooks/ebm.conf | 3 + etc/examples/hooks/gate.conf | 3 + etc/examples/hooks/hook-nodes.conf | 3 + etc/examples/hooks/ip-dft-pmu.conf | 3 + etc/examples/hooks/jitter_calc.conf | 3 + etc/examples/hooks/limit_rate.conf | 3 + etc/examples/hooks/limit_value.conf | 3 + etc/examples/hooks/lua.conf | 3 + etc/examples/hooks/ma.conf | 3 + etc/examples/hooks/pmu.conf | 3 + etc/examples/hooks/pmu_dft.conf | 3 + etc/examples/hooks/power.conf | 3 + etc/examples/hooks/pps_ts.conf | 3 + etc/examples/hooks/print.conf | 3 + etc/examples/hooks/rms.conf | 3 + etc/examples/hooks/round.conf | 3 + etc/examples/hooks/scale.conf | 3 + etc/examples/hooks/shift_seq.conf | 3 + etc/examples/hooks/shift_ts.conf | 3 + etc/examples/hooks/skip_first.conf | 3 + etc/examples/hooks/stats.conf | 3 + etc/examples/hooks/ts.conf | 3 + etc/examples/nodes/amqp.conf | 3 + etc/examples/nodes/api.conf | 3 + etc/examples/nodes/can.conf | 3 + etc/examples/nodes/comedi.conf | 3 + etc/examples/nodes/ethercat.conf | 3 + etc/examples/nodes/example.conf | 3 + etc/examples/nodes/exec.conf | 3 + etc/examples/nodes/file.conf | 3 + etc/examples/nodes/fpga.conf | 3 + .../nodes/iec60870-5-104-sequence.conf | 3 + etc/examples/nodes/iec60870-5-104.conf | 3 + etc/examples/nodes/iec61850-8-1.conf | 3 + etc/examples/nodes/iec61850-9-2.conf | 3 + etc/examples/nodes/infiniband.conf | 3 + etc/examples/nodes/influxdb.conf | 3 + etc/examples/nodes/kafka.conf | 3 + etc/examples/nodes/loopback.conf | 3 + etc/examples/nodes/modbus.conf | 3 + etc/examples/nodes/mqtt.conf | 3 + etc/examples/nodes/nanomsg.conf | 3 + etc/examples/nodes/netem.conf | 3 + etc/examples/nodes/ngsi.conf | 3 + etc/examples/nodes/opal.conf | 3 + etc/examples/nodes/redis.conf | 3 + etc/examples/nodes/rtp.conf | 3 + etc/examples/nodes/shmem.conf | 3 + etc/examples/nodes/signal-v2.conf | 3 + etc/examples/nodes/signal.conf | 3 + etc/examples/nodes/socket.conf | 3 + etc/examples/nodes/stats.conf | 3 + etc/examples/nodes/temper.conf | 3 + etc/examples/nodes/test_rtt.conf | 3 + etc/examples/nodes/uldaq.conf | 3 + etc/examples/nodes/unix_domain.conf | 3 + etc/examples/nodes/webrtc.conf | 3 + etc/examples/nodes/websocket.conf | 3 + etc/examples/nodes/zeromq.conf | 3 + etc/examples/paths.conf | 3 + etc/examples/typhoon.conf | 3 + etc/examples/villas-web.conf | 3 + etc/gtnet-skt/emulate_gtnet.conf | 19 +- etc/gtnet-skt/test1.conf | 19 +- etc/gtnet-skt/test2.conf | 19 +- etc/gtnet-skt/test3.conf | 19 +- etc/gtnet-skt/test4.conf | 19 +- etc/gtnet-skt/test5.conf | 19 +- etc/gtnet-skt/test6_gtsync_compare.conf | 6 +- etc/js/config.js | 6 +- etc/js/global.js | 6 +- etc/labs/lab10_nodes.conf | 3 + etc/labs/lab10_path_bidir.conf | 3 + etc/labs/lab10_path_hook.conf | 3 + .../lab10_path_multiple_destinations.conf | 3 + etc/labs/lab10_path_uni.conf | 3 + etc/labs/lab11.conf | 3 + etc/labs/lab12.conf | 3 + etc/labs/lab13.conf | 3 + etc/labs/lab17.conf | 2 + etc/labs/lab18.conf | 37 +++ etc/labs/lab3.conf | 3 + etc/labs/lab4.conf | 3 + etc/labs/lab5.conf | 3 + etc/labs/lab7.conf | 3 + etc/labs/lab8.conf | 3 + etc/labs/lab9_netem.conf | 3 + etc/loopback.conf | 6 +- etc/python/example.py | 6 +- etc/shmem_mqtt.conf | 3 + etc/syslab-zmq.conf | 3 + etc/test.conf | 3 + etc/tricks/nodes/node_sig1.conf | 3 + etc/tricks/nodes/node_sig2.conf | 3 + etc/tricks/tricks.conf | 3 + etc/websocket-client.conf | 6 +- etc/websocket-demo.conf | 8 +- fpga | 2 +- include/villas/api.hpp | 23 +- include/villas/api/request.hpp | 29 +-- include/villas/api/requests/node.hpp | 17 +- include/villas/api/requests/path.hpp | 17 +- include/villas/api/requests/universal.hpp | 17 +- include/villas/api/response.hpp | 24 +- include/villas/api/session.hpp | 29 +-- include/villas/api/universal.hpp | 11 +- include/villas/capabilities.hpp | 12 +- include/villas/config_class.hpp | 37 +-- include/villas/config_helper.hpp | 18 +- include/villas/dumper.hpp | 11 +- include/villas/format.hpp | 29 +-- include/villas/formats/column.hpp | 21 +- include/villas/formats/iotagent_ul.hpp | 12 +- include/villas/formats/json.hpp | 15 +- include/villas/formats/json_edgeflex.hpp | 10 +- include/villas/formats/json_kafka.hpp | 10 +- include/villas/formats/json_reserve.hpp | 10 +- include/villas/formats/line.hpp | 27 +- include/villas/formats/msg.hpp | 28 +- include/villas/formats/msg_format.hpp | 63 +++-- include/villas/formats/opal_asyncip.hpp | 14 +- include/villas/formats/protobuf.hpp | 15 +- include/villas/formats/raw.hpp | 15 +- include/villas/formats/value.hpp | 11 +- include/villas/formats/villas_binary.hpp | 14 +- include/villas/formats/villas_human.hpp | 11 +- include/villas/hook.hpp | 49 ++-- include/villas/hook_list.hpp | 18 +- include/villas/hooks/decimate.hpp | 11 +- include/villas/hooks/limit_rate.hpp | 22 +- include/villas/hooks/lua.hpp | 62 +++-- include/villas/hooks/pmu.hpp | 15 +- include/villas/kernel/if.hpp | 41 ++- include/villas/kernel/nl-private.h | 10 + include/villas/kernel/nl.hpp | 19 +- include/villas/kernel/tc.hpp | 21 +- include/villas/kernel/tc_netem.hpp | 19 +- include/villas/log_opal_sink.hpp | 14 +- include/villas/mapping.hpp | 23 +- include/villas/mapping_list.hpp | 11 +- include/villas/memory/ib.h | 11 +- include/villas/node.h | 11 +- include/villas/node.hpp | 117 ++++----- include/villas/node/config.hpp.in | 7 +- include/villas/node/exceptions.hpp | 13 +- include/villas/node/memory.hpp | 23 +- include/villas/node/memory_type.hpp | 27 +- include/villas/node_compat.hpp | 41 ++- include/villas/node_compat_type.hpp | 55 ++-- include/villas/node_direction.hpp | 29 +-- include/villas/node_list.hpp | 20 +- include/villas/nodes/amqp.hpp | 15 +- include/villas/nodes/api.hpp | 13 +- include/villas/nodes/can.hpp | 17 +- include/villas/nodes/comedi.hpp | 13 +- include/villas/nodes/ethercat.hpp | 41 ++- include/villas/nodes/ethercat_config.hpp | 244 +++++++++--------- include/villas/nodes/example.hpp | 22 +- include/villas/nodes/exec.hpp | 13 +- include/villas/nodes/file.hpp | 43 ++- include/villas/nodes/fpga.hpp | 12 +- include/villas/nodes/iec60870.hpp | 28 +- include/villas/nodes/iec61850.hpp | 17 +- include/villas/nodes/iec61850_goose.hpp | 12 +- include/villas/nodes/iec61850_sv.hpp | 17 +- include/villas/nodes/infiniband.hpp | 43 ++- include/villas/nodes/influxdb.hpp | 13 +- include/villas/nodes/kafka.hpp | 35 ++- include/villas/nodes/loopback.hpp | 11 +- include/villas/nodes/loopback_internal.hpp | 11 +- include/villas/nodes/modbus.hpp | 12 +- include/villas/nodes/mqtt.hpp | 51 ++-- include/villas/nodes/nanomsg.hpp | 15 +- include/villas/nodes/ngsi.hpp | 40 ++- include/villas/nodes/opal.hpp | 13 +- include/villas/nodes/redis.hpp | 17 +- include/villas/nodes/redis_helpers.hpp | 17 +- include/villas/nodes/rtp.hpp | 29 +-- include/villas/nodes/shmem.hpp | 23 +- include/villas/nodes/signal.hpp | 45 ++-- include/villas/nodes/signal_old.hpp | 51 ++-- include/villas/nodes/socket.hpp | 36 ++- include/villas/nodes/stats.hpp | 15 +- include/villas/nodes/temper.hpp | 92 ++++--- include/villas/nodes/test_rtt.hpp | 29 +-- include/villas/nodes/uldaq.hpp | 14 +- include/villas/nodes/webrtc.hpp | 19 +- .../villas/nodes/webrtc/peer_connection.hpp | 16 +- .../villas/nodes/webrtc/signaling_client.hpp | 34 +-- .../villas/nodes/webrtc/signaling_message.hpp | 18 +- include/villas/nodes/websocket.hpp | 33 ++- include/villas/nodes/zeromq.hpp | 15 +- include/villas/path.hpp | 80 +++--- include/villas/path_destination.hpp | 13 +- include/villas/path_list.hpp | 16 +- include/villas/path_source.hpp | 21 +- include/villas/pool.hpp | 35 ++- include/villas/queue.h | 40 +-- include/villas/queue.hpp | 11 +- include/villas/queue_signalled.h | 23 +- include/villas/queue_signalled.hpp | 11 +- include/villas/sample.hpp | 77 +++--- include/villas/shmem.hpp | 51 ++-- include/villas/signal.hpp | 27 +- include/villas/signal_data.hpp | 30 +-- include/villas/signal_list.hpp | 11 +- include/villas/signal_type.hpp | 21 +- include/villas/socket_addr.hpp | 17 +- include/villas/stats.hpp | 52 ++-- include/villas/super_node.hpp | 47 ++-- include/villas/usb.hpp | 16 +- include/villas/web.hpp | 39 +-- lib/CMakeLists.txt | 7 +- lib/api.cpp | 16 +- lib/api/CMakeLists.txt | 7 +- lib/api/request.cpp | 11 +- lib/api/requests/capabiltities.cpp | 15 +- lib/api/requests/config.cpp | 15 +- lib/api/requests/graph.cpp | 16 +- lib/api/requests/node.cpp | 11 +- lib/api/requests/node_action.cpp | 16 +- lib/api/requests/node_file.cpp | 15 +- lib/api/requests/node_info.cpp | 15 +- lib/api/requests/node_stats.cpp | 15 +- lib/api/requests/node_stats_reset.cpp | 15 +- lib/api/requests/nodes.cpp | 15 +- lib/api/requests/path.cpp | 11 +- lib/api/requests/path_action.cpp | 16 +- lib/api/requests/path_info.cpp | 15 +- lib/api/requests/paths.cpp | 15 +- lib/api/requests/restart.cpp | 32 +-- lib/api/requests/shutdown.cpp | 15 +- lib/api/requests/status.cpp | 16 +- lib/api/requests/universal.cpp | 11 +- lib/api/requests/universal/channel.cpp | 15 +- lib/api/requests/universal/channels.cpp | 15 +- lib/api/requests/universal/info.cpp | 15 +- lib/api/requests/universal/status.cpp | 15 +- lib/api/response.cpp | 13 +- lib/api/session.cpp | 14 +- lib/api/universal.cpp | 11 +- lib/capabilities.cpp | 10 +- lib/config.cpp | 26 +- lib/config_helper.cpp | 34 +-- lib/dumper.cpp | 10 +- lib/format.cpp | 10 +- lib/formats/CMakeLists.txt | 7 +- lib/formats/column.cpp | 16 +- lib/formats/iotagent_ul.cpp | 11 +- lib/formats/json.cpp | 13 +- lib/formats/json_edgeflex.cpp | 11 +- lib/formats/json_kafka.cpp | 23 +- lib/formats/json_reserve.cpp | 12 +- lib/formats/line.cpp | 18 +- lib/formats/msg.cpp | 10 +- lib/formats/opal_asyncip.cpp | 15 +- lib/formats/protobuf.cpp | 11 +- lib/formats/raw.cpp | 53 ++-- lib/formats/value.cpp | 13 +- lib/formats/villas.proto | 6 +- lib/formats/villas_binary.cpp | 35 +-- lib/formats/villas_human.cpp | 25 +- lib/hook.cpp | 18 +- lib/hook_list.cpp | 16 +- lib/hooks/CMakeLists.txt | 7 +- lib/hooks/average.cpp | 25 +- lib/hooks/cast.cpp | 24 +- lib/hooks/decimate.cpp | 12 +- lib/hooks/dp.cpp | 43 +-- lib/hooks/drop.cpp | 24 +- lib/hooks/dump.cpp | 15 +- lib/hooks/ebm.cpp | 26 +- lib/hooks/fix.cpp | 16 +- lib/hooks/gate.cpp | 23 +- lib/hooks/jitter_calc.cpp | 22 +- lib/hooks/limit_rate.cpp | 12 +- lib/hooks/limit_value.cpp | 20 +- lib/hooks/lua.cpp | 37 +-- lib/hooks/ma.cpp | 26 +- lib/hooks/pmu.cpp | 25 +- lib/hooks/pmu_dft.cpp | 70 ++--- lib/hooks/pmu_ipdft.cpp | 44 ++-- lib/hooks/power.cpp | 33 +-- lib/hooks/pps_ts.cpp | 38 +-- lib/hooks/print.cpp | 15 +- lib/hooks/restart.cpp | 25 +- lib/hooks/rms.cpp | 24 +- lib/hooks/round.cpp | 18 +- lib/hooks/scale.cpp | 18 +- lib/hooks/shift_seq.cpp | 18 +- lib/hooks/shift_ts.cpp | 18 +- lib/hooks/skip_first.cpp | 34 +-- lib/hooks/stats.cpp | 52 ++-- lib/hooks/ts.cpp | 15 +- lib/kernel/if.cpp | 26 +- lib/kernel/nl.cpp | 32 +-- lib/kernel/tc.cpp | 12 +- lib/kernel/tc_netem.cpp | 23 +- lib/mapping.cpp | 16 +- lib/mapping_list.cpp | 11 +- lib/memory.cpp | 30 ++- lib/memory/heap.cpp | 12 +- lib/memory/ib.cpp | 10 +- lib/memory/managed.cpp | 28 +- lib/memory/mmap.cpp | 22 +- lib/node.cpp | 44 ++-- lib/node_capi.cpp | 13 +- lib/node_compat.cpp | 12 +- lib/node_direction.cpp | 26 +- lib/node_list.cpp | 11 +- lib/nodes/CMakeLists.txt | 7 +- lib/nodes/amqp.cpp | 38 +-- lib/nodes/api.cpp | 11 +- lib/nodes/can.cpp | 34 +-- lib/nodes/comedi.cpp | 110 ++++---- lib/nodes/ethercat.cpp | 68 ++--- lib/nodes/example.cpp | 22 +- lib/nodes/exec.cpp | 23 +- lib/nodes/file.cpp | 60 ++--- lib/nodes/fpga.cpp | 26 +- lib/nodes/iec60870.cpp | 17 +- lib/nodes/iec61850.cpp | 32 ++- lib/nodes/iec61850_goose.cpp | 11 +- lib/nodes/iec61850_sv.cpp | 46 ++-- lib/nodes/infiniband.cpp | 176 ++++++------- lib/nodes/influxdb.cpp | 30 ++- lib/nodes/kafka.cpp | 35 +-- lib/nodes/loopback.cpp | 13 +- lib/nodes/loopback_internal.cpp | 15 +- lib/nodes/modbus.cpp | 12 +- lib/nodes/mqtt.cpp | 28 +- lib/nodes/nanomsg.cpp | 30 ++- lib/nodes/ngsi.cpp | 85 +++--- lib/nodes/opal.cpp | 75 +++--- lib/nodes/redis.cpp | 46 ++-- lib/nodes/rtp.cpp | 77 +++--- lib/nodes/shmem.cpp | 27 +- lib/nodes/signal.cpp | 18 +- lib/nodes/signal_v1.cpp | 27 +- lib/nodes/socket.cpp | 68 ++--- lib/nodes/stats.cpp | 25 +- lib/nodes/temper.cpp | 76 +++--- lib/nodes/test_rtt.cpp | 46 ++-- lib/nodes/uldaq.cpp | 66 ++--- lib/nodes/webrtc.cpp | 21 +- lib/nodes/webrtc/peer_connection.cpp | 15 +- lib/nodes/webrtc/signaling_client.cpp | 14 +- lib/nodes/webrtc/signaling_message.cpp | 14 +- lib/nodes/websocket.cpp | 58 +++-- lib/nodes/zeromq.cpp | 63 ++--- lib/path.cpp | 86 +++--- lib/path_destination.cpp | 14 +- lib/path_list.cpp | 11 +- lib/path_source.cpp | 26 +- lib/pool.cpp | 12 +- lib/queue.cpp | 14 +- lib/queue_signalled.cpp | 29 +-- lib/sample.cpp | 20 +- lib/shmem.cpp | 31 ++- lib/signal.cpp | 16 +- lib/signal_data.cpp | 10 +- lib/signal_list.cpp | 12 +- lib/signal_type.cpp | 10 +- lib/socket_addr.cpp | 44 ++-- lib/stats.cpp | 10 +- lib/super_node.cpp | 36 +-- lib/usb.cpp | 11 +- lib/web.cpp | 52 ++-- lua/hooks/test.lua | 3 + packaging/CMakeLists.txt | 7 +- packaging/archlinux/.gitignore | 3 + packaging/archlinux/PKGBUILD | 2 + packaging/deps.sh | 2 + packaging/docker/Dockerfile.debian | 7 +- packaging/docker/Dockerfile.debian-multiarch | 7 +- packaging/docker/Dockerfile.fedora | 7 +- packaging/docker/Dockerfile.fedora-minimal | 7 +- packaging/docker/Dockerfile.rocky | 7 +- packaging/docker/Dockerfile.ubuntu | 7 +- packaging/libvillas.pc.in | 2 + packaging/live-iso/.gitignore | 4 +- packaging/live-iso/.gitlab-ci.yml | 5 +- packaging/live-iso/Dockerfile | 7 +- packaging/live-iso/Makefile | 3 + packaging/live-iso/README.md | 5 + packaging/live-iso/ensure_loop.sh | 2 + packaging/live-iso/villas.ks | 7 +- packaging/nix/README.md | 11 +- packaging/nix/ethercat.nix | 2 + packaging/nix/flake.nix | 2 + packaging/nix/lib60870.nix | 2 + packaging/nix/libdatachannel.nix | 2 + packaging/nix/libiec61850.nix | 2 + packaging/nix/villas.nix | 2 + plugins/CMakeLists.txt | 7 +- plugins/example_hook.cpp | 15 +- python/CMakeLists.txt | 7 +- python/README.md | 10 +- python/examples/Shmem_CIGRE_MV.py | 3 + python/setup.py | 3 + python/villas/node/communicate.py | 3 + python/villas/node/node.py | 3 + python/villas/node/sample.py | 3 + src/CMakeLists.txt | 7 +- src/villas-compare.cpp | 22 +- src/villas-conf2json.cpp | 10 +- src/villas-convert.cpp | 17 +- src/villas-graph.cpp | 30 +-- src/villas-hook.cpp | 19 +- src/villas-node.cpp | 19 +- src/villas-pipe.cpp | 30 +-- src/villas-relay.cpp | 36 ++- src/villas-relay.hpp | 44 ++-- src/villas-signal.cpp | 17 +- src/villas-test-config.cpp | 10 +- src/villas-test-rtt.cpp | 23 +- src/villas-zmq-keygen.cpp | 32 +-- tests/CMakeLists.txt | 9 +- tests/benchmarks/configs/infiniband.conf | 3 + tests/benchmarks/configs/loopback.conf | 3 + tests/benchmarks/configs/nanomsg.conf | 3 + tests/benchmarks/configs/shmem.conf | 3 + tests/benchmarks/configs/socket.conf | 3 + tests/benchmarks/configs/zeromq.conf | 3 + tests/benchmarks/run-benchmark.sh | 43 +-- tests/integration/CMakeLists.txt | 7 +- tests/integration/README.md | 5 + tests/integration/api-capabilities.sh | 7 +- tests/integration/api-config.sh | 7 +- tests/integration/api-nodes.sh | 7 +- tests/integration/api-paths.sh | 7 +- tests/integration/api-restart.sh | 7 +- tests/integration/api-shutdown.sh | 7 +- tests/integration/api-stress.sh | 7 +- tests/integration/compare.sh | 7 +- tests/integration/convert.sh | 7 +- tests/integration/hook-average.sh | 7 +- tests/integration/hook-cast.sh | 7 +- tests/integration/hook-decimate.sh | 7 +- tests/integration/hook-drop.sh | 7 +- tests/integration/hook-gate.sh | 7 +- tests/integration/hook-limit_rate.sh | 7 +- tests/integration/hook-lua.sh | 7 +- tests/integration/hook-lua_script.sh | 7 +- tests/integration/hook-print.sh | 7 +- tests/integration/hook-scale.sh | 7 +- tests/integration/hook-shift_seq.sh | 7 +- tests/integration/hook-shift_ts.sh | 7 +- tests/integration/hook-skip_first.sh | 7 +- tests/integration/hook-skip_first2.sh | 7 +- tests/integration/missing-example-configs.sh | 7 +- tests/integration/node-can.sh | 7 +- tests/integration/node-example.sh | 7 +- tests/integration/node-hook.sh | 7 +- tests/integration/node-infiniband.sh | 13 +- tests/integration/node-loopback-socket.sh | 7 +- tests/integration/node-mapping.sh | 7 +- .../integration/node-multiple-destinations.sh | 7 +- tests/integration/node-multiple-sources.sh | 7 +- tests/integration/node-multiplexing.sh | 7 +- tests/integration/node-rate.sh | 7 +- tests/integration/node-stats.sh | 7 +- tests/integration/node-test_rtt.sh | 7 +- tests/integration/pipe-loopback-amqp.sh | 7 +- tests/integration/pipe-loopback-exec.sh | 7 +- tests/integration/pipe-loopback-file.sh | 7 +- .../integration/pipe-loopback-iec61850-9-2.sh | 7 +- tests/integration/pipe-loopback-loopback.sh | 7 +- tests/integration/pipe-loopback-mqtt.sh | 7 +- tests/integration/pipe-loopback-nanomsg.sh | 7 +- tests/integration/pipe-loopback-redis.sh | 7 +- tests/integration/pipe-loopback-rtp-dual.sh | 9 +- tests/integration/pipe-loopback-rtp-remote.sh | 9 +- tests/integration/pipe-loopback-rtp-tbf.sh | 9 +- tests/integration/pipe-loopback-rtp.sh | 7 +- tests/integration/pipe-loopback-shmem.sh | 7 +- .../pipe-loopback-socket-multicast.sh | 7 +- .../integration/pipe-loopback-socket-netem.sh | 7 +- tests/integration/pipe-loopback-socket.sh | 7 +- tests/integration/pipe-loopback-websocket.sh | 7 +- tests/integration/pipe-loopback-zeromq.sh | 7 +- tests/integration/pipe-python-protobuf.sh | 7 +- tests/integration/relay.sh | 7 +- tests/integration/signal.sh | 7 +- tests/integration/test-config.sh | 7 +- tests/unit/CMakeLists.txt | 7 +- tests/unit/config.cpp | 10 +- tests/unit/config_json.cpp | 14 +- tests/unit/format.cpp | 25 +- tests/unit/helpers.cpp | 7 + tests/unit/helpers.hpp | 7 + tests/unit/json.cpp | 14 +- tests/unit/main.cpp | 10 +- tests/unit/mapping.cpp | 10 +- tests/unit/memory.cpp | 13 +- tests/unit/pool.cpp | 18 +- tests/unit/queue.cpp | 73 +++--- tests/unit/queue_signalled.cpp | 35 +-- tests/unit/signal.cpp | 13 +- tools/CMakeLists.txt | 7 +- tools/docker-dev.sh | 7 +- tools/integration-tests.sh | 7 +- tools/start-fpga.sh | 2 + tools/tc-dump.sh | 7 +- tools/tc-netem.sh | 7 +- tools/tc-netem2.sh | 9 +- tools/tune-realtime.sh | 2 + tools/villas | 7 +- tools/villas-api.sh | 2 + tools/villas-helper.sh | 7 +- web/webrtc.html | 6 +- webrtc_a.conf | 35 +++ webrtc_b.conf | 35 +++ 826 files changed, 6102 insertions(+), 4984 deletions(-) create mode 100644 .reuse/dep5 delete mode 100644 COPYING.md create mode 100644 LICENSE create mode 100644 LICENSES/Apache-2.0.txt create mode 100644 LICENSES/BSD-1-Clause.txt create mode 100644 LICENSES/BSD-2-Clause.txt create mode 100644 LICENSES/LGPL-2.1-only.txt delete mode 100644 doc/openapi/README.md delete mode 100644 doc/openapi/components/README.md delete mode 100644 doc/openapi/paths/README.md create mode 100644 etc/labs/lab18.conf create mode 100644 webrtc_a.conf create mode 100644 webrtc_b.conf diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0cc585584..d7d74e749 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,8 @@ // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp +// +// SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +// SPDX-License-Identifier: Apache-2.0 { "name": "VILLASnode", "image": "registry.git.rwth-aachen.de/acs/public/villas/node/dev-vscode", diff --git a/.dockerignore b/.dockerignore index c8faab8d7..d1f1a4930 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + build/ build_*/ packaging/docker/Dockerfile.* diff --git a/.editorconfig b/.editorconfig index a75847bc8..35447f7c9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,6 @@ # EditorConfig is awesome: http://EditorConfig.org +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # top-most EditorConfig file root = true diff --git a/.envrc b/.envrc index 7239e2fce..604dd135d 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 export_or_unset() { diff --git a/.gitignore b/.gitignore index 38f0645ae..6d33a0f0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + /build*/ *~ *.swp diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index df48decba..7bdfc7bbc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + variables: GIT_SUBMODULE_STRATEGY: recursive GIT_DEPTH: 0 @@ -19,7 +22,6 @@ stages: - latest # Stage: prepare -############################################################################## # Build docker image which is used to build & test VILLASnode prepare:docker: @@ -47,7 +49,6 @@ prepare:docker: - docker # Stage: build -############################################################################## build:source: stage: build @@ -86,7 +87,6 @@ build:source: - docker # Stage: test -############################################################################## test:flake8: stage: test @@ -164,8 +164,15 @@ test:integration: - job: "build:source: [fedora]" artifacts: true +test:reuse: + stage: test + image: + name: fsfe/reuse:latest + entrypoint: [""] + script: + - reuse lint + # Stage: packaging -############################################################################## pkg:docker: stage: packaging @@ -214,7 +221,6 @@ pkg:docker: needs: [] # Stage: deploy -############################################################################## deploy:docker: stage: deploy @@ -265,7 +271,7 @@ deploy:docker-dev-vscode: - job: "prepare:docker: [fedora, dev-vscode, ${DOCKER_IMAGE}/dev-vscode]" # Stage: latest -############################################################################## + .latest:docker:latest: &deploy_latest_docker stage: latest diff --git a/.gitmodules b/.gitmodules index 0878dbb87..ffec47725 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + [submodule "common"] path = common url = https://github.com/VILLASframework/common.git diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 000000000..29a674205 --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,12 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: VILLASnode +Upstream-Contact: Steffen Vogel +Source: https://fein-aachen.org/en/projects/villas-node/ + +Files: *.vi *.opal *.dft *.sib *.json *.ipynb doc/pictures/* clients/opal/models/send_receive/eonerc_logo.png doc/favicon.png +Copyright: 2018-2023, Institute for Automation of Complex Power Systems, RWTH Aachen University +License: Apache-2.0 + +Files: clients/rtds/**/*.txt clients/hypersim/*.ecf etc/labs/lab3.pcap packaging/live-iso/files/etc/* packaging/nix/flake.lock tests/valgrind.supp packaging/archlinux/villas-node.install +Copyright: 2018-2023, Institute for Automation of Complex Power Systems, RWTH Aachen University +License: Apache-2.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d2b3ca1d..c2ea4135f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog + + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fffdec13..c4fae12ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,8 @@ # Main CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.14) diff --git a/CODEOWNERS b/CODEOWNERS index 0ea4b22e1..afeda374d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + # These owners will be the default owners for everything in # the repo. Unless a later match takes precedence, # @stv0g will be requested for diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77c712e58..e6b34b3c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -173,4 +173,9 @@ Please rebase your work against the `develop` before submitting a merge reqeuest ## Make the CI happy :-) -Only branches which pass the CI can be merged. \ No newline at end of file +Only branches which pass the CI can be merged. + +## License + +- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +- SPDX-License-Identifier: Apache-2.0 diff --git a/COPYING.md b/COPYING.md deleted file mode 100644 index d0af96c39..000000000 --- a/COPYING.md +++ /dev/null @@ -1,194 +0,0 @@ -Apache License -============== - -_Version 2.0, January 2004_ -_<>_ - -### Terms and Conditions for use, reproduction, and distribution - -#### 1. Definitions - -“License” shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -“Licensor” shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -“Legal Entity” shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, “control” means **(i)** the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the -outstanding shares, or **(iii)** beneficial ownership of such entity. - -“You” (or “Your”) shall mean an individual or Legal Entity exercising -permissions granted by this License. - -“Source” form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -“Object” form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -“Work” shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -“Derivative Works” shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -“Contribution” shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -“submitted” means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as “Not a Contribution.” - -“Contributor” shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -#### 2. Grant of Copyright License - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -#### 3. Grant of Patent License - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -#### 4. Redistribution - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -* **(a)** You must give any other recipients of the Work or Derivative Works a copy of -this License; and -* **(b)** You must cause any modified files to carry prominent notices stating that You -changed the files; and -* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. - -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -#### 5. Submission of Contributions - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -#### 6. Trademarks - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -#### 7. Disclaimer of Warranty - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -#### 8. Limitation of Liability - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -#### 9. Accepting Warranty or Additional Liability - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -_END OF TERMS AND CONDITIONS_ - -### APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets `[]` replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same “printed page” as the copyright notice for easier identification within -third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..38ab65d4f --- /dev/null +++ b/LICENSE @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 000000000..38ab65d4f --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/BSD-1-Clause.txt b/LICENSES/BSD-1-Clause.txt new file mode 100644 index 000000000..0d02ecb8b --- /dev/null +++ b/LICENSES/BSD-1-Clause.txt @@ -0,0 +1,7 @@ +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/BSD-2-Clause.txt b/LICENSES/BSD-2-Clause.txt new file mode 100644 index 000000000..f1c72cce8 --- /dev/null +++ b/LICENSES/BSD-2-Clause.txt @@ -0,0 +1,9 @@ +Copyright (c) + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/LGPL-2.1-only.txt b/LICENSES/LGPL-2.1-only.txt new file mode 100644 index 000000000..a7b06bf78 --- /dev/null +++ b/LICENSES/LGPL-2.1-only.txt @@ -0,0 +1,175 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. + +When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. + +To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. + +To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. + +Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. + +When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. + +We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. + +For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. + +In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. + +Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. + + This library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in +the library `Frob' (a library for tweaking knobs) written +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice +That's all there is to it! diff --git a/README.md b/README.md index 8db8c42cc..6f43f0275 100644 --- a/README.md +++ b/README.md @@ -31,13 +31,9 @@ VILLASnode is used in distributed- and co-simulation scenarios and developed for User documentation is available here: -## Copyright - -2014-2023, Institute for Automation of Complex Power Systems, EONERC - ## License -This project is released under the terms of the [Apache 2.0 license](COPYING.md). +This project is released under the terms of the [Apache 2.0 license](LICENSE). We kindly ask all academic publications employing components of VILLASframework to cite one of the following papers: @@ -46,6 +42,9 @@ We kindly ask all academic publications employing components of VILLASframework For other licensing options please consult [Prof. Antonello Monti](mailto:amonti@eonerc.rwth-aachen.de). +- SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +- SPDX-License-Identifier: Apache-2.0 + ## Contact [![EONERC ACS Logo](doc/pictures/eonerc_logo.png)](http://www.acs.eonerc.rwth-aachen.de) diff --git a/clients/CMakeLists.txt b/clients/CMakeLists.txt index 53b6c278e..18483662a 100644 --- a/clients/CMakeLists.txt +++ b/clients/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 add_subdirectory(opal) add_subdirectory(shmem) diff --git a/clients/hypersim/README.md b/clients/hypersim/README.md index 8ece256bd..858ce8283 100644 --- a/clients/hypersim/README.md +++ b/clients/hypersim/README.md @@ -9,3 +9,8 @@ Detailed information for installation and usage of the UCM is provided in the [u ## Author - Anju Meghwani + +## License + +- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +- SPDX-License-Identifier: Apache-2.0 diff --git a/clients/hypersim/model/ucm_node.def b/clients/hypersim/model/ucm_node.def index 1cab21fc1..fa959c3d7 100644 --- a/clients/hypersim/model/ucm_node.def +++ b/clients/hypersim/model/ucm_node.def @@ -2,6 +2,9 @@ %% Generated from : ucm_def_file_templ_en.sh Version 1.5 %% Hypersim (Ucm) : (c) Hydro-Quebec -- 2005 %% +%% SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +%% SPDX-License-Identifier: Apache-2.0 +%% %% ----------------------------------------------------------------------------- %% Model : villas -- Fri Jun 15 12:07:11 PDT 2018 %% ----------------------------------------------------------------------------- diff --git a/clients/matlab/README.md b/clients/matlab/README.md index ede5c361b..c6d42585f 100644 --- a/clients/matlab/README.md +++ b/clients/matlab/README.md @@ -2,3 +2,8 @@ Additional documentation about this example is available here: https://villas.fein-aachen.org/doc/node-client-matlab.html + +## License + +- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +- SPDX-License-Identifier: Apache-2.0 diff --git a/clients/matlab/receiver.m b/clients/matlab/receiver.m index 3cb234458..642a4cbb1 100644 --- a/clients/matlab/receiver.m +++ b/clients/matlab/receiver.m @@ -1,9 +1,9 @@ % Simple MATLAB code to receive VILLAS UDP samples % -% @author Megha Gupta -% @author Steffen Vogel -% @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -% @license Apache 2.0 +% Author: Megha Gupta +% Author: Steffen Vogel +% SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +% SPDX-License-Identifier: Apache-2.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% close all; diff --git a/clients/matlab/villas.conf b/clients/matlab/villas.conf index c785b46bf..1c18fe34f 100644 --- a/clients/matlab/villas.conf +++ b/clients/matlab/villas.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { signal = { type = "signal", diff --git a/clients/opal/.gitignore b/clients/opal/.gitignore index bf0824e59..5e2310b64 100644 --- a/clients/opal/.gitignore +++ b/clients/opal/.gitignore @@ -1 +1,4 @@ -*.log \ No newline at end of file +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +*.log diff --git a/clients/opal/.project b/clients/opal/.project index b6ea0fd2b..41a1564e5 100644 --- a/clients/opal/.project +++ b/clients/opal/.project @@ -10,3 +10,7 @@ com.opalrt.rtlab.ui.rtlabnature + diff --git a/clients/opal/CMakeLists.txt b/clients/opal/CMakeLists.txt index 774b83339..9496d9b54 100644 --- a/clients/opal/CMakeLists.txt +++ b/clients/opal/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 if(OPAL_FOUND) # Just call the original Makefile diff --git a/clients/opal/models/send_receive/.gitignore b/clients/opal/models/send_receive/.gitignore index f7b9f592e..291b31561 100644 --- a/clients/opal/models/send_receive/.gitignore +++ b/clients/opal/models/send_receive/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + *.o *.d AsyncIP diff --git a/clients/opal/models/send_receive/Makefile.mk b/clients/opal/models/send_receive/Makefile.mk index 8632312f8..56da211e9 100644 --- a/clients/opal/models/send_receive/Makefile.mk +++ b/clients/opal/models/send_receive/Makefile.mk @@ -1,9 +1,8 @@ # Makefile. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 TARGET = AsyncIP diff --git a/clients/opal/models/send_receive/include/config.h b/clients/opal/models/send_receive/include/config.h index bd2e88a24..1b28c4cfc 100644 --- a/clients/opal/models/send_receive/include/config.h +++ b/clients/opal/models/send_receive/include/config.h @@ -1,10 +1,9 @@ -/** Compile-time configuration. +/* Compile-time configuration. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _CONFIG_H_ #define _CONFIG_H_ @@ -14,13 +13,13 @@ #define MAX_VALUES 64 -/* List of protocols */ +// List of protocols #define VILLAS 1 #define GTNET_SKT 2 -/* Default protocol */ +// Default protocol #ifndef PROTOCOL #define PROTOCOL VILLAS -#endif /* PROTOCOL */ +#endif // PROTOCOL -#endif /* _CONFIG_H_ */ +#endif // _CONFIG_H_ diff --git a/clients/opal/models/send_receive/include/msg.h b/clients/opal/models/send_receive/include/msg.h index a2726756e..05d23e231 100644 --- a/clients/opal/models/send_receive/include/msg.h +++ b/clients/opal/models/send_receive/include/msg.h @@ -1,17 +1,16 @@ -/** Message related functions +/* Message related functions * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -/* Forward declarations. */ +// Forward declarations struct msg; -/** Swaps the byte-order of the message. +/* Swaps the byte-order of the message. * * Message are always transmitted in network (big endian) byte order. * @@ -25,7 +24,7 @@ void msg_ntoh(struct msg *m); void msg_hton(struct msg *m); -/** Check the consistency of a message. +/* Check the consistency of a message. * * The functions checks the header fields of a message. * diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index bcbb45824..e0263456a 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -1,33 +1,32 @@ -/** Message format +/* Message format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include -/** The current version number for the message format */ +// The current version number for the message format #define MSG_VERSION 2 -/** @todo Implement more message types */ -#define MSG_TYPE_DATA 0 /**< Message contains float values */ -#define MSG_TYPE_START 1 /**< Message marks the beginning of a new simulation case */ -#define MSG_TYPE_STOP 2 /**< Message marks the end of a simulation case */ +// @todo Implement more message types +#define MSG_TYPE_DATA 0 // Message contains float values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case -/** The total size in bytes of a message */ +// The total size in bytes of a message #define MSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) -/** The length of \p values values in bytes. */ +// The length of \p values values in bytes #define MSG_DATA_LEN(values) (sizeof(float) * (values)) -/** The offset to the first data value in a message. */ +// The offset to the first data value in a message #define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, data)) -/** Initialize a message with default values */ +// Initialize a message with default values #define MSG_INIT(len, seq) (struct msg) {\ .version = MSG_VERSION, \ .type = MSG_TYPE_DATA, \ @@ -36,43 +35,43 @@ .id = 0 \ } -/** The timestamp of a message in struct timespec format */ +// 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 \ } -/** This message format is used by all clients +/* This message format is used by all clients * * @diafile msg_format.dia - **/ + */ 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 reserved1 : 2; /**< Reserved bits */ + unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - 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) */ + 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 /* BYTEORDER */ +#endif // BYTEORDER - uint8_t id; /**< 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. */ + uint8_t id; // 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 - /** A timestamp per message. */ + // A timestamp per message struct { - uint32_t sec; /**< Seconds since 1970-01-01 00:00:00 */ - uint32_t nsec; /**< Nanoseconds of the current second. */ + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second } ts; - /** The message payload. */ + // The message payload union { - float f; /**< Floating point values. */ - uint32_t i; /**< Integer values. */ + float f; // Floating point values + uint32_t i; // Integer values } data[]; } __attribute__((packed)); diff --git a/clients/opal/models/send_receive/include/socket.h b/clients/opal/models/send_receive/include/socket.h index f8f6d41dc..372ad6ce2 100644 --- a/clients/opal/models/send_receive/include/socket.h +++ b/clients/opal/models/send_receive/include/socket.h @@ -1,10 +1,9 @@ -/** Helper functions for sockets. +/* Helper functions for sockets. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOCKET_H_ #define _SOCKET_H_ @@ -18,9 +17,9 @@ #define TCP_PROTOCOL 2 struct socket { - struct sockaddr_in send_ad; /* Send address */ - struct sockaddr_in recv_ad; /* Receive address */ - int sd; /* socket descriptor */ + struct sockaddr_in send_ad; // Send address + struct sockaddr_in recv_ad; // Receive address + int sd; // socket descriptor }; int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct); @@ -31,4 +30,4 @@ int socket_recv(struct socket *s, char *data, int len, double timeout); int socket_close(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct); -#endif /* _SOCKET_H_ */ +#endif // _SOCKET_H_ diff --git a/clients/opal/models/send_receive/include/utils.h b/clients/opal/models/send_receive/include/utils.h index 0ea275c5c..1d9f3b740 100644 --- a/clients/opal/models/send_receive/include/utils.h +++ b/clients/opal/models/send_receive/include/utils.h @@ -1,16 +1,15 @@ -/** Configure scheduler. +/* Configure scheduler. * - * @file - * @author Steffen Vogel - * @author Mathieu Dubé-Dallaire - * @copyright 2003, OPAL-RT Technologies inc - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Mathieu Dubé-Dallaire + * SPDX-FileCopyrightText: 2003 OPAL-RT Technologies inc + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _UTILS_H_ #define _UTILS_H_ int AssignProcToCpu0(void); -#endif /* _UTILS_H_ */ +#endif // _UTILS_H_ diff --git a/clients/opal/models/send_receive/send_receive.llm b/clients/opal/models/send_receive/send_receive.llm index 8e9920b5b..51ab8a042 100644 --- a/clients/opal/models/send_receive/send_receive.llm +++ b/clients/opal/models/send_receive/send_receive.llm @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 [EnvVars] ABORT_COMPILE_WHEN_NO_BITSTREAM=0 ACTION_AFTER_N_OVERRUNS=10 diff --git a/clients/opal/models/send_receive/send_receive.mdl b/clients/opal/models/send_receive/send_receive.mdl index e2db790ec..8e2786703 100644 --- a/clients/opal/models/send_receive/send_receive.mdl +++ b/clients/opal/models/send_receive/send_receive.mdl @@ -1,4 +1,6 @@ # $Revision: 1.1 $ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 Model { Name "send_receive" Version 8.4 diff --git a/clients/opal/models/send_receive/send_receive.probe b/clients/opal/models/send_receive/send_receive.probe index 543ee070d..7f8547967 100644 --- a/clients/opal/models/send_receive/send_receive.probe +++ b/clients/opal/models/send_receive/send_receive.probe @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 [General] ATT_VERSION=6 FileVersion=6 diff --git a/clients/opal/models/send_receive/src/compat.c b/clients/opal/models/send_receive/src/compat.c index f5958b3ba..d0d8f5132 100644 --- a/clients/opal/models/send_receive/src/compat.c +++ b/clients/opal/models/send_receive/src/compat.c @@ -1,12 +1,11 @@ -/** Compatibility code for GCC +/* Compatibility code for GCC * * OPAL-RT's libSystem.a links against some Intel * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/clients/opal/models/send_receive/src/main.asv b/clients/opal/models/send_receive/src/main.asv index 0046dc9f1..bdc8c1ad4 100644 --- a/clients/opal/models/send_receive/src/main.asv +++ b/clients/opal/models/send_receive/src/main.asv @@ -1,9 +1,8 @@ /** Main routine of AsyncIP. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ /* Standard ANSI C headers needed for this program */ diff --git a/clients/opal/models/send_receive/src/main.c b/clients/opal/models/send_receive/src/main.c index 12975126d..5714a4f86 100644 --- a/clients/opal/models/send_receive/src/main.c +++ b/clients/opal/models/send_receive/src/main.c @@ -1,12 +1,11 @@ -/** Main routine of AsyncIP. +/* Main routine of AsyncIP. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ -/* Standard ANSI C headers needed for this program */ +// Standard ANSI C headers needed for this program #include #include #include @@ -24,7 +23,7 @@ #include "OpalPrint.h" #include "AsyncApi.h" -/* This is the message format */ +// This is the message format #include "config.h" #include "socket.h" #include "utils.h" @@ -40,15 +39,16 @@ #define ASYNC_SHMEM_SIZE atoi(argv[2]) #define PRINT_SHMEM_NAME argv[3] -/* Global Variables */ +// Global Variables struct socket skt; -static void * SendToIPPort(void *arg) +static +void * SendToIPPort(void *arg) { unsigned int ModelState, SendID, Sequence = 0; int nbSend = 0, ret, cnt, len; - /* Data from OPAL-RT model */ + // Data from OPAL-RT model double mdldata[MAX_VALUES]; int mdldata_size; @@ -69,7 +69,7 @@ static void * SendToIPPort(void *arg) } do { - /* This call unblocks when the 'Data Ready' line of a send icon is asserted. */ + // This call unblocks when the 'Data Ready' line of a send icon is asserted. ret = OpalWaitForAsyncSendRequest(&SendID); if (ret != EOK) { ModelState = OpalGetAsyncModelState(); @@ -81,10 +81,10 @@ static void * SendToIPPort(void *arg) continue; } - /* No errors encountered yet */ + // No errors encountered yet OpalSetAsyncSendIconError(0, SendID); - /* Get the size of the data being sent by the unblocking SendID */ + // Get the size of the data being sent by the unblocking SendID OpalGetAsyncSendIconDataLength(&mdldata_size, SendID); cnt = mdldata_size / sizeof(double); if (cnt > MAX_VALUES) { @@ -93,11 +93,11 @@ static void * SendToIPPort(void *arg) cnt = MAX_VALUES; } - /* Read data from the model */ + // Read data from the model OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID); #if PROTOCOL == VILLAS - /* Get current time */ + // Get current time struct timespec now; clock_gettime(CLOCK_REALTIME, &now); @@ -128,7 +128,7 @@ static void * SendToIPPort(void *arg) #error Unknown protocol #endif - /* Perform the actual write to the ip port */ + // Perform the actual write to the ip port ret = socket_send(&skt, (char *) msg, len); if (ret < 0) OpalSetAsyncSendIconError(errno, SendID); @@ -153,12 +153,13 @@ static void * SendToIPPort(void *arg) return NULL; } -static void * RecvFromIPPort(void *arg) +static +void * RecvFromIPPort(void *arg) { unsigned int ModelState, RecvID; int nbRecv = 0, ret, cnt; - /* Data from OPAL-RT model */ + // Data from OPAL-RT model double mdldata[MAX_VALUES]; int mdldata_size; @@ -180,7 +181,7 @@ static void * RecvFromIPPort(void *arg) return NULL; } - /* Get list of RecvIds */ + // Get list of RecvIds unsigned int RecvIDs[nbRecv]; ret = OpalGetAsyncRecvIDList(RecvIDs, sizeof(RecvIDs)); if (ret != EOK) { @@ -189,14 +190,14 @@ static void * RecvFromIPPort(void *arg) } do { - /* Receive message */ + // Receive message ret = socket_recv(&skt, (char *) msg, sizeof(buf), 1.0); if (ret < 1) { ModelState = OpalGetAsyncModelState(); if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { - if (ret == 0) /* timeout, so we continue silently */ + if (ret == 0) // timeout, so we continue silently OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno); - if (ret == -1) /* a more serious error, so we print it */ + if (ret == -1) // a more serious error, so we print it OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno); continue; @@ -211,7 +212,7 @@ static void * RecvFromIPPort(void *arg) #else #error Unknown protocol #endif - /* Check if this RecvID exists */ + // Check if this RecvID exists for (int i = 0; i < nbRecv; i++) { if (RecvIDs[i] == RecvID) goto found; @@ -220,7 +221,7 @@ static void * RecvFromIPPort(void *arg) OpalPrint("%s: Received message with non-existent RecvID=%d. Changing to RecvID=%d...\n", PROGNAME, RecvID, RecvIDs[0]); RecvID = RecvIDs[0]; -found: /* Get the number of signals to send back to the model */ +found: // Get the number of signals to send back to the model OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID); cnt = mdldata_size / sizeof(double); if (cnt > MAX_VALUES) { @@ -246,8 +247,8 @@ found: /* Get the number of signals to send back to the model */ for (int i = 0; i < msg->length; i++) mdldata[i] = (double) msg->data[i].f; - /* Update OPAL model */ - OpalSetAsyncRecvIconStatus(msg->sequence, RecvID); /* Set the Status to the message ID */ + // Update OPAL model + OpalSetAsyncRecvIconStatus(msg->sequence, RecvID); // Set the Status to the message ID #elif PROTOCOL == GTNET_SKT uint32_t *imsg = (uint32_t *) msg; for (int i = 0; i < cnt; i++) { @@ -258,7 +259,7 @@ found: /* Get the number of signals to send back to the model */ #error Unknown protocol #endif - OpalSetAsyncRecvIconError(0, RecvID); /* Set the Error to 0 */ + OpalSetAsyncRecvIconError(0, RecvID); // Set the Error to 0 OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); @@ -282,20 +283,20 @@ int main(int argc, char *argv[]) OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION); - /* Check for the proper arguments to the program */ + // Check for the proper arguments to the program if (argc < 4) { printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize 3-PrintShmemName\n"); exit(0); } - /* Enable the OpalPrint function. This prints to the OpalDisplay. */ + // Enable the OpalPrint function. This prints to the OpalDisplay. ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME); if (ret != EOK) { printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME); exit(EXIT_FAILURE); } - /* Open Share Memory created by the model. */ + // Open Share Memory created by the model. ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); if (ret != EOK) { OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME); @@ -314,14 +315,14 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - /* Initialize socket */ + // Initialize socket ret = socket_init(&skt, IconCtrlStruct); if (ret != EOK) { OpalPrint("%s: ERROR: Failed to create socket.\n", PROGNAME); exit(EXIT_FAILURE); } - /* Start send/receive threads */ + // Start send/receive threads ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL); if (ret < 0) OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", PROGNAME, errno); @@ -330,7 +331,7 @@ int main(int argc, char *argv[]) if (ret < 0) OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", PROGNAME, errno); - /* Wait for both threads to finish */ + // Wait for both threads to finish ret = pthread_join(tid_send, NULL); if (ret) OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, ret); @@ -339,7 +340,7 @@ int main(int argc, char *argv[]) if (ret) OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, ret); - /* Close the ip port and shared memories */ + // Close the ip port and shared memories socket_close(&skt, IconCtrlStruct); OpalCloseAsyncMem (ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); diff --git a/clients/opal/models/send_receive/src/msg.c b/clients/opal/models/send_receive/src/msg.c index 5cc9c7fd9..d07252191 100644 --- a/clients/opal/models/send_receive/src/msg.c +++ b/clients/opal/models/send_receive/src/msg.c @@ -1,9 +1,9 @@ -/** Message related functions. +/* Message related functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/clients/opal/models/send_receive/src/socket.c b/clients/opal/models/send_receive/src/socket.c index c6cbd94fd..a4d314b3e 100644 --- a/clients/opal/models/send_receive/src/socket.c +++ b/clients/opal/models/send_receive/src/socket.c @@ -1,9 +1,9 @@ -/** Helper functions for sockets. +/* Helper functions for sockets. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -25,7 +25,7 @@ int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) { - struct ip_mreq mreq; /* Multicast group structure */ + struct ip_mreq mreq; // Multicast group structure unsigned char TTL = 1, LOOP = 0; int rc, proto, ret; @@ -39,26 +39,26 @@ int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) OpalPrint("%s: Remote Address : %s\n", PROGNAME, IconCtrlStruct.StringParam[0]); OpalPrint("%s: Remote Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[1]); - /* Initialize the socket */ + // Initialize the socket s->sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s->sd < 0) { OpalPrint("%s: ERROR: Could not open socket\n", PROGNAME); return EIO; } - /* Set the structure for the remote port and address */ + // Set the structure for the remote port and address memset(&s->send_ad, 0, sizeof(s->send_ad)); s->send_ad.sin_family = AF_INET; s->send_ad.sin_addr.s_addr = inet_addr(IconCtrlStruct.StringParam[0]); s->send_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[1]); - /* Set the structure for the local port and address */ + // Set the structure for the local port and address memset(&s->recv_ad, 0, sizeof(s->recv_ad)); s->recv_ad.sin_family = AF_INET; s->recv_ad.sin_addr.s_addr = INADDR_ANY; s->recv_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[2]); - /* Bind local port and address to socket. */ + // Bind local port and address to socket. ret = bind(s->sd, (struct sockaddr *) &s->recv_ad, sizeof(struct sockaddr_in)); if (ret < 0) { OpalPrint("%s: ERROR: Could not bind local port to socket\n", PROGNAME); @@ -67,7 +67,7 @@ int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) else OpalPrint("%s: Local Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[2]); - /* If sending to a multicast address */ + // If sending to a multicast address if ((inet_addr(IconCtrlStruct.StringParam[0]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL)); if (ret == -1) { @@ -84,13 +84,13 @@ int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) OpalPrint("%s: Configured socket for sending to multicast address\n", PROGNAME); } - /* If receiving from a multicast group, register for it. */ + // If receiving from a multicast group, register for it. if (inet_addr(IconCtrlStruct.StringParam[1]) > 0) { if ((inet_addr(IconCtrlStruct.StringParam[1]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { mreq.imr_multiaddr.s_addr = inet_addr(IconCtrlStruct.StringParam[1]); mreq.imr_interface.s_addr = INADDR_ANY; - /* Have the multicast socket join the multicast group */ + // Have the multicast socket join the multicast group ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)); if (ret == -1) { OpalPrint("%s: ERROR: Could not join multicast group (%d)\n", PROGNAME, errno); @@ -134,11 +134,11 @@ int socket_recv(struct socket *s, char *data, int len, double timeout) socklen_t client_ad_size = sizeof(client_ad); fd_set sd_set; - /* Set the descriptor set for the select() call */ + // Set the descriptor set for the select() call FD_ZERO(&sd_set); FD_SET(s->sd, &sd_set); - /* Set the tv structure to the correct timeout value */ + // Set the tv structure to the correct timeout value tv.tv_sec = (int) timeout; tv.tv_usec = (int) ((timeout - tv.tv_sec) * 1000000); @@ -148,9 +148,9 @@ int socket_recv(struct socket *s, char *data, int len, double timeout) * a future instance (model load). */ ret = select(s->sd + 1, &sd_set, (fd_set *) 0, (fd_set *) 0, &tv); switch (ret) { - case -1: /* Error */ + case -1: // Error return -1; - case 0: /* We hit the timeout */ + case 0: // We hit the timeout return 0; default: if (!(FD_ISSET(s->sd, &sd_set))) { @@ -161,9 +161,9 @@ int socket_recv(struct socket *s, char *data, int len, double timeout) } } - /* Clear the data array (in case we receive an incomplete packet) */ + // Clear the data array (in case we receive an incomplete packet) memset(data, 0, len); - /* Perform the reception */ + // Perform the reception return recvfrom(s->sd, data, len, 0, (struct sockaddr *) &client_ad, &client_ad_size); } diff --git a/clients/opal/models/send_receive/src/utils.c b/clients/opal/models/send_receive/src/utils.c index 3a8118ed2..3015fc344 100644 --- a/clients/opal/models/send_receive/src/utils.c +++ b/clients/opal/models/send_receive/src/utils.c @@ -1,11 +1,11 @@ -/** Configure scheduler. +/* Configure scheduler. * - * @author Steffen Vogel - * @author Mathieu Dubé-Dallaire - * @copyright 2003, OPAL-RT Technologies inc - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Mathieu Dubé-Dallaire + * SPDX-FileCopyrightText: 2003 OPAL-RT Technologies inc + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,7 +26,7 @@ int AssignProcToCpu0(void) CPU_ZERO(&bindSet); CPU_SET(0, &bindSet); - /* Changing process cpu affinity */ + // Changing process cpu affinity ret = sched_setaffinity(0, sizeof(cpu_set_t), &bindSet); if (ret) { OpalPrint("Unable to bind the process to CPU 0: %d\n", errno); diff --git a/clients/opal/villas_udp.llp b/clients/opal/villas_udp.llp index 472a97c08..230f74e7b 100644 --- a/clients/opal/villas_udp.llp +++ b/clients/opal/villas_udp.llp @@ -1,4 +1,8 @@ + villas_udp diff --git a/clients/python/client.py b/clients/python/client.py index d70b4e0fb..daff5bb0d 100644 --- a/clients/python/client.py +++ b/clients/python/client.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + import villas_pb2 import time, socket, errno, sys, os, signal diff --git a/clients/shmem/CMakeLists.txt b/clients/shmem/CMakeLists.txt index 0cffc905f..a2f5a2bb8 100644 --- a/clients/shmem/CMakeLists.txt +++ b/clients/shmem/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 add_executable(villas-shmem villas-shmem.cpp) diff --git a/clients/shmem/villas-shmem.cpp b/clients/shmem/villas-shmem.cpp index 345b5ca4f..289970905 100644 --- a/clients/shmem/villas-shmem.cpp +++ b/clients/shmem/villas-shmem.cpp @@ -1,12 +1,12 @@ -/** Test "client" for the shared memory interface. +/* Test "client" for the shared memory interface. * * Waits on the incoming queue, prints received samples and writes them * back to the other queue. * - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/clients/typhoon/villas_typhoon_ethernet_variable_exchange.tse b/clients/typhoon/villas_typhoon_ethernet_variable_exchange.tse index d9773ab1d..93be472e2 100644 --- a/clients/typhoon/villas_typhoon_ethernet_variable_exchange.tse +++ b/clients/typhoon/villas_typhoon_ethernet_variable_exchange.tse @@ -1,5 +1,8 @@ version = 4.2 +// SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +// SPDX-License-Identifier: Apache-2.0 + // // Saved by sw version: 2022.1 SP1 // Save timestamp: 24-Mar-2022 @ 04:26:31 PM diff --git a/cmake/FindEtherlab.cmake b/cmake/FindEtherlab.cmake index bd343ac5e..95a22afab 100644 --- a/cmake/FindEtherlab.cmake +++ b/cmake/FindEtherlab.cmake @@ -1,10 +1,9 @@ # CMakeLists.txt. # -# @author Niklas Eiling -# @author Steffen Vogel -# @copyright 2018, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Niklas Eiling +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2018 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 find_path(ETHERLAB_INCLUDE_DIR NAMES ecrt.h diff --git a/cmake/FindIBVerbs.cmake b/cmake/FindIBVerbs.cmake index 57315d6c8..38806105f 100644 --- a/cmake/FindIBVerbs.cmake +++ b/cmake/FindIBVerbs.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 find_path(IBVERBS_INCLUDE_DIR NAMES infiniband/verbs.h diff --git a/cmake/FindOpal.cmake b/cmake/FindOpal.cmake index 1d659e883..4cfb5656d 100644 --- a/cmake/FindOpal.cmake +++ b/cmake/FindOpal.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(OPAL_PREFIX /usr/opalrt/common) diff --git a/cmake/FindRDMACM.cmake b/cmake/FindRDMACM.cmake index b5cbd466d..6e6f92ef7 100644 --- a/cmake/FindRDMACM.cmake +++ b/cmake/FindRDMACM.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 find_path(RDMACM_INCLUDE_DIR NAMES rdma/rdma_cma.h diff --git a/cmake/FindSymbol.cmake b/cmake/FindSymbol.cmake index c6654ede8..0b566ef95 100644 --- a/cmake/FindSymbol.cmake +++ b/cmake/FindSymbol.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 function(FindSymbol LIBRARY SYMBOL FOUND) find_program(OBJDUMP_EXECUTABLE NAMES objdump) diff --git a/cmake/VILLASnodePackaging.cmake b/cmake/VILLASnodePackaging.cmake index 2fcf94ade..57fbe67e8 100644 --- a/cmake/VILLASnodePackaging.cmake +++ b/cmake/VILLASnodePackaging.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 include(CPackComponent) get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS) @@ -61,7 +60,7 @@ set(CPACK_RPM_PACKAGE_LICENSE "Apache-2.0") set(CPACK_RPM_PACKAGE_URL ${PROJECT_HOMEPAGE_URL}) set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") -set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING.md") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.md") set(CPACK_SOURCE_IGNORE_FILES "build/;\\\\.gitmodules;\\\\.git/;\\\\.vscode;\\\\.editorconfig;\\\\.gitlab-ci.yml;\\\\.(docker|git)ignore;\\\\.DS_Store") diff --git a/cmake/config/Coverage.cmake b/cmake/config/Coverage.cmake index ec4852bdf..84868c279 100644 --- a/cmake/config/Coverage.cmake +++ b/cmake/config/Coverage.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage" diff --git a/cmake/config/Debug.cmake b/cmake/config/Debug.cmake index 37961761c..4188605c0 100644 --- a/cmake/config/Debug.cmake +++ b/cmake/config/Debug.cmake @@ -1,6 +1,5 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 diff --git a/cmake/config/Profiling.cmake b/cmake/config/Profiling.cmake index 7296d4fdf..d9c2aa422 100644 --- a/cmake/config/Profiling.cmake +++ b/cmake/config/Profiling.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS} -pg" diff --git a/cmake/config/Release.cmake b/cmake/config/Release.cmake index 1cc8307c5..7c02eae4c 100644 --- a/cmake/config/Release.cmake +++ b/cmake/config/Release.cmake @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # don't treat warnings as errors on normal release builds if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT DEFINED VILLAS_COMPILE_WARNING_AS_ERROR) diff --git a/cmake/toolchains/debian-arm64.cmake b/cmake/toolchains/debian-arm64.cmake index a55b0829a..7cfc37f3b 100644 --- a/cmake/toolchains/debian-arm64.cmake +++ b/cmake/toolchains/debian-arm64.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) diff --git a/cmake/toolchains/debian-armhf.cmake b/cmake/toolchains/debian-armhf.cmake index e153e8216..65b57b262 100644 --- a/cmake/toolchains/debian-armhf.cmake +++ b/cmake/toolchains/debian-armhf.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR armv7l) diff --git a/common b/common index 120312e93..413a0ba31 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 120312e938dc298b4dc13792e1acf7510190bbf4 +Subproject commit 413a0ba31971730f60664ef69709b70d64c9de80 diff --git a/doc/.gitignore b/doc/.gitignore index b3fbf1bb9..6109c45b3 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + html/ doxygen_sqlite3.db warnings.log diff --git a/doc/.redocly.yaml b/doc/.redocly.yaml index 47dc94ec0..acbf12858 100644 --- a/doc/.redocly.yaml +++ b/doc/.redocly.yaml @@ -1,4 +1,8 @@ # See https://redoc.ly/docs/cli/configuration/ for more information. +# +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- apiDefinitions: main: openapi/openapi.yaml lint: diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 4cf0e4023..ec7d18766 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 find_package(Doxygen) @@ -37,7 +36,7 @@ if(DOXYGEN_FOUND) set(DOXYGEN_DIAFILE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/figures/) doxygen_add_docs(doc - README.md CONTRIBUTING.md COPYING.md src/ lib/ tests/ include/ doc/ + README.md CONTRIBUTING.md LICENSE src/ lib/ tests/ include/ doc/ WORKING_DIRECTORY ${PROJECT_DIR} ) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 4db7e3af4..a4fcdfe26 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1,4 +1,6 @@ # Doxyfile 1.8.10 +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -765,7 +767,7 @@ WARN_LOGFILE = doc/warnings.log # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = README.md CONTRIBUTING.md COPYING.md src/ lib/ tests/ include/ doc/ +INPUT = README.md CONTRIBUTING.md LICENSE src/ lib/ tests/ include/ doc/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/index.html b/doc/index.html index e4b850287..abf11b59a 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,3 +1,7 @@ + diff --git a/doc/openapi-relay.yaml b/doc/openapi-relay.yaml index 9fd870414..4f2ca883f 100644 --- a/doc/openapi-relay.yaml +++ b/doc/openapi-relay.yaml @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- openapi: '3.0.0' info: diff --git a/doc/openapi/README.md b/doc/openapi/README.md deleted file mode 100644 index ae48cf097..000000000 --- a/doc/openapi/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## The `openapi` folder - -This folder contains your entrypoint `openapi.yaml`. - -That file contains references to the entire API definition. - -Here are some sections to pay attention to: - -* Top-level **description**: this accepts markdown, and Redoc and Redocly API Reference will render it at the top of the docs. Consider maintaining your markdown in a separate file and [embedding it](https://redoc.ly/docs/api-reference-docs/embedded-markdown/). Note to Redoc community edition users, the special tags are only available to the Redocly API Reference users, but you can still embed markdown. -* Security schemes: you will define the scheme(s) your API uses for security (eg OAuth2, API Key, etc...). The security schemes are used by the Redocly API Reference "Try It" API console feature. -* [Paths](paths/README.md): this defines each endpoint. A path can have one operation per http method. -* Tags: it's a good idea to organize each operation. Each tag can have a description. The description is used as a section description within the reference docs. -* Servers: a list of your servers, each with a URL. diff --git a/doc/openapi/components/README.md b/doc/openapi/components/README.md deleted file mode 100644 index 26eaeb5d5..000000000 --- a/doc/openapi/components/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Reusable components -=========== - -* You can create the following folders here: - - `schemas` - reusable [Schema Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schemaObject) - - `responses` - reusable [Response Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responseObject) - - `parameters` - reusable [Parameter Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject) - - `examples` - reusable [Example Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#exampleObject) - - `headers` - reusable [Header Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#headerObject) - - `requestBodies` - reusable [Request Body Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#requestBodyObject) - - `links` - reusable [Link Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#linkObject) - - `callbacks` - reusable [Callback Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#callbackObject) - - `securitySchemes` - reusable [Security Scheme Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#securitySchemeObject) -* Filename of files inside the folders represent component name, e.g. `Customer.yaml` diff --git a/doc/openapi/components/parameters/node-uuid-name.yaml b/doc/openapi/components/parameters/node-uuid-name.yaml index 5494e3152..dba4ec868 100644 --- a/doc/openapi/components/parameters/node-uuid-name.yaml +++ b/doc/openapi/components/parameters/node-uuid-name.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- name: uuid-or-name description: Either a UUID or node-name in: path diff --git a/doc/openapi/components/parameters/node-uuid.yaml b/doc/openapi/components/parameters/node-uuid.yaml index e0499f60c..63b4a75a8 100644 --- a/doc/openapi/components/parameters/node-uuid.yaml +++ b/doc/openapi/components/parameters/node-uuid.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- name: uuid description: A globally unique identifier for each node. in: path diff --git a/doc/openapi/components/parameters/path-uuid.yaml b/doc/openapi/components/parameters/path-uuid.yaml index 3423a9eb4..5d7bd9a31 100644 --- a/doc/openapi/components/parameters/path-uuid.yaml +++ b/doc/openapi/components/parameters/path-uuid.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- name: uuid description: A globally unique identifier for each path. in: path diff --git a/doc/openapi/components/schemas/config.yaml b/doc/openapi/components/schemas/config.yaml index 830d6930b..f79ccb389 100644 --- a/doc/openapi/components/schemas/config.yaml +++ b/doc/openapi/components/schemas/config.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: VILLASnode configuration file description: Schema of the VILLASnode configuration file. diff --git a/doc/openapi/components/schemas/config/format.yaml b/doc/openapi/components/schemas/config/format.yaml index d8b2948f6..85ba3fc4c 100644 --- a/doc/openapi/components/schemas/config/format.yaml +++ b/doc/openapi/components/schemas/config/format.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: diff --git a/doc/openapi/components/schemas/config/format_obj.yaml b/doc/openapi/components/schemas/config/format_obj.yaml index 4d30832f2..29a847af6 100644 --- a/doc/openapi/components/schemas/config/format_obj.yaml +++ b/doc/openapi/components/schemas/config/format_obj.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: Format Object required: diff --git a/doc/openapi/components/schemas/config/format_spec.yaml b/doc/openapi/components/schemas/config/format_spec.yaml index e51bac1c6..981161fef 100644 --- a/doc/openapi/components/schemas/config/format_spec.yaml +++ b/doc/openapi/components/schemas/config/format_spec.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - description: | The payload format which is used to encode and decode exchanged messages. example: villas.human diff --git a/doc/openapi/components/schemas/config/formats/_csv.yaml b/doc/openapi/components/schemas/config/formats/_csv.yaml index f44b43a42..217dbe72e 100644 --- a/doc/openapi/components/schemas/config/formats/_csv.yaml +++ b/doc/openapi/components/schemas/config/formats/_csv.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: csv.yaml diff --git a/doc/openapi/components/schemas/config/formats/_gtnet.yaml b/doc/openapi/components/schemas/config/formats/_gtnet.yaml index 0b90d185e..cadb2e015 100644 --- a/doc/openapi/components/schemas/config/formats/_gtnet.yaml +++ b/doc/openapi/components/schemas/config/formats/_gtnet.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: gtnet.yaml diff --git a/doc/openapi/components/schemas/config/formats/_iotagent_ul.yaml b/doc/openapi/components/schemas/config/formats/_iotagent_ul.yaml index 9ec5939bf..ee1c4e1fb 100644 --- a/doc/openapi/components/schemas/config/formats/_iotagent_ul.yaml +++ b/doc/openapi/components/schemas/config/formats/_iotagent_ul.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: iotagent_ul.yaml diff --git a/doc/openapi/components/schemas/config/formats/_json.yaml b/doc/openapi/components/schemas/config/formats/_json.yaml index 402bdbaa2..ded744931 100644 --- a/doc/openapi/components/schemas/config/formats/_json.yaml +++ b/doc/openapi/components/schemas/config/formats/_json.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: json.yaml diff --git a/doc/openapi/components/schemas/config/formats/_json_edgeflex.yaml b/doc/openapi/components/schemas/config/formats/_json_edgeflex.yaml index 5f0f4f2c0..f39b60ca6 100644 --- a/doc/openapi/components/schemas/config/formats/_json_edgeflex.yaml +++ b/doc/openapi/components/schemas/config/formats/_json_edgeflex.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: json_edgeflex.yaml diff --git a/doc/openapi/components/schemas/config/formats/_json_kafka.yaml b/doc/openapi/components/schemas/config/formats/_json_kafka.yaml index 538128471..0d7f2986c 100644 --- a/doc/openapi/components/schemas/config/formats/_json_kafka.yaml +++ b/doc/openapi/components/schemas/config/formats/_json_kafka.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: json_kafka.yaml diff --git a/doc/openapi/components/schemas/config/formats/_json_reserve.yaml b/doc/openapi/components/schemas/config/formats/_json_reserve.yaml index 82d883689..afcd37e24 100644 --- a/doc/openapi/components/schemas/config/formats/_json_reserve.yaml +++ b/doc/openapi/components/schemas/config/formats/_json_reserve.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: json_reserve.yaml diff --git a/doc/openapi/components/schemas/config/formats/_opal_asyncip.yaml b/doc/openapi/components/schemas/config/formats/_opal_asyncip.yaml index 988eb6c98..5c6402be4 100644 --- a/doc/openapi/components/schemas/config/formats/_opal_asyncip.yaml +++ b/doc/openapi/components/schemas/config/formats/_opal_asyncip.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: opal_asyncip.yaml diff --git a/doc/openapi/components/schemas/config/formats/_protobuf.yaml b/doc/openapi/components/schemas/config/formats/_protobuf.yaml index ac4852a41..b4d2f9f8a 100644 --- a/doc/openapi/components/schemas/config/formats/_protobuf.yaml +++ b/doc/openapi/components/schemas/config/formats/_protobuf.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: protobuf.yaml diff --git a/doc/openapi/components/schemas/config/formats/_raw.yaml b/doc/openapi/components/schemas/config/formats/_raw.yaml index 1f867b024..51b0fb3fa 100644 --- a/doc/openapi/components/schemas/config/formats/_raw.yaml +++ b/doc/openapi/components/schemas/config/formats/_raw.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: raw.yaml diff --git a/doc/openapi/components/schemas/config/formats/_tsv.yaml b/doc/openapi/components/schemas/config/formats/_tsv.yaml index 769ebeca4..a7c5c42b8 100644 --- a/doc/openapi/components/schemas/config/formats/_tsv.yaml +++ b/doc/openapi/components/schemas/config/formats/_tsv.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: tsv.yaml diff --git a/doc/openapi/components/schemas/config/formats/_value.yaml b/doc/openapi/components/schemas/config/formats/_value.yaml index e64e79d37..ffe058b93 100644 --- a/doc/openapi/components/schemas/config/formats/_value.yaml +++ b/doc/openapi/components/schemas/config/formats/_value.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: value.yaml diff --git a/doc/openapi/components/schemas/config/formats/_villas_binary.yaml b/doc/openapi/components/schemas/config/formats/_villas_binary.yaml index d08f0e3e1..688161550 100644 --- a/doc/openapi/components/schemas/config/formats/_villas_binary.yaml +++ b/doc/openapi/components/schemas/config/formats/_villas_binary.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: villas_binary.yaml diff --git a/doc/openapi/components/schemas/config/formats/_villas_human.yaml b/doc/openapi/components/schemas/config/formats/_villas_human.yaml index 5dcaabb08..36a060b5a 100644 --- a/doc/openapi/components/schemas/config/formats/_villas_human.yaml +++ b/doc/openapi/components/schemas/config/formats/_villas_human.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: villas_human.yaml diff --git a/doc/openapi/components/schemas/config/formats/_villas_web.yaml b/doc/openapi/components/schemas/config/formats/_villas_web.yaml index 9f9d4cb79..64eb89eb6 100644 --- a/doc/openapi/components/schemas/config/formats/_villas_web.yaml +++ b/doc/openapi/components/schemas/config/formats/_villas_web.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../format_obj.yaml - $ref: villas_web.yaml diff --git a/doc/openapi/components/schemas/config/formats/column.yaml b/doc/openapi/components/schemas/config/formats/column.yaml index 28a16b910..17e26dc14 100644 --- a/doc/openapi/components/schemas/config/formats/column.yaml +++ b/doc/openapi/components/schemas/config/formats/column.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/csv.yaml b/doc/openapi/components/schemas/config/formats/csv.yaml index 7ac680bf8..47ce32c21 100644 --- a/doc/openapi/components/schemas/config/formats/csv.yaml +++ b/doc/openapi/components/schemas/config/formats/csv.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/gtnet.yaml b/doc/openapi/components/schemas/config/formats/gtnet.yaml index 32369c22c..82a8940b7 100644 --- a/doc/openapi/components/schemas/config/formats/gtnet.yaml +++ b/doc/openapi/components/schemas/config/formats/gtnet.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: raw.yaml diff --git a/doc/openapi/components/schemas/config/formats/iotagent_ul.yaml b/doc/openapi/components/schemas/config/formats/iotagent_ul.yaml index 155db87eb..e884bc98e 100644 --- a/doc/openapi/components/schemas/config/formats/iotagent_ul.yaml +++ b/doc/openapi/components/schemas/config/formats/iotagent_ul.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/json.yaml b/doc/openapi/components/schemas/config/formats/json.yaml index cae3501bb..0603c0f03 100644 --- a/doc/openapi/components/schemas/config/formats/json.yaml +++ b/doc/openapi/components/schemas/config/formats/json.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/json_edgeflex.yaml b/doc/openapi/components/schemas/config/formats/json_edgeflex.yaml index 4d163d8e5..842c450fe 100644 --- a/doc/openapi/components/schemas/config/formats/json_edgeflex.yaml +++ b/doc/openapi/components/schemas/config/formats/json_edgeflex.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/json_kafka.yaml b/doc/openapi/components/schemas/config/formats/json_kafka.yaml index 4d163d8e5..842c450fe 100644 --- a/doc/openapi/components/schemas/config/formats/json_kafka.yaml +++ b/doc/openapi/components/schemas/config/formats/json_kafka.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/json_reserve.yaml b/doc/openapi/components/schemas/config/formats/json_reserve.yaml index 4d163d8e5..842c450fe 100644 --- a/doc/openapi/components/schemas/config/formats/json_reserve.yaml +++ b/doc/openapi/components/schemas/config/formats/json_reserve.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/line.yaml b/doc/openapi/components/schemas/config/formats/line.yaml index 479554427..427491f73 100644 --- a/doc/openapi/components/schemas/config/formats/line.yaml +++ b/doc/openapi/components/schemas/config/formats/line.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/opal_asyncip.yaml b/doc/openapi/components/schemas/config/formats/opal_asyncip.yaml index 5d7af8db9..7eb36fae2 100644 --- a/doc/openapi/components/schemas/config/formats/opal_asyncip.yaml +++ b/doc/openapi/components/schemas/config/formats/opal_asyncip.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/protobuf.yaml b/doc/openapi/components/schemas/config/formats/protobuf.yaml index 155db87eb..e884bc98e 100644 --- a/doc/openapi/components/schemas/config/formats/protobuf.yaml +++ b/doc/openapi/components/schemas/config/formats/protobuf.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/raw.yaml b/doc/openapi/components/schemas/config/formats/raw.yaml index f08acd0e3..28692de9e 100644 --- a/doc/openapi/components/schemas/config/formats/raw.yaml +++ b/doc/openapi/components/schemas/config/formats/raw.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/tsv.yaml b/doc/openapi/components/schemas/config/formats/tsv.yaml index 7ac680bf8..47ce32c21 100644 --- a/doc/openapi/components/schemas/config/formats/tsv.yaml +++ b/doc/openapi/components/schemas/config/formats/tsv.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/value.yaml b/doc/openapi/components/schemas/config/formats/value.yaml index 155db87eb..e884bc98e 100644 --- a/doc/openapi/components/schemas/config/formats/value.yaml +++ b/doc/openapi/components/schemas/config/formats/value.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/villas_binary.yaml b/doc/openapi/components/schemas/config/formats/villas_binary.yaml index 155db87eb..e884bc98e 100644 --- a/doc/openapi/components/schemas/config/formats/villas_binary.yaml +++ b/doc/openapi/components/schemas/config/formats/villas_binary.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/villas_human.yaml b/doc/openapi/components/schemas/config/formats/villas_human.yaml index 28a16b910..17e26dc14 100644 --- a/doc/openapi/components/schemas/config/formats/villas_human.yaml +++ b/doc/openapi/components/schemas/config/formats/villas_human.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/formats/villas_web.yaml b/doc/openapi/components/schemas/config/formats/villas_web.yaml index 49044ec21..69c91ead8 100644 --- a/doc/openapi/components/schemas/config/formats/villas_web.yaml +++ b/doc/openapi/components/schemas/config/formats/villas_web.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/global.yaml b/doc/openapi/components/schemas/config/global.yaml index ab9075cf8..efd7d0784 100644 --- a/doc/openapi/components/schemas/config/global.yaml +++ b/doc/openapi/components/schemas/config/global.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: diff --git a/doc/openapi/components/schemas/config/hook.yaml b/doc/openapi/components/schemas/config/hook.yaml index 8049ab7a9..f6014aefa 100644 --- a/doc/openapi/components/schemas/config/hook.yaml +++ b/doc/openapi/components/schemas/config/hook.yaml @@ -1,5 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: enabled: diff --git a/doc/openapi/components/schemas/config/hook_list.yaml b/doc/openapi/components/schemas/config/hook_list.yaml index 778aba80f..48fa6fe10 100644 --- a/doc/openapi/components/schemas/config/hook_list.yaml +++ b/doc/openapi/components/schemas/config/hook_list.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: array title: Hook List example: diff --git a/doc/openapi/components/schemas/config/hook_multi.yaml b/doc/openapi/components/schemas/config/hook_multi.yaml index b7b83cb64..983db59fe 100644 --- a/doc/openapi/components/schemas/config/hook_multi.yaml +++ b/doc/openapi/components/schemas/config/hook_multi.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hook_obj.yaml b/doc/openapi/components/schemas/config/hook_obj.yaml index 81d1cd117..37d4021b5 100644 --- a/doc/openapi/components/schemas/config/hook_obj.yaml +++ b/doc/openapi/components/schemas/config/hook_obj.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: Hook Object required: diff --git a/doc/openapi/components/schemas/config/hook_single.yaml b/doc/openapi/components/schemas/config/hook_single.yaml index 1090813ff..3e6b4cb67 100644 --- a/doc/openapi/components/schemas/config/hook_single.yaml +++ b/doc/openapi/components/schemas/config/hook_single.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hook_spec.yaml b/doc/openapi/components/schemas/config/hook_spec.yaml index fc566d688..f0776559c 100644 --- a/doc/openapi/components/schemas/config/hook_spec.yaml +++ b/doc/openapi/components/schemas/config/hook_spec.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - description: | Hooks form a pipeline of steps which process, filter or alter sample data. example: print diff --git a/doc/openapi/components/schemas/config/hooks/_average.yaml b/doc/openapi/components/schemas/config/hooks/_average.yaml index d0e2011a8..460c5864c 100644 --- a/doc/openapi/components/schemas/config/hooks/_average.yaml +++ b/doc/openapi/components/schemas/config/hooks/_average.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: average.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_cast.yaml b/doc/openapi/components/schemas/config/hooks/_cast.yaml index 25d4ff2ab..56c9cf67f 100644 --- a/doc/openapi/components/schemas/config/hooks/_cast.yaml +++ b/doc/openapi/components/schemas/config/hooks/_cast.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: cast.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_decimate.yaml b/doc/openapi/components/schemas/config/hooks/_decimate.yaml index a0919b2ee..12890d4a7 100644 --- a/doc/openapi/components/schemas/config/hooks/_decimate.yaml +++ b/doc/openapi/components/schemas/config/hooks/_decimate.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: decimate.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_dp.yaml b/doc/openapi/components/schemas/config/hooks/_dp.yaml index 573ad0d7b..db8baf17d 100644 --- a/doc/openapi/components/schemas/config/hooks/_dp.yaml +++ b/doc/openapi/components/schemas/config/hooks/_dp.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: dp.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_drop.yaml b/doc/openapi/components/schemas/config/hooks/_drop.yaml index d251e88e3..fb708c3e2 100644 --- a/doc/openapi/components/schemas/config/hooks/_drop.yaml +++ b/doc/openapi/components/schemas/config/hooks/_drop.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: drop.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_dump.yaml b/doc/openapi/components/schemas/config/hooks/_dump.yaml index f5fcdbc8d..1bd301bb7 100644 --- a/doc/openapi/components/schemas/config/hooks/_dump.yaml +++ b/doc/openapi/components/schemas/config/hooks/_dump.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: dump.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_ebm.yaml b/doc/openapi/components/schemas/config/hooks/_ebm.yaml index db125d977..8d7e9b0b5 100644 --- a/doc/openapi/components/schemas/config/hooks/_ebm.yaml +++ b/doc/openapi/components/schemas/config/hooks/_ebm.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: ebm.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_fix.yaml b/doc/openapi/components/schemas/config/hooks/_fix.yaml index 4ef520298..6221c3e7b 100644 --- a/doc/openapi/components/schemas/config/hooks/_fix.yaml +++ b/doc/openapi/components/schemas/config/hooks/_fix.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: fix.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_gate.yaml b/doc/openapi/components/schemas/config/hooks/_gate.yaml index 4c14ce308..5702f7fb8 100644 --- a/doc/openapi/components/schemas/config/hooks/_gate.yaml +++ b/doc/openapi/components/schemas/config/hooks/_gate.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: gate.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_jitter_calc.yaml b/doc/openapi/components/schemas/config/hooks/_jitter_calc.yaml index 2a4e5ce8a..4f251752e 100644 --- a/doc/openapi/components/schemas/config/hooks/_jitter_calc.yaml +++ b/doc/openapi/components/schemas/config/hooks/_jitter_calc.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: jitter_calc.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_limit_rate.yaml b/doc/openapi/components/schemas/config/hooks/_limit_rate.yaml index 298b6a6cb..36f465543 100644 --- a/doc/openapi/components/schemas/config/hooks/_limit_rate.yaml +++ b/doc/openapi/components/schemas/config/hooks/_limit_rate.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: limit_rate.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_limit_value.yaml b/doc/openapi/components/schemas/config/hooks/_limit_value.yaml index 2212ad325..aa4ada76b 100644 --- a/doc/openapi/components/schemas/config/hooks/_limit_value.yaml +++ b/doc/openapi/components/schemas/config/hooks/_limit_value.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: limit_value.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_lua.yaml b/doc/openapi/components/schemas/config/hooks/_lua.yaml index ac3ba59ce..36a51c205 100644 --- a/doc/openapi/components/schemas/config/hooks/_lua.yaml +++ b/doc/openapi/components/schemas/config/hooks/_lua.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: lua.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_ma.yaml b/doc/openapi/components/schemas/config/hooks/_ma.yaml index 56e8fc95b..0754a5b2b 100644 --- a/doc/openapi/components/schemas/config/hooks/_ma.yaml +++ b/doc/openapi/components/schemas/config/hooks/_ma.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: ma.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_pmu_dft.yaml b/doc/openapi/components/schemas/config/hooks/_pmu_dft.yaml index 73d4a4c78..30d0d69ae 100644 --- a/doc/openapi/components/schemas/config/hooks/_pmu_dft.yaml +++ b/doc/openapi/components/schemas/config/hooks/_pmu_dft.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: pmu_dft.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_pps_ts.yaml b/doc/openapi/components/schemas/config/hooks/_pps_ts.yaml index 7aedb280f..fd6526fc0 100644 --- a/doc/openapi/components/schemas/config/hooks/_pps_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/_pps_ts.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: pps_ts.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_print.yaml b/doc/openapi/components/schemas/config/hooks/_print.yaml index 4d74fbc20..f5f908140 100644 --- a/doc/openapi/components/schemas/config/hooks/_print.yaml +++ b/doc/openapi/components/schemas/config/hooks/_print.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: print.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_restart.yaml b/doc/openapi/components/schemas/config/hooks/_restart.yaml index a7f74c120..f01584c12 100644 --- a/doc/openapi/components/schemas/config/hooks/_restart.yaml +++ b/doc/openapi/components/schemas/config/hooks/_restart.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: restart.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_rms.yaml b/doc/openapi/components/schemas/config/hooks/_rms.yaml index d16d9295c..5da6ec15b 100644 --- a/doc/openapi/components/schemas/config/hooks/_rms.yaml +++ b/doc/openapi/components/schemas/config/hooks/_rms.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: rms.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_round.yaml b/doc/openapi/components/schemas/config/hooks/_round.yaml index 04f1796fc..7334d85c9 100644 --- a/doc/openapi/components/schemas/config/hooks/_round.yaml +++ b/doc/openapi/components/schemas/config/hooks/_round.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: round.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_scale.yaml b/doc/openapi/components/schemas/config/hooks/_scale.yaml index 190c37418..f8ee9f8c9 100644 --- a/doc/openapi/components/schemas/config/hooks/_scale.yaml +++ b/doc/openapi/components/schemas/config/hooks/_scale.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: scale.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_shift_seq.yaml b/doc/openapi/components/schemas/config/hooks/_shift_seq.yaml index 13065120c..ee86e61b9 100644 --- a/doc/openapi/components/schemas/config/hooks/_shift_seq.yaml +++ b/doc/openapi/components/schemas/config/hooks/_shift_seq.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: shift_seq.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_shift_ts.yaml b/doc/openapi/components/schemas/config/hooks/_shift_ts.yaml index d260b165f..2d2dceee0 100644 --- a/doc/openapi/components/schemas/config/hooks/_shift_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/_shift_ts.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: shift_ts.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_skip_first.yaml b/doc/openapi/components/schemas/config/hooks/_skip_first.yaml index dd51e8018..00170ba1a 100644 --- a/doc/openapi/components/schemas/config/hooks/_skip_first.yaml +++ b/doc/openapi/components/schemas/config/hooks/_skip_first.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: skip_first.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_stats.yaml b/doc/openapi/components/schemas/config/hooks/_stats.yaml index 061528214..a12bef088 100644 --- a/doc/openapi/components/schemas/config/hooks/_stats.yaml +++ b/doc/openapi/components/schemas/config/hooks/_stats.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: stats.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_ts.yaml b/doc/openapi/components/schemas/config/hooks/_ts.yaml index f9e438fc5..803400f5c 100644 --- a/doc/openapi/components/schemas/config/hooks/_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/_ts.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: ts.yaml diff --git a/doc/openapi/components/schemas/config/hooks/average.yaml b/doc/openapi/components/schemas/config/hooks/average.yaml index b772292ec..046d2a599 100644 --- a/doc/openapi/components/schemas/config/hooks/average.yaml +++ b/doc/openapi/components/schemas/config/hooks/average.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/cast.yaml b/doc/openapi/components/schemas/config/hooks/cast.yaml index 0c01489e0..38af5fad2 100644 --- a/doc/openapi/components/schemas/config/hooks/cast.yaml +++ b/doc/openapi/components/schemas/config/hooks/cast.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/decimate.yaml b/doc/openapi/components/schemas/config/hooks/decimate.yaml index c7cb8dc37..5fe375a39 100644 --- a/doc/openapi/components/schemas/config/hooks/decimate.yaml +++ b/doc/openapi/components/schemas/config/hooks/decimate.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/dp.yaml b/doc/openapi/components/schemas/config/hooks/dp.yaml index 2be619f38..49d7ccf5c 100644 --- a/doc/openapi/components/schemas/config/hooks/dp.yaml +++ b/doc/openapi/components/schemas/config/hooks/dp.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/drop.yaml b/doc/openapi/components/schemas/config/hooks/drop.yaml index 4783a3b94..38b20dcd1 100644 --- a/doc/openapi/components/schemas/config/hooks/drop.yaml +++ b/doc/openapi/components/schemas/config/hooks/drop.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/hooks/dump.yaml b/doc/openapi/components/schemas/config/hooks/dump.yaml index 4783a3b94..38b20dcd1 100644 --- a/doc/openapi/components/schemas/config/hooks/dump.yaml +++ b/doc/openapi/components/schemas/config/hooks/dump.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/hooks/ebm.yaml b/doc/openapi/components/schemas/config/hooks/ebm.yaml index ea9cb22d6..9dedcbca0 100644 --- a/doc/openapi/components/schemas/config/hooks/ebm.yaml +++ b/doc/openapi/components/schemas/config/hooks/ebm.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/fix.yaml b/doc/openapi/components/schemas/config/hooks/fix.yaml index 4783a3b94..38b20dcd1 100644 --- a/doc/openapi/components/schemas/config/hooks/fix.yaml +++ b/doc/openapi/components/schemas/config/hooks/fix.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/hooks/gate.yaml b/doc/openapi/components/schemas/config/hooks/gate.yaml index 24b30a12c..49b6af027 100644 --- a/doc/openapi/components/schemas/config/hooks/gate.yaml +++ b/doc/openapi/components/schemas/config/hooks/gate.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/jitter_calc.yaml b/doc/openapi/components/schemas/config/hooks/jitter_calc.yaml index 4783a3b94..38b20dcd1 100644 --- a/doc/openapi/components/schemas/config/hooks/jitter_calc.yaml +++ b/doc/openapi/components/schemas/config/hooks/jitter_calc.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/hooks/limit_rate.yaml b/doc/openapi/components/schemas/config/hooks/limit_rate.yaml index a3bb32f0e..87c3fcf84 100644 --- a/doc/openapi/components/schemas/config/hooks/limit_rate.yaml +++ b/doc/openapi/components/schemas/config/hooks/limit_rate.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/limit_value.yaml b/doc/openapi/components/schemas/config/hooks/limit_value.yaml index 37ccd0f97..de89d1448 100644 --- a/doc/openapi/components/schemas/config/hooks/limit_value.yaml +++ b/doc/openapi/components/schemas/config/hooks/limit_value.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/lua.yaml b/doc/openapi/components/schemas/config/hooks/lua.yaml index 64e219fa8..a6abb38c2 100644 --- a/doc/openapi/components/schemas/config/hooks/lua.yaml +++ b/doc/openapi/components/schemas/config/hooks/lua.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object additionalProperties: diff --git a/doc/openapi/components/schemas/config/hooks/ma.yaml b/doc/openapi/components/schemas/config/hooks/ma.yaml index 4325c880b..8f388e7b7 100644 --- a/doc/openapi/components/schemas/config/hooks/ma.yaml +++ b/doc/openapi/components/schemas/config/hooks/ma.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/pmu_dft.yaml b/doc/openapi/components/schemas/config/hooks/pmu_dft.yaml index d6ce71fa4..c86e7d1c3 100644 --- a/doc/openapi/components/schemas/config/hooks/pmu_dft.yaml +++ b/doc/openapi/components/schemas/config/hooks/pmu_dft.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/pps_ts.yaml b/doc/openapi/components/schemas/config/hooks/pps_ts.yaml index 7660280ef..17899eb56 100644 --- a/doc/openapi/components/schemas/config/hooks/pps_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/pps_ts.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/print.yaml b/doc/openapi/components/schemas/config/hooks/print.yaml index df1cff11c..de90bc800 100644 --- a/doc/openapi/components/schemas/config/hooks/print.yaml +++ b/doc/openapi/components/schemas/config/hooks/print.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/restart.yaml b/doc/openapi/components/schemas/config/hooks/restart.yaml index 0c99bd84b..20247f665 100644 --- a/doc/openapi/components/schemas/config/hooks/restart.yaml +++ b/doc/openapi/components/schemas/config/hooks/restart.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/hooks/rms.yaml b/doc/openapi/components/schemas/config/hooks/rms.yaml index 4325c880b..8f388e7b7 100644 --- a/doc/openapi/components/schemas/config/hooks/rms.yaml +++ b/doc/openapi/components/schemas/config/hooks/rms.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/round.yaml b/doc/openapi/components/schemas/config/hooks/round.yaml index 287d214aa..9822f8b19 100644 --- a/doc/openapi/components/schemas/config/hooks/round.yaml +++ b/doc/openapi/components/schemas/config/hooks/round.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/scale.yaml b/doc/openapi/components/schemas/config/hooks/scale.yaml index fe6743028..1349048f2 100644 --- a/doc/openapi/components/schemas/config/hooks/scale.yaml +++ b/doc/openapi/components/schemas/config/hooks/scale.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/shift_seq.yaml b/doc/openapi/components/schemas/config/hooks/shift_seq.yaml index 387ac0500..8ec50b6d8 100644 --- a/doc/openapi/components/schemas/config/hooks/shift_seq.yaml +++ b/doc/openapi/components/schemas/config/hooks/shift_seq.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/shift_ts.yaml b/doc/openapi/components/schemas/config/hooks/shift_ts.yaml index 2881cbe10..d2c3661aa 100644 --- a/doc/openapi/components/schemas/config/hooks/shift_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/shift_ts.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/hooks/skip_first.yaml b/doc/openapi/components/schemas/config/hooks/skip_first.yaml index 84a1f05f2..58046aa64 100644 --- a/doc/openapi/components/schemas/config/hooks/skip_first.yaml +++ b/doc/openapi/components/schemas/config/hooks/skip_first.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/stats.yaml b/doc/openapi/components/schemas/config/hooks/stats.yaml index 8da13d0d4..43911fe98 100644 --- a/doc/openapi/components/schemas/config/hooks/stats.yaml +++ b/doc/openapi/components/schemas/config/hooks/stats.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/hooks/ts.yaml b/doc/openapi/components/schemas/config/hooks/ts.yaml index 4783a3b94..38b20dcd1 100644 --- a/doc/openapi/components/schemas/config/hooks/ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/ts.yaml @@ -1,5 +1,6 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../hook.yaml diff --git a/doc/openapi/components/schemas/config/http.yaml b/doc/openapi/components/schemas/config/http.yaml index 1e9d4f4fe..f8ecfd215 100644 --- a/doc/openapi/components/schemas/config/http.yaml +++ b/doc/openapi/components/schemas/config/http.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: port: diff --git a/doc/openapi/components/schemas/config/logging.yaml b/doc/openapi/components/schemas/config/logging.yaml index a85737a41..d82471689 100644 --- a/doc/openapi/components/schemas/config/logging.yaml +++ b/doc/openapi/components/schemas/config/logging.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: Logging configuration properties: diff --git a/doc/openapi/components/schemas/config/netem.yaml b/doc/openapi/components/schemas/config/netem.yaml index bf99cd314..1ce51addb 100644 --- a/doc/openapi/components/schemas/config/netem.yaml +++ b/doc/openapi/components/schemas/config/netem.yaml @@ -1,5 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - description: | The netem configuration allows the user to apply network impairments to packets send out by the nodes. diff --git a/doc/openapi/components/schemas/config/node.yaml b/doc/openapi/components/schemas/config/node.yaml index d6ee16c2d..fc6c6bf64 100644 --- a/doc/openapi/components/schemas/config/node.yaml +++ b/doc/openapi/components/schemas/config/node.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: Node properties: diff --git a/doc/openapi/components/schemas/config/node_obj.yaml b/doc/openapi/components/schemas/config/node_obj.yaml index dfe8cd92e..258dfdbe2 100644 --- a/doc/openapi/components/schemas/config/node_obj.yaml +++ b/doc/openapi/components/schemas/config/node_obj.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: Format Object required: diff --git a/doc/openapi/components/schemas/config/node_signals.yaml b/doc/openapi/components/schemas/config/node_signals.yaml index db4ac7dbd..a594cec8a 100644 --- a/doc/openapi/components/schemas/config/node_signals.yaml +++ b/doc/openapi/components/schemas/config/node_signals.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: in: diff --git a/doc/openapi/components/schemas/config/nodes/_amqp.yaml b/doc/openapi/components/schemas/config/nodes/_amqp.yaml index 331d62dfb..b6cf3b342 100644 --- a/doc/openapi/components/schemas/config/nodes/_amqp.yaml +++ b/doc/openapi/components/schemas/config/nodes/_amqp.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: amqp.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_api.yaml b/doc/openapi/components/schemas/config/nodes/_api.yaml index c5b6347b8..8c7cb8603 100644 --- a/doc/openapi/components/schemas/config/nodes/_api.yaml +++ b/doc/openapi/components/schemas/config/nodes/_api.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: api.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_can.yaml b/doc/openapi/components/schemas/config/nodes/_can.yaml index 79a0caa67..35379af9e 100644 --- a/doc/openapi/components/schemas/config/nodes/_can.yaml +++ b/doc/openapi/components/schemas/config/nodes/_can.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: can.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_comedi.yaml b/doc/openapi/components/schemas/config/nodes/_comedi.yaml index 8fc9ebde2..f604da3a6 100644 --- a/doc/openapi/components/schemas/config/nodes/_comedi.yaml +++ b/doc/openapi/components/schemas/config/nodes/_comedi.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: comedi.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_ethercat.yaml b/doc/openapi/components/schemas/config/nodes/_ethercat.yaml index 414fa0f1f..5bf4c87ef 100644 --- a/doc/openapi/components/schemas/config/nodes/_ethercat.yaml +++ b/doc/openapi/components/schemas/config/nodes/_ethercat.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: ethercat.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_example.yaml b/doc/openapi/components/schemas/config/nodes/_example.yaml index 74f345f12..9b768110b 100644 --- a/doc/openapi/components/schemas/config/nodes/_example.yaml +++ b/doc/openapi/components/schemas/config/nodes/_example.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: example.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_exec.yaml b/doc/openapi/components/schemas/config/nodes/_exec.yaml index 93cb4bb82..99bb87eb1 100644 --- a/doc/openapi/components/schemas/config/nodes/_exec.yaml +++ b/doc/openapi/components/schemas/config/nodes/_exec.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: exec.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_file.yaml b/doc/openapi/components/schemas/config/nodes/_file.yaml index 690eca03b..3366cdf65 100644 --- a/doc/openapi/components/schemas/config/nodes/_file.yaml +++ b/doc/openapi/components/schemas/config/nodes/_file.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: file.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_fpga.yaml b/doc/openapi/components/schemas/config/nodes/_fpga.yaml index 168fc2572..537105d09 100644 --- a/doc/openapi/components/schemas/config/nodes/_fpga.yaml +++ b/doc/openapi/components/schemas/config/nodes/_fpga.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: fpga.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_iec60870-5-104.yaml b/doc/openapi/components/schemas/config/nodes/_iec60870-5-104.yaml index 47c5f4796..c3fc3fe20 100644 --- a/doc/openapi/components/schemas/config/nodes/_iec60870-5-104.yaml +++ b/doc/openapi/components/schemas/config/nodes/_iec60870-5-104.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: iec60870-5-104.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_iec61850-8-1.yaml b/doc/openapi/components/schemas/config/nodes/_iec61850-8-1.yaml index b37ffc302..9d1354a31 100644 --- a/doc/openapi/components/schemas/config/nodes/_iec61850-8-1.yaml +++ b/doc/openapi/components/schemas/config/nodes/_iec61850-8-1.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: iec61850-8-1.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_iec61850-9-2.yaml b/doc/openapi/components/schemas/config/nodes/_iec61850-9-2.yaml index 82e884739..cdcc44075 100644 --- a/doc/openapi/components/schemas/config/nodes/_iec61850-9-2.yaml +++ b/doc/openapi/components/schemas/config/nodes/_iec61850-9-2.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: iec61850-9-2.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_infiniband.yaml b/doc/openapi/components/schemas/config/nodes/_infiniband.yaml index a6cdca7bd..5a4eb4975 100644 --- a/doc/openapi/components/schemas/config/nodes/_infiniband.yaml +++ b/doc/openapi/components/schemas/config/nodes/_infiniband.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: infiniband.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_influxdb.yaml b/doc/openapi/components/schemas/config/nodes/_influxdb.yaml index 774751530..8da5a3d8b 100644 --- a/doc/openapi/components/schemas/config/nodes/_influxdb.yaml +++ b/doc/openapi/components/schemas/config/nodes/_influxdb.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: influxdb.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_kafka.yaml b/doc/openapi/components/schemas/config/nodes/_kafka.yaml index b6316f789..e976bbc48 100644 --- a/doc/openapi/components/schemas/config/nodes/_kafka.yaml +++ b/doc/openapi/components/schemas/config/nodes/_kafka.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: kafka.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_loopback.yaml b/doc/openapi/components/schemas/config/nodes/_loopback.yaml index 0407a01d6..f9ed90504 100644 --- a/doc/openapi/components/schemas/config/nodes/_loopback.yaml +++ b/doc/openapi/components/schemas/config/nodes/_loopback.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: loopback.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_modbus.yaml b/doc/openapi/components/schemas/config/nodes/_modbus.yaml index 2ecbc813d..2212b8bf5 100644 --- a/doc/openapi/components/schemas/config/nodes/_modbus.yaml +++ b/doc/openapi/components/schemas/config/nodes/_modbus.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: modbus.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_mqtt.yaml b/doc/openapi/components/schemas/config/nodes/_mqtt.yaml index 65bca5f28..4c1acf563 100644 --- a/doc/openapi/components/schemas/config/nodes/_mqtt.yaml +++ b/doc/openapi/components/schemas/config/nodes/_mqtt.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: mqtt.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_nanomsg.yaml b/doc/openapi/components/schemas/config/nodes/_nanomsg.yaml index b882440e8..6e6dab14a 100644 --- a/doc/openapi/components/schemas/config/nodes/_nanomsg.yaml +++ b/doc/openapi/components/schemas/config/nodes/_nanomsg.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: nanomsg.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_ngsi.yaml b/doc/openapi/components/schemas/config/nodes/_ngsi.yaml index 9df504f3c..ff89d23d3 100644 --- a/doc/openapi/components/schemas/config/nodes/_ngsi.yaml +++ b/doc/openapi/components/schemas/config/nodes/_ngsi.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: ngsi.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_opal.yaml b/doc/openapi/components/schemas/config/nodes/_opal.yaml index 1fbe97c8e..0f26cf2fe 100644 --- a/doc/openapi/components/schemas/config/nodes/_opal.yaml +++ b/doc/openapi/components/schemas/config/nodes/_opal.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: opal.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_redis.yaml b/doc/openapi/components/schemas/config/nodes/_redis.yaml index fd0c386ea..780474bc1 100644 --- a/doc/openapi/components/schemas/config/nodes/_redis.yaml +++ b/doc/openapi/components/schemas/config/nodes/_redis.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: redis.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_rtp.yaml b/doc/openapi/components/schemas/config/nodes/_rtp.yaml index 7eae9569b..8fdc442f1 100644 --- a/doc/openapi/components/schemas/config/nodes/_rtp.yaml +++ b/doc/openapi/components/schemas/config/nodes/_rtp.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: rtp.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_shmem.yaml b/doc/openapi/components/schemas/config/nodes/_shmem.yaml index 074a1eaff..5abb56d35 100644 --- a/doc/openapi/components/schemas/config/nodes/_shmem.yaml +++ b/doc/openapi/components/schemas/config/nodes/_shmem.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: shmem.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_signal_node.yaml b/doc/openapi/components/schemas/config/nodes/_signal_node.yaml index 1f2be236b..71c7b902a 100644 --- a/doc/openapi/components/schemas/config/nodes/_signal_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/_signal_node.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: signal_node.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_signal_v2_node.yaml b/doc/openapi/components/schemas/config/nodes/_signal_v2_node.yaml index 414c2a3e9..1ec4a962e 100644 --- a/doc/openapi/components/schemas/config/nodes/_signal_v2_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/_signal_v2_node.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: signal_v2_node.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_socket.yaml b/doc/openapi/components/schemas/config/nodes/_socket.yaml index cc5330e16..94da3b0f6 100644 --- a/doc/openapi/components/schemas/config/nodes/_socket.yaml +++ b/doc/openapi/components/schemas/config/nodes/_socket.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: socket.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_stats_node.yaml b/doc/openapi/components/schemas/config/nodes/_stats_node.yaml index b716510f8..18fd2c320 100644 --- a/doc/openapi/components/schemas/config/nodes/_stats_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/_stats_node.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: stats_node.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_temper.yaml b/doc/openapi/components/schemas/config/nodes/_temper.yaml index dacb2b000..770d10a53 100644 --- a/doc/openapi/components/schemas/config/nodes/_temper.yaml +++ b/doc/openapi/components/schemas/config/nodes/_temper.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: temper.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_test_rtt.yaml b/doc/openapi/components/schemas/config/nodes/_test_rtt.yaml index 827e45090..ca76d63ff 100644 --- a/doc/openapi/components/schemas/config/nodes/_test_rtt.yaml +++ b/doc/openapi/components/schemas/config/nodes/_test_rtt.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: test_rtt.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_uldaq.yaml b/doc/openapi/components/schemas/config/nodes/_uldaq.yaml index ec446ffce..3b082c334 100644 --- a/doc/openapi/components/schemas/config/nodes/_uldaq.yaml +++ b/doc/openapi/components/schemas/config/nodes/_uldaq.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: uldaq.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_webrtc.yaml b/doc/openapi/components/schemas/config/nodes/_webrtc.yaml index ce9514c00..54838ac00 100644 --- a/doc/openapi/components/schemas/config/nodes/_webrtc.yaml +++ b/doc/openapi/components/schemas/config/nodes/_webrtc.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: webrtc.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_websocket.yaml b/doc/openapi/components/schemas/config/nodes/_websocket.yaml index 2937af718..7d0812792 100644 --- a/doc/openapi/components/schemas/config/nodes/_websocket.yaml +++ b/doc/openapi/components/schemas/config/nodes/_websocket.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: websocket.yaml diff --git a/doc/openapi/components/schemas/config/nodes/_zeromq.yaml b/doc/openapi/components/schemas/config/nodes/_zeromq.yaml index 36e940bd6..4604ee28b 100644 --- a/doc/openapi/components/schemas/config/nodes/_zeromq.yaml +++ b/doc/openapi/components/schemas/config/nodes/_zeromq.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../node_obj.yaml - $ref: zeromq.yaml diff --git a/doc/openapi/components/schemas/config/nodes/amqp.yaml b/doc/openapi/components/schemas/config/nodes/amqp.yaml index 3c0175398..396a2ec8c 100644 --- a/doc/openapi/components/schemas/config/nodes/amqp.yaml +++ b/doc/openapi/components/schemas/config/nodes/amqp.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: Advanced Messaging & Queuing Protocol (AMQP) allOf: - type: object diff --git a/doc/openapi/components/schemas/config/nodes/api.yaml b/doc/openapi/components/schemas/config/nodes/api.yaml index 260acf78a..d259227db 100644 --- a/doc/openapi/components/schemas/config/nodes/api.yaml +++ b/doc/openapi/components/schemas/config/nodes/api.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../node.yaml - type: object diff --git a/doc/openapi/components/schemas/config/nodes/can.yaml b/doc/openapi/components/schemas/config/nodes/can.yaml index 1ac7b73e8..3c078ef94 100644 --- a/doc/openapi/components/schemas/config/nodes/can.yaml +++ b/doc/openapi/components/schemas/config/nodes/can.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/comedi.yaml b/doc/openapi/components/schemas/config/nodes/comedi.yaml index e144771cd..13ea62adf 100644 --- a/doc/openapi/components/schemas/config/nodes/comedi.yaml +++ b/doc/openapi/components/schemas/config/nodes/comedi.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/ethercat.yaml b/doc/openapi/components/schemas/config/nodes/ethercat.yaml index eb7b79203..5e379cab8 100644 --- a/doc/openapi/components/schemas/config/nodes/ethercat.yaml +++ b/doc/openapi/components/schemas/config/nodes/ethercat.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/example.yaml b/doc/openapi/components/schemas/config/nodes/example.yaml index 33e14d720..f1a1ac697 100644 --- a/doc/openapi/components/schemas/config/nodes/example.yaml +++ b/doc/openapi/components/schemas/config/nodes/example.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/exec.yaml b/doc/openapi/components/schemas/config/nodes/exec.yaml index 44491bdd7..ac3bcf143 100644 --- a/doc/openapi/components/schemas/config/nodes/exec.yaml +++ b/doc/openapi/components/schemas/config/nodes/exec.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/file.yaml b/doc/openapi/components/schemas/config/nodes/file.yaml index 36cd5536d..187efcbf1 100644 --- a/doc/openapi/components/schemas/config/nodes/file.yaml +++ b/doc/openapi/components/schemas/config/nodes/file.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/fpga.yaml b/doc/openapi/components/schemas/config/nodes/fpga.yaml index a571d19c9..86c508cc1 100644 --- a/doc/openapi/components/schemas/config/nodes/fpga.yaml +++ b/doc/openapi/components/schemas/config/nodes/fpga.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/iec60870-5-104.yaml b/doc/openapi/components/schemas/config/nodes/iec60870-5-104.yaml index 0a34b7657..cf26d0063 100644 --- a/doc/openapi/components/schemas/config/nodes/iec60870-5-104.yaml +++ b/doc/openapi/components/schemas/config/nodes/iec60870-5-104.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/iec61850-8-1.yaml b/doc/openapi/components/schemas/config/nodes/iec61850-8-1.yaml index 1953d8eaa..e60f96851 100644 --- a/doc/openapi/components/schemas/config/nodes/iec61850-8-1.yaml +++ b/doc/openapi/components/schemas/config/nodes/iec61850-8-1.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - $ref: ../node.yaml - type: object diff --git a/doc/openapi/components/schemas/config/nodes/iec61850-9-2.yaml b/doc/openapi/components/schemas/config/nodes/iec61850-9-2.yaml index 0c0e24ba6..fa6a64d5c 100644 --- a/doc/openapi/components/schemas/config/nodes/iec61850-9-2.yaml +++ b/doc/openapi/components/schemas/config/nodes/iec61850-9-2.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/infiniband.yaml b/doc/openapi/components/schemas/config/nodes/infiniband.yaml index 8bad27f1f..220780275 100644 --- a/doc/openapi/components/schemas/config/nodes/infiniband.yaml +++ b/doc/openapi/components/schemas/config/nodes/infiniband.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/influxdb.yaml b/doc/openapi/components/schemas/config/nodes/influxdb.yaml index 65f94469f..c6718946f 100644 --- a/doc/openapi/components/schemas/config/nodes/influxdb.yaml +++ b/doc/openapi/components/schemas/config/nodes/influxdb.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/kafka.yaml b/doc/openapi/components/schemas/config/nodes/kafka.yaml index 1b132a8e5..e98fb4f32 100644 --- a/doc/openapi/components/schemas/config/nodes/kafka.yaml +++ b/doc/openapi/components/schemas/config/nodes/kafka.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/loopback.yaml b/doc/openapi/components/schemas/config/nodes/loopback.yaml index c4d7a1aea..70e76fb55 100644 --- a/doc/openapi/components/schemas/config/nodes/loopback.yaml +++ b/doc/openapi/components/schemas/config/nodes/loopback.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/modbus.yaml b/doc/openapi/components/schemas/config/nodes/modbus.yaml index 4c1a8efc9..3d9715063 100644 --- a/doc/openapi/components/schemas/config/nodes/modbus.yaml +++ b/doc/openapi/components/schemas/config/nodes/modbus.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object anyOf: diff --git a/doc/openapi/components/schemas/config/nodes/mqtt.yaml b/doc/openapi/components/schemas/config/nodes/mqtt.yaml index a57f4c0cc..d2cc3a6b8 100644 --- a/doc/openapi/components/schemas/config/nodes/mqtt.yaml +++ b/doc/openapi/components/schemas/config/nodes/mqtt.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/nanomsg.yaml b/doc/openapi/components/schemas/config/nodes/nanomsg.yaml index 2f569f17e..f83a50a32 100644 --- a/doc/openapi/components/schemas/config/nodes/nanomsg.yaml +++ b/doc/openapi/components/schemas/config/nodes/nanomsg.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/ngsi.yaml b/doc/openapi/components/schemas/config/nodes/ngsi.yaml index 6c59a7e7f..d6db7fc49 100644 --- a/doc/openapi/components/schemas/config/nodes/ngsi.yaml +++ b/doc/openapi/components/schemas/config/nodes/ngsi.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/opal.yaml b/doc/openapi/components/schemas/config/nodes/opal.yaml index 1ef2044fd..6266dc69e 100644 --- a/doc/openapi/components/schemas/config/nodes/opal.yaml +++ b/doc/openapi/components/schemas/config/nodes/opal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/redis.yaml b/doc/openapi/components/schemas/config/nodes/redis.yaml index 2022b161f..47432bef1 100644 --- a/doc/openapi/components/schemas/config/nodes/redis.yaml +++ b/doc/openapi/components/schemas/config/nodes/redis.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/rtp.yaml b/doc/openapi/components/schemas/config/nodes/rtp.yaml index 5d2f68fc9..e3970527d 100644 --- a/doc/openapi/components/schemas/config/nodes/rtp.yaml +++ b/doc/openapi/components/schemas/config/nodes/rtp.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/shmem.yaml b/doc/openapi/components/schemas/config/nodes/shmem.yaml index 0613dc5c3..c67b9ca7a 100644 --- a/doc/openapi/components/schemas/config/nodes/shmem.yaml +++ b/doc/openapi/components/schemas/config/nodes/shmem.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signal_node.yaml b/doc/openapi/components/schemas/config/nodes/signal_node.yaml index 58979e404..988b57acf 100644 --- a/doc/openapi/components/schemas/config/nodes/signal_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/signal_node.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signal_v2_node.yaml b/doc/openapi/components/schemas/config/nodes/signal_v2_node.yaml index 1ad78137f..13e7804e0 100644 --- a/doc/openapi/components/schemas/config/nodes/signal_v2_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/signal_v2_node.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signals/api_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/api_signal.yaml index df2b9b6ed..3e99d969f 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/api_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/api_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signals/can_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/can_signal.yaml index 7ea2d1531..f2c564981 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/can_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/can_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signals/comedi_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/comedi_signal.yaml index 744dbfe1c..2ec1f8775 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/comedi_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/comedi_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signals/iec60870_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/iec60870_signal.yaml index e3fa38443..5d4b69c95 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/iec60870_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/iec60870_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_data.yaml b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_data.yaml index ee4a5b8b2..816382ff3 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_data.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_data.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_publisher_data.yaml b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_publisher_data.yaml index a4fdf1ace..57098098a 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_publisher_data.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_publisher_data.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - oneOf: - type: object diff --git a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_subscriber_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_subscriber_signal.yaml index 7a83e130b..69c0f8042 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_subscriber_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/iec61850_goose_subscriber_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signals/iec61850_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/iec61850_signal.yaml index f33d55385..8e65658de 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/iec61850_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/iec61850_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml index ae1861603..439d21da8 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/modbus_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: [type, address] diff --git a/doc/openapi/components/schemas/config/nodes/signals/signal_v2_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/signal_v2_signal.yaml index 7065251a7..e9ab4a1a1 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/signal_v2_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/signal_v2_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signals/stats_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/stats_signal.yaml index fdbdaf506..200434896 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/stats_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/stats_signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/signals/uldaq_signal.yaml b/doc/openapi/components/schemas/config/nodes/signals/uldaq_signal.yaml index f8c3344d9..5200ae976 100644 --- a/doc/openapi/components/schemas/config/nodes/signals/uldaq_signal.yaml +++ b/doc/openapi/components/schemas/config/nodes/signals/uldaq_signal.yaml @@ -1,5 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/socket.yaml b/doc/openapi/components/schemas/config/nodes/socket.yaml index 4a0db8ff3..49c9b1ec7 100644 --- a/doc/openapi/components/schemas/config/nodes/socket.yaml +++ b/doc/openapi/components/schemas/config/nodes/socket.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/stats_node.yaml b/doc/openapi/components/schemas/config/nodes/stats_node.yaml index 5ed9aa27b..e69b5e8f1 100644 --- a/doc/openapi/components/schemas/config/nodes/stats_node.yaml +++ b/doc/openapi/components/schemas/config/nodes/stats_node.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/temper.yaml b/doc/openapi/components/schemas/config/nodes/temper.yaml index 4b2321289..221483be1 100644 --- a/doc/openapi/components/schemas/config/nodes/temper.yaml +++ b/doc/openapi/components/schemas/config/nodes/temper.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/test_rtt.yaml b/doc/openapi/components/schemas/config/nodes/test_rtt.yaml index ca6540f84..03a03355d 100644 --- a/doc/openapi/components/schemas/config/nodes/test_rtt.yaml +++ b/doc/openapi/components/schemas/config/nodes/test_rtt.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/uldaq.yaml b/doc/openapi/components/schemas/config/nodes/uldaq.yaml index d8e05a323..e6189b659 100644 --- a/doc/openapi/components/schemas/config/nodes/uldaq.yaml +++ b/doc/openapi/components/schemas/config/nodes/uldaq.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object required: diff --git a/doc/openapi/components/schemas/config/nodes/webrtc.yaml b/doc/openapi/components/schemas/config/nodes/webrtc.yaml index 1b2d94229..64c10373b 100644 --- a/doc/openapi/components/schemas/config/nodes/webrtc.yaml +++ b/doc/openapi/components/schemas/config/nodes/webrtc.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/websocket.yaml b/doc/openapi/components/schemas/config/nodes/websocket.yaml index 580684456..236b1559e 100644 --- a/doc/openapi/components/schemas/config/nodes/websocket.yaml +++ b/doc/openapi/components/schemas/config/nodes/websocket.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/nodes/zeromq.yaml b/doc/openapi/components/schemas/config/nodes/zeromq.yaml index 50701d8be..aafa81243 100644 --- a/doc/openapi/components/schemas/config/nodes/zeromq.yaml +++ b/doc/openapi/components/schemas/config/nodes/zeromq.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/doc/openapi/components/schemas/config/path.yaml b/doc/openapi/components/schemas/config/path.yaml index 7b8c41ac3..5483c6c2e 100644 --- a/doc/openapi/components/schemas/config/path.yaml +++ b/doc/openapi/components/schemas/config/path.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object title: The first anyOf schema description: An explanation about the purpose of this instance. diff --git a/doc/openapi/components/schemas/config/signal.yaml b/doc/openapi/components/schemas/config/signal.yaml index ef026ee3f..72a67c8cd 100644 --- a/doc/openapi/components/schemas/config/signal.yaml +++ b/doc/openapi/components/schemas/config/signal.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - type: object properties: name: diff --git a/doc/openapi/components/schemas/config/signal_list.yaml b/doc/openapi/components/schemas/config/signal_list.yaml index 6e6c02b59..60c646239 100644 --- a/doc/openapi/components/schemas/config/signal_list.yaml +++ b/doc/openapi/components/schemas/config/signal_list.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: Signal list description: | Each node should define a list of signals which it receives. diff --git a/doc/openapi/components/schemas/formats/edgeflex.yaml b/doc/openapi/components/schemas/formats/edgeflex.yaml index 771ccd99a..58c283c01 100644 --- a/doc/openapi/components/schemas/formats/edgeflex.yaml +++ b/doc/openapi/components/schemas/formats/edgeflex.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: PMU measurements as used in the EdgeFlex project by Manuel description: | VILLASnode does not support deseralization (yet). diff --git a/doc/openapi/components/schemas/formats/igor.yaml b/doc/openapi/components/schemas/formats/igor.yaml index a4df356e8..12bd23a9d 100644 --- a/doc/openapi/components/schemas/formats/igor.yaml +++ b/doc/openapi/components/schemas/formats/igor.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: PMU format used by Igor example: diff --git a/doc/openapi/components/schemas/formats/sogno-old.yaml b/doc/openapi/components/schemas/formats/sogno-old.yaml index 249eb51d4..77ad74657 100644 --- a/doc/openapi/components/schemas/formats/sogno-old.yaml +++ b/doc/openapi/components/schemas/formats/sogno-old.yaml @@ -1,7 +1,8 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: Original PMU sensor data format as used in the SOGNO EU project type: object diff --git a/doc/openapi/components/schemas/formats/sogno.yaml b/doc/openapi/components/schemas/formats/sogno.yaml index 2543d41fc..e12862ba8 100644 --- a/doc/openapi/components/schemas/formats/sogno.yaml +++ b/doc/openapi/components/schemas/formats/sogno.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - title: PMU format used in SOGNO LF project example: diff --git a/doc/openapi/openapi.yaml b/doc/openapi/openapi.yaml index 5b277260b..f28d7edc3 100644 --- a/doc/openapi/openapi.yaml +++ b/doc/openapi/openapi.yaml @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- openapi: 3.0.3 diff --git a/doc/openapi/paths/README.md b/doc/openapi/paths/README.md deleted file mode 100644 index 04496597e..000000000 --- a/doc/openapi/paths/README.md +++ /dev/null @@ -1,105 +0,0 @@ -Paths -===== - -Organize your path definitions within this folder. You will reference your paths from your main `openapi.yaml` entrypoint file. - -It may help you to adopt some conventions: - -* path separator token (e.g. `@`) or subfolders -* path parameter (e.g. `{example}`) -* file-per-path or file-per-operation - -There are different benefits and drawbacks to each decision. - -You can adopt any organization you wish. We have some tips for organizing paths based on common practices. - -## Each path in a separate file - -Use a predefined "path separator" and keep all of your path files in the top level of the `paths` folder. - -``` -# todo: insert tree view of paths folder -``` - -Redocly recommends using the `@` character for this case. - -In addition, Redocly recommends placing path parameters within `{}` curly braces if you adopt this style. - -#### Motivations - -* Quickly see a list of all paths. Many people think in terms of the "number" of "endpoints" (paths), and not the "number" of "operations" (paths * http methods). - -* Only the "file-per-path" option is semantically correct with the OpenAPI Specification 3.0.2. However, Redocly's openapi-cli will build valid bundles for any of the other options too. - - -#### Drawbacks - -* This may require multiple definitions per http method within a single file. -* It requires settling on a path separator (that is allowed to be used in filenames) and sticking to that convention. - -## Each operation in a separate file - -You may also place each operation in a separate file. - -In this case, if you want all paths at the top-level, you can concatenate the http method to the path name. Similar to the above option, you can - -### Files at top-level of `paths` - -You may name your files with some concatenation for the http method. For example, following a convention such as: `-.yaml`. - -#### Motivations - -* Quickly see all operations without needing to navigate subfolders. - -#### Drawbacks - -* Adopting an unusual path separator convention, instead of using subfolders. - -### Use subfolders to mirror API path structure - -Example: -``` -GET /customers - -/paths/customers/get.yaml -``` - -In this case, the path id defined within subfolders which mirror the API URL structure. - -Example with path parameter: -``` -GET /customers/{id} - -/paths/customers/{id}/get.yaml -``` - -#### Motivations - -It matches the URL structure. - -It is pretty easy to reference: - -```yaml -paths: - '/customers/{id}': - get: - $ref: ./paths/customers/{id}/get.yaml - put: - $ref: ./paths/customers/{id}/put.yaml -``` - -#### Drawbacks - -If you have a lot of nested folders, it may be confusing to reference your schemas. - -Example -``` -file: /paths/customers/{id}/timeline/{messageId}/get.yaml - -# excerpt of file - headers: - Rate-Limit-Remaining: - $ref: ../../../../../components/headers/Rate-Limit-Remaining.yaml - -``` -Notice the `../../../../../` in the ref which requires some attention to formulate correctly. While openapi-cli has a linter which suggests possible refs when there is a mistake, this is still a net drawback for APIs with deep paths. diff --git a/doc/openapi/paths/capabilities.yaml b/doc/openapi/paths/capabilities.yaml index c2881bf21..d8b873e3c 100644 --- a/doc/openapi/paths/capabilities.yaml +++ b/doc/openapi/paths/capabilities.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-capabilities diff --git a/doc/openapi/paths/config.yaml b/doc/openapi/paths/config.yaml index 1b8e2f656..bc4a65b13 100644 --- a/doc/openapi/paths/config.yaml +++ b/doc/openapi/paths/config.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-config diff --git a/doc/openapi/paths/graph.{format}.yaml b/doc/openapi/paths/graph.{format}.yaml index e1ea2cf30..23e2b2b57 100644 --- a/doc/openapi/paths/graph.{format}.yaml +++ b/doc/openapi/paths/graph.{format}.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-graph diff --git a/doc/openapi/paths/node/node@{uuid-or-name}.yaml b/doc/openapi/paths/node/node@{uuid-or-name}.yaml index ccdea0f0e..ee8b5484d 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-node diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml index 76cbaac7f..373c0cc83 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: rewind-file-node diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml index 0fcd76250..77b329e13 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: seek-file-node diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml index 0487b1702..6915f87a1 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: pause-graph diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml index 175999261..320d8b4b5 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: restart-node diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml index b0f2f0037..a53b819aa 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: resume-node diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml index 38060a4d7..bf0a0182e 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: start-node summary: Start a node. diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml index 97e805d82..daef64382 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-node-stats summary: Get the statistics of a node. diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml index 50f38ccd9..8e279210f 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: reset-node-stats summary: Reset the statistics counters for a specific node. diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml index 370e88534..e4182c664 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: stop-node summary: Stop a node. diff --git a/doc/openapi/paths/nodes.yaml b/doc/openapi/paths/nodes.yaml index 521a0b4f5..e49dcf175 100644 --- a/doc/openapi/paths/nodes.yaml +++ b/doc/openapi/paths/nodes.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-nodes summary: Get a list of all configure node instances. diff --git a/doc/openapi/paths/path/path@{uuid}.yaml b/doc/openapi/paths/path/path@{uuid}.yaml index 6b13f6b3a..5c1792cac 100644 --- a/doc/openapi/paths/path/path@{uuid}.yaml +++ b/doc/openapi/paths/path/path@{uuid}.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: get-path summary: Get details of a single path. diff --git a/doc/openapi/paths/path/path@{uuid}@start.yaml b/doc/openapi/paths/path/path@{uuid}@start.yaml index 0807cc36c..0898e1104 100644 --- a/doc/openapi/paths/path/path@{uuid}@start.yaml +++ b/doc/openapi/paths/path/path@{uuid}@start.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: start-path summary: Start a path. diff --git a/doc/openapi/paths/path/path@{uuid}@stop.yaml b/doc/openapi/paths/path/path@{uuid}@stop.yaml index f63f5e059..8a4a7cb54 100644 --- a/doc/openapi/paths/path/path@{uuid}@stop.yaml +++ b/doc/openapi/paths/path/path@{uuid}@stop.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: stop-path summary: Start a path. diff --git a/doc/openapi/paths/paths.yaml b/doc/openapi/paths/paths.yaml index d73b612be..8bb80fe1d 100644 --- a/doc/openapi/paths/paths.yaml +++ b/doc/openapi/paths/paths.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-paths summary: Get a list of all paths. diff --git a/doc/openapi/paths/restart.yaml b/doc/openapi/paths/restart.yaml index 4da89adb3..fa4d892fd 100644 --- a/doc/openapi/paths/restart.yaml +++ b/doc/openapi/paths/restart.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: restart summary: Restart the VILLASnode instance. diff --git a/doc/openapi/paths/shutdown.yaml b/doc/openapi/paths/shutdown.yaml index da170e100..179721ffb 100644 --- a/doc/openapi/paths/shutdown.yaml +++ b/doc/openapi/paths/shutdown.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- post: operationId: shutdown summary: Shutdown the VILLASnode instance. diff --git a/doc/openapi/paths/status.yaml b/doc/openapi/paths/status.yaml index 6e431efce..65441c6a7 100644 --- a/doc/openapi/paths/status.yaml +++ b/doc/openapi/paths/status.yaml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- get: operationId: get-status summary: Get the current status of the VILLASnode instance. diff --git a/doc/theme/header.html b/doc/theme/header.html index 9ae595d6a..93e1cd4ab 100644 --- a/doc/theme/header.html +++ b/doc/theme/header.html @@ -1,4 +1,8 @@ - + diff --git a/doc/theme/layout.xml b/doc/theme/layout.xml index aead553c7..bc43e0556 100644 --- a/doc/theme/layout.xml +++ b/doc/theme/layout.xml @@ -1,3 +1,7 @@ + diff --git a/doc/theme/style.css b/doc/theme/style.css index 069249785..2f0e4d845 100644 --- a/doc/theme/style.css +++ b/doc/theme/style.css @@ -1,3 +1,8 @@ +/* +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +*/ + #projectname { font-size: 200%; } diff --git a/etc/CMakeLists.txt b/etc/CMakeLists.txt index 38d9b6685..b4b9ca7f9 100644 --- a/etc/CMakeLists.txt +++ b/etc/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/etc/WSCC_9bus_MV.conf b/etc/WSCC_9bus_MV.conf index e88c1db7e..0eabebb42 100644 --- a/etc/WSCC_9bus_MV.conf +++ b/etc/WSCC_9bus_MV.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + logging = { level = "info" } diff --git a/etc/eric-lab.conf b/etc/eric-lab.conf index 64a812413..62eaa57b6 100644 --- a/etc/eric-lab.conf +++ b/etc/eric-lab.conf @@ -8,9 +8,9 @@ # A detailed description of the format can be found here: # http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files # -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 name = "villas-acs" # The name of this VILLASnode. Might by used by node-types # to identify themselves (default is the hostname). @@ -24,7 +24,7 @@ http = { port = 80 # Port for HTTP connections } -############ Dictionary of nodes ############ +## Dictionary of nodes nodes = { ws = { @@ -63,7 +63,7 @@ nodes = { } } -############ List of paths ############ +## List of paths paths = ( { diff --git a/etc/examples/api.conf b/etc/examples/api.conf index 0596af7ef..144d660e4 100644 --- a/etc/examples/api.conf +++ b/etc/examples/api.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + http = { port = 8080 } diff --git a/etc/examples/example.conf b/etc/examples/example.conf index bb56b247d..945242b99 100644 --- a/etc/examples/example.conf +++ b/etc/examples/example.conf @@ -1,17 +1,16 @@ -/** Example configuration file for VILLASnode. - * - * This example includes all valid configuration options for the server. - * Please note, that using all options at the same time does not really - * makes sense. The purpose of this example is to serve as a reference. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# Example configuration file for VILLASnode. +# +# This example includes all valid configuration options for the server. +# Please note, that using all options at the same time does not really +# makes sense. The purpose of this example is to serve as a reference. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Some global settings are used by multiple configuration files # and therefore defined in separate files diff --git a/etc/examples/formats/csv.conf b/etc/examples/formats/csv.conf index 14b49e433..35f727b62 100644 --- a/etc/examples/formats/csv.conf +++ b/etc/examples/formats/csv.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/gtnet.conf b/etc/examples/formats/gtnet.conf index c2e9199cc..d7b661d65 100644 --- a/etc/examples/formats/gtnet.conf +++ b/etc/examples/formats/gtnet.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/iotagent_ul.conf b/etc/examples/formats/iotagent_ul.conf index 29a6769e2..e9af8373e 100644 --- a/etc/examples/formats/iotagent_ul.conf +++ b/etc/examples/formats/iotagent_ul.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/json-edgeflex.conf b/etc/examples/formats/json-edgeflex.conf index ebf71ba84..5c894286c 100644 --- a/etc/examples/formats/json-edgeflex.conf +++ b/etc/examples/formats/json-edgeflex.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/json-kafka.conf b/etc/examples/formats/json-kafka.conf index 207c95488..5a7b46341 100644 --- a/etc/examples/formats/json-kafka.conf +++ b/etc/examples/formats/json-kafka.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/json-reserve.conf b/etc/examples/formats/json-reserve.conf index d20441ba6..604d21caa 100644 --- a/etc/examples/formats/json-reserve.conf +++ b/etc/examples/formats/json-reserve.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/json.conf b/etc/examples/formats/json.conf index 00d5d47bc..0a57d9d6d 100644 --- a/etc/examples/formats/json.conf +++ b/etc/examples/formats/json.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/opal-asyncip.conf b/etc/examples/formats/opal-asyncip.conf index 98612e54c..9860ef48d 100644 --- a/etc/examples/formats/opal-asyncip.conf +++ b/etc/examples/formats/opal-asyncip.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "socket" diff --git a/etc/examples/formats/protobuf.conf b/etc/examples/formats/protobuf.conf index 46f688165..bb3ff56d3 100644 --- a/etc/examples/formats/protobuf.conf +++ b/etc/examples/formats/protobuf.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/raw.conf b/etc/examples/formats/raw.conf index 1da00032e..a86d13ceb 100644 --- a/etc/examples/formats/raw.conf +++ b/etc/examples/formats/raw.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/tsv.conf b/etc/examples/formats/tsv.conf index ed1bb1b88..0e6a64bea 100644 --- a/etc/examples/formats/tsv.conf +++ b/etc/examples/formats/tsv.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/value.conf b/etc/examples/formats/value.conf index f14bcfa41..a054c36e4 100644 --- a/etc/examples/formats/value.conf +++ b/etc/examples/formats/value.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/villas-binary.conf b/etc/examples/formats/villas-binary.conf index 055357e24..1346d3f32 100644 --- a/etc/examples/formats/villas-binary.conf +++ b/etc/examples/formats/villas-binary.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/villas-human.conf b/etc/examples/formats/villas-human.conf index 4c4bdce8e..b5f6fcfa9 100644 --- a/etc/examples/formats/villas-human.conf +++ b/etc/examples/formats/villas-human.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/formats/villas-web.conf b/etc/examples/formats/villas-web.conf index ee3ef865d..c2439e966 100644 --- a/etc/examples/formats/villas-web.conf +++ b/etc/examples/formats/villas-web.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { node = { type = "file" diff --git a/etc/examples/global.conf b/etc/examples/global.conf index c1bf60e63..e3b78ee27 100644 --- a/etc/examples/global.conf +++ b/etc/examples/global.conf @@ -1,15 +1,14 @@ -/** Global configuration file for VILLASnode. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# Global configuration file for VILLASnode. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 -############ Global Options ############ +## Global Options affinity = 0x01 # Mask of cores the server should run on # This also maps the NIC interrupts to those cores! diff --git a/etc/examples/hooks/average.conf b/etc/examples/hooks/average.conf index 5b8c94bef..9f03a7eb9 100644 --- a/etc/examples/hooks/average.conf +++ b/etc/examples/hooks/average.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/cast.conf b/etc/examples/hooks/cast.conf index e9602d3f3..2b45e9bcd 100644 --- a/etc/examples/hooks/cast.conf +++ b/etc/examples/hooks/cast.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/decimate.conf b/etc/examples/hooks/decimate.conf index 0ea5031d0..7555fa432 100644 --- a/etc/examples/hooks/decimate.conf +++ b/etc/examples/hooks/decimate.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/dp.conf b/etc/examples/hooks/dp.conf index a98b0acad..6f897fa4b 100644 --- a/etc/examples/hooks/dp.conf +++ b/etc/examples/hooks/dp.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/dump.conf b/etc/examples/hooks/dump.conf index a88f93c85..142eaf28c 100644 --- a/etc/examples/hooks/dump.conf +++ b/etc/examples/hooks/dump.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/ebm.conf b/etc/examples/hooks/ebm.conf index 61de4d024..58c47f3e0 100644 --- a/etc/examples/hooks/ebm.conf +++ b/etc/examples/hooks/ebm.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/gate.conf b/etc/examples/hooks/gate.conf index ac5467e8f..4cb8e848a 100644 --- a/etc/examples/hooks/gate.conf +++ b/etc/examples/hooks/gate.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/hook-nodes.conf b/etc/examples/hooks/hook-nodes.conf index 54b2bba70..2240af636 100644 --- a/etc/examples/hooks/hook-nodes.conf +++ b/etc/examples/hooks/hook-nodes.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + # This files just contains some simple nodes # which are used to demonstrate the functionalities # of different hooks diff --git a/etc/examples/hooks/ip-dft-pmu.conf b/etc/examples/hooks/ip-dft-pmu.conf index e7c4bb0d5..31de833c9 100644 --- a/etc/examples/hooks/ip-dft-pmu.conf +++ b/etc/examples/hooks/ip-dft-pmu.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/jitter_calc.conf b/etc/examples/hooks/jitter_calc.conf index 242451fc6..012633a18 100644 --- a/etc/examples/hooks/jitter_calc.conf +++ b/etc/examples/hooks/jitter_calc.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/limit_rate.conf b/etc/examples/hooks/limit_rate.conf index 97381ead2..162e24783 100644 --- a/etc/examples/hooks/limit_rate.conf +++ b/etc/examples/hooks/limit_rate.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/limit_value.conf b/etc/examples/hooks/limit_value.conf index 7120894bb..00848b04f 100644 --- a/etc/examples/hooks/limit_value.conf +++ b/etc/examples/hooks/limit_value.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/lua.conf b/etc/examples/hooks/lua.conf index 9e4f3a77e..49c48000b 100644 --- a/etc/examples/hooks/lua.conf +++ b/etc/examples/hooks/lua.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" stats = 1 diff --git a/etc/examples/hooks/ma.conf b/etc/examples/hooks/ma.conf index 962c85e81..8e8d2eeac 100644 --- a/etc/examples/hooks/ma.conf +++ b/etc/examples/hooks/ma.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/pmu.conf b/etc/examples/hooks/pmu.conf index ab36e9d2e..e49349ece 100644 --- a/etc/examples/hooks/pmu.conf +++ b/etc/examples/hooks/pmu.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/pmu_dft.conf b/etc/examples/hooks/pmu_dft.conf index dcc6d993f..878733238 100644 --- a/etc/examples/hooks/pmu_dft.conf +++ b/etc/examples/hooks/pmu_dft.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/power.conf b/etc/examples/hooks/power.conf index 34d7320d6..bb277b558 100644 --- a/etc/examples/hooks/power.conf +++ b/etc/examples/hooks/power.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/pps_ts.conf b/etc/examples/hooks/pps_ts.conf index f001a8931..ea9132d02 100644 --- a/etc/examples/hooks/pps_ts.conf +++ b/etc/examples/hooks/pps_ts.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/print.conf b/etc/examples/hooks/print.conf index c16b5a4a4..5ed4aba09 100644 --- a/etc/examples/hooks/print.conf +++ b/etc/examples/hooks/print.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/rms.conf b/etc/examples/hooks/rms.conf index 776372ef8..a57398004 100644 --- a/etc/examples/hooks/rms.conf +++ b/etc/examples/hooks/rms.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/round.conf b/etc/examples/hooks/round.conf index 269586c62..5f69b5b55 100644 --- a/etc/examples/hooks/round.conf +++ b/etc/examples/hooks/round.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/scale.conf b/etc/examples/hooks/scale.conf index 988a99b28..94d59c874 100644 --- a/etc/examples/hooks/scale.conf +++ b/etc/examples/hooks/scale.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/shift_seq.conf b/etc/examples/hooks/shift_seq.conf index cd9aeed26..c32e32ee4 100644 --- a/etc/examples/hooks/shift_seq.conf +++ b/etc/examples/hooks/shift_seq.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/shift_ts.conf b/etc/examples/hooks/shift_ts.conf index 90d47dad2..4c4448c91 100644 --- a/etc/examples/hooks/shift_ts.conf +++ b/etc/examples/hooks/shift_ts.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/skip_first.conf b/etc/examples/hooks/skip_first.conf index 01527656b..348b8328c 100644 --- a/etc/examples/hooks/skip_first.conf +++ b/etc/examples/hooks/skip_first.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/hooks/stats.conf b/etc/examples/hooks/stats.conf index fab47328a..1523343ef 100644 --- a/etc/examples/hooks/stats.conf +++ b/etc/examples/hooks/stats.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node = { type = "socket" diff --git a/etc/examples/hooks/ts.conf b/etc/examples/hooks/ts.conf index 204a39cfc..c25f9ca7e 100644 --- a/etc/examples/hooks/ts.conf +++ b/etc/examples/hooks/ts.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/etc/examples/nodes/amqp.conf b/etc/examples/nodes/amqp.conf index d6f216c2d..1fa1133e5 100644 --- a/etc/examples/nodes/amqp.conf +++ b/etc/examples/nodes/amqp.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { amqp_node = { type = "amqp", diff --git a/etc/examples/nodes/api.conf b/etc/examples/nodes/api.conf index 02a0f783f..a72ab1a19 100644 --- a/etc/examples/nodes/api.conf +++ b/etc/examples/nodes/api.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { api_node = { type = "api" diff --git a/etc/examples/nodes/can.conf b/etc/examples/nodes/can.conf index 8dbcec6f1..582eecb21 100644 --- a/etc/examples/nodes/can.conf +++ b/etc/examples/nodes/can.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { can_node1 = { type = "can" diff --git a/etc/examples/nodes/comedi.conf b/etc/examples/nodes/comedi.conf index 962d17eec..9b4e563e0 100644 --- a/etc/examples/nodes/comedi.conf +++ b/etc/examples/nodes/comedi.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { pcie6259 = { type = "comedi", diff --git a/etc/examples/nodes/ethercat.conf b/etc/examples/nodes/ethercat.conf index a51ca0130..c60b4433a 100644 --- a/etc/examples/nodes/ethercat.conf +++ b/etc/examples/nodes/ethercat.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + ethercat = { coupler = { position = 0 diff --git a/etc/examples/nodes/example.conf b/etc/examples/nodes/example.conf index 763a3de1a..272e9e86f 100644 --- a/etc/examples/nodes/example.conf +++ b/etc/examples/nodes/example.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { example_node = { type = "example" diff --git a/etc/examples/nodes/exec.conf b/etc/examples/nodes/exec.conf index ff336f5bf..0c39377ad 100644 --- a/etc/examples/nodes/exec.conf +++ b/etc/examples/nodes/exec.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { exec_node = { type = "exec" diff --git a/etc/examples/nodes/file.conf b/etc/examples/nodes/file.conf index c2ce9219b..16ca5366b 100644 --- a/etc/examples/nodes/file.conf +++ b/etc/examples/nodes/file.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { file_node = { type = "file" diff --git a/etc/examples/nodes/fpga.conf b/etc/examples/nodes/fpga.conf index 5066d4d49..56a1e1ac3 100644 --- a/etc/examples/nodes/fpga.conf +++ b/etc/examples/nodes/fpga.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + logging = { level = "debug" } diff --git a/etc/examples/nodes/iec60870-5-104-sequence.conf b/etc/examples/nodes/iec60870-5-104-sequence.conf index 5037b3933..d10e1d057 100644 --- a/etc/examples/nodes/iec60870-5-104-sequence.conf +++ b/etc/examples/nodes/iec60870-5-104-sequence.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { iec104_node_seq = { type = "iec60870-5-104" diff --git a/etc/examples/nodes/iec60870-5-104.conf b/etc/examples/nodes/iec60870-5-104.conf index d47b2405a..f0711c899 100644 --- a/etc/examples/nodes/iec60870-5-104.conf +++ b/etc/examples/nodes/iec60870-5-104.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { iec104_node = { diff --git a/etc/examples/nodes/iec61850-8-1.conf b/etc/examples/nodes/iec61850-8-1.conf index 819e128ef..9b77ca4b8 100644 --- a/etc/examples/nodes/iec61850-8-1.conf +++ b/etc/examples/nodes/iec61850-8-1.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { goose = { diff --git a/etc/examples/nodes/iec61850-9-2.conf b/etc/examples/nodes/iec61850-9-2.conf index bac280062..9f316762f 100644 --- a/etc/examples/nodes/iec61850-9-2.conf +++ b/etc/examples/nodes/iec61850-9-2.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { sampled_values_node = { type = "iec61850-9-2", diff --git a/etc/examples/nodes/infiniband.conf b/etc/examples/nodes/infiniband.conf index 409b73e79..61a444083 100644 --- a/etc/examples/nodes/infiniband.conf +++ b/etc/examples/nodes/infiniband.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { results = { type = "file", diff --git a/etc/examples/nodes/influxdb.conf b/etc/examples/nodes/influxdb.conf index 78ab415ba..b4f0ed806 100644 --- a/etc/examples/nodes/influxdb.conf +++ b/etc/examples/nodes/influxdb.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { influxdb_node = { type = "influxdb", diff --git a/etc/examples/nodes/kafka.conf b/etc/examples/nodes/kafka.conf index c303e2692..7ca158fff 100644 --- a/etc/examples/nodes/kafka.conf +++ b/etc/examples/nodes/kafka.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { kafka_node = { type = "kafka", diff --git a/etc/examples/nodes/loopback.conf b/etc/examples/nodes/loopback.conf index 1ab457568..25870a3a9 100644 --- a/etc/examples/nodes/loopback.conf +++ b/etc/examples/nodes/loopback.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { loopback_node = { type = "loopback", # A loopback node will receive exactly the same data which has been sent to it. diff --git a/etc/examples/nodes/modbus.conf b/etc/examples/nodes/modbus.conf index c1b3952df..4f8bf3a96 100644 --- a/etc/examples/nodes/modbus.conf +++ b/etc/examples/nodes/modbus.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { modbus_node = { type = "modbus" diff --git a/etc/examples/nodes/mqtt.conf b/etc/examples/nodes/mqtt.conf index 0ead39152..14e9f6729 100644 --- a/etc/examples/nodes/mqtt.conf +++ b/etc/examples/nodes/mqtt.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { mqtt_node = { type = "mqtt", diff --git a/etc/examples/nodes/nanomsg.conf b/etc/examples/nodes/nanomsg.conf index f856e34d1..d270ed2b1 100644 --- a/etc/examples/nodes/nanomsg.conf +++ b/etc/examples/nodes/nanomsg.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { nanomsg_node = { type = "nanomsg", diff --git a/etc/examples/nodes/netem.conf b/etc/examples/nodes/netem.conf index 35290b314..7d8067020 100644 --- a/etc/examples/nodes/netem.conf +++ b/etc/examples/nodes/netem.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node = { # The dictionary is indexed by the name of the node. type = "socket", # For a list of available node-types run: 'villas-node -h' diff --git a/etc/examples/nodes/ngsi.conf b/etc/examples/nodes/ngsi.conf index 3d40a5efd..8b99fd29b 100644 --- a/etc/examples/nodes/ngsi.conf +++ b/etc/examples/nodes/ngsi.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { ngsi_node = { type = "ngsi", diff --git a/etc/examples/nodes/opal.conf b/etc/examples/nodes/opal.conf index 51e76187c..96d96c199 100644 --- a/etc/examples/nodes/opal.conf +++ b/etc/examples/nodes/opal.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { opal_node = { # The server can be started as an Asynchronous process type = "opal", # from within an OPAL-RT model. diff --git a/etc/examples/nodes/redis.conf b/etc/examples/nodes/redis.conf index dc0288ba3..3d2ad5317 100644 --- a/etc/examples/nodes/redis.conf +++ b/etc/examples/nodes/redis.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { redis_node = { type = "redis", diff --git a/etc/examples/nodes/rtp.conf b/etc/examples/nodes/rtp.conf index 99fcd27bf..e88889b8e 100644 --- a/etc/examples/nodes/rtp.conf +++ b/etc/examples/nodes/rtp.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { rtp_node = { type = "rtp" diff --git a/etc/examples/nodes/shmem.conf b/etc/examples/nodes/shmem.conf index 5484b7864..ad1e98ae3 100644 --- a/etc/examples/nodes/shmem.conf +++ b/etc/examples/nodes/shmem.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { shmem_node = { type = "shmem", diff --git a/etc/examples/nodes/signal-v2.conf b/etc/examples/nodes/signal-v2.conf index 77789dad2..03c89b50b 100644 --- a/etc/examples/nodes/signal-v2.conf +++ b/etc/examples/nodes/signal-v2.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { signal_node = { type = "signal.v2", diff --git a/etc/examples/nodes/signal.conf b/etc/examples/nodes/signal.conf index 318d7def4..b25fe9d59 100644 --- a/etc/examples/nodes/signal.conf +++ b/etc/examples/nodes/signal.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { signal_node = { type = "signal", diff --git a/etc/examples/nodes/socket.conf b/etc/examples/nodes/socket.conf index a165eabfa..68173f1ce 100644 --- a/etc/examples/nodes/socket.conf +++ b/etc/examples/nodes/socket.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node = { # The dictionary is indexed by the name of the node. type = "socket", # For a list of available node-types run: 'villas-node -h' diff --git a/etc/examples/nodes/stats.conf b/etc/examples/nodes/stats.conf index f9aeb6539..4ce7c5c59 100644 --- a/etc/examples/nodes/stats.conf +++ b/etc/examples/nodes/stats.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node = { type = "socket" diff --git a/etc/examples/nodes/temper.conf b/etc/examples/nodes/temper.conf index 0de395ac3..10c9b4447 100644 --- a/etc/examples/nodes/temper.conf +++ b/etc/examples/nodes/temper.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { temper_node = { type = "temper" diff --git a/etc/examples/nodes/test_rtt.conf b/etc/examples/nodes/test_rtt.conf index b4814d692..7c5006a98 100644 --- a/etc/examples/nodes/test_rtt.conf +++ b/etc/examples/nodes/test_rtt.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { rtt_node = { # The "test_rtt" node-type runs a set of test cases for varying type = "test_rtt", # sending rates, number of values and generates statistics. diff --git a/etc/examples/nodes/uldaq.conf b/etc/examples/nodes/uldaq.conf index 3990c7d09..bd9bc9c14 100644 --- a/etc/examples/nodes/uldaq.conf +++ b/etc/examples/nodes/uldaq.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + http = { enabled = false } diff --git a/etc/examples/nodes/unix_domain.conf b/etc/examples/nodes/unix_domain.conf index 2da239f5d..ee18dd86a 100644 --- a/etc/examples/nodes/unix_domain.conf +++ b/etc/examples/nodes/unix_domain.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { unix_domain_node = { type = "socket", diff --git a/etc/examples/nodes/webrtc.conf b/etc/examples/nodes/webrtc.conf index 441ed41a0..077067077 100644 --- a/etc/examples/nodes/webrtc.conf +++ b/etc/examples/nodes/webrtc.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { webrtc_node = { type = "webrtc", diff --git a/etc/examples/nodes/websocket.conf b/etc/examples/nodes/websocket.conf index 579588941..9cc84e964 100644 --- a/etc/examples/nodes/websocket.conf +++ b/etc/examples/nodes/websocket.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { ws = { type = "websocket" diff --git a/etc/examples/nodes/zeromq.conf b/etc/examples/nodes/zeromq.conf index 3351e33be..63674c035 100644 --- a/etc/examples/nodes/zeromq.conf +++ b/etc/examples/nodes/zeromq.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { zeromq_node = { type = "zeromq" diff --git a/etc/examples/paths.conf b/etc/examples/paths.conf index 98a9f7359..e4ea04b3a 100644 --- a/etc/examples/paths.conf +++ b/etc/examples/paths.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + paths = ( { enabled = true, # Enable this path (default: true) diff --git a/etc/examples/typhoon.conf b/etc/examples/typhoon.conf index 1b9da8b17..4b1484aa6 100644 --- a/etc/examples/typhoon.conf +++ b/etc/examples/typhoon.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + stats = 1.0 nodes = { diff --git a/etc/examples/villas-web.conf b/etc/examples/villas-web.conf index 7178ca24d..c5065f2f0 100644 --- a/etc/examples/villas-web.conf +++ b/etc/examples/villas-web.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { sine = { type = "signal" diff --git a/etc/gtnet-skt/emulate_gtnet.conf b/etc/gtnet-skt/emulate_gtnet.conf index c3b517c93..9e8b4921f 100644 --- a/etc/gtnet-skt/emulate_gtnet.conf +++ b/etc/gtnet-skt/emulate_gtnet.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +#* GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test1.conf b/etc/gtnet-skt/test1.conf index 9b670d54f..1b7a02a32 100644 --- a/etc/gtnet-skt/test1.conf +++ b/etc/gtnet-skt/test1.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test2.conf b/etc/gtnet-skt/test2.conf index 04a492ab1..a2495dc8a 100644 --- a/etc/gtnet-skt/test2.conf +++ b/etc/gtnet-skt/test2.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test3.conf b/etc/gtnet-skt/test3.conf index a99410a76..df37cbbdc 100644 --- a/etc/gtnet-skt/test3.conf +++ b/etc/gtnet-skt/test3.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test4.conf b/etc/gtnet-skt/test4.conf index 2261c9111..df2b9c711 100644 --- a/etc/gtnet-skt/test4.conf +++ b/etc/gtnet-skt/test4.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test5.conf b/etc/gtnet-skt/test5.conf index 3ec13249a..e2aae0ee1 100644 --- a/etc/gtnet-skt/test5.conf +++ b/etc/gtnet-skt/test5.conf @@ -1,13 +1,12 @@ -/** GTNET-SKT test configuration. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ +# GTNET-SKT test configuration. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/gtnet-skt/test6_gtsync_compare.conf b/etc/gtnet-skt/test6_gtsync_compare.conf index a9c72e708..7ef93e8d0 100644 --- a/etc/gtnet-skt/test6_gtsync_compare.conf +++ b/etc/gtnet-skt/test6_gtsync_compare.conf @@ -21,9 +21,9 @@ # # $ ./pipe etc/loopback.conf node2 # -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 logging = { level = "debug" diff --git a/etc/js/config.js b/etc/js/config.js index 8efbf78e0..637cfad22 100644 --- a/etc/js/config.js +++ b/etc/js/config.js @@ -7,9 +7,9 @@ * * villas node <(node /etc/villas/node/js/config.js) * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ var glob = require('glob'); diff --git a/etc/js/global.js b/etc/js/global.js index ddfceb43d..3ea55f673 100644 --- a/etc/js/global.js +++ b/etc/js/global.js @@ -4,9 +4,9 @@ * A detailed description of the format can be found here: * http://www.hyperrealm.com/libconfig/libconfig_manual.html//Configuration-Files * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ os = require('os'); diff --git a/etc/labs/lab10_nodes.conf b/etc/labs/lab10_nodes.conf index 8e6446c65..b3a747eee 100644 --- a/etc/labs/lab10_nodes.conf +++ b/etc/labs/lab10_nodes.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + hugepages = 200 nodes = { diff --git a/etc/labs/lab10_path_bidir.conf b/etc/labs/lab10_path_bidir.conf index 9cc469bd5..6c629d02b 100644 --- a/etc/labs/lab10_path_bidir.conf +++ b/etc/labs/lab10_path_bidir.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "lab10_nodes.conf" paths = ( diff --git a/etc/labs/lab10_path_hook.conf b/etc/labs/lab10_path_hook.conf index ac3aac655..d67a69f14 100644 --- a/etc/labs/lab10_path_hook.conf +++ b/etc/labs/lab10_path_hook.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "lab10_nodes.conf" paths = ( diff --git a/etc/labs/lab10_path_multiple_destinations.conf b/etc/labs/lab10_path_multiple_destinations.conf index 9a0c585e3..56cf5267d 100644 --- a/etc/labs/lab10_path_multiple_destinations.conf +++ b/etc/labs/lab10_path_multiple_destinations.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "lab10_nodes.conf" paths = ( diff --git a/etc/labs/lab10_path_uni.conf b/etc/labs/lab10_path_uni.conf index db2b28756..e40b4c139 100644 --- a/etc/labs/lab10_path_uni.conf +++ b/etc/labs/lab10_path_uni.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "lab10_nodes.conf" paths = ( diff --git a/etc/labs/lab11.conf b/etc/labs/lab11.conf index 11a02442a..3bf31a450 100644 --- a/etc/labs/lab11.conf +++ b/etc/labs/lab11.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { rtds_gtnet1 = { type = "socket" diff --git a/etc/labs/lab12.conf b/etc/labs/lab12.conf index de274541c..c4cee9a55 100644 --- a/etc/labs/lab12.conf +++ b/etc/labs/lab12.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node1 = { type = "socket", diff --git a/etc/labs/lab13.conf b/etc/labs/lab13.conf index d66045ce6..a1cd8876d 100644 --- a/etc/labs/lab13.conf +++ b/etc/labs/lab13.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + affinity = 0x8, nodes = { diff --git a/etc/labs/lab17.conf b/etc/labs/lab17.conf index 6a72fb2ac..d6d5d7045 100644 --- a/etc/labs/lab17.conf +++ b/etc/labs/lab17.conf @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 nodes = { rtds_ss1 = { diff --git a/etc/labs/lab18.conf b/etc/labs/lab18.conf new file mode 100644 index 000000000..e3e84cf90 --- /dev/null +++ b/etc/labs/lab18.conf @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +# docker run -v C:\Git\villas\node:/node -ti registry.git.rwth-aachen.de/acs/public/villas/node:master node /node/etc/labs/lab18.conf + +nodes = { + webrtc = { + type = "webrtc" + session = "KUCHEN" + server = "https://villas.k8s.eonerc.rwth-aachen.de/ws/signaling" + wait_seconds = 120 + in = { + hooks = ("stats") + } + } + + signal = { + type = "signal.v2" + rate = 0.2 + in = { + signals = { + signal = "mixed" + count = 5 + } + } + } +} + +paths = ( + { + in = "webrtc" + }, + { + in = "signal" + out = "webrtc" + } +) diff --git a/etc/labs/lab3.conf b/etc/labs/lab3.conf index a6fd04e3b..490ad8564 100644 --- a/etc/labs/lab3.conf +++ b/etc/labs/lab3.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node1 = { type = "socket", diff --git a/etc/labs/lab4.conf b/etc/labs/lab4.conf index b92cdb600..0dd83a32d 100644 --- a/etc/labs/lab4.conf +++ b/etc/labs/lab4.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node1 = { type = "socket", diff --git a/etc/labs/lab5.conf b/etc/labs/lab5.conf index 0c0d392db..3085dbe74 100644 --- a/etc/labs/lab5.conf +++ b/etc/labs/lab5.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { rtds_gtnet1 = { type = "socket", diff --git a/etc/labs/lab7.conf b/etc/labs/lab7.conf index 8cee37886..5217a31bb 100644 --- a/etc/labs/lab7.conf +++ b/etc/labs/lab7.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { file_node1 = { type = "file", diff --git a/etc/labs/lab8.conf b/etc/labs/lab8.conf index 7ed74da87..a4f12ab4e 100644 --- a/etc/labs/lab8.conf +++ b/etc/labs/lab8.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node1 = { type = "socket" diff --git a/etc/labs/lab9_netem.conf b/etc/labs/lab9_netem.conf index 54f69dd28..849a467bb 100644 --- a/etc/labs/lab9_netem.conf +++ b/etc/labs/lab9_netem.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { udp_node1 = { type = "socket", diff --git a/etc/loopback.conf b/etc/loopback.conf index 87f3b2704..11b1b5eb6 100644 --- a/etc/loopback.conf +++ b/etc/loopback.conf @@ -25,9 +25,9 @@ * A detailed description of the format can be found here: * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ nodes = { diff --git a/etc/python/example.py b/etc/python/example.py index bb725cbe4..0132ad884 100644 --- a/etc/python/example.py +++ b/etc/python/example.py @@ -8,9 +8,9 @@ villas node <(python3 etc/python/example.py) - @author Steffen Vogel - @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - @license Apache 2.0 + Author: Steffen Vogel + SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + SPDX-License-Identifier: Apache-2.0 ''' import json diff --git a/etc/shmem_mqtt.conf b/etc/shmem_mqtt.conf index 02060fc83..f73c928cb 100644 --- a/etc/shmem_mqtt.conf +++ b/etc/shmem_mqtt.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { sig = { type = "signal" diff --git a/etc/syslab-zmq.conf b/etc/syslab-zmq.conf index dc158bcad..fa22731c6 100644 --- a/etc/syslab-zmq.conf +++ b/etc/syslab-zmq.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { b2b = { type = "zeromq" diff --git a/etc/test.conf b/etc/test.conf index 1e174dc6e..3adca8344 100644 --- a/etc/test.conf +++ b/etc/test.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + nodes = { signal = { type = "signal" diff --git a/etc/tricks/nodes/node_sig1.conf b/etc/tricks/nodes/node_sig1.conf index f70d46872..a252fdf13 100644 --- a/etc/tricks/nodes/node_sig1.conf +++ b/etc/tricks/nodes/node_sig1.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + sig1 = { type = "signal" signal = "sine" diff --git a/etc/tricks/nodes/node_sig2.conf b/etc/tricks/nodes/node_sig2.conf index 03d155036..51880a1c1 100644 --- a/etc/tricks/nodes/node_sig2.conf +++ b/etc/tricks/nodes/node_sig2.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + sig2 = { type = "signal" signal = "sine" diff --git a/etc/tricks/tricks.conf b/etc/tricks/tricks.conf index 39a3ca4d5..b56dfe492 100644 --- a/etc/tricks/tricks.conf +++ b/etc/tricks/tricks.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + logging = { level = "${LEVEL}" } diff --git a/etc/websocket-client.conf b/etc/websocket-client.conf index 27dc4386f..4bb7cce9b 100644 --- a/etc/websocket-client.conf +++ b/etc/websocket-client.conf @@ -4,9 +4,9 @@ * A detailed description of the format can be found here: * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ nodes = { diff --git a/etc/websocket-demo.conf b/etc/websocket-demo.conf index ecc8372b0..114f954cd 100644 --- a/etc/websocket-demo.conf +++ b/etc/websocket-demo.conf @@ -4,9 +4,9 @@ * A detailed description of the format can be found here: * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ nodes = { @@ -64,7 +64,7 @@ nodes = { } } -############ List of paths ############ +## List of paths paths = ( { diff --git a/fpga b/fpga index 1cac3fafd..14b425fc9 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 1cac3fafde6ef3098a145f9d5d936a2dc6b7d7c0 +Subproject commit 14b425fc9893ef63527d6230c1ec87ab10366850 diff --git a/include/villas/api.hpp b/include/villas/api.hpp index fc8da99de..59622799f 100644 --- a/include/villas/api.hpp +++ b/include/villas/api.hpp @@ -1,10 +1,9 @@ -/** REST-API-releated functions. +/* REST-API-releated functions. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -28,7 +27,7 @@ namespace api { const int version = 2; -/* Forward declarations */ +// Forward declarations class Session; class Response; class Request; @@ -75,7 +74,7 @@ public: } // namespace api -/* Forward declarations */ +// Forward declarations class SuperNode; class Api { @@ -86,7 +85,7 @@ protected: enum State state; std::thread thread; - std::atomic running; /**< Atomic flag for signalizing thread termination. */ + std::atomic running; // Atomic flag for signalizing thread termination. SuperNode *super_node; @@ -94,7 +93,7 @@ protected: void worker(); public: - /** Initialize the API. + /* Initialize the API. * * Save references to list of paths / nodes for command execution. */ @@ -109,8 +108,8 @@ public: return super_node; } - std::list sessions; /**< List of currently active connections */ - villas::QueueSignalled pending; /**< A queue of api_sessions which have pending requests. */ + std::list sessions; // List of currently active connections + villas::QueueSignalled pending; // A queue of api_sessions which have pending requests. }; } // namespace node diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index 5f3b3b29a..45fcb0d5e 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -1,10 +1,9 @@ -/** API Request. +/* API Request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,7 +23,7 @@ namespace villas { namespace node { namespace api { -/* Forward declarations */ +// Forward declarations class Session; class Response; class RequestFactory; @@ -148,8 +147,8 @@ public: regex(re) { } - virtual Request * - make(Session *s) + virtual + Request * make(Session *s) { auto *r = new T(s); @@ -159,21 +158,21 @@ public: } // Get plugin name - virtual std::string - getName() const + virtual + std::string getName() const { return name; } // Get plugin description - virtual std::string - getDescription() const + virtual + std::string getDescription() const { return desc; } - virtual bool - match(const std::string &uri, std::smatch &match) const + virtual + bool match(const std::string &uri, std::smatch &match) const { return std::regex_match(uri, match, regex); } diff --git a/include/villas/api/requests/node.hpp b/include/villas/api/requests/node.hpp index e8672f770..dda48a628 100644 --- a/include/villas/api/requests/node.hpp +++ b/include/villas/api/requests/node.hpp @@ -1,10 +1,9 @@ -/** API Request for nodes. +/* API Request for nodes. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -13,7 +12,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; namespace api { @@ -26,8 +25,8 @@ protected: public: using Request::Request; - virtual void - prepare(); + virtual + void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/path.hpp b/include/villas/api/requests/path.hpp index 9868cd0ce..260aaf385 100644 --- a/include/villas/api/requests/path.hpp +++ b/include/villas/api/requests/path.hpp @@ -1,17 +1,16 @@ -/** API Request for paths. +/* API Request for paths. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Path; namespace api { @@ -24,8 +23,8 @@ protected: public: using Request::Request; - virtual void - prepare(); + virtual + void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/universal.hpp b/include/villas/api/requests/universal.hpp index cc12d2ba6..c5772c6a6 100644 --- a/include/villas/api/requests/universal.hpp +++ b/include/villas/api/requests/universal.hpp @@ -1,10 +1,9 @@ -/** Universal Data-exchange API request. +/* Universal Data-exchange API request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,7 +13,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; namespace api { @@ -27,8 +26,8 @@ protected: public: using NodeRequest::NodeRequest; - virtual void - prepare(); + virtual + void prepare(); }; } // namespace api diff --git a/include/villas/api/response.hpp b/include/villas/api/response.hpp index 79afd3be9..ebf1286ef 100644 --- a/include/villas/api/response.hpp +++ b/include/villas/api/response.hpp @@ -1,10 +1,9 @@ -/** API response. +/* API response. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,7 +21,7 @@ namespace villas { namespace node { namespace api { -/* Forward declarations */ +// Forward declarations class Session; class Request; @@ -37,8 +36,8 @@ public: ~Response() { } - virtual void - encodeBody() + virtual + void encodeBody() { } int @@ -74,10 +73,11 @@ public: response(r) { } - virtual ~JsonResponse(); + virtual + ~JsonResponse(); - virtual void - encodeBody(); + virtual + void encodeBody(); }; class ErrorResponse : public JsonResponse { diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index b62ec896c..901d727a1 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -1,10 +1,9 @@ -/** API session. +/* API session. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,25 +16,25 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class SuperNode; class Api; class Web; namespace api { -/* Forward declarations */ +// Forward declarations class Request; class Response; class StatusRequest; class RequestFactory; -/** A connection via HTTP REST or WebSockets to issue API requests. */ +// A connection via HTTP REST or WebSockets to issue API requests. class Session { public: - friend Request; /**< Requires access to wsi for getting URL args and headers */ - friend StatusRequest; /**< Requires access to wsi for context status */ + friend Request; // Requires access to wsi for getting URL args and headers + friend StatusRequest; // Requires access to wsi for context status friend RequestFactory; enum State { @@ -93,13 +92,13 @@ public: void execute(); void shutdown(); - static int - protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static + int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); Method getRequestMethod() const; - static std::string - methodToString(Method meth); + static + std::string methodToString(Method meth); }; } // namespace api diff --git a/include/villas/api/universal.hpp b/include/villas/api/universal.hpp index fb13678ed..d27e5509d 100644 --- a/include/villas/api/universal.hpp +++ b/include/villas/api/universal.hpp @@ -1,11 +1,10 @@ -/** Universal Data-exchange API request. +/* Universal Data-exchange API request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/capabilities.hpp b/include/villas/capabilities.hpp index 195f3c5f3..f4ec72099 100644 --- a/include/villas/capabilities.hpp +++ b/include/villas/capabilities.hpp @@ -1,9 +1,9 @@ -/** Capabilities +/* Capabilities * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,4 +15,4 @@ namespace node { json_t * getCapabilities(); } // namespace node -} /* namepace vilals */ +} // namepace vilals diff --git a/include/villas/config_class.hpp b/include/villas/config_class.hpp index f49563655..68dbf6445 100644 --- a/include/villas/config_class.hpp +++ b/include/villas/config_class.hpp @@ -1,10 +1,9 @@ -/** Configuration file parsing. +/* Configuration file parsing. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -34,44 +33,46 @@ protected: std::list includeDirectories; - /** Check if file exists on local system. */ - static bool isLocalFile(const std::string &uri) + // Check if file exists on local system. + static + bool isLocalFile(const std::string &uri) { return access(uri.c_str(), F_OK) != -1; } - /** Decode configuration file. */ + // Decode configuration file. json_t * decode(FILE *f); #ifdef WITH_CONFIG - /** Convert libconfig .conf file to libjansson .json file. */ + // Convert libconfig .conf file to libjansson .json file. json_t * libconfigDecode(FILE *f); - static const char ** includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error); + static + const char ** includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error); const char ** includeFunc(config_t *cfg, const char *include_dir, const char *path, const char **error); -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG - /** Load configuration from standard input (stdim). */ + // Load configuration from standard input (stdim). FILE * loadFromStdio(); - /** Load configuration from local file. */ + // Load configuration from local file. FILE * loadFromLocalFile(const std::string &u); std::list resolveIncludes(const std::string &name); void resolveEnvVars(std::string &text); - /** Resolve custom include directives. */ + // Resolve custom include directives. json_t * expandIncludes(json_t *in); - /** To shell-like subsitution of environment variables in strings. */ + // To shell-like subsitution of environment variables in strings. json_t * expandEnvVars(json_t *in); - /** Run a callback function for each string in the config */ + // Run a callback function for each string in the config json_t * walkStrings(json_t *in, str_walk_fcn_t cb); - /** Get the include dirs */ + // Get the include dirs std::list getIncludeDirectories(FILE *f) const; public: diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index ae66b2811..6a1ea189c 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -1,9 +1,9 @@ -/** Helpers for configuration parsers. +/* Helpers for configuration parsers. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -21,13 +21,13 @@ namespace node { #ifdef WITH_CONFIG -/** Convert a libconfig object to a jansson object */ +// Convert a libconfig object to a jansson object json_t * config_to_json(struct config_setting_t *cfg); -/** Convert a jansson object into a libconfig object. */ +// Convert a jansson object into a libconfig object. int json_to_config(json_t *json, struct config_setting_t *parent); -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG int json_object_extend_str(json_t *orig, const char *str); @@ -35,7 +35,7 @@ void json_object_extend_key_value(json_t *obj, const char *key, const char *valu void json_object_extend_key_value_token(json_t *obj, const char *key, const char *value); -/** Merge two JSON objects recursively. */ +// Merge two JSON objects recursively. int json_object_extend(json_t *orig, json_t *merge); json_t * json_load_cli(int argc, const char *argv[]); diff --git a/include/villas/dumper.hpp b/include/villas/dumper.hpp index 762814230..9eb34fea0 100644 --- a/include/villas/dumper.hpp +++ b/include/villas/dumper.hpp @@ -1,10 +1,9 @@ -/** Dump fields and values in a socket to plot them with villasDump.py. +/* Dump fields and values in a socket to plot them with villasDump.py. * - * @file - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 8cafd277b..4d570a8e7 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -1,10 +1,9 @@ -/** Read / write sample data in different formats. +/* Read / write sample data in different formats. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,21 +17,20 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class FormatFactory; class Format { friend FormatFactory; - public: using Ptr = std::unique_ptr; protected: - int flags; /**< A set of flags which is automatically used. */ - int real_precision; /**< Number of digits used for floatint point numbers */ + int flags; // A set of flags which is automatically used. + int real_precision; // Number of digits used for floatint point numbers Logger logger; @@ -41,7 +39,7 @@ protected: size_t buflen; } in, out; - SignalList::Ptr signals; /**< Signal meta data for parsed samples by Format::scan() */ + SignalList::Ptr signals; // Signal meta data for parsed samples by Format::scan() public: Format(int fl); @@ -75,7 +73,7 @@ public: virtual int scan(FILE *f, struct Sample * const smps[], unsigned cnt); - /** Print \p cnt samples from \p smps into buffer \p buf of length \p len. + /* Print \p cnt samples from \p smps into buffer \p buf of length \p len. * * @param buf[out] The buffer which should be filled with serialized data. * @param len[in] The length of the buffer \p buf. @@ -89,7 +87,7 @@ public: virtual int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) = 0; - /** Parse samples from the buffer \p buf with a length of \p len bytes. + /* Parse samples from the buffer \p buf with a length of \p len bytes. * * @param buf[in] The buffer of data which should be parsed / de-serialized. * @param len[in] The length of the buffer \p buf. @@ -103,7 +101,7 @@ public: virtual int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) = 0; - /* Wrappers for sending a (un)parsing single samples */ + // Wrappers for sending a (un)parsing single samples int print(FILE *f, const struct Sample *smp) { @@ -171,7 +169,8 @@ class FormatPlugin : public FormatFactory { public: using FormatFactory::FormatFactory; - virtual Format * make() + virtual + Format * make() { auto *f = new T(flags); diff --git a/include/villas/formats/column.hpp b/include/villas/formats/column.hpp index 5449a5d16..528b68091 100644 --- a/include/villas/formats/column.hpp +++ b/include/villas/formats/column.hpp @@ -1,10 +1,9 @@ -/** Comma-separated values. +/* Comma-separated values. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,16 +14,18 @@ namespace villas { namespace node { -/* Forward declarations. */ +// Forward declarations struct Sample; class ColumnLineFormat : public LineFormat { protected: - virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp); - virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp); + virtual + size_t sprintLine(char *buf, size_t len, const struct Sample *smp); + virtual + size_t sscanLine(const char *buf, size_t len, struct Sample *smp); - char separator; /**< Column separator */ + char separator; // Column separator public: ColumnLineFormat(int fl, char delim, char sep) : diff --git a/include/villas/formats/iotagent_ul.hpp b/include/villas/formats/iotagent_ul.hpp index 547ff40f3..d7ec53fc1 100644 --- a/include/villas/formats/iotagent_ul.hpp +++ b/include/villas/formats/iotagent_ul.hpp @@ -1,9 +1,9 @@ -/** UltraLight format for FISMEP project. +/* UltraLight format for FISMEP project. * - * @author Iris Koester - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Iris Koester + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -12,7 +12,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class IotAgentUltraLightFormat : public Format { diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 40cbb9e56..234ffb47e 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -1,9 +1,9 @@ -/** JSON serializtion sample data. +/* JSON serializtion sample data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,13 +14,14 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class JsonFormat : public Format { protected: - static enum SignalType detect(const json_t *val); + static + enum SignalType detect(const json_t *val); json_t * packTimestamps(const struct Sample *smp); int unpackTimestamps(json_t *json_ts, struct Sample *smp); diff --git a/include/villas/formats/json_edgeflex.hpp b/include/villas/formats/json_edgeflex.hpp index 8a22c714d..05c897ecb 100644 --- a/include/villas/formats/json_edgeflex.hpp +++ b/include/villas/formats/json_edgeflex.hpp @@ -1,9 +1,9 @@ -/** JSON serializtion for edgeFlex project. +/* JSON serializtion for edgeFlex project. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/formats/json_kafka.hpp b/include/villas/formats/json_kafka.hpp index 236388465..492b4da6b 100644 --- a/include/villas/formats/json_kafka.hpp +++ b/include/villas/formats/json_kafka.hpp @@ -1,9 +1,9 @@ -/** JSON serializtion for Kafka schema/payloads. +/* JSON serializtion for Kafka schema/payloads. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/formats/json_reserve.hpp b/include/villas/formats/json_reserve.hpp index 7800a0419..f90ee2feb 100644 --- a/include/villas/formats/json_reserve.hpp +++ b/include/villas/formats/json_reserve.hpp @@ -1,9 +1,9 @@ -/** JSON serializtion for RESERVE project. +/* JSON serializtion for RESERVE project. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index 54a4df2f1..9f8004752 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -1,10 +1,9 @@ -/** Line-based formats +/* Line-based formats * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -16,14 +15,16 @@ namespace node { class LineFormat : public Format { protected: - virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp) = 0; - virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; + virtual + size_t sprintLine(char *buf, size_t len, const struct Sample *smp) = 0; + virtual + size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; - char delimiter; /**< Newline delimiter. */ - char comment; /**< Prefix for comment lines. */ + char delimiter; // Newline delimiter. + char comment; // Prefix for comment lines. - bool skip_first_line; /**< While reading, the first line is skipped (header) */ - bool print_header; /**< Before any data, a header line is printed */ + bool skip_first_line; // While reading, the first line is skipped (header) + bool print_header; // Before any data, a header line is printed bool first_line_skipped; bool header_printed; @@ -39,7 +40,7 @@ public: header_printed(false) { } - /** Print a header. */ + // Print a header virtual void header(FILE *f, const SignalList::Ptr sigs) { diff --git a/include/villas/formats/msg.hpp b/include/villas/formats/msg.hpp index dc9c6e795..0dac505aa 100644 --- a/include/villas/formats/msg.hpp +++ b/include/villas/formats/msg.hpp @@ -1,9 +1,9 @@ -/** Message related functions. +/* Message related functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -11,28 +11,28 @@ namespace villas { -/* Forward declarataions */ +// Forward declarataions struct List; namespace node { -/* Forward declaration */ +// Forward declarations struct Message; struct Sample; -/** Convert msg from network to host byteorder */ +// Convert msg from network to host byteorder void msg_ntoh(struct Message *m); -/** Convert msg from host to network byteorder */ +// Convert msg from host to network byteorder void msg_hton(struct Message *m); -/** Convert msg header from network to host byteorder */ +// Convert msg header from network to host byteorder void msg_hdr_hton(struct Message *m); -/** Convert msg header from host to network byteorder */ +// Convert msg header from host to network byteorder void msg_hdr_ntoh(struct Message *m); -/** Check the consistency of a message. +/* Check the consistency of a message. * * The functions checks the header fields of a message. * @@ -42,10 +42,10 @@ void msg_hdr_ntoh(struct Message *m); */ int msg_verify(const struct Message *m); -/** Copy fields from \p msg into \p smp. */ +// Copy fields from \p msg into \p smp. int msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalList::Ptr sigs, uint8_t *source_index); -/** Copy fields form \p smp into \p msg. */ +// Copy fields form \p smp into \p msg. int msg_from_sample(struct Message *msg, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index); } // namespace node diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 64ed1e4b1..7f1982495 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -1,33 +1,32 @@ -/** Message format +/* Message format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include -/** The current version number for the message format */ +// The current version number for the message format #define MSG_VERSION 2 -/** @todo Implement more message types */ -#define MSG_TYPE_DATA 0 /**< Message contains float / integer values */ -#define MSG_TYPE_START 1 /**< Message marks the beginning of a new simulation case */ -#define MSG_TYPE_STOP 2 /**< Message marks the end of a simulation case */ +// @todo Implement more message types +#define MSG_TYPE_DATA 0 // Message contains float / integer values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case -/** The total size in bytes of a message */ +// The total size in bytes of a message #define MSG_LEN(values) (sizeof(struct Message) + MSG_DATA_LEN(values)) -/** The length of \p values values in bytes. */ +// The length of \p values values in bytes. #define MSG_DATA_LEN(values) (sizeof(float) * (values)) -/** The offset to the first data value in a message. */ +// The offset to the first data value in a message. #define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct Message, data)) -/** The timestamp of a message in struct timespec format */ +// The timestamp of a message in struct timespec format #define MSG_TS(msg, i) \ i.tv_sec = (msg)->ts.sec; \ i.tv_nsec = (msg)->ts.nsec; @@ -35,38 +34,38 @@ namespace villas { namespace node { -/** This message format is used by all clients +/* This message format is used by all clients * * @diafile msg_format.dia - **/ + */ struct Message { #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 reserved1 : 2; /**< Reserved bits */ + unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - 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) */ + 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 source_index; /**< 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. */ + uint8_t source_index; // 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. - /** A timestamp per message. */ + // A timestamp per message. struct { - uint32_t sec; /**< Seconds since 1970-01-01 00:00:00 */ - uint32_t nsec; /**< Nanoseconds of the current second. */ + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second } ts; - /** The message payload. */ + // The message payload. union { - float f; /**< Floating point values. */ - uint32_t i; /**< Integer values. */ + float f; // Floating point values + uint32_t i; // Integer values } data[]; } __attribute__((packed)); diff --git a/include/villas/formats/opal_asyncip.hpp b/include/villas/formats/opal_asyncip.hpp index d74593923..20cc5aa83 100644 --- a/include/villas/formats/opal_asyncip.hpp +++ b/include/villas/formats/opal_asyncip.hpp @@ -1,10 +1,9 @@ -/** A custom format for OPAL-RTs AsyncIP example +/* A custom format for OPAL-RTs AsyncIP example * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations. */ +// Forward declarations struct Sample; class OpalAsyncIPFormat : public BinaryFormat { @@ -47,7 +46,6 @@ public: void parse(json_t *json); }; - class OpalAsyncIPFormatPlugin : public FormatFactory { public: diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index cac4f68c9..be5fa5c06 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -1,10 +1,9 @@ -/** Protobuf IO format +/* Protobuf IO format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -12,13 +11,13 @@ #include -/* Generated message descriptors by protoc */ +// Generated message descriptors by protoc #include namespace villas { namespace node { -/* Forward declarations. */ +// Forward declarations struct Sample; class ProtobufFormat : public BinaryFormat { diff --git a/include/villas/formats/raw.hpp b/include/villas/formats/raw.hpp index c4e0201c0..49ae10b36 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -1,10 +1,9 @@ -/** RAW IO format +/* RAW IO format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -13,7 +12,7 @@ #include -/* float128 is currently not yet supported as htole128() functions a missing */ +// float128 is currently not yet supported as htole128() functions a missing #if 0 && defined(__GNUC__) && defined(__linux__) #define HAS_128BIT #endif @@ -21,7 +20,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class RawFormat : public BinaryFormat { diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 4cc1e902a..66db86098 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -1,10 +1,9 @@ -/** The VILLASframework sample format +/* The VILLASframework sample format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/formats/villas_binary.hpp b/include/villas/formats/villas_binary.hpp index 520e1a84b..916bba8d8 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -1,10 +1,9 @@ -/** Message related functions +/* Message related functions * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations. */ +// Forward declarations struct Sample; class VillasBinaryFormat : public BinaryFormat { @@ -42,7 +41,6 @@ public: void parse(json_t *json); }; - template class VillasBinaryFormatPlugin : public FormatFactory { diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index bf99a6475..257b14a8f 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -1,10 +1,9 @@ -/** The VILLASframework sample format +/* The VILLASframework sample format * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 3624b3d20..94143f9eb 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -1,14 +1,13 @@ -/** Hook functions +/* 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 - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,7 +21,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class Path; struct Sample; @@ -36,10 +35,10 @@ public: using Ptr = std::shared_ptr; 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. */ + 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 { @@ -57,15 +56,15 @@ protected: enum State state; int flags; - unsigned priority; /**< A priority to change the order of execution within one type of hook. */ - bool enabled; /**< Is this hook active? */ + unsigned priority; // A priority to change the order of execution within one type of hook. + bool enabled; // Is this hook active? Path *path; Node *node; SignalList::Ptr signals; - json_t *config; /**< A JSON object containing the configuration of the hook. */ + json_t *config; // A JSON object containing the configuration of the hook. public: Hook(Path *p, Node *n, int fl, int prio, bool en = true); @@ -84,7 +83,7 @@ public: return logger; } - /** Called whenever a hook is started; before threads are created. */ + // Called whenever a hook is started; before threads are created. virtual void start() { @@ -93,7 +92,7 @@ public: state = State::STARTED; } - /** Called whenever a hook is stopped; after threads are destoyed. */ + // Called whenever a hook is stopped; after threads are destoyed. virtual void stop() { @@ -118,21 +117,21 @@ public: state = State::PREPARED; } - /** Called periodically. Period is set by global 'stats' option in the configuration file. */ + // Called periodically. Period is set by global 'stats' option in the configuration file. virtual void periodic() { assert(state == State::STARTED); } - /** Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. */ + // 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); } - /** Called whenever a sample is processed. */ + // Called whenever a sample is processed. virtual Reason process(struct Sample *smp) { @@ -215,9 +214,11 @@ public: using Ptr = std::shared_ptr; using Hook::Hook; - virtual void setRate(double rate, double maxRate = -1) = 0; + virtual + void setRate(double rate, double maxRate = -1) = 0; - virtual void parse() + virtual + void parse() { assert(state == State::INITIALIZED); @@ -246,7 +247,8 @@ protected: public: using plugin::Plugin::Plugin; - virtual Hook::Ptr make(Path *p, Node *n) = 0; + virtual + Hook::Ptr make(Path *p, Node *n) = 0; virtual int getFlags() const = 0; @@ -273,7 +275,8 @@ class HookPlugin : public HookFactory { public: using HookFactory::HookFactory; - virtual Hook::Ptr make(Path *p, Node *n) + virtual + Hook::Ptr make(Path *p, Node *n) { auto h = std::make_shared(p, n, getFlags(), getPriority()); diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index 70d23eba7..f9964158b 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -1,13 +1,11 @@ -/** Hook list functions +/* Hook list functions * * This file includes some examples. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,7 +16,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class Path; struct Sample; @@ -29,7 +27,7 @@ public: HookList() { } - /** Parses an object of hooks + /* Parses an object of hooks * * Example: * @@ -58,7 +56,7 @@ public: SignalList::Ptr getSignals() const; - /** Get the maximum number of signals which is used by any of the hooks in the list. */ + // Get the maximum number of signals which is used by any of the hooks in the list. unsigned getSignalsMaxCount() const; json_t * toJson() const; diff --git a/include/villas/hooks/decimate.hpp b/include/villas/hooks/decimate.hpp index d5f1c8a17..01a5388f2 100644 --- a/include/villas/hooks/decimate.hpp +++ b/include/villas/hooks/decimate.hpp @@ -1,9 +1,9 @@ -/** Decimate hook. +/* Decimate hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -51,4 +51,3 @@ public: } // namespace node } // namespace villas - diff --git a/include/villas/hooks/limit_rate.hpp b/include/villas/hooks/limit_rate.hpp index 92b08ad99..2ee99b3a3 100644 --- a/include/villas/hooks/limit_rate.hpp +++ b/include/villas/hooks/limit_rate.hpp @@ -1,9 +1,9 @@ -/** Rate-limiting hook. +/* Rate-limiting hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,11 +15,12 @@ namespace node { class LimitRateHook : public LimitHook { protected: + // The timestamp which should be used for limiting. enum { LIMIT_RATE_LOCAL, LIMIT_RATE_RECEIVED, LIMIT_RATE_ORIGIN - } mode; /**< The timestamp which should be used for limiting. */ + } mode; double deadtime; timespec last; @@ -32,14 +33,17 @@ public: last({0, 0}) { } - virtual void setRate(double rate, double maxRate = -1) + virtual + void setRate(double rate, double maxRate = -1) { deadtime = 1.0 / rate; } - virtual void parse(json_t *json); + virtual + void parse(json_t *json); - virtual Hook::Reason process(struct Sample *smp); + virtual + Hook::Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/lua.hpp b/include/villas/hooks/lua.hpp index 49de8b140..85b3365ee 100644 --- a/include/villas/hooks/lua.hpp +++ b/include/villas/hooks/lua.hpp @@ -1,9 +1,9 @@ -/** Lua expressions hook. +/* Lua expressions hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,7 +19,7 @@ extern "C" { namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class LuaHook; enum SignalType; @@ -48,14 +48,15 @@ class LuaHook : public Hook { friend LuaSignalExpression; private: - static const int SELF_REFERENCE = 55; + static + const int SELF_REFERENCE = 55; protected: std::string script; std::vector expressions; - SignalList::Ptr signalsProcessed; /**> Signals as emited by Lua process() function */ - SignalList::Ptr signalsExpressions; /**> Signals as emited by Lua expressions */ + SignalList::Ptr signalsProcessed; // Signals as emited by Lua process() function + SignalList::Ptr signalsExpressions; // Signals as emited by Lua expressions lua_State *L; std::mutex mutex; @@ -64,7 +65,7 @@ protected: bool hasExpressions; bool needsLocking; - /* Function indizes */ + // Function indices struct { int start; int stop; @@ -80,7 +81,7 @@ protected: void lookupFunctions(); void setupEnvironment(); - /* Lua functions */ + // Lua functions int luaInfo(lua_State *L); int luaWarn(lua_State *L); @@ -93,8 +94,8 @@ protected: // This template wraps a member function into a C-style "free" function compatible with lua. template - static int - dispatch(lua_State * L) { + static + int dispatch(lua_State * L) { lua_rawgeti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); void *vptr = lua_touserdata(L, -1); lua_pop(L, 1); @@ -106,28 +107,35 @@ protected: public: LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual ~LuaHook(); + virtual + ~LuaHook(); - virtual void parse(json_t *json); + virtual + void parse(json_t *json); - virtual void prepare(); + virtual + void prepare(); - /** Periodically called by the main thread. */ - virtual void periodic(); + // Periodically called by the main thread. + virtual + void periodic(); - /** Called whenever a hook is started; before threads are created. */ - virtual void start(); + // Called whenever a hook is started; before threads are created. + virtual + void start(); - /** Called whenever a hook is stopped; after threads are destoyed. */ - virtual void stop(); + // Called whenever a hook is stopped; after threads are destoyed. + virtual + void stop(); - /** Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. */ - virtual void restart(); + // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. + virtual + void restart(); - /** Called whenever a sample is processed. */ - virtual Reason process(struct Sample *smp); + // Called whenever a sample is processed. + virtual + Reason process(struct Sample *smp); }; - } // namespace node } // namespace villas diff --git a/include/villas/hooks/pmu.hpp b/include/villas/hooks/pmu.hpp index 088f52381..e530c2632 100644 --- a/include/villas/hooks/pmu.hpp +++ b/include/villas/hooks/pmu.hpp @@ -1,9 +1,9 @@ -/** PMU hook. +/* PMU hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -14,7 +14,6 @@ namespace node { class PmuHook : public MultiSignalHook { - protected: enum class Status { INVALID, @@ -25,7 +24,7 @@ protected: double frequency; double amplitude; double phase; - double rocof; /* Rate of change of frequency. */ + double rocof; // Rate of change of frequency. Status valid; }; @@ -62,7 +61,7 @@ protected: timespec nextRun; bool init; unsigned initSampleCount; - /* Correction factors. */ + // Correction factors. double phaseOffset; double amplitudeOffset; double frequencyOffset; diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index 0fdcb1bf4..3543d6b2d 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -1,13 +1,12 @@ -/** Interface related functions +/* Interface related functions * * These functions are used to manage a network interface. * Most of them make use of Linux-specific APIs. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,10 +18,10 @@ #include #ifndef SO_MARK - #define SO_MARK 36 /**< Workaround: add missing constant for OPAL-RT Redhawk target */ + #define SO_MARK 36 // Workaround: add missing constant for OPAL-RT Redhawk target #endif -/* Forward declarations */ +// Forward declarations struct nl_addr; struct rtnl_link; struct rtnl_qdisc; @@ -30,7 +29,7 @@ struct rtnl_qdisc; namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class SuperNode; @@ -38,27 +37,27 @@ class SuperNode; namespace kernel { -/** Interface data structure */ +// Interface data structure class Interface { public: - struct rtnl_link *nl_link; /**< libnl3: Handle of interface. */ - struct rtnl_qdisc *tc_qdisc; /**< libnl3: Root priority queuing discipline (qdisc). */ + struct rtnl_link *nl_link; // libnl3: Handle of interface. + struct rtnl_qdisc *tc_qdisc; // libnl3: Root priority queuing discipline (qdisc). protected: - int affinity; /**< IRQ / Core Affinity of this interface. */ + int affinity; // IRQ / Core Affinity of this interface. - std::list irqs; /**< List of IRQs of the NIC. */ - std::list nodes; /**< List of nodes which use this interface. */ + std::list irqs; // List of IRQs of the NIC. + std::list nodes; // List of nodes which use this interface. Logger logger; public: - /** Add a new interface to the global list and lookup name, irqs... */ + // Add a new interface to the global list and lookup name, irqs... Interface(struct rtnl_link *link, int affinity = 0); ~Interface(); - /** Start interface. + /* Start interface. * * This setups traffic controls queue discs, network emulation and * maps interface IRQs according to affinity. @@ -69,7 +68,7 @@ public: */ int start(); - /** Stop interface + /* Stop interface * * This resets traffic qdiscs ant network emulation * and maps interface IRQs to all CPUs. @@ -80,14 +79,14 @@ public: */ int stop(); - /** Find existing or create new interface instance on which packets for a certain destination + /* Find existing or create new interface instance on which packets for a certain destination * will leave the system. */ static Interface * getEgress(struct sockaddr *sa, node::SuperNode *sn); - /** Get all IRQs for this interface. + /* Get all IRQs for this interface. * * Only MSI IRQs are determined by looking at: * /sys/class/net/{ifname}/device/msi_irqs/ @@ -98,7 +97,7 @@ public: */ int getIRQs(); - /** Change the SMP affinity of NIC interrupts. + /* Change the SMP affinity of NIC interrupts. * * @param i A pointer to the interface structure * @param affinity A mask specifying which cores should handle this interrupt. diff --git a/include/villas/kernel/nl-private.h b/include/villas/kernel/nl-private.h index ded3b0a97..c708c4ba9 100644 --- a/include/villas/kernel/nl-private.h +++ b/include/villas/kernel/nl-private.h @@ -1,3 +1,13 @@ +/* Netlink Types (Private) + * + * Copied from: https://github.com/tgraf/libnl/blob/master/include/netlink-private/types.h + * + * SPDX-License-Identifier: LGPL-2.1-only + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-FileCopyrightText: 2003-2013 Thomas Graf + * SPDX-FileCopyrightText: 2013 Sassano Systems LLC + */ + #pragma once #ifdef __cplusplus diff --git a/include/villas/kernel/nl.hpp b/include/villas/kernel/nl.hpp index ca4fcbda6..2317a347b 100644 --- a/include/villas/kernel/nl.hpp +++ b/include/villas/kernel/nl.hpp @@ -1,10 +1,9 @@ -/** Netlink related functions. +/* Netlink related functions. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,14 +17,14 @@ namespace villas { namespace kernel { namespace nl { -/** Get index of outgoing interface for given destination address. +/* Get index of outgoing interface for given destination address. * * @retval >=0 Interface index of outgoing interface. * @retval <0 Error. Something went wrong. */ int get_egress(struct nl_addr *addr); -/** Lookup routing tables to get the interface on which packets for a certain destination +/* Lookup routing tables to get the interface on which packets for a certain destination * will leave the system. * * @param[in] sa The destination address for outgoing packets. @@ -35,10 +34,10 @@ int get_egress(struct nl_addr *addr); */ struct rtnl_link * get_egress_link(struct sockaddr *sa); -/** Get or create global netlink socket. */ +// Get or create global netlink socket. struct nl_sock * init(); -/** Close and free global netlink socket. */ +// Close and free global netlink socket. void shutdown(); } // namespace nl diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index 55adcab83..a7f820356 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -1,15 +1,14 @@ -/** Setup interface queuing desciplines for network emulation +/* Setup interface queuing desciplines for network emulation * * We use the firewall mark to apply individual netem qdiscs * per node. Every node uses an own BSD socket. * By using so SO_MARK socket option (see socket(7)) * we can classify traffic originating from a node seperately. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -23,14 +22,14 @@ namespace villas { namespace kernel { -/* Forward declarations */ +// Forward declarations class Interface; namespace tc { typedef uint32_t tc_hdl_t; -/** Remove all queuing disciplines and filters. +/* Remove all queuing disciplines and filters. * * @param i The interface * @retval 0 Success. Everything went well. @@ -38,7 +37,7 @@ typedef uint32_t tc_hdl_t; */ int reset(Interface *i); -/** Create a priority (prio) queueing discipline. +/* Create a priority (prio) queueing discipline. * * @param i[in] The interface * @param qd[in,out] The libnl3 object of the new prio qdisc. @@ -50,7 +49,7 @@ int reset(Interface *i); */ int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, int bands); -/** Add a new filter based on the netfilter mark. +/* Add a new filter based on the netfilter mark. * * @param i The interface to which this classifier is applied to. * @param cls[in,out] The libnl3 object of the new prio qdisc. @@ -58,7 +57,7 @@ int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, int ba * @param mark The netfilter firewall mark (sometime called 'fwmark') * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. -*/ + */ int mark(Interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark); } // namespace tc diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index dea2d776c..5fe4b9085 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -1,15 +1,14 @@ -/** Setup network emulation +/* Setup network emulation * * We use the firewall mark to apply individual netem qdiscs * per node. Every node uses an own BSD socket. * By using so SO_MARK socket option (see socket(7)) * we can classify traffic originating from a node seperately. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -23,14 +22,14 @@ namespace villas { namespace kernel { -/* Forward declarations */ +// Forward declarations class Interface; namespace tc { typedef uint32_t tc_hdl_t; -/** Parse network emulator (netem) settings. +/* Parse network emulator (netem) settings. * * @param json A jansson object containing the settings. * @param[out] ne A pointer to a libnl3 qdisc object where setting will be written to. @@ -39,14 +38,14 @@ typedef uint32_t tc_hdl_t; */ int netem_parse(struct rtnl_qdisc **ne, json_t *json); -/** Print network emulator (netem) setting into buffer. +/* Print network emulator (netem) setting into buffer. * * @param tc A pointer to the libnl3 qdisc object where settings will be read from. * @return A pointer to a string which must be freed() by the caller. */ char * netem_print(struct rtnl_qdisc *ne); -/** Add a new network emulator (netem) discipline. +/* Add a new network emulator (netem) discipline. * * @param i[in] The interface to which this qdisc will be added. * @param qd[in,out] The libnl3 object of the new prio qdisc. diff --git a/include/villas/log_opal_sink.hpp b/include/villas/log_opal_sink.hpp index 9cd390c79..e0e85eb79 100644 --- a/include/villas/log_opal_sink.hpp +++ b/include/villas/log_opal_sink.hpp @@ -1,10 +1,9 @@ -/** Log sink for OPAL-RTs OpalPrint(). +/* Log sink for OPAL-RTs OpalPrint(). * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -46,13 +45,12 @@ protected: void flush_() override { - /* nothing to do */ + // nothing to do } }; using OpalSink_mt = OpalSink; using OpalSink_st = OpalSink; - } // namespace node } // namespace villas diff --git a/include/villas/mapping.hpp b/include/villas/mapping.hpp index c760325e9..d347cb959 100644 --- a/include/villas/mapping.hpp +++ b/include/villas/mapping.hpp @@ -1,10 +1,9 @@ -/** Sample value remapping for path source muxing. +/* Sample value remapping for path source muxing. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -28,7 +27,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; struct Sample; class Signal; @@ -56,15 +55,15 @@ public: RECEIVED }; - Node *node; /**< The node to which this mapping refers. */ - enum Type type; /**< The mapping type. Selects one of the union fields below. */ + Node *node; // The node to which this mapping refers. + enum Type type; // The mapping type. Selects one of the union fields below. - /** The number of values which is covered by this mapping entry. + /* The number of values which is covered by this mapping entry. * * A value of 0 indicates that all remaining values starting from the offset of a sample should be mapped. */ int length; - unsigned offset; /**< Offset of this mapping entry within sample::data */ + unsigned offset; // Offset of this mapping entry within sample::data union { struct { @@ -89,7 +88,7 @@ public: } timestamp; }; - std::string nodeName; /**< Used for between parse and prepare only. */ + std::string nodeName; // Used for between parse and prepare only. MappingEntry(); diff --git a/include/villas/mapping_list.hpp b/include/villas/mapping_list.hpp index e6e480ddb..47218ef6e 100644 --- a/include/villas/mapping_list.hpp +++ b/include/villas/mapping_list.hpp @@ -1,12 +1,11 @@ #pragma once -/** Sample value remapping for path source muxing. +/* Sample value remapping for path source muxing. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/include/villas/memory/ib.h b/include/villas/memory/ib.h index 164b6640d..56e2a559c 100644 --- a/include/villas/memory/ib.h +++ b/include/villas/memory/ib.h @@ -1,10 +1,9 @@ -/** Memory allocators. +/* Memory allocators. * - * @file - * @author Dennis Potter - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Dennis Potter + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/node.h b/include/villas/node.h index 25936ca62..85572f3d4 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -1,10 +1,9 @@ -/** Node C-API +/* Node C-API * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/node.hpp b/include/villas/node.hpp index a69ab1eab..e601fa462 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -1,10 +1,9 @@ -/** Nodes +/* Nodes * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -28,24 +27,24 @@ #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) #define WITH_NETEM -#endif /* LIBNL3_ROUTE_FOUND */ +#endif // LIBNL3_ROUTE_FOUND -/* Forward declarations */ +// Forward declarations #ifdef WITH_NETEM struct rtnl_qdisc; struct rtnl_cls; -#endif /* WITH_NETEM */ +#endif // WITH_NETEM #define RE_NODE_NAME "[a-z0-9_-]{2,32}" namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeFactory; class SuperNode; -/** The class for a node. +/* The class for a node. * * Every entity which exchanges messages is represented by a node. * Nodes can be remote machines and simulators or locally running processes. @@ -58,21 +57,21 @@ public: Logger logger; uint64_t sequence_init; - uint64_t sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */ + uint64_t sequence; // This is a counter of received samples, in case the node-type does not generate sequence numbers itself. NodeDirection in, out; - PathSourceList sources; /**< A list of path sources which reference this node. */ - PathDestinationList destinations; /**< A list of path destinations which reference this node. */ + PathSourceList sources; // A list of path sources which reference this node. + PathDestinationList destinations; // A list of path destinations which reference this node. #ifdef __linux__ - int fwmark; /**< Socket mark for netem, routing and filtering */ + int fwmark; // Socket mark for netem, routing and filtering #ifdef WITH_NETEM - struct rtnl_qdisc *tc_qdisc; /**< libnl3: Network emulator queuing discipline */ - struct rtnl_cls *tc_classifier; /**< libnl3: Firewall mark classifier */ -#endif /* WITH_NETEM */ -#endif /* __linux__ */ + struct rtnl_qdisc *tc_qdisc; // libnl3: Network emulator queuing discipline + struct rtnl_cls *tc_classifier; // libnl3: Firewall mark classifier +#endif // WITH_NETEM +#endif // __linux__ protected: enum State state; @@ -81,18 +80,18 @@ protected: bool enabled; - Stats::Ptr stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */ + Stats::Ptr stats; // Statistic counters. This is a pointer to the statistic hooks private data. - json_t *config; /**< A JSON object containing the configuration of the node. */ + json_t *config; // A JSON object containing the configuration of the node. - std::string name_short; /**< A short identifier of the node, only used for configuration and logging */ - std::string name_long; /**< Singleton: A string used to print to screen. */ - std::string name_full; /**< Singleton: A string used to print to screen. */ + std::string name_short; // A short identifier of the node, only used for configuration and logging + std::string name_long; // Singleton: A string used to print to screen. + std::string name_full; // Singleton: A string used to print to screen. std::string details; - int affinity; /**< CPU Affinity of this node */ + int affinity; // CPU Affinity of this node - NodeFactory *factory; /**< The factory which created this instance */ + NodeFactory *factory; // The factory which created this instance virtual int _read(struct Sample * smps[], unsigned cnt) @@ -113,18 +112,18 @@ protected: } public: - /** Initialize node with default values */ + // Initialize node with default values Node(const uuid_t &id = {}, const std::string &name = ""); - /** Destroy node by freeing dynamically allocated memory. */ + // Destroy node by freeing dynamically allocated memory. virtual ~Node(); - /** Do initialization after parsing the configuration */ + // Do initialization after parsing the configuration virtual int prepare(); - /** Parse settings of a node. + /* Parse settings of a node. * * @param json A JSON object containing the configuration of the node. * @retval 0 Success. Everything went well. @@ -133,19 +132,19 @@ public: virtual int parse(json_t *json); - /** Validate node configuration. */ + // Validate node configuration. virtual int check(); - /** Start operation of a node. */ + // Start operation of a node. virtual int start(); - /** Stops operation of a node. */ + // Stops operation of a node. virtual int stop(); - /** Pauses operation of a node. */ + // Pauses operation of a node. virtual int pause() { @@ -157,18 +156,18 @@ public: return 0; } - /** Resumes operation of a node. */ + // Resumes operation of a node. virtual int resume() { return 0; } - /** Restarts operation of a node. */ + // Restarts operation of a node. virtual int restart(); - /** Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -184,7 +183,7 @@ public: */ int read(struct Sample * smps[], unsigned cnt); - /** Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -199,14 +198,14 @@ public: */ int write(struct Sample * smps[], unsigned cnt); - /** Reverse local and remote socket address. */ + // Reverse local and remote socket address. virtual int reverse() { return -1; } - /** Get a list of file descriptors on which the path should poll + /* Get a list of file descriptors on which the path should poll * to detect the availability of new samples which can be read. */ virtual @@ -215,7 +214,7 @@ public: return {}; } - /** Get a list of socket file descriptors which are used by the node + /* Get a list of socket file descriptors which are used by the node * To perform network IO. We use those to selectively apply network emulation */ virtual @@ -224,7 +223,7 @@ public: return {}; } - /** Get the memory type which this node-type expects. + /* Get the memory type which this node-type expects. * * This is useful for special node-types like Infiniband, GPUs & FPGAs * which require DMA-backed memory. @@ -235,13 +234,13 @@ public: return villas::node::memory::default_type; } - /** Get the factory which was used to construct this node. */ + // Get the factory which was used to construct this node. villas::node::NodeFactory * getFactory() const { return factory; } - /** Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ @@ -250,63 +249,65 @@ public: return name_short; } - /** Return a pointer to a string which should be used to print this node. */ + // Return a pointer to a string which should be used to print this node. const std::string & getName() const { return name_long; } - /** Get the full name including type and details of the node. */ + // Get the full name including type and details of the node. const std::string & getNameFull(); - /** Just get the config details of this node as a string */ + // Just get the config details of this node as a string virtual const std::string & getDetails() { - static std::string empty; + static + std::string empty; + return empty; } - /** Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ const std::string & getNameLong(); - /** Return a list of signals which are sent to this node. + /* Return a list of signals which are sent to this node. * * This list is derived from the path which uses the node as destination. */ SignalList::Ptr getOutputSignals(bool after_hooks = true) const; SignalList::Ptr getInputSignals(bool after_hooks = true) const; - /** Get the number of input signals (received by this node) */ + // Get the number of input signals (received by this node) unsigned getInputSignalsMaxCount() const; - /** Get the number of output signals (send out via this node) */ + // Get the number of output signals (send out via this node) unsigned getOutputSignalsMaxCount() const; void swapSignals(); - /** Get the node configuration as JSON. */ + // Get the node configuration as JSON. json_t * getConfig() { return config; } - /** Get the state of this node. */ + // Get the state of this node. enum State getState() const { return state; } - /** Set the state of this node. */ + // Set the state of this node. void setState(enum State s) { state = s; } - /** Get the UUID of this node. */ + // Get the UUID of this node. const uuid_t & getUuid() const { return uuid; @@ -327,7 +328,7 @@ public: enabled = en; } - /** Custom formatter for spdlog */ + // Custom formatter for spdlog template friend OStream &operator<<(OStream &os, const Node &n) { @@ -399,7 +400,7 @@ public: return "node"; } - /** Custom formatter for spdlog */ + // Custom formatter for spdlog template friend OStream &operator<<(OStream &os, const NodeFactory &f) { diff --git a/include/villas/node/config.hpp.in b/include/villas/node/config.hpp.in index 7bad18763..9176fa292 100644 --- a/include/villas/node/config.hpp.in +++ b/include/villas/node/config.hpp.in @@ -3,10 +3,9 @@ * This file contains some compiled-in settings. * This settings are not part of the configuration file. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ #pragma once diff --git a/include/villas/node/exceptions.hpp b/include/villas/node/exceptions.hpp index 4f72e828d..0093585f8 100644 --- a/include/villas/node/exceptions.hpp +++ b/include/villas/node/exceptions.hpp @@ -1,10 +1,9 @@ -/** VILLASnode exceptions. +/* VILLASnode exceptions. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -52,7 +51,7 @@ public: config(c) { } }; -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG class JanssonParseError : public ParseError { diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index 930cda757..fe9230584 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -1,16 +1,15 @@ -/** Memory allocators. +/* Memory allocators. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #ifdef IBVERBS_FOUND #include -#endif /* IBVERBS_FOUND */ +#endif // IBVERBS_FOUND #include #include @@ -22,16 +21,16 @@ namespace villas { namespace node { namespace memory { -/** Descriptor of a memory block. Associated block always starts at +/* Descriptor of a memory block. Associated block always starts at * &m + sizeof(struct Block). */ struct Block { struct Block *prev; struct Block *next; - size_t length; /**< Length of the block; doesn't include the descriptor itself */ + size_t length; // Length of the block; doesn't include the descriptor itself bool used; }; -/** @todo Unused for now */ +// @todo Unused for now struct Allocation { struct Type *type; @@ -53,12 +52,12 @@ struct Allocation { }; }; -/** Initilialize memory subsystem */ +// Initilialize memory subsystem int init(int hugepages) __attribute__ ((warn_unused_result)); int lock(size_t lock); -/** Allocate \p len bytes memory of type \p m. +/* Allocate \p len bytes memory of type \p m. * * @retval nullptr If allocation failed. * @retval <>0 If allocation was successful. diff --git a/include/villas/node/memory_type.hpp b/include/villas/node/memory_type.hpp index 0756b885e..553a94483 100644 --- a/include/villas/node/memory_type.hpp +++ b/include/villas/node/memory_type.hpp @@ -1,10 +1,9 @@ -/** Memory allocators. +/* Memory allocators. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,7 +13,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; namespace memory { @@ -40,13 +39,17 @@ struct Type { allocator_t alloc; deallocator_t free; - void *_vd; /**< Virtual data for internal state */ + void *_vd; // Virtual data for internal state }; -extern struct Type heap; -extern struct Type mmap; -extern struct Type mmap_hugetlb; -extern struct Type *default_type; +extern +struct Type heap; +extern +struct Type mmap; +extern +struct Type mmap_hugetlb; +extern +struct Type *default_type; struct Type * ib(NodeCompat *n, struct Type *parent); struct Type * managed(void *ptr, size_t len); diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index 4c8b13333..3b9c5dd8b 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -1,12 +1,11 @@ -/** Node compatability layer for C++ +/* Node compatability layer for C++ * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ -/** +/* * @addtogroup node Node * @{ */ @@ -22,14 +21,14 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompatFactory; class NodeCompat : public Node { protected: - struct NodeCompatType *_vt; /**< Virtual functions (C++ OOP style) */ - void *_vd; /**< Virtual data (used by struct vnode::_vt functions) */ + struct NodeCompatType *_vt; // Virtual functions (C++ OOP style) + void *_vd; // Virtual data (used by struct vnode::_vt functions) std::string _details; @@ -63,7 +62,7 @@ public: return _vt; } - /** Parse node connection details. + /* Parse node connection details. * * @param json A JSON object containing the configuration of the node. @@ -73,11 +72,11 @@ public: virtual int parse(json_t *json); - /** Returns a string with a textual represenation of this node. */ + // Returns a string with a textual represenation of this node. virtual const std::string & getDetails(); - /** Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * @retval 0 Success. Node configuration is good. @@ -89,7 +88,7 @@ public: virtual int prepare(); - /** Start this node. + /* Start this node. * * @retval 0 Success. Everything went well. @@ -98,7 +97,7 @@ public: virtual int start(); - /** Stop this node. + /* Stop this node. * * @retval 0 Success. Everything went well. @@ -107,7 +106,7 @@ public: virtual int stop(); - /** Restart this node. + /* Restart this node. * * @param n A pointer to the node object. @@ -117,7 +116,7 @@ public: virtual int restart(); - /** Pause this node. + /* Pause this node. * * @param n A pointer to the node object. @@ -127,7 +126,7 @@ public: virtual int pause(); - /** Resume this node. + /* Resume this node. * * @retval 0 Success. Everything went well. @@ -136,7 +135,7 @@ public: virtual int resume(); - /** Reverse source and destination of a node. + /* Reverse source and destination of a node. */ virtual @@ -145,7 +144,7 @@ public: virtual std::vector getPollFDs(); - /** Get list of socket file descriptors for configuring network emulation. + /* Get list of socket file descriptors for configuring network emulation. * * @return The number of file descriptors which have been put into \p sds. @@ -153,7 +152,7 @@ public: virtual std::vector getNetemFDs(); - /** Return a memory allocator which should be used for sample pools passed to this node. */ + // Return a memory allocator which should be used for sample pools passed to this node. virtual struct memory::Type * getMemoryType(); }; diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index 4535b28f7..328626b57 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -1,10 +1,9 @@ -/** Nodes +/* Nodes * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,7 +17,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class Node; class SuperNode; @@ -29,15 +28,15 @@ public: const char *name; const char *description; - unsigned vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */ + 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. - size_t size; /**< Size of private data bock. @see node::_vd */ + size_t size; // Size of private data bock. @see node::_vd struct { - /** Global initialization per node type. + /* Global initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -47,7 +46,7 @@ public: */ int (*start)(SuperNode *sn); - /** Global de-initialization per node type. + /* Global de-initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -58,7 +57,7 @@ public: int (*stop)(); } type; - /** Initialize a new node instance. + /* Initialize a new node instance. * * This callback is optional. It will only be called if non-null. * @@ -67,7 +66,7 @@ public: */ int (*init)(NodeCompat *n); - /** Free memory of an instance of this type. + /* Free memory of an instance of this type. * * This callback is optional. It will only be called if non-null. * @@ -75,7 +74,7 @@ public: */ int (*destroy)(NodeCompat *n); - /** Parse node connection details. + /* Parse node connection details. * * This callback is optional. It will only be called if non-null. * @@ -86,7 +85,7 @@ public: */ int (*parse)(NodeCompat *n, json_t *json); - /** Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * This callback is optional. It will only be called if non-null. * @@ -98,7 +97,7 @@ public: int (*prepare)(NodeCompat *n); - /** Returns a string with a textual represenation of this node. + /* Returns a string with a textual represenation of this node. * * This callback is optional. It will only be called if non-null. * @@ -107,7 +106,7 @@ public: */ char * (*print)(NodeCompat *n); - /** Start this node. + /* Start this node. * * This callback is optional. It will only be called if non-null. * @@ -117,7 +116,7 @@ public: */ int (*start)(NodeCompat *n); - /** Restart this node. + /* Restart this node. * * This callback is optional. It will only be called if non-null. * @@ -127,7 +126,7 @@ public: */ int (*restart)(NodeCompat *n); - /** Stop this node. + /* Stop this node. * * This callback is optional. It will only be called if non-null. * @@ -137,7 +136,7 @@ public: */ int (*stop)(NodeCompat *n); - /** Pause this node. + /* Pause this node. * * This callback is optional. It will only be called if non-null. * @@ -147,7 +146,7 @@ public: */ int (*pause)(NodeCompat *n); - /** Resume this node. + /* Resume this node. * * This callback is optional. It will only be called if non-null. * @@ -157,7 +156,7 @@ public: */ int (*resume)(NodeCompat *n); - /** Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -175,7 +174,7 @@ public: */ int (*read)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); - /** Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -192,7 +191,7 @@ public: */ int (*write)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); - /** Reverse source and destination of a node. + /* Reverse source and destination of a node. * * This callback is optional. It will only be called if non-null. * @@ -200,7 +199,7 @@ public: */ int (*reverse)(NodeCompat *n); - /** Get list of file descriptors which can be used by poll/select to detect the availability of new data. + /* Get list of file descriptors which can be used by poll/select to detect the availability of new data. * * This callback is optional. It will only be called if non-null. * @@ -208,7 +207,7 @@ public: */ int (*poll_fds)(NodeCompat *n, int fds[]); - /** Get list of socket file descriptors for configuring network emulation. + /* Get list of socket file descriptors for configuring network emulation. * * This callback is optional. It will only be called if non-null. * @@ -216,7 +215,7 @@ public: */ int (*netem_fds)(NodeCompat *n, int sds[]); - /** Return a memory allocator which should be used for sample pools passed to this node. */ + // Return a memory allocator which should be used for sample pools passed to this node. struct memory::Type * (*memory_type)(NodeCompat *n, struct memory::Type *parent); }; diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp index 54b87d518..c02506887 100644 --- a/include/villas/node_direction.hpp +++ b/include/villas/node_direction.hpp @@ -1,10 +1,9 @@ -/** Node direction +/* Node direction * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,7 +17,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class Path; @@ -27,11 +26,11 @@ class NodeDirection { public: enum class Direction { - IN, /**< VILLASnode is receiving/reading */ - OUT /**< VILLASnode is sending/writing */ + IN, // VILLASnode is receiving/reading + OUT // VILLASnode is sending/writing } direction; - /** The path which uses this node as a source/destination. + /* The path which uses this node as a source/destination. * * Usually every node should be used only by a single path as destination. * Otherwise samples from different paths would be interleaved. @@ -40,13 +39,13 @@ public: Node *node; int enabled; - int builtin; /**< This node should use built-in hooks by default. */ - unsigned vectorize; /**< Number of messages to send / recv at once (scatter / gather) */ + int builtin; // This node should use built-in hooks by default. + unsigned vectorize; // Number of messages to send / recv at once (scatter / gather) - HookList hooks; /**< List of read / write hooks (struct hook). */ - SignalList::Ptr signals; /**< Signal description. */ + HookList hooks; // List of read / write hooks (struct hook). + SignalList::Ptr signals; // Signal description. - json_t *config; /**< A JSON object containing the configuration of the node. */ + json_t *config; // A JSON object containing the configuration of the node. NodeDirection(enum NodeDirection::Direction dir, Node *n); diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index 51d95f954..e954ff339 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -1,11 +1,9 @@ -/** Node list +/* Node list * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,19 +16,19 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class NodeList : public std::list { public: - /** Lookup a node from the list based on its name */ + // Lookup a node from the list based on its name Node * lookup(const std::string &name); - /** Lookup a node from the list based on its UUID */ + // Lookup a node from the list based on its UUID Node * lookup(const uuid_t &uuid); - /** Parse an array or single node and checks if they exist in the "nodes" section. + /* Parse an array or single node and checks if they exist in the "nodes" section. * * Examples: * out = [ "sintef", "scedu" ] diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index e928cc5ef..f710bfbcd 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -1,10 +1,9 @@ -/** Node type: amqp +/* Node type: amqp * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,7 +21,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct amqp_ssl_info { @@ -42,7 +41,7 @@ struct amqp { amqp_bytes_t routing_key; amqp_bytes_t exchange; - /* We need to create two connection because rabbitmq-c is not thread-safe! */ + // We need to create two connection because rabbitmq-c is not thread-safe! amqp_connection_state_t producer; amqp_connection_state_t consumer; diff --git a/include/villas/nodes/api.hpp b/include/villas/nodes/api.hpp index 79ce3f4e2..4185d955c 100644 --- a/include/villas/nodes/api.hpp +++ b/include/villas/nodes/api.hpp @@ -1,11 +1,10 @@ -/** Node type: Universal Data-exchange API (v2) +/* Node type: Universal Data-exchange API (v2) * * @see https://github.com/ERIGrid2/JRA-3.1-api - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -16,7 +15,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class APINode : public Node { diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index 0c382da04..a8667d17e 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -1,10 +1,9 @@ -/** Node-type: CAN bus +/* Node-type: CAN bus * - * @file - * @author Niklas Eiling - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Niklas Eiling + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; union SignalData; @@ -26,12 +25,12 @@ struct can_signal { }; struct can { - /* Settings */ + // Settings char *interface_name; struct can_signal *in; struct can_signal *out; - /* States */ + // States int socket; union SignalData *sample_buf; size_t sample_buf_num; diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index c09a8970a..cd291e53c 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -1,10 +1,9 @@ -/** Node type: comedi +/* Node type: comedi * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -16,7 +15,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; // whether to use read() or mmap() kernel interface diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 3de4a57d0..7d47e9650 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -1,12 +1,11 @@ -/** Node type: ethercat +/* Node type: ethercat * - * @file - * @author Niklas Eiling - * @author Steffen Vogel - * @author Divya Laxetti - * @copyright 2018-2020, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Niklas Eiling + * Author: Steffen Vogel + * Author: Divya Laxetti + * SPDX-FileCopyrightText: 2018-2020 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,11 +21,11 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; class SuperNode; -/* Include hard-coded Ethercat Bus configuration */ +// Include hard-coded Ethercat Bus configuration #include extern "C" { @@ -35,35 +34,35 @@ extern "C" { #define DEFAULT_ETHERCAT_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) -/** Internal data per ethercat node */ +// Internal data per ethercat node struct ethercat { - /* Settings */ + // Settings double rate; struct { unsigned num_channels; double range; unsigned position; - unsigned product_code; /**< Product ID of EtherCAT slave */ - unsigned vendor_id; /**< Vendor ID of EtherCAT slave */ + unsigned product_code; // Product ID of EtherCAT slave + unsigned vendor_id; // Vendor ID of EtherCAT slave ec_slave_config_t *sc; - unsigned *offsets; /**< Offsets for PDO entries */ + unsigned *offsets; // Offsets for PDO entries } in, out; ec_domain_t *domain; ec_pdo_entry_reg_t *domain_regs; - uint8_t *domain_pd; /**< Process data */ + uint8_t *domain_pd; // Process data - std::thread thread; /**< Cyclic task thread */ - struct Task task; /**< Periodic timer */ + std::thread thread; // Cyclic task thread + struct Task task; // Periodic timer struct Pool pool; - struct CQueueSignalled queue; /**< For samples which are received from WebSockets */ + struct CQueueSignalled queue; // For samples which are received from WebSockets - std::atomic send; /**< Last sample to be sent via EtherCAT */ + std::atomic send; // Last sample to be sent via EtherCAT }; -/* Internal datastructures */ +// Internal datastructures int ethercat_type_start(SuperNode *sn); diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index 19a996b68..c72687cdc 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -1,12 +1,11 @@ -/** Configuration for Ethercat Node-type +/* Configuration for Ethercat Node-type * - * @file - * @author Niklas Eiling - * @author Steffen Vogel - * @author Divya Laxetti - * @copyright 2018-2020, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Niklas Eiling + * Author: Steffen Vogel + * Author: Divya Laxetti + * SPDX-FileCopyrightText: 2018-2020 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -26,8 +25,7 @@ #define ETHERCAT_PID_EL3008 0x0bc03052 #define ETHERCAT_PID_FC1100 0x044c0c62 - -/** @todo Make PDO entry tables configurable */ +// @todo Make PDO entry tables configurable /* Master 0, Slave 3, "EL4038" * Vendor ID: 0x00000002 @@ -35,29 +33,32 @@ * Revision number: 0x00140000 */ -static ec_pdo_entry_info_t slave_3_pdo_entries[] = { - {0x7000, 0x01, 16}, /* Analog output */ - {0x7010, 0x01, 16}, /* Analog output */ - {0x7020, 0x01, 16}, /* Analog output */ - {0x7030, 0x01, 16}, /* Analog output */ - {0x7040, 0x01, 16}, /* Analog output */ - {0x7050, 0x01, 16}, /* Analog output */ - {0x7060, 0x01, 16}, /* Analog output */ - {0x7070, 0x01, 16}, /* Analog output */ +static +ec_pdo_entry_info_t slave_3_pdo_entries[] = { + {0x7000, 0x01, 16}, // Analog output + {0x7010, 0x01, 16}, // Analog output + {0x7020, 0x01, 16}, // Analog output + {0x7030, 0x01, 16}, // Analog output + {0x7040, 0x01, 16}, // Analog output + {0x7050, 0x01, 16}, // Analog output + {0x7060, 0x01, 16}, // Analog output + {0x7070, 0x01, 16}, // Analog output }; -static ec_pdo_info_t slave_3_pdos[] = { - {0x1600, 1, slave_3_pdo_entries + 0}, /* AO RxPDO-Map Outputs Ch.1 */ - {0x1601, 1, slave_3_pdo_entries + 1}, /* AO RxPDO-Map Outputs Ch.2 */ - {0x1602, 1, slave_3_pdo_entries + 2}, /* AO RxPDO-Map Outputs Ch.3 */ - {0x1603, 1, slave_3_pdo_entries + 3}, /* AO RxPDO-Map Outputs Ch.4 */ - {0x1604, 1, slave_3_pdo_entries + 4}, /* AO RxPDO-Map Outputs Ch.5 */ - {0x1605, 1, slave_3_pdo_entries + 5}, /* AO RxPDO-Map Outputs Ch.6 */ - {0x1606, 1, slave_3_pdo_entries + 6}, /* AO RxPDO-Map Outputs Ch.7 */ - {0x1607, 1, slave_3_pdo_entries + 7}, /* AO RxPDO-Map Outputs Ch.8 */ +static +ec_pdo_info_t slave_3_pdos[] = { + {0x1600, 1, slave_3_pdo_entries + 0}, // AO RxPDO-Map Outputs Ch.1 + {0x1601, 1, slave_3_pdo_entries + 1}, // AO RxPDO-Map Outputs Ch.2 + {0x1602, 1, slave_3_pdo_entries + 2}, // AO RxPDO-Map Outputs Ch.3 + {0x1603, 1, slave_3_pdo_entries + 3}, // AO RxPDO-Map Outputs Ch.4 + {0x1604, 1, slave_3_pdo_entries + 4}, // AO RxPDO-Map Outputs Ch.5 + {0x1605, 1, slave_3_pdo_entries + 5}, // AO RxPDO-Map Outputs Ch.6 + {0x1606, 1, slave_3_pdo_entries + 6}, // AO RxPDO-Map Outputs Ch.7 + {0x1607, 1, slave_3_pdo_entries + 7}, // AO RxPDO-Map Outputs Ch.8 }; -static ec_sync_info_t slave_3_syncs[] = { +static +ec_sync_info_t slave_3_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 8, slave_3_pdos + 0, EC_WD_DISABLE}, @@ -71,101 +72,104 @@ static ec_sync_info_t slave_3_syncs[] = { * Revision number: 0x00150000 */ -static ec_pdo_entry_info_t slave_4_pdo_entries[] = { - {0x6000, 0x01, 1}, /* Underrange */ - {0x6000, 0x02, 1}, /* Overrange */ - {0x6000, 0x03, 2}, /* Limit 1 */ - {0x6000, 0x05, 2}, /* Limit 2 */ - {0x6000, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6000, 0x0f, 1}, /* TxPDO State */ - {0x6000, 0x10, 1}, /* TxPDO Toggle */ - {0x6000, 0x11, 16}, /* Value */ - {0x6010, 0x01, 1}, /* Underrange */ - {0x6010, 0x02, 1}, /* Overrange */ - {0x6010, 0x03, 2}, /* Limit 1 */ - {0x6010, 0x05, 2}, /* Limit 2 */ - {0x6010, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6010, 0x0f, 1}, /* TxPDO State */ - {0x6010, 0x10, 1}, /* TxPDO Toggle */ - {0x6010, 0x11, 16}, /* Value */ - {0x6020, 0x01, 1}, /* Underrange */ - {0x6020, 0x02, 1}, /* Overrange */ - {0x6020, 0x03, 2}, /* Limit 1 */ - {0x6020, 0x05, 2}, /* Limit 2 */ - {0x6020, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6020, 0x0f, 1}, /* TxPDO State */ - {0x6020, 0x10, 1}, /* TxPDO Toggle */ - {0x6020, 0x11, 16}, /* Value */ - {0x6030, 0x01, 1}, /* Underrange */ - {0x6030, 0x02, 1}, /* Overrange */ - {0x6030, 0x03, 2}, /* Limit 1 */ - {0x6030, 0x05, 2}, /* Limit 2 */ - {0x6030, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6030, 0x0f, 1}, /* TxPDO State */ - {0x6030, 0x10, 1}, /* TxPDO Toggle */ - {0x6030, 0x11, 16}, /* Value */ - {0x6040, 0x01, 1}, /* Underrange */ - {0x6040, 0x02, 1}, /* Overrange */ - {0x6040, 0x03, 2}, /* Limit 1 */ - {0x6040, 0x05, 2}, /* Limit 2 */ - {0x6040, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6040, 0x0f, 1}, /* TxPDO State */ - {0x6040, 0x10, 1}, /* TxPDO Toggle */ - {0x6040, 0x11, 16}, /* Value */ - {0x6050, 0x01, 1}, /* Underrange */ - {0x6050, 0x02, 1}, /* Overrange */ - {0x6050, 0x03, 2}, /* Limit 1 */ - {0x6050, 0x05, 2}, /* Limit 2 */ - {0x6050, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6050, 0x0f, 1}, /* TxPDO State */ - {0x6050, 0x10, 1}, /* TxPDO Toggle */ - {0x6050, 0x11, 16}, /* Value */ - {0x6060, 0x01, 1}, /* Underrange */ - {0x6060, 0x02, 1}, /* Overrange */ - {0x6060, 0x03, 2}, /* Limit 1 */ - {0x6060, 0x05, 2}, /* Limit 2 */ - {0x6060, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6060, 0x0f, 1}, /* TxPDO State */ - {0x6060, 0x10, 1}, /* TxPDO Toggle */ - {0x6060, 0x11, 16}, /* Value */ - {0x6070, 0x01, 1}, /* Underrange */ - {0x6070, 0x02, 1}, /* Overrange */ - {0x6070, 0x03, 2}, /* Limit 1 */ - {0x6070, 0x05, 2}, /* Limit 2 */ - {0x6070, 0x07, 1}, /* Error */ - {0x0000, 0x00, 1}, /* Gap */ - {0x0000, 0x00, 6}, /* Gap */ - {0x6070, 0x0f, 1}, /* TxPDO State */ - {0x6070, 0x10, 1}, /* TxPDO Toggle */ - {0x6070, 0x11, 16}, /* Value */ +static +ec_pdo_entry_info_t slave_4_pdo_entries[] = { + {0x6000, 0x01, 1}, // Underrange + {0x6000, 0x02, 1}, // Overrange + {0x6000, 0x03, 2}, // Limit 1 + {0x6000, 0x05, 2}, // Limit 2 + {0x6000, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6000, 0x0f, 1}, // TxPDO State + {0x6000, 0x10, 1}, // TxPDO Toggle + {0x6000, 0x11, 16}, // Value + {0x6010, 0x01, 1}, // Underrange + {0x6010, 0x02, 1}, // Overrange + {0x6010, 0x03, 2}, // Limit 1 + {0x6010, 0x05, 2}, // Limit 2 + {0x6010, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6010, 0x0f, 1}, // TxPDO State + {0x6010, 0x10, 1}, // TxPDO Toggle + {0x6010, 0x11, 16}, // Value + {0x6020, 0x01, 1}, // Underrange + {0x6020, 0x02, 1}, // Overrange + {0x6020, 0x03, 2}, // Limit 1 + {0x6020, 0x05, 2}, // Limit 2 + {0x6020, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6020, 0x0f, 1}, // TxPDO State + {0x6020, 0x10, 1}, // TxPDO Toggle + {0x6020, 0x11, 16}, // Value + {0x6030, 0x01, 1}, // Underrange + {0x6030, 0x02, 1}, // Overrange + {0x6030, 0x03, 2}, // Limit 1 + {0x6030, 0x05, 2}, // Limit 2 + {0x6030, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6030, 0x0f, 1}, // TxPDO State + {0x6030, 0x10, 1}, // TxPDO Toggle + {0x6030, 0x11, 16}, // Value + {0x6040, 0x01, 1}, // Underrange + {0x6040, 0x02, 1}, // Overrange + {0x6040, 0x03, 2}, // Limit 1 + {0x6040, 0x05, 2}, // Limit 2 + {0x6040, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6040, 0x0f, 1}, // TxPDO State + {0x6040, 0x10, 1}, // TxPDO Toggle + {0x6040, 0x11, 16}, // Value + {0x6050, 0x01, 1}, // Underrange + {0x6050, 0x02, 1}, // Overrange + {0x6050, 0x03, 2}, // Limit 1 + {0x6050, 0x05, 2}, // Limit 2 + {0x6050, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6050, 0x0f, 1}, // TxPDO State + {0x6050, 0x10, 1}, // TxPDO Toggle + {0x6050, 0x11, 16}, // Value + {0x6060, 0x01, 1}, // Underrange + {0x6060, 0x02, 1}, // Overrange + {0x6060, 0x03, 2}, // Limit 1 + {0x6060, 0x05, 2}, // Limit 2 + {0x6060, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6060, 0x0f, 1}, // TxPDO State + {0x6060, 0x10, 1}, // TxPDO Toggle + {0x6060, 0x11, 16}, // Value + {0x6070, 0x01, 1}, // Underrange + {0x6070, 0x02, 1}, // Overrange + {0x6070, 0x03, 2}, // Limit 1 + {0x6070, 0x05, 2}, // Limit 2 + {0x6070, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6070, 0x0f, 1}, // TxPDO State + {0x6070, 0x10, 1}, // TxPDO Toggle + {0x6070, 0x11, 16}, // Value }; -static ec_pdo_info_t slave_4_pdos[] = { - {0x1a00, 10, slave_4_pdo_entries + 0}, /* AI TxPDO-Map Standard Ch.1 */ - {0x1a02, 10, slave_4_pdo_entries + 10}, /* AI TxPDO-Map Standard Ch.2 */ - {0x1a04, 10, slave_4_pdo_entries + 20}, /* AI TxPDO-Map Standard Ch.3 */ - {0x1a06, 10, slave_4_pdo_entries + 30}, /* AI TxPDO-Map Standard Ch.4 */ - {0x1a08, 10, slave_4_pdo_entries + 40}, /* AI TxPDO-Map Standard Ch.5 */ - {0x1a0a, 10, slave_4_pdo_entries + 50}, /* AI TxPDO-Map Standard Ch.6 */ - {0x1a0c, 10, slave_4_pdo_entries + 60}, /* AI TxPDO-Map Standard Ch.7 */ - {0x1a0e, 10, slave_4_pdo_entries + 70}, /* AI TxPDO-Map Standard Ch.8 */ +static +ec_pdo_info_t slave_4_pdos[] = { + {0x1a00, 10, slave_4_pdo_entries + 0}, // AI TxPDO-Map Standard Ch.1 + {0x1a02, 10, slave_4_pdo_entries + 10}, // AI TxPDO-Map Standard Ch.2 + {0x1a04, 10, slave_4_pdo_entries + 20}, // AI TxPDO-Map Standard Ch.3 + {0x1a06, 10, slave_4_pdo_entries + 30}, // AI TxPDO-Map Standard Ch.4 + {0x1a08, 10, slave_4_pdo_entries + 40}, // AI TxPDO-Map Standard Ch.5 + {0x1a0a, 10, slave_4_pdo_entries + 50}, // AI TxPDO-Map Standard Ch.6 + {0x1a0c, 10, slave_4_pdo_entries + 60}, // AI TxPDO-Map Standard Ch.7 + {0x1a0e, 10, slave_4_pdo_entries + 70}, // AI TxPDO-Map Standard Ch.8 }; -static ec_sync_info_t slave_4_syncs[] = { +static +ec_sync_info_t slave_4_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index 5afbe6e9f..1e4daf4a6 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -1,13 +1,12 @@ -/** An example get started with new implementations of new node-types +/* An example get started with new implementations of new node-types * * This example does not do any particulary useful. * It is just a skeleton to get you started with new node-types. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,20 +17,20 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class ExampleNode : public Node { protected: - /* Place any configuration and per-node state here */ + // Place any configuration and per-node state here - /* Settings */ + // Settings int setting1; std::string setting2; - /* States */ + // States int state1; struct timespec start_time; @@ -57,7 +56,7 @@ public: virtual int parse(json_t *json); - /** Validate node configuration. */ + // Validate node configuration virtual int check(); @@ -92,6 +91,5 @@ public: const std::string & getDetails(); }; - } // namespace node } // namespace villas diff --git a/include/villas/nodes/exec.hpp b/include/villas/nodes/exec.hpp index 6f666cdd7..000222a57 100644 --- a/include/villas/nodes/exec.hpp +++ b/include/villas/nodes/exec.hpp @@ -1,10 +1,9 @@ -/** Node-type for exec node-types. +/* Node-type for exec node-types. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class ExecNode : public Node { diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index 72dd1bf4b..a5ebad8c2 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -1,10 +1,9 @@ -/** Node type: File +/* Node type: File * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -16,7 +15,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; #define FILE_MAX_PATHLEN 512 @@ -26,15 +25,15 @@ struct file { FILE *stream_in; FILE *stream_out; - char *uri_tmpl; /**< Format string for file name. */ - char *uri; /**< Real file name. */ + char *uri_tmpl; // Format string for file name. + char *uri; // Real file name. - unsigned skip_lines; /**< Skip the first n-th lines/samples of the file. */ - int flush; /**< Flush / upload file contents after each write. */ - struct Task task; /**< Timer file descriptor. Blocks until 1 / rate seconds are elapsed. */ - double rate; /**< The read rate. */ - 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. */ + unsigned skip_lines; // Skip the first n-th lines/samples of the file. + int flush; // Flush / upload file contents after each write. + struct Task task; // Timer file descriptor. Blocks until 1 / rate seconds are elapsed. + double rate; // The read rate. + 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 class EpochMode { DIRECT, @@ -42,17 +41,17 @@ struct file { RELATIVE, ABSOLUTE, ORIGINAL - } epoch_mode; /**< Specifies how file::offset is calculated. */ + } epoch_mode; // Specifies how file::offset is calculated. enum class EOFBehaviour { - STOP, /**< Terminate when EOF is reached. */ - REWIND, /**< Rewind the file when EOF is reached. */ - SUSPEND /**< Blocking wait when EOF is reached. */ + STOP, // Terminate when EOF is reached. + REWIND, // Rewind the file when EOF is reached. + SUSPEND // Blocking wait when EOF is reached. } eof_mode; - struct timespec first; /**< The first timestamp in the file file::{read,write}::uri */ - struct timespec epoch; /**< The epoch timestamp from the configuration. */ - struct timespec offset; /**< An offset between the timestamp in the input file and the current time */ + struct timespec first; // The first timestamp in the file file::{read,write}::uri + struct timespec epoch; // The epoch timestamp from the configuration. + struct timespec offset; // An offset between the timestamp in the input file and the current time }; char * file_print(NodeCompat *n); diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 79edaf907..2c035716f 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -1,10 +1,9 @@ -/** Communicate with VILLASfpga Xilinx FPGA boards +/* Communicate with VILLASfpga Xilinx FPGA boards * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -73,7 +72,6 @@ public: std::vector getPollFDs(); }; - class FpgaNodeFactory : public NodeFactory { public: diff --git a/include/villas/nodes/iec60870.hpp b/include/villas/nodes/iec60870.hpp index e487f2040..45fc4f879 100644 --- a/include/villas/nodes/iec60870.hpp +++ b/include/villas/nodes/iec60870.hpp @@ -1,10 +1,9 @@ -/** Node type: IEC60870-5-104 +/* Node type: IEC60870-5-104 * - * @file - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -48,7 +47,8 @@ public: }; // Parse the config json - static ASDUData parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence); + static + ASDUData parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence); // Does this data include a timestamp bool hasTimestamp() const; @@ -89,7 +89,8 @@ private: SignalType signal_type; }; - inline static std::array const descriptors { + inline static + std::array const descriptors { ASDUData::Descriptor { Type::SINGLE_POINT, "single-point", "M_SP_NA_1", false, Type::SINGLE_POINT, SignalType::BOOLEAN }, ASDUData::Descriptor { Type::SINGLE_POINT_WITH_TIMESTAMP, "single-point", "M_SP_TB_1", true, Type::SINGLE_POINT, SignalType::BOOLEAN }, ASDUData::Descriptor { Type::DOUBLE_POINT, "double-point", "M_DP_NA_1", false, Type::DOUBLE_POINT, SignalType::INTEGER }, @@ -105,13 +106,16 @@ private: ASDUData(ASDUData::Descriptor const *descriptor, int ioa, int ioa_sequence_start); // Lookup datatype for config key asdu_type - static std::optional lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start); + static + std::optional lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start); // Lookup datatype for config key asdu_type_id - static std::optional lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start); + static + std::optional lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start); // Lookup datatype for numeric type identifier - static std::optional lookupType(int type, int ioa, int ioa_sequence_start); + static + std::optional lookupType(int type, int ioa, int ioa_sequence_start); // Descriptor within the descriptors table above ASDUData::Descriptor const *descriptor; @@ -186,6 +190,6 @@ public: int stop() override; }; -} /* namespace iec60870 */ +} // namespace iec60870 } // namespace node } // namespace villas diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index 786744129..c2182970b 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -1,10 +1,9 @@ -/** Some helpers to libiec61850 +/* Some helpers to libiec61850 * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -27,11 +26,11 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; enum class IEC61850Type { - /* According to IEC 61850-7-2 */ + // According to IEC 61850-7-2 BOOLEAN, INT8, INT16, @@ -52,7 +51,7 @@ enum class IEC61850Type { TIMESTAMP, ENTRYTIME, - /* According to IEC 61850-8-1 */ + // According to IEC 61850-8-1 BITSTRING }; diff --git a/include/villas/nodes/iec61850_goose.hpp b/include/villas/nodes/iec61850_goose.hpp index c11770b4e..7e2b20bc3 100644 --- a/include/villas/nodes/iec61850_goose.hpp +++ b/include/villas/nodes/iec61850_goose.hpp @@ -1,9 +1,9 @@ -/** Node type: IEC 61850 - GOOSE +/* Node type: IEC 61850 - GOOSE * - * @author Philipp Jungkamp - * @copyright 2023, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -254,6 +254,6 @@ public: int stop() override; }; -} /* namespace iec61850 */ +} // namespace iec61850 } // namespace node } // namespace villas diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index 51c7ef121..26b4e85e6 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -1,10 +1,9 @@ -/** Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values) * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -21,7 +20,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct iec61850_sv { @@ -38,7 +37,7 @@ struct iec61850_sv { struct CQueueSignalled queue; struct Pool pool; - struct List signals; /**< Mappings of type struct iec61850_type_descriptor */ + struct List signals; // Mappings of type struct iec61850_type_descriptor int total_size; } in; @@ -56,7 +55,7 @@ struct iec61850_sv { int smprate; int confrev; - struct List signals; /**< Mappings of type struct iec61850_type_descriptor */ + struct List signals; // Mappings of type struct iec61850_type_descriptor int total_size; } out; }; diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index 0678b37a5..1b2651433 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -1,10 +1,9 @@ -/** Node type: infiniband +/* Node type: infiniband * - * @file - * @author Dennis Potter - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Dennis Potter + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -16,17 +15,17 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; -/* Constants */ +// Constants #define META_SIZE 24 #define GRH_SIZE 40 #define META_GRH_SIZE META_SIZE + GRH_SIZE #define CHK_PER_ITER 2048 struct infiniband { - /* IBV/RDMA CM structs */ + // IBV/RDMA CM structs struct context_s { struct rdma_cm_id *listen_id; struct rdma_cm_id *id; @@ -38,48 +37,48 @@ struct infiniband { struct ibv_comp_channel *comp_channel; } ctx; - /* Queue Pair init variables */ + // Queue Pair init variables struct ibv_qp_init_attr qp_init; - /* Size of receive and send completion queue */ + // Size of receive and send completion queue int recv_cq_size; int send_cq_size; - /* Bool, set if threads should be aborted */ + // Bool, set if threads should be aborted int stopThreads; - /* When most messages are sent inline, once every cycles a signal must be sent. */ + // When most messages are sent inline, once every cycles a signal must be sent. unsigned signaling_counter; unsigned periodic_signaling; - /* Connection specific variables */ + // Connection specific variables struct connection_s { struct addrinfo *src_addr; struct addrinfo *dst_addr; - /* RDMA_PS_TCP or RDMA_PS_UDP */ + // RDMA_PS_TCP or RDMA_PS_UDP enum rdma_port_space port_space; - /* Timeout for rdma_resolve_route */ + // Timeout for rdma_resolve_route int timeout; - /* Thread to monitor RDMA CM Event threads */ + // Thread to monitor RDMA CM Event threads pthread_t rdma_cm_event_thread; - /* Bool, should data be send inline if possible? */ + // Bool, should data be send inline if possible? int send_inline; - /* Bool, should node have a fallback if it can't connect to a remote host? */ + // Bool, should node have a fallback if it can't connect to a remote host? int use_fallback; - /* Counter to keep track of available recv. WRs */ + // Counter to keep track of available recv. WRs unsigned available_recv_wrs; /* Fixed number to substract from min. number available * WRs in receive queue */ unsigned buffer_subtraction; - /* Unrealiable connectionless data */ + // Unrealiable connectionless data struct ud_s { struct rdma_ud_param ud; struct ibv_ah *ah; @@ -89,7 +88,7 @@ struct infiniband { } conn; - /* Misc settings */ + // Misc settings int is_source; }; diff --git a/include/villas/nodes/influxdb.hpp b/include/villas/nodes/influxdb.hpp index 91e66e6bf..2352a12ed 100644 --- a/include/villas/nodes/influxdb.hpp +++ b/include/villas/nodes/influxdb.hpp @@ -1,10 +1,9 @@ -/** Node-type for InfluxDB. +/* Node-type for InfluxDB. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -13,7 +12,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct Sample; diff --git a/include/villas/nodes/kafka.hpp b/include/villas/nodes/kafka.hpp index a7bffb9c6..e00149324 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -1,10 +1,9 @@ -/** Node type: kafka +/* Node type: kafka * - * @file - * @author Juan Pablo Noreña - * @copyright 2021, Universidad Nacional de Colombia - * @license Apache 2.0 - *********************************************************************************/ + * Author: Juan Pablo Noreña + * SPDX-FileCopyrightText: 2021 Universidad Nacional de Colombia + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,19 +16,19 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct kafka { struct CQueueSignalled queue; struct Pool pool; - double timeout; /**< Timeout in seconds. */ - char *server; /**< Hostname/IP:Port address of the bootstrap server. */ - char *protocol; /**< Security protocol. */ - char *produce; /**< Producer topic. */ - char *consume; /**< Consumer topic. */ - char *client_id; /**< Client ID. */ + double timeout; // Timeout in seconds. + char *server; // Hostname/IP:Port address of the bootstrap server. + char *protocol; // Security protocol. + char *produce; // Producer topic. + char *consume; // Consumer topic. + char *client_id; // Client ID. struct { rd_kafka_t *client; @@ -38,17 +37,17 @@ struct kafka { struct { rd_kafka_t *client; - char *group_id; /**< Group id. */ + char *group_id; // Group id. } consumer; struct { - char *ca; /**< SSL CA file. */ + char *ca; // SSL CA file. } ssl; struct { - char *mechanisms; /**< SASL mechanisms. */ - char *username; /**< SSL CA path. */ - char *password; /**< SSL certificate. */ + char *mechanisms; // SASL mechanisms. + char *username; // SSL CA path. + char *password; // SSL certificate. } sasl; Format *formatter; diff --git a/include/villas/nodes/loopback.hpp b/include/villas/nodes/loopback.hpp index 7813e24e4..404ce1571 100644 --- a/include/villas/nodes/loopback.hpp +++ b/include/villas/nodes/loopback.hpp @@ -1,10 +1,9 @@ -/** Node-type for loopback connections. +/* Node-type for loopback connections. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index ff38604e2..7dcfc30a8 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -1,10 +1,9 @@ -/** Node type: internal loopback +/* Node type: internal loopback * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index b5472602d..27436d2be 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -1,9 +1,9 @@ -/** A Modbus node-type supporting RTU and TCP based transports. +/* A Modbus node-type supporting RTU and TCP based transports. * - * @author Philipp Jungkamp - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -65,7 +65,7 @@ struct Tcp { Tcp parse(json_t *json); }; -// Forward declaration. +// Forward declarations class RegisterMappingSingle; // A merged block of mappings. diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 0e5ba87e0..7c852b163 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -1,10 +1,9 @@ -/** Node type: mqtt +/* Node type: mqtt * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -13,13 +12,13 @@ #include #include -/* Forward declarations */ +// Forward declarations struct mosquitto; namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct mqtt { @@ -27,26 +26,26 @@ struct mqtt { struct CQueueSignalled queue; struct Pool pool; - int keepalive; /**< Keep-alive interval in seconds. Zero for no keepalive. */ - int port; /**< Hostname / IP address of the broker. */ - int qos; /**< Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. */ - int retain; /**< Mark published messages as retained. */ - char *host; /**< Hostname / IP address of the broker. */ - char *username; /**< Username for authentication to the broker. */ - char *password; /**< Password for authentication to the broker. */ - char *publish; /**< Publish topic. */ - char *subscribe; /**< Subscribe topic. */ + int keepalive; // Keep-alive interval in seconds. Zero for no keepalive. + int port; // Hostname / IP address of the broker. + int qos; // Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. + int retain; // Mark published messages as retained. + char *host; // Hostname / IP address of the broker. + char *username; // Username for authentication to the broker. + char *password; // Password for authentication to the broker. + char *publish; // Publish topic. + char *subscribe; // Subscribe topic. struct { - int enabled; /**< Enable SSL encrypted connection to broker. */ - int insecure; /**< Allow insecure SSL connections. */ - char *cafile; /**< SSL CA file. */ - char *capath; /**< SSL CA path. */ - char *certfile; /**< SSL certificate. */ - char *keyfile; /**< SSL private key. */ - int cert_reqs; /**< SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) */ - char *tls_version; /**< SSL tls verion */ - char *ciphers; /**< SSL chipher list. */ + int enabled; // Enable SSL encrypted connection to broker. + int insecure; // Allow insecure SSL connections. + char *cafile; // SSL CA file. + char *capath; // SSL CA path. + char *certfile; // SSL certificate. + char *keyfile; // SSL private key. + int cert_reqs; // SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) + char *tls_version; // SSL tls verion + char *ciphers; // SSL chipher list. } ssl; Format *formatter; diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index b280a690a..05c786618 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -1,10 +1,9 @@ -/** Node type: nanomsg +/* Node type: nanomsg * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,10 +13,10 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; -/** The maximum length of a packet which contains stuct msg. */ +// The maximum length of a packet which contains stuct msg. #define NANOMSG_MAX_PACKET_LEN 1500 struct nanomsg { diff --git a/include/villas/nodes/ngsi.hpp b/include/villas/nodes/ngsi.hpp index 3202e7382..ff81e095d 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -1,4 +1,4 @@ -/** Node type: OMA Next Generation Services Interface 10 (NGSI) (FIWARE context broker) +/* Node type: OMA Next Generation Services Interface 10 (NGSI) (FIWARE context broker) * * This file implements the NGSI context interface. NGSI is RESTful HTTP is specified by * the Open Mobile Alliance (OMA). @@ -6,11 +6,10 @@ * * @see https://forge.fiware.org/plugins/mediawiki/wiki/fiware/index.php/FI-WARE_NGSI-10_Open_RESTful_API_Specification * @see http://technical.openmobilealliance.org/Technical/Release_Program/docs/NGSI/V1_0-20120529-A/OMA-TS-NGSI_Context_Management-V1_0-20120529-A.pdf - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -23,33 +22,32 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct ngsi { - const char *endpoint; /**< The NGSI context broker endpoint URL. */ - const char *entity_id; /**< The context broker entity id related to this node */ - const char *entity_type; /**< The type of the entity */ - const char *access_token; /**< An optional authentication token which will be sent as HTTP header. */ + const char *endpoint; // The NGSI context broker endpoint URL. + const char *entity_id; // The context broker entity id related to this node + const char *entity_type; // The type of the entity + const char *access_token; // An optional authentication token which will be sent as HTTP header. - bool create; /**< Weather we want to create the context element during startup. */ - bool remove; /**< Weather we want to delete the context element during startup. */ + bool create; // Weather we want to create the context element during startup. + bool remove; // Weather we want to delete the context element during startup. - double timeout; /**< HTTP timeout in seconds */ - double rate; /**< Rate used for polling. */ + double timeout; // HTTP timeout in seconds + double rate; // Rate used for polling. - struct Task task; /**< Timer for periodic events. */ - int ssl_verify; /**< Boolean flag whether SSL server certificates should be verified or not. */ + struct Task task; // Timer for periodic events. + int ssl_verify; // Boolean flag whether SSL server certificates should be verified or not. - struct curl_slist *headers; /**< List of HTTP request headers for libcurl */ + struct curl_slist *headers; // List of HTTP request headers for libcurl struct { - CURL *curl; /**< libcurl: handle */ - struct List signals; /**< A mapping between indices of the VILLASnode samples and the attributes in ngsi::context */ + CURL *curl; // libcurl: handle + struct List signals; // A mapping between indices of the VILLASnode samples and the attributes in ngsi::context } in, out; }; - int ngsi_type_start(SuperNode *sn); int ngsi_type_stop(); diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index ba09adac5..038f8767e 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -1,10 +1,9 @@ -/** Node type: OPAL (libOpalAsync API) +/* Node type: OPAL (libOpalAsync API) * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; extern "C" { diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index d2cbd0181..0ecb4bc8f 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -1,10 +1,9 @@ -/** Redis node-type +/* Redis node-type * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -79,10 +78,10 @@ struct redis { std::string key; - bool notify; /**< Use Redis Keyspace notifications to listen for updates. */ + bool notify; // Use Redis Keyspace notifications to listen for updates. - struct Task task; /**< Timer for periodic events. */ - double rate; /**< Rate for polling key updates if keyspace notifications are disabled. */ + struct Task task; // Timer for periodic events. + double rate; // Rate for polling key updates if keyspace notifications are disabled. Format *formatter; diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index be967972c..3de183da5 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -1,10 +1,9 @@ -/** Redis node-type helpers +/* Redis node-type helpers * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -40,7 +39,7 @@ struct hash hash()(t.sni); #else return 0; -#endif /* REDISPP_WITH_TLS */ +#endif // REDISPP_WITH_TLS } }; @@ -79,7 +78,7 @@ bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) o1.sni == o2.sni; #else return true; -#endif /* REDISPP_WITH_TLS */ +#endif // REDISPP_WITH_TLS } bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) @@ -122,7 +121,7 @@ OStream &operator<<(OStream &os, const tls::TlsOptions &t) return os; } -#endif /* REDISPP_WITH_TLS */ +#endif // REDISPP_WITH_TLS template OStream &operator<<(OStream &os, const ConnectionType &t) diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index 1f3c96372..2005c6e0b 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -1,11 +1,10 @@ -/** Node type: rtp +/* Node type: rtp * - * @file - * @author Steffen Vogel - * @author Marvin Klimke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Marvin Klimke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -29,11 +28,11 @@ extern "C" { namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; class SuperNode; -/** The maximum length of a packet which contains rtp data. */ +// The maximum length of a packet which contains rtp data. #define RTP_INITIAL_BUFFER_LEN 1500 #define RTP_PACKET_TYPE 21 @@ -44,11 +43,11 @@ enum class RTPHookType { }; struct rtp { - struct rtp_sock *rs; /**< RTP socket */ + struct rtp_sock *rs; // RTP socket struct { - struct sa saddr_rtp; /**< Local/Remote address of the RTP socket */ - struct sa saddr_rtcp; /**< Local/Remote address of the RTCP socket */ + struct sa saddr_rtp; // Local/Remote address of the RTP socket + struct sa saddr_rtcp; // Local/Remote address of the RTCP socket } in, out; Format *formatter; @@ -68,16 +67,16 @@ struct rtp { LimitHook::Ptr rate_hook; dsp::PID rate_pid; - /* PID parameters for rate controller */ + // PID parameters for rate controller double Kp, Ki, Kd; double rate_min; double rate; - double rate_source; /**< Sample rate of source */ + double rate_source; // Sample rate of source std::ofstream *log; char *log_filename; - } aimd; /** AIMD state */ + } aimd; // AIMD state struct CQueueSignalled recv_queue; struct mbuf *send_mb; diff --git a/include/villas/nodes/shmem.hpp b/include/villas/nodes/shmem.hpp index ae94d446b..7fbf4d81e 100644 --- a/include/villas/nodes/shmem.hpp +++ b/include/villas/nodes/shmem.hpp @@ -1,10 +1,9 @@ -/** Node-type for shared memory communication. +/* Node-type for shared memory communication. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,15 +16,15 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct shmem { - const char* out_name; /**< Name of the shm object for the output queue. */ - const char* in_name; /**< Name of the shm object for the input queue. */ - struct ShmemConfig conf; /**< Interface configuration struct. */ - char **exec; /**< External program to execute on start. */ - struct ShmemInterface intf; /**< Shmem interface */ + const char* out_name; // Name of the shm object for the output queue. + const char* in_name; // Name of the shm object for the input queue. + struct ShmemConfig conf; // Interface configuration struct. + char **exec; // External program to execute on start. + struct ShmemInterface intf; // Shmem interface }; char * shmem_print(NodeCompat *n); diff --git a/include/villas/nodes/signal.hpp b/include/villas/nodes/signal.hpp index f63dcc328..e0a09a0e0 100644 --- a/include/villas/nodes/signal.hpp +++ b/include/villas/nodes/signal.hpp @@ -1,10 +1,9 @@ -/** Node-type for signal generation. +/* Node-type for signal generation. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class SignalNodeSignal { @@ -35,15 +34,15 @@ public: enum Type type; - double frequency; /**< Frequency of the generated signals. */ - double amplitude; /**< Amplitude of the generated signals. */ - double stddev; /**< Standard deviation of random signals (normal distributed). */ - double offset; /**< A constant bias. */ - double pulse_width; /**< Width of a pulse with respect to the rate (duration = pulse_width/rate) */ - double pulse_low; /**< Amplitude when pulse signal is off */ - double pulse_high; /**< Amplitude when pulse signal is on */ - double phase; /**< Phase (rad) offset with respect to program start */ - double last; /**< The values from the previous period which are required for random walk. */ + double frequency; // Frequency of the generated signals. + double amplitude; // Amplitude of the generated signals. + double stddev; // Standard deviation of random signals (normal distributed). + double offset; // A constant bias. + double pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double pulse_low; // Amplitude when pulse signal is off + double pulse_high; // Amplitude when pulse signal is on + double phase; // Phase (rad) offset with respect to program start + double last; // The values from the previous period which are required for random walk. public: SignalNodeSignal(json_t *json); @@ -68,15 +67,15 @@ class SignalNode : public Node { protected: std::vector signals; - struct Task task; /**< Timer for periodic events. */ - int rt; /**< Real-time mode? */ + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? - double rate; /**< Sampling rate. */ - bool monitor_missed; /**< Boolean, if set, node counts missed steps and warns user. */ - int limit; /**< The number of values which should be generated by this node. <0 for infinite. */ + double rate; // Sampling rate. + bool monitor_missed; // Boolean, if set, node counts missed steps and warns user. + int limit; // The number of values which should be generated by this node. <0 for infinite. - struct timespec started; /**< Point in time when this node was started. */ - unsigned missed_steps; /**< Total number of missed steps. */ + struct timespec started; // Point in time when this node was started. + unsigned missed_steps; // Total number of missed steps. virtual int _read(struct Sample *smps[], unsigned cnt); diff --git a/include/villas/nodes/signal_old.hpp b/include/villas/nodes/signal_old.hpp index c0200cf0d..9617d4a1a 100644 --- a/include/villas/nodes/signal_old.hpp +++ b/include/villas/nodes/signal_old.hpp @@ -1,10 +1,9 @@ -/** Node-type for signal generation. +/* Node-type for signal generation. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,13 +13,13 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct Sample; struct signal_node { - struct Task task; /**< Timer for periodic events. */ - int rt; /**< Real-time mode? */ + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? enum class SignalType { RANDOM, @@ -32,27 +31,27 @@ struct signal_node { CONSTANT, MIXED, PULSE - } *type; /**< Signal type */ + } *type; // Signal type - double rate; /**< Sampling rate. */ - double *frequency; /**< Frequency of the generated signals. */ - double *amplitude; /**< Amplitude of the generated signals. */ - double *stddev; /**< Standard deviation of random signals (normal distributed). */ - double *offset; /**< A constant bias. */ - double *pulse_width; /**< Width of a pulse with respect to the rate (duration = pulse_width/rate) */ - double *pulse_low; /**< Amplitude when pulse signal is off */ - double *pulse_high; /**< Amplitude when pulse signal is on */ - double *phase; /**< Phase (rad) offset with respect to program start */ - int monitor_missed; /**< Boolean, if set, node counts missed steps and warns user. */ + double rate; // Sampling rate. + double *frequency; // Frequency of the generated signals. + double *amplitude; // Amplitude of the generated signals. + double *stddev; // Standard deviation of random signals (normal distributed). + double *offset; // A constant bias. + double *pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double *pulse_low; // Amplitude when pulse signal is off + double *pulse_high; // Amplitude when pulse signal is on + double *phase; // Phase (rad) offset with respect to program start + int monitor_missed; // Boolean, if set, node counts missed steps and warns user. - double *last; /**< The values from the previous period which are required for random walk. */ + double *last; // The values from the previous period which are required for random walk. - unsigned values; /**< The number of values which will be emitted by this node. */ - int limit; /**< The number of values which should be generated by this node. <0 for infinitve. */ + unsigned values; // The number of values which will be emitted by this node. + int limit; // The number of values which should be generated by this node. <0 for infinitve. - struct timespec started; /**< Point in time when this node was started. */ - unsigned counter; /**< The number of packets already emitted. */ - unsigned missed_steps; /**< Total number of missed steps. */ + struct timespec started; // Point in time when this node was started. + unsigned counter; // The number of packets already emitted. + unsigned missed_steps; // Total number of missed steps. }; char * signal_node_print(NodeCompat *n); diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index f4fc53539..31284b387 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -1,10 +1,9 @@ -/** The socket node-type for Layer 2, 3, 4 BSD-style sockets +/* The socket node-type for Layer 2, 3, 4 BSD-style sockets * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,36 +14,35 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; -/** The maximum length of a packet which contains stuct msg. */ +// The maximum length of a packet which contains stuct msg. #define SOCKET_INITIAL_BUFFER_LEN (64*1024) struct Socket { - int sd; /**< The socket descriptor */ - int verify_source; /**< Verify the source address of incoming packets against socket::remote. */ + int sd; // The socket descriptor + int verify_source; // Verify the source address of incoming packets against socket::remote. - enum SocketLayer 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 Format *formatter; - /* Multicast options */ + // Multicast options struct multicast { - int enabled; /**< Is multicast enabled? */ - unsigned char loop; /** Loopback multicast packets to local host? */ - unsigned char ttl; /**< The time to live for multicast packets. */ - struct ip_mreq mreq; /**< A multicast group to join. */ + int enabled; // Is multicast enabled? + unsigned char loop; // Loopback multicast packets to local host? + unsigned char ttl; // The time to live for multicast packets. + struct ip_mreq mreq; // A multicast group to join. } multicast; struct { - char *buf; /**< Buffer for receiving messages */ + char *buf; // Buffer for receiving messages size_t buflen; - union sockaddr_union saddr; /**< Remote address of the socket */ + union sockaddr_union saddr; // Remote address of the socket } in, out; }; - int socket_type_start(SuperNode *sn); int socket_type_stop(); diff --git a/include/villas/nodes/stats.hpp b/include/villas/nodes/stats.hpp index 9b9c45b7b..f25dac4b5 100644 --- a/include/villas/nodes/stats.hpp +++ b/include/villas/nodes/stats.hpp @@ -1,10 +1,9 @@ -/** Node-type for stats streaming. +/* Node-type for stats streaming. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,7 +16,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct stats_node_signal { @@ -33,7 +32,7 @@ struct stats_node { struct Task task; - struct List signals; /** List of type struct stats_node_signal */ + struct List signals; // List of type struct stats_node_signal }; int stats_node_type_start(SuperNode *sn); diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index 9224b3540..4089d7aa7 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -1,10 +1,9 @@ -/** An temper get started with new implementations of new node-types +/* An temper get started with new implementations of new node-types * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,13 +16,14 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; class TEMPerDevice : public villas::usb::Device { protected: - constexpr static unsigned char question_temperature[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 }; + constexpr static + unsigned char question_temperature[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 }; float scale; float offset; @@ -32,22 +32,31 @@ protected: villas::Logger logger; - virtual void decode(unsigned char *answer, float *temp) = 0; + virtual + void decode(unsigned char *answer, float *temp) = 0; public: - static TEMPerDevice * make(struct libusb_device *desc); + static + TEMPerDevice * make(struct libusb_device *desc); TEMPerDevice(struct libusb_device *dev); - virtual ~TEMPerDevice() + virtual + ~TEMPerDevice() { } void open(bool reset = true); void close(); - virtual int getNumSensors() const - { return 1; } + virtual + int getNumSensors() const + { + return 1; + } - virtual bool hasHumiditySensor() const - { return false; }; + virtual + bool hasHumiditySensor() const + { + return false; + } void read(struct Sample *smp); }; @@ -55,49 +64,70 @@ public: class TEMPer1Device : public TEMPerDevice { protected: - virtual void decode(unsigned char *answer, float *temp); + virtual + void decode(unsigned char *answer, float *temp); using TEMPerDevice::TEMPerDevice; public: - static bool match(struct libusb_device *dev); + static + bool match(struct libusb_device *dev); - static std::string getName() - { return "TEMPer1"; } + static + std::string getName() + { + return "TEMPer1"; + } }; class TEMPer2Device : public TEMPer1Device { protected: - virtual void decode(unsigned char *answer, float *temp); + virtual + void decode(unsigned char *answer, float *temp); using TEMPer1Device::TEMPer1Device; public: - static bool match(struct libusb_device *dev); + static + bool match(struct libusb_device *dev); - static std::string getName() - { return "TEMPer2"; } + static + std::string getName() + { + return "TEMPer2"; + } - virtual int getNumSensors() const - { return 2; } + virtual + int getNumSensors() const + { + return 2; + } }; class TEMPerHUMDevice : public TEMPerDevice { protected: - virtual void decode(unsigned char *answer, float *temp); + virtual + void decode(unsigned char *answer, float *temp); using TEMPerDevice::TEMPerDevice; public: - static bool match(struct libusb_device *dev); + static + bool match(struct libusb_device *dev); - static std::string getName() - { return "TEMPerHUM"; } + static + std::string getName() + { + return "TEMPerHUM"; + } - virtual bool hasHumiditySensor() const - { return true; } + virtual + bool hasHumiditySensor() const + { + return true; + } }; struct temper { diff --git a/include/villas/nodes/test_rtt.hpp b/include/villas/nodes/test_rtt.hpp index 0e357f090..1d04ef4a5 100644 --- a/include/villas/nodes/test_rtt.hpp +++ b/include/villas/nodes/test_rtt.hpp @@ -1,10 +1,9 @@ -/** Node type: Node-type for testing Round-trip Time. +/* Node type: Node-type for testing Round-trip Time. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct Sample; @@ -24,7 +23,7 @@ struct test_rtt; struct test_rtt_case { double rate; unsigned values; - unsigned limit; /**< The number of samples we take per test. */ + unsigned limit; // The number of samples we take per test. char *filename; char *filename_formatted; @@ -33,19 +32,19 @@ struct test_rtt_case { }; struct test_rtt { - struct Task task; /**< The periodic task for test_rtt_read() */ - Format *formatter;/**< The format of the output file */ + struct Task task; // The periodic task for test_rtt_read() + Format *formatter;// The format of the output file FILE *stream; - double cooldown; /**< Number of seconds to wait beween tests. */ + double cooldown; // Number of seconds to wait beween tests. - int current; /**< Index of current test in test_rtt::cases */ + int current; // Index of current test in test_rtt::cases int counter; - struct List cases; /**< List of test cases */ + struct List cases; // List of test cases - char *output; /**< The directory where we place the results. */ - char *prefix; /**< An optional prefix in the filename. */ + char *output; // The directory where we place the results. + char *prefix; // An optional prefix in the filename. }; char * test_rtt_print(NodeCompat *n); diff --git a/include/villas/nodes/uldaq.hpp b/include/villas/nodes/uldaq.hpp index 8378844ca..0a13c00fc 100644 --- a/include/villas/nodes/uldaq.hpp +++ b/include/villas/nodes/uldaq.hpp @@ -1,11 +1,10 @@ -/** Node-type for uldaq connections. +/* Node-type for uldaq connections. * - * @file - * @author Manuel Pitz - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -71,6 +70,5 @@ int uldaq_stop(NodeCompat *n); int uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); - } // namespace node } // namespace villas diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp index 3d7593fd1..89d359ce6 100644 --- a/include/villas/nodes/webrtc.hpp +++ b/include/villas/nodes/webrtc.hpp @@ -1,12 +1,11 @@ -/** Node-type webrtc. +/* Node-type webrtc. * - * @file - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,7 +21,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class WebRTCNode : public Node { @@ -75,7 +74,6 @@ public: const std::string & getDetails(); }; - class WebRTCNodeFactory : public NodeFactory { public: @@ -116,6 +114,5 @@ public: int start(SuperNode *sn); }; - } // namespace node } // namespace villas diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index ebbfd42e7..9565b6eba 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -1,12 +1,11 @@ -/** WebRTC peer connection +/* WebRTC peer connection * - * @file - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -93,4 +92,3 @@ protected: } // namespace webrtc } // namespace node } // namespace villas - diff --git a/include/villas/nodes/webrtc/signaling_client.hpp b/include/villas/nodes/webrtc/signaling_client.hpp index 13e09eccd..e72bfc714 100644 --- a/include/villas/nodes/webrtc/signaling_client.hpp +++ b/include/villas/nodes/webrtc/signaling_client.hpp @@ -1,12 +1,11 @@ -/** WebRTC signaling client +/* WebRTC signaling client * - * @file - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,7 +23,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Web; namespace webrtc { @@ -33,24 +32,26 @@ class SignalingClient { protected: struct sul_offsetof_helper { - lws_sorted_usec_list_t sul; /**> Schedule connection retry */ + lws_sorted_usec_list_t sul; // Schedule connection retry SignalingClient *self; } sul_helper; - uint16_t retry_count; /**> Count of consecutive retries */ + uint16_t retry_count; // Count of consecutive retries struct lws *wsi; struct lws_client_connect_info info; - /* The retry and backoff policy we want to use for our client connections */ - static constexpr uint32_t backoff_ms[] = { 1<<4, 1<<6, 1<<8, 1<<10, 1<<12, 1<<14, 1<<16 }; - static constexpr lws_retry_bo_t retry = { + // The retry and backoff policy we want to use for our client connections + static constexpr + uint32_t backoff_ms[] = { 1<<4, 1<<6, 1<<8, 1<<10, 1<<12, 1<<14, 1<<16 }; + static constexpr + lws_retry_bo_t retry = { .retry_ms_table = backoff_ms, .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), .conceal_count = LWS_ARRAY_SIZE(backoff_ms) + 1, - .secs_since_valid_ping = 3, /* force PINGs after secs idle */ - .secs_since_valid_hangup = 10, /* hangup after secs idle */ + .secs_since_valid_ping = 3, // force PINGs after secs idle + .secs_since_valid_hangup = 10, // hangup after secs idle .jitter_percent = 20, }; @@ -116,4 +117,3 @@ public: } // namespace webrtc } // namespace node } // namespace villas - diff --git a/include/villas/nodes/webrtc/signaling_message.hpp b/include/villas/nodes/webrtc/signaling_message.hpp index b0d651691..f07b350e8 100644 --- a/include/villas/nodes/webrtc/signaling_message.hpp +++ b/include/villas/nodes/webrtc/signaling_message.hpp @@ -1,12 +1,11 @@ -/** WebRTC signaling messages. +/* WebRTC signaling messages. * - * @file - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -52,7 +51,8 @@ struct ControlMessage { struct SignalingMessage { std::variant message; - static SignalingMessage fromJson(json_t *j); + static + SignalingMessage fromJson(json_t *j); json_t * toJson() const; std::string toString() const; }; diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index 7a3d74017..581ef2b21 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -1,10 +1,9 @@ -/** Node type: WebSockets +/* Node type: WebSockets * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,7 +18,7 @@ #include #include -/* Forward declaration */ +// Forward declarations struct lws; namespace villas { @@ -27,14 +26,14 @@ namespace node { #define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) -/** Internal data per websocket node */ +// Internal data per websocket node struct websocket { - struct List destinations; /**< List of websocket servers connect to in client mode (struct websocket_destination). */ + struct List destinations; // List of websocket servers connect to in client mode (struct websocket_destination). - bool wait; /**< Wait until all destinations are connected. */ + bool wait; // Wait until all destinations are connected. struct Pool pool; - struct CQueueSignalled queue; /**< For samples which are received from WebSockets */ + struct CQueueSignalled queue; // For samples which are received from WebSockets }; struct websocket_destination { @@ -42,7 +41,7 @@ struct websocket_destination { struct lws_client_connect_info info; }; -/* Internal datastructures */ +// Internal datastructures struct websocket_connection { enum State { DESTROYED, @@ -53,7 +52,7 @@ struct websocket_connection { CLOSING, CLOSED, ERROR - } state; /**< The current status of this connection. */ + } state; // The current status of this connection. enum class Mode { CLIENT, @@ -63,16 +62,16 @@ struct websocket_connection { struct lws *wsi; NodeCompat *node; Format *formatter; - struct CQueue queue; /**< For samples which are sent to the Websocket */ + struct CQueue queue; // For samples which are sent to the Websocket struct websocket_destination *destination; struct { - villas::Buffer *recv; /**< A buffer for reconstructing fragmented messages. */ - villas::Buffer *send; /**< A buffer for constructing messages before calling lws_write() */ + villas::Buffer *recv; // A buffer for reconstructing fragmented messages. + villas::Buffer *send; // A buffer for constructing messages before calling lws_write() } buffers; - /** Custom formatter for spdlog */ + // Custom formatter for spdlog template friend OStream &operator<<(OStream &os, const struct websocket_connection &c) { diff --git a/include/villas/nodes/zeromq.hpp b/include/villas/nodes/zeromq.hpp index 40de65a29..af3cb5d7e 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -1,10 +1,9 @@ -/** Node type: ZeroMQ +/* Node type: ZeroMQ * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,7 +21,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class NodeCompat; struct Sample; @@ -47,7 +46,7 @@ struct zeromq { } pattern; struct Dir { - void *socket; /**< ZeroMQ socket. */ + void *socket; // ZeroMQ socket. void *mon_socket; struct List endpoints; char *filter; diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 3f84f2ac3..a33c15042 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -1,10 +1,9 @@ -/** Message paths +/* Message paths * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -30,16 +29,16 @@ #include -/* Forward declarations */ +// Forward declarations struct pollfd; namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; -/** The datastructure for a path. */ +// The datastructure for a path. class Path { friend PathSource; friend SecondaryPathSource; @@ -54,16 +53,17 @@ protected: void startPoll(); - static int id; + static + int id; public: - enum State state; /**< Path state. */ + enum State state; // Path state. - /** The register mode determines under which condition the path is triggered. */ + // The register mode determines under which condition the path is triggered. enum class Mode { - 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. */ - } mode; /**< Determines when this path is triggered. */ + 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. + } mode; // Determines when this path is triggered. uuid_t uuid; @@ -74,32 +74,32 @@ public: int last_sequence; NodeList masked; - MappingList mappings; /**< List of all input mappings. */ - PathSourceList sources; /**< List of all incoming nodes. */ - PathDestinationList destinations; /**< List of all outgoing nodes. */ - HookList hooks; /**< List of processing hooks. */ - SignalList::Ptr signals; /**< List of signals which this path creates. */ + MappingList mappings; // List of all input mappings. + PathSourceList sources; // List of all incoming nodes. + PathDestinationList destinations; // List of all outgoing nodes. + HookList hooks; // List of processing hooks. + SignalList::Ptr signals; // List of signals which this path creates. struct Task timeout; - double rate; /**< A timeout for */ - int affinity; /**< Thread affinity. */ - bool enabled; /**< Is this path enabled? */ - int poll; /**< Weather or not to use poll(2). */ - bool reversed; /**< This path has a matching reverse path. */ - bool builtin; /**< This path should use built-in hooks by default. */ - int original_sequence_no; /**< Use original source sequence number when multiplexing */ - unsigned queuelen; /**< The queue length for each path_destination::queue */ + double rate; // A timeout for + int affinity; // Thread affinity. + bool enabled; // Is this path enabled? + int poll; // Weather or not to use poll(2). + bool reversed; // This path has a matching reverse path. + bool builtin; // This path should use built-in hooks by default. + int original_sequence_no; // Use original source sequence number when multiplexing + unsigned queuelen; // The queue length for each path_destination::queue - pthread_t tid; /**< The thread id for this path. */ - json_t *config; /**< A JSON object containing the configuration of the path. */ + pthread_t tid; // The thread id for this path. + json_t *config; // A JSON object containing the configuration of the path. Logger logger; - std::bitset mask; /**< A mask of PathSources which are enabled for poll(). */ - std::bitset received; /**< A mask of PathSources for which we already received samples. */ + std::bitset mask; // A mask of PathSources which are enabled for poll(). + std::bitset received; // A mask of PathSources for which we already received samples. - /** Custom formatter for spdlog */ + // Custom formatter for spdlog template friend OStream &operator<<(OStream &os, const Path &p) { @@ -138,27 +138,27 @@ public: void prepare(NodeList &nodes); - /** Check if path configuration is proper. */ + // Check if path configuration is proper. void check(); - /** Check prepared path. */ + // Check prepared path. void checkPrepared(); - /** Start a path. + /* Start a path. * * Start a new pthread for receiving/sending messages over this path. */ void start(); - /** Stop a path. */ + // Stop a path. void stop(); - /** Get a list of signals which is emitted by the path. */ + // Get a list of signals which is emitted by the path. SignalList::Ptr getOutputSignals(bool after_hooks = true); unsigned getOutputSignalsMaxCount(); - /** Parse a single path and add it to the global configuration. + /* Parse a single path and add it to the global configuration. * * @param json A JSON object containing the configuration of the path. * @param p Pointer to the allocated memory for this path @@ -188,7 +188,7 @@ public: return state; } - /** Get the UUID of this path. */ + // Get the UUID of this path. const uuid_t & getUuid() const { return uuid; diff --git a/include/villas/path_destination.hpp b/include/villas/path_destination.hpp index 9239c3a00..90117fe2c 100644 --- a/include/villas/path_destination.hpp +++ b/include/villas/path_destination.hpp @@ -1,10 +1,9 @@ -/** Path destination +/* Path destination * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,7 +14,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; class Path; struct Sample; diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 220c8ebce..53198bfc6 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -1,11 +1,9 @@ -/** Node list +/* Node list * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,13 +16,13 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Path; class PathList : public std::list { public: - /** Lookup a path from the list based on its UUID */ + // Lookup a path from the list based on its UUID Path * lookup(const uuid_t &uuid) const; json_t * toJson() const; diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp index ea7da31c7..28bec72fb 100644 --- a/include/villas/path_source.hpp +++ b/include/villas/path_source.hpp @@ -1,10 +1,9 @@ -/** Message source +/* Message source * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,7 +16,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class Node; class Path; @@ -36,11 +35,12 @@ protected: struct Pool pool; - MappingList mappings; /**< List of mappings (struct MappingEntry). */ + MappingList mappings; // List of mappings (struct MappingEntry). public: PathSource(Path *p, Node *n); - virtual ~PathSource(); + virtual + ~PathSource(); void check(); @@ -79,7 +79,7 @@ using SecondaryPathSourceList = std::vector; class MasterPathSource : public PathSource { protected: - SecondaryPathSourceList secondaries; /**< List of secondary path sources (PathSource). */ + SecondaryPathSourceList secondaries; // List of secondary path sources (PathSource). public: MasterPathSource(Path *p, Node *n); @@ -99,6 +99,5 @@ public: }; - } // namespace node } // namespace villas diff --git a/include/villas/pool.hpp b/include/villas/pool.hpp index 41932a395..41fb88caf 100644 --- a/include/villas/pool.hpp +++ b/include/villas/pool.hpp @@ -1,12 +1,11 @@ -/** Memory pool for fixed size objects. +/* Memory pool for fixed size objects. * * This datastructure is based on a lock-less stack (lstack). * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -20,22 +19,22 @@ namespace villas { namespace node { -/** A thread-safe memory pool */ +// A thread-safe memory pool struct Pool { enum State state; - off_t buffer_off; /**< Offset from the struct address to the underlying memory area */ + off_t buffer_off; // Offset from the struct address to the underlying memory area - size_t len; /**< Length of the underlying memory area */ - size_t blocksz; /**< Length of a block in bytes */ - size_t alignment; /**< Alignment of a block in bytes */ + size_t len; // Length of the underlying memory area + size_t blocksz; // Length of a block in bytes + size_t alignment; // Alignment of a block in bytes - struct CQueue queue; /**< The queue which is used to keep track of free blocks */ + struct CQueue queue; // The queue which is used to keep track of free blocks }; #define pool_buffer(p) ((char *) (p) + (p)->buffer_off) -/** Initiazlize a pool +/* Initiazlize a pool * * @param[inout] p The pool data structure. * @param[in] cnt The total number of blocks which are reserverd by this pool. @@ -46,10 +45,10 @@ struct Pool { */ int pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); -/** Destroy and release memory used by pool. */ +// Destroy and release memory used by pool. int pool_destroy(struct Pool *p) __attribute__ ((warn_unused_result)); -/** Pop up to \p cnt values from the stack an place them in the array \p blocks. +/* Pop up to \p cnt values from the stack an place them in the array \p blocks. * * @return The number of blocks actually retrieved from the pool. * This number can be smaller than the requested \p cnt blocks @@ -57,13 +56,13 @@ int pool_destroy(struct Pool *p) __attribute__ ((warn_unused_result)); */ ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt); -/** Push \p cnt values which are giving by the array values to the stack. */ +// Push \p cnt values which are giving by the array values to the stack. ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt); -/** Get a free memory block from pool. */ +// Get a free memory block from pool. void * pool_get(struct Pool *p); -/** Release a memory block back to the pool. */ +// Release a memory block back to the pool. int pool_put(struct Pool *p, void *buf); } // namespace node diff --git a/include/villas/queue.h b/include/villas/queue.h index 7906628ed..e4dc8d728 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -1,11 +1,11 @@ -/** Lock-free Multiple-Producer Multiple-consumer (MPMC) queue. +/* Lock-free Multiple-Producer Multiple-consumer (MPMC) queue. * * Based on Dmitry Vyukov#s Bounded MPMC queue: * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * - * @author Steffen Vogel - * @copyright 2014-2021, Steffen Vogel - * @license BSD 2-Clause License + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2021 Steffen Vogel + * SPDX-License-Identifier: BSD-2-Clause * * All rights reserved. * @@ -29,7 +29,7 @@ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *********************************************************************************/ + */ #pragma once @@ -50,36 +50,36 @@ typedef char cacheline_pad_t[CACHELINE_SIZE]; struct CQueue_cell { std::atomic sequence; - off_t data_off; /**< Pointer relative to the queue struct */ + off_t data_off; // Pointer relative to the queue struct }; -/** A lock-free multiple-producer, multiple-consumer (MPMC) queue. */ +// A lock-free multiple-producer, multiple-consumer (MPMC) queue. struct CQueue { std::atomic state; - cacheline_pad_t _pad0; /**< Shared area: all threads read */ + cacheline_pad_t _pad0; // Shared area: all threads read size_t buffer_mask; - off_t buffer_off; /**< Relative pointer to struct CQueue_cell[] */ + off_t buffer_off; // Relative pointer to struct CQueue_cell[] - cacheline_pad_t _pad1; /**< Producer area: only producers read & write */ + cacheline_pad_t _pad1; // Producer area: only producers read & write - std::atomic tail; /**< Queue tail pointer */ + std::atomic tail; // Queue tail pointer - cacheline_pad_t _pad2; /**< Consumer area: only consumers read & write */ + cacheline_pad_t _pad2; // Consumer area: only consumers read & write - std::atomic head; /**< Queue head pointer */ + std::atomic head; // Queue head pointer - cacheline_pad_t _pad3; /**< @todo Why needed? */ + cacheline_pad_t _pad3; // @todo Why needed? }; -/** Initialize MPMC queue */ +// Initialize MPMC queue int queue_init(struct CQueue *q, size_t size, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); -/** Desroy MPMC queue and release memory */ +// Desroy MPMC queue and release memory int queue_destroy(struct CQueue *q) __attribute__ ((warn_unused_result)); -/** Return estimation of current queue usage. +/* Return estimation of current queue usage. * * Note: This is only an estimation and not accurate as long other * threads are performing operations. @@ -90,14 +90,14 @@ int queue_push(struct CQueue *q, void *ptr); int queue_pull(struct CQueue *q, void **ptr); -/** Enqueue up to \p cnt pointers of the \p ptr array into the queue. +/* Enqueue up to \p cnt pointers of the \p ptr array into the queue. * * @return The number of pointers actually enqueued. * This number can be smaller then \p cnt in case the queue is filled. */ int queue_push_many(struct CQueue *q, void *ptr[], size_t cnt); -/** Dequeue up to \p cnt pointers from the queue and place them into the \p ptr array. +/* Dequeue up to \p cnt pointers from the queue and place them into the \p ptr array. * * @return The number of pointers actually dequeued. * This number can be smaller than \p cnt in case the queue contained less than @@ -105,7 +105,7 @@ int queue_push_many(struct CQueue *q, void *ptr[], size_t cnt); */ int queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt); -/** Closes the queue, causing following writes to fail and following reads (after +/* Closes the queue, causing following writes to fail and following reads (after * the queue is empty) to fail. * * @return 0 on success. diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index 3e783b40d..d5b50046c 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -1,10 +1,9 @@ -/** Wrapper around queue that uses POSIX CV's for signalling writes. +/* Wrapper around queue that uses POSIX CV's for signalling writes. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index 6a50ce5a8..a33cd65e2 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -1,10 +1,9 @@ -/** Wrapper around queue that uses POSIX CV's for signalling writes. +/* Wrapper around queue that uses POSIX CV's for signalling writes. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -17,7 +16,7 @@ namespace villas { namespace node { enum class QueueSignalledMode { - AUTO, /**< We will choose the best method available on the platform */ + AUTO, // We will choose the best method available on the platform PTHREAD, POLLING, #ifdef HAS_EVENTFD @@ -30,17 +29,17 @@ enum class QueueSignalledFlags { PROCESS_SHARED = (1 << 4) }; -/** Wrapper around queue that uses POSIX CV's for signalling writes. */ +// Wrapper around queue that uses POSIX CV's for signalling writes. struct CQueueSignalled { - struct CQueue queue; /**< Actual underlying queue. */ + struct CQueue queue; // Actual underlying queue. enum QueueSignalledMode mode; enum QueueSignalledFlags flags; union { struct { - pthread_cond_t ready; /**< Condition variable to signal writes to the queue. */ - pthread_mutex_t mutex; /**< Mutex for ready. */ + pthread_cond_t ready; // Condition variable to signal writes to the queue. + pthread_mutex_t mutex; // Mutex for ready. } pthread; #ifdef __linux__ int eventfd; @@ -64,7 +63,7 @@ int queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cn int queue_signalled_close(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); -/** Returns a file descriptor which can be used with poll / select to wait for new data */ +// Returns a file descriptor which can be used with poll / select to wait for new data int queue_signalled_fd(struct CQueueSignalled *qs); } // namespace node diff --git a/include/villas/queue_signalled.hpp b/include/villas/queue_signalled.hpp index a343181cf..6e474b533 100644 --- a/include/villas/queue_signalled.hpp +++ b/include/villas/queue_signalled.hpp @@ -1,10 +1,9 @@ -/** Wrapper around queue that uses POSIX CV's for signalling writes. +/* Wrapper around queue that uses POSIX CV's for signalling writes. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index 4964476e0..600037e00 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -1,10 +1,9 @@ -/** The internal datastructure for a sample of simulation data. +/* The internal datastructure for a sample of simulation data. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,57 +18,57 @@ #include #include -/** The length of a sample datastructure with \p values values in bytes. */ +// The length of a sample datastructure with \p values values in bytes. #define SAMPLE_LENGTH(len) (sizeof(struct Sample) + SAMPLE_DATA_LENGTH(len)) -/** The length of a sample data portion of a sample datastructure with \p values values in bytes. */ +// The length of a sample data portion of a sample datastructure with \p values values in bytes. #define SAMPLE_DATA_LENGTH(len) ((len) * sizeof(double)) -/** The number of values in a sample datastructure. */ +// The number of values in a sample datastructure. #define SAMPLE_NUMBER_OF_VALUES(len) ((len) / sizeof(double)) -/** The offset to the beginning of the data section. */ +// The offset to the beginning of the data section. #define SAMPLE_DATA_OFFSET(smp) ((char *) (smp) + offsetof(struct Sample, data)) namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Pool; -/** Parts of a sample that can be serialized / de-serialized by the IO formats */ +// Parts of a sample that can be serialized / de-serialized by the IO formats 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_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_TS = HAS_TS_ORIGIN | HAS_TS_RECEIVED, /**< Include origin timestamp in output. */ - HAS_ALL = (1 << 5) - 1, /**< Enable all output options. */ + HAS_TS = HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. + HAS_ALL = (1 << 5) - 1, // Enable all output options. - 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 */ + 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 { - uint64_t sequence; /**< The sequence number of this sample. */ - unsigned length; /**< The number of values in sample::values which are valid. */ - unsigned capacity; /**< The number of values in sample::values for which memory is reserved. */ - int flags; /**< Flags are used to store binary properties of a sample. */ + uint64_t sequence; // The sequence number of this sample. + unsigned length; // The number of values in sample::values which are valid. + unsigned capacity; // The number of values in sample::values for which memory is reserved. + int flags; // Flags are used to store binary properties of a sample. - SignalList::Ptr signals; /**< The list of signal descriptors. */ + SignalList::Ptr signals; // The list of signal descriptors. - std::atomic refcnt; /**< Reference counter. */ - ptrdiff_t pool_off; /**< This sample belongs to this memory pool (relative pointer). See sample_pool(). */ + std::atomic refcnt; // Reference counter. + ptrdiff_t pool_off; // This sample belongs to this memory pool (relative pointer). See sample_pool(). - /** All timestamps are seconds / nano seconds after 1.1.1970 UTC */ + // All timestamps are seconds / nano seconds after 1.1.1970 UTC struct { - struct timespec origin; /**< The point in time when this data was sampled. */ - struct timespec received; /**< The point in time when this data was received. */ + struct timespec origin; // The point in time when this data was sampled. + struct timespec received; // The point in time when this data was received. } ts; - /** The sample signal values. + /* The sample signal values. * * This variable length array (VLA) extends over the end of struct Sample. * Make sure that pointers to struct Sample point to memory blocks of adequate size. @@ -84,7 +83,7 @@ struct Sample { #define SAMPLE_NON_POOL PTRDIFF_MIN -/** Get the address of the pool to which the sample belongs. */ +// Get the address of the pool to which the sample belongs. #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); @@ -97,26 +96,26 @@ struct Sample * sample_clone(struct Sample *smp); void sample_free(struct Sample *s); -/** Request \p cnt samples from memory pool \p p and initialize them. +/* Request \p cnt samples from memory pool \p p and initialize them. * The reference count will already be set to 1. * Use the sample_incref() function to increase it. */ int sample_alloc_many(struct Pool *p, struct Sample *smps[], int cnt); -/** Release an array of samples back to their pools */ +// Release an array of samples back to their pools void sample_free_many(struct Sample *smps[], int cnt); -/** Increase reference count of sample */ +// Increase reference count of sample int sample_incref(struct Sample *s); -/** Decrease reference count and release memory if last reference was held. */ +// Decrease reference count and release memory if last reference was held. int sample_decref(struct Sample *s); int sample_copy(struct Sample *dst, const struct Sample *src); -/** Dump all details about a sample to debug log */ +// Dump all details about a sample to debug log void sample_dump(villas::Logger logger, struct Sample *s); -/** Compare two samples */ +// Compare two samples int sample_cmp(struct Sample *a, struct Sample *b, double epsilon, int flags); int sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt); diff --git a/include/villas/shmem.hpp b/include/villas/shmem.hpp index ebeefe0a3..d8940c24c 100644 --- a/include/villas/shmem.hpp +++ b/include/villas/shmem.hpp @@ -1,10 +1,9 @@ -/** Shared-memory interface: The interface functions that the external program should use. +/* Shared-memory interface: The interface functions that the external program should use. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,36 +18,36 @@ namespace villas { namespace node { -/** Struct containing all parameters that need to be known when creating a new +/* Struct containing all parameters that need to be known when creating a new * shared memory object. */ struct ShmemConfig { - int polling; /**< Whether to use polling instead of POSIX CVs */ - int queuelen; /**< Size of the queues (in elements) */ - int samplelen; /**< Maximum number of data entries in a single sample */ + int polling; // Whether to use polling instead of POSIX CVs + int queuelen; // Size of the queues (in elements) + int samplelen; // Maximum number of data entries in a single sample }; -/** The structure that actually resides in the shared memory. */ +// The structure that actually resides in the shared memory. struct ShmemShared { - int polling; /**< Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. */ - struct CQueueSignalled queue; /**< Queue for samples passed in both directions. */ - struct Pool pool; /**< Pool for the samples in the queues. */ + int polling; // Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. + struct CQueueSignalled queue; // Queue for samples passed in both directions. + struct Pool pool; // Pool for the samples in the queues. }; -/** Relevant information for one direction of the interface. */ +// Relevant information for one direction of the interface. struct shmem_dir { - void *base; /**< Base address of the region. */ - const char *name; /**< Name of the shmem object. */ - size_t len; /**< Total size of the region. */ - struct ShmemShared *shared; /**< Actually shared datastructure */ + void *base; // Base address of the region. + const char *name; // Name of the shmem object. + size_t len; // Total size of the region. + struct ShmemShared *shared; // Actually shared datastructure }; -/** Main structure representing the shared memory interface. */ +// Main structure representing the shared memory interface. struct ShmemInterface { struct shmem_dir read, write; std::atomic readers, writers, closed; }; -/** Open the shared memory objects and retrieve / initialize the shared data structures. +/* Open the shared memory objects and retrieve / initialize the shared data structures. * Blocks until another process connects by opening the same objects. * * @param[in] wname Name of the POSIX shared memory object containing the output queue. @@ -61,7 +60,7 @@ struct ShmemInterface { */ int shmem_int_open(const char* wname, const char* rname, struct ShmemInterface* shm, struct ShmemConfig* conf); -/** Close and destroy the shared memory interface and related structures. +/* Close and destroy the shared memory interface and related structures. * * @param shm The shared memory interface. * @retval 0 Closing successfull. @@ -69,7 +68,7 @@ int shmem_int_open(const char* wname, const char* rname, struct ShmemInterface* */ int shmem_int_close(struct ShmemInterface *shm); -/** Read samples from the interface. +/* Read samples from the interface. * * @param shm The shared memory interface. * @param smps An array where the pointers to the samples will be written. The samples @@ -80,7 +79,7 @@ int shmem_int_close(struct ShmemInterface *shm); */ int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt); -/** Write samples to the interface. +/* Write samples to the interface. * * @param shm The shared memory interface. * @param smps The samples to be written. Must be allocated from shm_int_alloc. @@ -90,7 +89,7 @@ int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], uns */ int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt); -/** Allocate samples to be written to the interface. +/* Allocate samples to be written to the interface. * * The writing process must not free the samples; only the receiving process should free them using sample_decref after use. * @param shm The shared memory interface. @@ -100,7 +99,7 @@ int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps */ int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned cnt); -/** Returns the total size of the shared memory region with the given size of +/* Returns the total size of the shared memory region with the given size of * the input/output queues (in elements) and the given number of data elements * per struct Sample. */ size_t shmem_total_size(int queuelen, int samplelen); diff --git a/include/villas/signal.hpp b/include/villas/signal.hpp index e654431ea..58a9ef14a 100644 --- a/include/villas/signal.hpp +++ b/include/villas/signal.hpp @@ -1,10 +1,9 @@ -/** Signal meta data. +/* Signal meta data. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -15,13 +14,13 @@ #include #include -/* "I" defined by complex.h collides with a define in OpenSSL */ +// "I" defined by complex.h collides with a define in OpenSSL #undef I namespace villas { namespace node { -/** Signal descriptor. +/* Signal descriptor. * * This data structure contains meta data about samples values in struct Sample::data */ @@ -30,21 +29,21 @@ class Signal { public: using Ptr = std::shared_ptr; - std::string name; /**< The name of the signal. */ - std::string unit; /**< The unit of the signal. */ + std::string name; // The name of the signal. + std::string unit; // The unit of the signal. - union SignalData init; /**< The initial value of the signal. */ + union SignalData init; // The initial value of the signal. enum SignalType type; - /** Initialize a signal with default values. */ + // Initialize a signal with default values. Signal(const std::string &n = "", const std::string &u = "", enum SignalType t = SignalType::INVALID); - /** Parse signal description. */ + // Parse signal description. int parse(json_t *json); std::string toString(const union SignalData *d = nullptr) const; - /** Produce JSON representation of signal. */ + // Produce JSON representation of signal. json_t * toJson() const; bool isNext(const Signal &sig); diff --git a/include/villas/signal_data.hpp b/include/villas/signal_data.hpp index be6c91169..56ee7105f 100644 --- a/include/villas/signal_data.hpp +++ b/include/villas/signal_data.hpp @@ -1,10 +1,9 @@ -/** Signal data. +/* Signal data. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -19,21 +18,22 @@ namespace villas { namespace node { -/** A signal value. +/* A signal value. * * Data is in host endianess! */ union SignalData { - double f; /**< Floating point values. */ - int64_t i; /**< Integer values. */ - bool b; /**< Boolean values. */ - std::complex z; /**< Complex values. */ + double f; // Floating point values. + int64_t i; // Integer values. + bool b; // Boolean values. + std::complex z; // Complex values. SignalData() : i(0) { } - static union SignalData nan() + static + union SignalData nan() { union SignalData d; @@ -47,13 +47,13 @@ union SignalData { return f == std::numeric_limits::quiet_NaN(); } - /** Convert signal data from one description/format to another. */ + // Convert signal data from one description/format to another. SignalData cast(enum SignalType type, enum SignalType to) const; - /** Set data from double */ + // Set data from double void set(enum SignalType type, double val); - /** Print value of a signal to a character buffer. */ + // Print value of a signal to a character buffer. int printString(enum SignalType type, char *buf, size_t len, int precision = 5) const; int parseString(enum SignalType type, const char *ptr, char **end); diff --git a/include/villas/signal_list.hpp b/include/villas/signal_list.hpp index 77f34b06e..8fe04c777 100644 --- a/include/villas/signal_list.hpp +++ b/include/villas/signal_list.hpp @@ -1,10 +1,9 @@ -/** Signal metadata lits. +/* Signal metadata lits. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/include/villas/signal_type.hpp b/include/villas/signal_type.hpp index e606eba8f..f890afd67 100644 --- a/include/villas/signal_type.hpp +++ b/include/villas/signal_type.hpp @@ -1,10 +1,9 @@ -/** Signal type. +/* Signal type. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -14,11 +13,11 @@ namespace villas { namespace node { enum class SignalType { - INVALID = 0, /**< Signal type is invalid. */ - FLOAT = 1, /**< See SignalData::f */ - INTEGER = 2, /**< See SignalData::i */ - BOOLEAN = 3, /**< See SignalData::b */ - COMPLEX = 4 /**< See SignalData::z */ + INVALID = 0, // Signal type is invalid. + FLOAT = 1, // See SignalData::f + INTEGER = 2, // See SignalData::i + BOOLEAN = 3, // See SignalData::b + COMPLEX = 4 // See SignalData::z }; enum SignalType signalTypeFromString(const std::string &str); diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index f7312e987..adf0c1b51 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -1,10 +1,9 @@ -/** Node type: socket +/* Node type: socket * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -20,7 +19,7 @@ #include #include -#endif /* LIBNL3_ROUTE_FOUND */ +#endif // LIBNL3_ROUTE_FOUND union sockaddr_union { struct sockaddr sa; @@ -43,7 +42,7 @@ enum class SocketLayer { UNIX }; -/** Generate printable socket address depending on the address family +/* Generate printable socket address depending on the address family * * A IPv4 address is formatted as dotted decimals followed by the port/protocol number * A link layer address is formatted in hexadecimals digits seperated by colons and the inferface name @@ -53,7 +52,7 @@ enum class SocketLayer { */ char * socket_print_addr(struct sockaddr *saddr); -/** Parse a socket address depending on the address family +/* Parse a socket address depending on the address family * * A IPv4 address has the follwing format: [hostname/ip]:[port/protocol] * A link layer address has the following format: [mac]%[interface]:[ethertype] diff --git a/include/villas/stats.hpp b/include/villas/stats.hpp index 18d0671cb..696aa29c1 100644 --- a/include/villas/stats.hpp +++ b/include/villas/stats.hpp @@ -1,10 +1,9 @@ -/** Statistic collection. +/* Statistic collection. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,7 +23,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations struct Sample; class Node; @@ -42,20 +41,20 @@ public: }; enum class Metric { - SMPS_SKIPPED, /**< Counter for skipped samples due to hooks. */ - SMPS_REORDERED, /**< Counter for reordered samples. */ + 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. */ - SIGNAL_COUNT, /**< Number of signals per sample. */ + // 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. + SIGNAL_COUNT, // Number of signals per sample. - /* RTP metrics */ - RTP_LOSS_FRACTION, /**< Fraction lost since last RTP SR/RR. */ - RTP_PKTS_LOST, /**< Cumul. no. pkts lost. */ - RTP_JITTER /**< Interarrival jitter. */ + // 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 { @@ -82,9 +81,11 @@ protected: enum node::SignalType signal_type; }; - static std::shared_ptr table; + static + std::shared_ptr
table; - static void setupTable(); + static + void setupTable(); Logger logger; @@ -118,9 +119,12 @@ public: const Hist & getHistogram(enum Metric sm) const; - static std::unordered_map metrics; - static std::unordered_map types; - static std::vector columns; + static + std::unordered_map metrics; + static + std::unordered_map types; + static + std::vector columns; }; } // namespace villas diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index 7711420e4..a843a8bc6 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -1,10 +1,9 @@ -/** The super node object holding the state of the application. +/* The super node object holding the state of the application. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -32,10 +31,10 @@ extern "C" { namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Node; -/** Global configuration */ +// Global configuration class SuperNode { protected: @@ -57,40 +56,40 @@ protected: Web web; #endif - int priority; /**< Process priority (lower is better) */ - int affinity; /**< Process affinity of the server and all created threads */ - int hugepages; /**< Number of hugepages to reserve. */ - double statsRate; /**< Rate at which we display the periodic stats. */ + int priority; // Process priority (lower is better) + int affinity; // Process affinity of the server and all created threads + int hugepages; // Number of hugepages to reserve. + double statsRate; // Rate at which we display the periodic stats. - struct Task task; /**< Task for periodic stats output */ + struct Task task; // Task for periodic stats output - uuid_t uuid; /**< A globally unique identifier of the instance */ + uuid_t uuid; // A globally unique identifier of the instance - struct timespec started; /**< The time at which the instance has been started. */ + struct timespec started; // The time at which the instance has been started. - std::string uri; /**< URI of configuration */ + std::string uri; // URI of configuration - Config config; /** The configuration file. */ + Config config; // The configuration file. public: - /** Inititalize configuration object before parsing the configuration. */ + // Inititalize configuration object before parsing the configuration. SuperNode(); int init(); - /** Wrapper for parse() which loads the config first. */ + // Wrapper for parse() which loads the config first. void parse(const std::string &name); - /** Parse super-node configuration. + /* Parse super-node configuration. * * @param json A libjansson object which contains the configuration. */ void parse(json_t *json); - /** Check validity of super node configuration. */ + // Check validity of super node configuration. void check(); - /** Initialize after parsing the configuration file. */ + // Initialize after parsing the configuration file. void prepare(); void start(); void stop(); @@ -113,7 +112,7 @@ public: graph_t * getGraph(); #endif - /** Run periodic hooks of this super node. */ + // Run periodic hooks of this super node. int periodic(); void setState(enum State st) @@ -190,7 +189,7 @@ public: return logger; } - /** Destroy configuration object. */ + // Destroy configuration object. ~SuperNode(); }; diff --git a/include/villas/usb.hpp b/include/villas/usb.hpp index 9ff70e184..12c280896 100644 --- a/include/villas/usb.hpp +++ b/include/villas/usb.hpp @@ -1,10 +1,9 @@ -/** Helpers for USB node-types +/* Helpers for USB node-types * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -42,7 +41,7 @@ public: usb::Error(e, fmt::format(what, std::forward(args)...)) { } - /* Same as above but with int */ + // Same as above but with int Error(int e, const std::string &what) : usb::Error((enum libusb_error) e, what) { } @@ -58,7 +57,8 @@ public: free(msg); } - virtual const char * what() const noexcept + virtual + const char * what() const noexcept { return msg; } diff --git a/include/villas/web.hpp b/include/villas/web.hpp index 64f43dc45..acf73edbd 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -1,10 +1,9 @@ -/** LWS-releated functions. +/* LWS-releated functions. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -21,7 +20,7 @@ namespace villas { namespace node { -/* Forward declarations */ +// Forward declarations class Api; class Web final { @@ -31,17 +30,17 @@ private: Logger logger; - lws_context *context; /**< The libwebsockets server context. */ - lws_vhost *vhost; /**< The libwebsockets vhost. */ + lws_context *context; // The libwebsockets server context. + lws_vhost *vhost; // The libwebsockets vhost. - Queue writables; /**< Queue of WSIs for which we will call lws_callback_on_writable() */ + Queue writables; // Queue of WSIs for which we will call lws_callback_on_writable() - int port; /**< Port of the build in HTTP / WebSocket server. */ - std::string ssl_cert; /**< Path to the SSL certitifcate for HTTPS / WSS. */ - std::string ssl_private_key; /**< Path to the SSL private key for HTTPS / WSS. */ + int port; // Port of the build in HTTP / WebSocket server. + std::string ssl_cert; // Path to the SSL certitifcate for HTTPS / WSS. + std::string ssl_private_key; // Path to the SSL private key for HTTPS / WSS. std::thread thread; - std::atomic running; /**< Atomic flag for signalizing thread termination. */ + std::atomic running; // Atomic flag for signalizing thread termination. Api *api; @@ -49,7 +48,7 @@ private: public: - /** Initialize the web interface. + /* Initialize the web interface. * * The web interface is based on the libwebsockets library. */ @@ -60,10 +59,12 @@ public: void start(); void stop(); - static void lwsLogger(int level, const char *msg); - static int lwsLogLevel(Log::Level lvl); + static + void lwsLogger(int level, const char *msg); + static + int lwsLogLevel(Log::Level lvl); - /** Parse HTTPd and WebSocket related options */ + // Parse HTTPd and WebSocket related options int parse(json_t *json); Api * getApi() @@ -71,7 +72,7 @@ public: return api; } - /* for C-compatability */ + // for C-compatability lws_context * getContext() { return context; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e9798795f..81a1a2975 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 add_compile_options(-fPIC) diff --git a/lib/api.cpp b/lib/api.cpp index 289e9e457..01b0e7547 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -1,9 +1,9 @@ -/** REST-API-releated functions. +/* REST-API-releated functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -64,7 +64,7 @@ void Api::stop() } running = false; - pending.push(nullptr); /* unblock thread */ + pending.push(nullptr); // unblock thread thread.join(); state = State::STOPPED; @@ -74,11 +74,11 @@ void Api::worker() { logger->info("Started worker"); - /* Process pending requests */ + // Process pending requests while (running) { Session *s = pending.pop(); if (s) { - /* Check that the session is still alive */ + // Check that the session is still alive auto it = std::find(sessions.begin(), sessions.end(), s); if (it != sessions.end()) s->execute(); diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index 452980a85..b52e3eee1 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -1,10 +1,9 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(API_SRC session.cpp diff --git a/lib/api/request.cpp b/lib/api/request.cpp index e735a4a49..2f9b20fda 100644 --- a/lib/api/request.cpp +++ b/lib/api/request.cpp @@ -1,10 +1,9 @@ -/** API Request. +/* API Request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index cf0a494c2..68c30346b 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -1,9 +1,9 @@ -/** The "capabiltities" API ressource. +/* The "capabiltities" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -18,7 +18,8 @@ class CapabilitiesRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -32,7 +33,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "capabilities"; static char r[] = "/capabilities"; static char d[] = "get capabiltities and details about this VILLASnode instance"; diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index c341402ac..ae8a76f29 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -1,9 +1,9 @@ -/** The "config" API ressource. +/* The "config" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +19,8 @@ class ConfigRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { json_t *json = session->getSuperNode()->getConfig(); @@ -37,7 +38,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "config"; static char r[] = "/config"; static char d[] = "get configuration of this VILLASnode instance"; diff --git a/lib/api/requests/graph.cpp b/lib/api/requests/graph.cpp index 963a00292..cddb698c3 100644 --- a/lib/api/requests/graph.cpp +++ b/lib/api/requests/graph.cpp @@ -1,9 +1,9 @@ -/** The "stats" API request. +/* The "stats" API request. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ extern "C" { #include @@ -40,7 +40,8 @@ public: gvFreeContext(gvc); } - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -107,7 +108,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "graph"; static char r[] = "/graph\\.([a-z]+)"; static char d[] = "get graph representation of configuration"; @@ -116,4 +117,3 @@ static RequestPlugin p; } // namespace api } // namespace node } // namespace villas - diff --git a/lib/api/requests/node.cpp b/lib/api/requests/node.cpp index ae32855aa..fd4452359 100644 --- a/lib/api/requests/node.cpp +++ b/lib/api/requests/node.cpp @@ -1,10 +1,9 @@ -/** Node API Request. +/* Node API Request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index eff4b24dc..d3d811601 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -1,9 +1,9 @@ -/** The API ressource for start/stop/pause/resume nodes. +/* The API ressource for start/stop/pause/resume nodes. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -25,7 +25,8 @@ class NodeActionRequest : public NodeRequest { public: using NodeRequest::NodeRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::POST) throw InvalidMethod(this); @@ -44,7 +45,7 @@ public: }; -/* Register API requests */ +// Register API requests static char n1[] = "node/start"; static char r1[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/start"; static char d1[] = "start a node"; @@ -70,7 +71,6 @@ static char r5[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/restart"; static char d5[] = "restart a node"; static RequestPlugin, n5, r5, d5> p5; - } // namespace api } // namespace node } // namespace villas diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 2ecc6c661..200c61189 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -1,9 +1,9 @@ -/** The "file" API ressource. +/* The "file" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,7 +23,8 @@ class FileRequest : public NodeRequest { public: using NodeRequest::NodeRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET && method != Session::Method::POST) throw InvalidMethod(this); @@ -48,7 +49,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "node/file"; static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/file(?:/([^/]+))?"; static char d[] = "control instances of 'file' node-type"; diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index 9b31b8170..bd5ca0c27 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -1,9 +1,9 @@ -/** The "node" API ressource. +/* The "node" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,7 +24,8 @@ class NodeInfoRequest : public NodeRequest { public: using NodeRequest::NodeRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -45,7 +46,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "node"; static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")"; static char d[] = "retrieve info of a node"; diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index 086ba4d10..271764d67 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -1,9 +1,9 @@ -/** The API ressource for querying statistics. +/* The API ressource for querying statistics. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -25,7 +25,8 @@ class StatsRequest : public NodeRequest { public: using NodeRequest::NodeRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -40,7 +41,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "node/stats"; static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/stats"; static char d[] = "get internal statistics counters"; diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index 889d68dde..778c15e44 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -1,9 +1,9 @@ -/** The API ressource for resetting statistics. +/* The API ressource for resetting statistics. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -25,7 +25,8 @@ class StatsRequest : public NodeRequest { public: using NodeRequest::NodeRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::POST) throw InvalidMethod(this); @@ -42,7 +43,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "node/stats/reset"; static char r[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/stats/reset"; static char d[] = "reset internal statistics counters"; diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index 167d3c866..b73230639 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -1,9 +1,9 @@ -/** The "nodes" API ressource. +/* The "nodes" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,7 +24,8 @@ class NodesRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -38,7 +39,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "nodes"; static char r[] = "/nodes"; static char d[] = "retrieve list of all known nodes"; diff --git a/lib/api/requests/path.cpp b/lib/api/requests/path.cpp index a3db85f86..f5dc2cd74 100644 --- a/lib/api/requests/path.cpp +++ b/lib/api/requests/path.cpp @@ -1,10 +1,9 @@ -/** Path API Request. +/* Path API Request. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 30cb7957e..020ab91b1 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -1,9 +1,9 @@ -/** The API ressource for start/stop/pause/resume paths. +/* The API ressource for start/stop/pause/resume paths. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -25,7 +25,8 @@ class PathActionRequest : public PathRequest { public: using PathRequest::PathRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::POST) throw InvalidMethod(this); @@ -40,7 +41,7 @@ public: }; -/* Register API requests */ +// Register API requests static char n1[] = "path/start"; static char r1[] = "/path/(" RE_UUID ")/start"; static char d1[] = "start a path"; @@ -51,7 +52,6 @@ static char r2[] = "/path/(" RE_UUID ")/stop"; static char d2[] = "stop a path"; static RequestPlugin, n2, r2, d2> p2; - } // namespace api } // namespace node } // namespace villas diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index ad3f8549f..9b834d180 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -1,9 +1,9 @@ -/** The "path" API ressource. +/* The "path" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,7 +24,8 @@ class PathInfoRequest : public PathRequest { public: using PathRequest::PathRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -36,7 +37,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "path"; static char r[] = "/path/(" RE_UUID ")"; static char d[] = "retrieve info of a path"; diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index 7ee255641..8043d8dad 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -1,9 +1,9 @@ -/** The "paths" API ressource. +/* The "paths" API ressource. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,7 +24,8 @@ class PathsRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -38,7 +39,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "paths"; static char r[] = "/paths"; static char d[] = "retrieve list of all paths with details"; diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 2fa383ede..9f481c26b 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -1,9 +1,9 @@ -/** The "restart" API request. +/* The "restart" API request. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -20,9 +20,11 @@ namespace api { class RestartRequest : public Request { protected: - static std::string configUri; + static + std::string configUri; - static void handler() + static + void handler() { int ret; const char *cfg = !configUri.empty() @@ -46,7 +48,8 @@ protected: public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { int ret; json_error_t err; @@ -83,18 +86,18 @@ public: else if (json_config != nullptr) throw BadRequest("Parameter 'config' must be either a URL (string) or a configuration (object)"); } - else /* If no config is provided via request, we will use the previous one */ + else // If no config is provided via request, we will use the previous one configUri = session->getSuperNode()->getConfigUri(); logger->info("Restarting to {}", configUri); - /* Increment API restart counter */ + // Increment API restart counter char *scnt = getenv("VILLAS_API_RESTART_COUNT"); int cnt = scnt ? atoi(scnt) : 0; char buf[32]; snprintf(buf, sizeof(buf), "%d", cnt + 1); - /* We pass some env variables to the new process */ + // We pass some env variables to the new process setenv("VILLAS_API_RESTART_COUNT", buf, 1); auto *json_response = json_pack("{ s: i, s: o }", @@ -104,12 +107,12 @@ public: : json_string(configUri.c_str()) ); - /* Register exit handler */ + // Register exit handler ret = atexit(handler); if (ret) throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to restart VILLASnode instance"); - /* Properly terminate current instance */ + // Properly terminate current instance utils::killme(SIGTERM); return new JsonResponse(session, HTTP_STATUS_OK, json_response); @@ -118,7 +121,7 @@ public: std::string RestartRequest::configUri; -/* Register API request */ +// Register API request static char n[] = "restart"; static char r[] = "/restart"; static char d[] = "restart VILLASnode with new configuration"; @@ -127,4 +130,3 @@ static RequestPlugin p; } // namespace api } // namespace node } // namespace villas - diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index 60b24b3d2..c7869f4e4 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -1,9 +1,9 @@ -/** The "shutdown" API request. +/* The "shutdown" API request. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -20,7 +20,8 @@ class ShutdownRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::POST) throw InvalidMethod(this); @@ -34,7 +35,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "shutdown"; static char r[] = "/shutdown"; static char d[] = "quit VILLASnode"; diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index 74be93763..a1895eef4 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -1,9 +1,9 @@ -/** The "status" API request. +/* The "status" API request. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,7 +23,8 @@ class StatusRequest : public Request { public: using Request::Request; - virtual Response * execute() + virtual + Response * execute() { int ret; @@ -108,7 +109,7 @@ public: } }; -/* Register API request */ +// Register API request static char n[] = "status"; static char r[] = "/status"; static char d[] = "get status and statistics of web server"; @@ -117,4 +118,3 @@ static RequestPlugin p; } // namespace api } // namespace node } // namespace villas - diff --git a/lib/api/requests/universal.cpp b/lib/api/requests/universal.cpp index 8d716c159..481c54b7c 100644 --- a/lib/api/requests/universal.cpp +++ b/lib/api/requests/universal.cpp @@ -1,10 +1,9 @@ -/** Universal Data-exchange API request +/* Universal Data-exchange API request * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/api/requests/universal/channel.cpp b/lib/api/requests/universal/channel.cpp index d8b1a971b..94e0851fa 100644 --- a/lib/api/requests/universal/channel.cpp +++ b/lib/api/requests/universal/channel.cpp @@ -1,9 +1,9 @@ -/** The Universal Data-exchange API. +/* The Universal Data-exchange API. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -127,7 +127,8 @@ public: return new JsonResponse(session, HTTP_STATUS_OK, json_object()); } - virtual Response * execute() + virtual + Response * execute() { auto const &signalName = matches[2]; auto const &subResource = matches[3]; @@ -151,7 +152,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "universal/channel/sample"; static char r[] = "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|event)"; static char d[] = "retrieve or send samples via universal data-exchange API"; diff --git a/lib/api/requests/universal/channels.cpp b/lib/api/requests/universal/channels.cpp index 576a9216f..ae7a720a1 100644 --- a/lib/api/requests/universal/channels.cpp +++ b/lib/api/requests/universal/channels.cpp @@ -1,9 +1,9 @@ -/** The Universal Data-exchange API. +/* The Universal Data-exchange API. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -18,7 +18,8 @@ class SignalsRequest : public UniversalRequest { public: using UniversalRequest::UniversalRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -48,7 +49,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "universal/channels"; static char r[] = "/universal/(" RE_NODE_NAME ")/channels"; static char d[] = "get channels of universal data-exchange API node"; diff --git a/lib/api/requests/universal/info.cpp b/lib/api/requests/universal/info.cpp index efbc46023..6ec3b58bd 100644 --- a/lib/api/requests/universal/info.cpp +++ b/lib/api/requests/universal/info.cpp @@ -1,9 +1,9 @@ -/** The Universal Data-exchange API. +/* The Universal Data-exchange API. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +19,8 @@ class InfoRequest : public UniversalRequest { public: using UniversalRequest::UniversalRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -41,7 +42,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "universal/info"; static char r[] = "/universal/(" RE_NODE_NAME ")/info"; static char d[] = "get infos of universal data-exchange API"; diff --git a/lib/api/requests/universal/status.cpp b/lib/api/requests/universal/status.cpp index 222681e4c..dc4d43130 100644 --- a/lib/api/requests/universal/status.cpp +++ b/lib/api/requests/universal/status.cpp @@ -1,9 +1,9 @@ -/** The Universal Data-exchange API. +/* The Universal Data-exchange API. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -18,7 +18,8 @@ class StatusRequest : public UniversalRequest { public: using UniversalRequest::UniversalRequest; - virtual Response * execute() + virtual + Response * execute() { if (method != Session::Method::GET) throw InvalidMethod(this); @@ -35,7 +36,7 @@ public: } }; -/* Register API requests */ +// Register API requests static char n[] = "universal/status"; static char r[] = "/universal/(" RE_NODE_NAME ")/status"; static char d[] = "get status of universal data-exchange API"; diff --git a/lib/api/response.cpp b/lib/api/response.cpp index d48477d2d..8048a0890 100644 --- a/lib/api/response.cpp +++ b/lib/api/response.cpp @@ -1,10 +1,9 @@ -/** API Response. +/* API Response. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -65,7 +64,7 @@ int Response::writeHeaders(struct lws *wsi) if (ret) return 1; - /* Do we have a body to send? */ + // Do we have a body to send? if (buffer.size() > 0) lws_callback_on_writable(wsi); diff --git a/lib/api/session.cpp b/lib/api/session.cpp index d8e94f9d8..a734f015d 100644 --- a/lib/api/session.cpp +++ b/lib/api/session.cpp @@ -1,9 +1,9 @@ -/** API session. +/* API session. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -132,7 +132,7 @@ void Session::open(void *in, size_t len) else if (len == 0) api->pending.push(this); else { - /* This request has a HTTP body. We wait for more data to arrive */ + // This request has a HTTP body. We wait for more data to arrive } } catch (const Error &e) { response = std::make_unique(this, e); @@ -169,7 +169,7 @@ int Session::writeable() if (!headersSent) { response->writeHeaders(wsi); - /* Now wait, until we can send the body */ + // Now wait, until we can send the body headersSent = true; return 0; diff --git a/lib/api/universal.cpp b/lib/api/universal.cpp index 6f09dca25..ed2140125 100644 --- a/lib/api/universal.cpp +++ b/lib/api/universal.cpp @@ -1,10 +1,9 @@ -/** API Response. +/* API Response. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/capabilities.cpp b/lib/capabilities.cpp index b7b221045..0d19977d6 100644 --- a/lib/capabilities.cpp +++ b/lib/capabilities.cpp @@ -1,9 +1,9 @@ -/** Capabilities +/* Capabilities * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/config.cpp b/lib/config.cpp index 2c2e8a699..221cfdebd 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -1,9 +1,9 @@ -/** Configuration file parsing. +/* Configuration file parsing. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -110,11 +110,11 @@ json_t * Config::decode(FILE *f) json_t *root = json_loadf(f, 0, &err); if (root == nullptr) { #ifdef WITH_CONFIG - /* We try again to parse the config in the legacy format */ + // We try again to parse the config in the legacy format root = libconfigDecode(f); #else throw JanssonParseError(err); -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG } return root; @@ -193,7 +193,8 @@ out: std::list files; void Config::resolveEnvVars(std::string &text) { - static const std::regex env_re{R"--(\$\{([^}]+)\})--"}; + static + const std::regex env_re{R"--(\$\{([^}]+)\})--"}; std::smatch match; while (std::regex_search(text, match, env_re)) { @@ -244,7 +245,7 @@ json_t * Config::libconfigDecode(FILE *f) config_init(&cfg); config_set_auto_convert(&cfg, 1); - /* Setup libconfig include path. */ + // Setup libconfig include path #if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) config_set_hook(&cfg, this); @@ -262,7 +263,7 @@ json_t * Config::libconfigDecode(FILE *f) } #endif - /* Rewind before re-reading */ + // Rewind before re-reading rewind(f); ret = config_read(&cfg, f); @@ -279,7 +280,7 @@ json_t * Config::libconfigDecode(FILE *f) return root; } -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG json_t * Config::walkStrings(json_t *root, str_walk_fcn_t cb) { @@ -334,7 +335,8 @@ json_t * Config::expandIncludes(json_t *in) return walkStrings(in, [this](json_t *str) -> json_t * { int ret; std::string text = json_string_value(str); - static const std::string kw = "@include "; + static + const std::string kw = "@include "; if (text.find(kw) != 0) return json_incref(str); diff --git a/lib/config_helper.cpp b/lib/config_helper.cpp index d91f19e3d..5e0747518 100644 --- a/lib/config_helper.cpp +++ b/lib/config_helper.cpp @@ -1,9 +1,9 @@ -/** Helpers for configuration parsers. +/* Helpers for configuration parsers. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -100,7 +100,7 @@ int villas::node::json_to_config(json_t *json, config_setting_t *parent) if (config_setting_is_root(parent)) { if (!json_is_object(json)) - return -1; /* The root must be an object! */ + return -1; // The root must be an object! } switch (json_typeof(json)) { @@ -155,7 +155,7 @@ int villas::node::json_to_config(json_t *json, config_setting_t *parent) return 0; } -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG void villas::node::json_object_extend_key_value_token(json_t *obj, const char *key, const char *value) { @@ -183,7 +183,7 @@ void villas::node::json_object_extend_key_value(json_t *obj, const char *key, co json_t *arr, *add, *existing, *subobj; - /* Is the key pointing to an object? */ + // Is the key pointing to an object? subobj = obj; cpy = strdup(key); @@ -205,21 +205,21 @@ void villas::node::json_object_extend_key_value(json_t *obj, const char *key, co key2 = strtok_r(nullptr, ".", &lasts); } - /* Try to parse as integer */ + // Try to parse as integer integer = strtol(value, &end, 0); if (*end == 0) { add = json_integer(integer); goto success; } - /* Try to parse as floating point */ + // Try to parse as floating point real = strtod(value, &end); if (*end == 0) { add = json_real(real); goto success; } - /* Try to parse special types */ + // Try to parse special types if (!strcmp(value, "true")) { add = json_true(); goto success; @@ -235,7 +235,7 @@ void villas::node::json_object_extend_key_value(json_t *obj, const char *key, co goto success; } - /* Fallback to string */ + // Fallback to string add = json_string(value); success: @@ -270,15 +270,15 @@ json_t * villas::node::json_load_cli(int argc, const char *argv[]) for (int i = 1; i < argc; i++) { opt = argv[i]; - /* Long Option */ + // Long Option if (opt[0] == '-' && opt[1] == '-') { - /* Option without value? Abort. */ + // Option without value? Abort if (key != nullptr) return nullptr; key = opt + 2; - /* Does this option has the form "--option=value"? */ + // Does this option has the form "--option=value"? sep = strchr(key, '='); if (sep) { cpy = strdup(key); @@ -292,9 +292,9 @@ json_t * villas::node::json_load_cli(int argc, const char *argv[]) key = nullptr; } } - /* Value */ + // Value else { - /* Value without key. Abort. */ + // Value without key. Abort if (key == nullptr) return nullptr; diff --git a/lib/dumper.cpp b/lib/dumper.cpp index cbb737e40..f4e4f186a 100644 --- a/lib/dumper.cpp +++ b/lib/dumper.cpp @@ -1,9 +1,9 @@ -/** Dump fields and values in a socket to plot them with villasDump.py. +/* Dump fields and values in a socket to plot them with villasDump.py. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/format.cpp b/lib/format.cpp index c91ba39e2..02e7ae293 100644 --- a/lib/format.cpp +++ b/lib/format.cpp @@ -1,9 +1,9 @@ -/** Reading and writing simulation samples in various formats. +/* Reading and writing simulation samples in various formats. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/formats/CMakeLists.txt b/lib/formats/CMakeLists.txt index 410a2378c..67afa3cbc 100644 --- a/lib/formats/CMakeLists.txt +++ b/lib/formats/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 if(DEFINED PROTOBUF_COMPILER AND PROTOBUF_FOUND) add_custom_command( diff --git a/lib/formats/column.cpp b/lib/formats/column.cpp index 26d474574..12cbcdf67 100644 --- a/lib/formats/column.cpp +++ b/lib/formats/column.cpp @@ -1,9 +1,9 @@ -/** Comma-separated values. +/* Comma-separated values. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -103,7 +103,7 @@ size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct Sample *s goto out; ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) /* There are no valid values anymore. */ + if (ret || end == ptr) // There are no valid values anymore. goto out; } @@ -119,7 +119,7 @@ out: if (*end == delimiter) void ColumnLineFormat::header(FILE *f, const SignalList::Ptr sigs) { - /* Abort if we are not supposed to, or have already printed the header */ + // Abort if we are not supposed to, or have already printed the header if (!print_header || header_printed) return; @@ -181,7 +181,7 @@ void ColumnLineFormat::parse(json_t *json) LineFormat::parse(json); } - +// Register formats static char n1[] = "csv"; static char d1[] = "Comma-separated values"; static ColumnLineFormatPlugin p1; diff --git a/lib/formats/iotagent_ul.cpp b/lib/formats/iotagent_ul.cpp index 86fdc7e4b..069fa9d40 100644 --- a/lib/formats/iotagent_ul.cpp +++ b/lib/formats/iotagent_ul.cpp @@ -1,11 +1,11 @@ -/** UltraLight 2.0 format as used by FIWARE IotAgent. +/* UltraLight 2.0 format as used by FIWARE IotAgent. * * See: https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html * - * @author Iris Koester - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Iris Koester + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -47,6 +47,7 @@ int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, return -1; } +// Register format static char n[] = "iotagent_ul"; static char d[] = "FIWARE IotAgent UltraLight format"; static FormatPlugin p; diff --git a/lib/formats/json.cpp b/lib/formats/json.cpp index d42eaed3c..854255f8c 100644 --- a/lib/formats/json.cpp +++ b/lib/formats/json.cpp @@ -1,9 +1,9 @@ -/** JSON serializtion of sample data. +/* JSON serializtion of sample data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -30,7 +30,7 @@ enum SignalType JsonFormat::detect(const json_t *val) return SignalType::BOOLEAN; case JSON_OBJECT: - return SignalType::COMPLEX; /* must be a complex number */ + return SignalType::COMPLEX; // must be a complex number default: return SignalType::INVALID; @@ -367,6 +367,7 @@ void JsonFormat::parse(json_t *json) dump_flags |= JSON_REAL_PRECISION(real_precision); } +// Register format static char n[] = "json"; static char d[] = "Javascript Object Notation"; static FormatPlugin p; diff --git a/lib/formats/json_edgeflex.cpp b/lib/formats/json_edgeflex.cpp index 9b493f86e..eaee6236b 100644 --- a/lib/formats/json_edgeflex.cpp +++ b/lib/formats/json_edgeflex.cpp @@ -1,9 +1,9 @@ -/** JSON serializtion for edgeFlex project. +/* JSON serializtion for edgeFlex project. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -92,6 +92,7 @@ int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) return 0; } +// Register format static char n[] = "json.edgeflex"; static char d[] = "EdgeFlex JSON format"; static FormatPlugin p; diff --git a/lib/formats/json_kafka.cpp b/lib/formats/json_kafka.cpp index b40e199b6..4bae33c7b 100644 --- a/lib/formats/json_kafka.cpp +++ b/lib/formats/json_kafka.cpp @@ -1,9 +1,9 @@ -/** JSON serializtion for Kafka schema/payloads. +/* JSON serializtion for Kafka schema/payloads. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -39,7 +39,7 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) json_fields = json_array(); json_payload = json_object(); - /* Include sample timestamp */ + // Include sample timestamp if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", @@ -52,7 +52,7 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) json_object_set_new(json_payload, "timestamp", json_integer(ts_origin_ms)); } - /* Include sample sequence no */ + // Include sample sequence no if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", @@ -64,7 +64,7 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) json_object_set_new(json_payload, "sequence", json_integer(smp->sequence)); } - /* Include sample data */ + // Include sample data for (size_t i = 0; i < MIN(smp->length, smp->signals->size()); i++) { const auto sig = smp->signals->getByIndex(i); const auto *data = &smp->data[i]; @@ -106,7 +106,7 @@ int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) smp->flags = 0; smp->signals = signals; - /* Unpack timestamp */ + // Unpack timestamp json_value = json_object_get(json_payload, "timestamp"); if (json_value) { uint64_t ts_origin_ms = json_integer_value(json_value); @@ -115,7 +115,7 @@ int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; } - /* Unpack sequence no */ + // Unpack sequence no json_value = json_object_get(json_payload, "sequence"); if (json_value) { smp->sequence = json_integer_value(json_value); @@ -123,7 +123,7 @@ int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) smp->flags |= (int) SampleFlags::HAS_SEQUENCE; } - /* Unpack signal data */ + // Unpack signal data for (size_t i = 0; i < signals->size(); i++) { auto sig = signals->getByIndex(i); @@ -176,6 +176,7 @@ JsonKafkaFormat::JsonKafkaFormat(int fl) : ); } +// Register format static char n[] = "json.kafka"; static char d[] = "JSON Kafka schema/payload messages"; static FormatPlugin p; diff --git a/lib/formats/json_reserve.cpp b/lib/formats/json_reserve.cpp index 54f0cef4a..29913a1b8 100644 --- a/lib/formats/json_reserve.cpp +++ b/lib/formats/json_reserve.cpp @@ -1,9 +1,9 @@ -/** JSON serializtion for RESERVE project. +/* JSON serializtion for RESERVE project. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -196,7 +196,7 @@ int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) return smp->length > 0 ? 1 : 0; } - +// Register format static char n[] = "json.reserve"; static char d[] = "RESERVE JSON format"; static FormatPlugin p; diff --git a/lib/formats/line.cpp b/lib/formats/line.cpp index 5692d0c5c..32a698aa3 100644 --- a/lib/formats/line.cpp +++ b/lib/formats/line.cpp @@ -1,9 +1,9 @@ -/** Line-based formats +/* Line-based formats * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -42,7 +42,7 @@ int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample } for (i = 0; i < cnt && off < len; i++) { - /* Skip comment lines */ + // Skip comment lines if (buf[off] == comment) { while (off < len) { if (buf[++off] == delimiter) @@ -93,7 +93,7 @@ int LineFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) if (!first_line_skipped) { bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); if (bytes < 0) - return -1; /* An error or eof occured */ + return -1; // An error or eof occured first_line_skipped = true; } @@ -107,9 +107,9 @@ skip: bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); if (feof(f)) break; else if (bytes < 0) - return -1; /* An error or eof occured */ + return -1; // An error or eof occured - /* Skip whitespaces, empty and comment lines */ + // Skip whitespaces, empty and comment lines for (ptr = in.buffer; isspace(*ptr); ptr++); if (ptr[0] == '\0' || ptr[0] == comment) diff --git a/lib/formats/msg.cpp b/lib/formats/msg.cpp index b01a17f7e..85b672b82 100644 --- a/lib/formats/msg.cpp +++ b/lib/formats/msg.cpp @@ -1,9 +1,9 @@ -/** Message related functions. +/* Message related functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/formats/opal_asyncip.cpp b/lib/formats/opal_asyncip.cpp index a3907589c..3e72fd547 100644 --- a/lib/formats/opal_asyncip.cpp +++ b/lib/formats/opal_asyncip.cpp @@ -1,9 +1,9 @@ -/** A custom format for OPAL-RTs AsyncIP example +/* A custom format for OPAL-RTs AsyncIP example * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -61,7 +61,7 @@ int OpalAsyncIPFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct auto *ptr = buf; if (len % 8 != 0) - return -1; /* Packet size is invalid: Must be multiple of 8 bytes */ + return -1; // Packet size is invalid: Must be multiple of 8 bytes for (i = 0; i < cnt && ptr - buf + sizeof(struct Payload) < len; i++) { auto *pl = (struct Payload *) ptr; @@ -113,4 +113,5 @@ void OpalAsyncIPFormat::parse(json_t *json) Format::parse(json); } -static OpalAsyncIPFormatPlugin p; +static +OpalAsyncIPFormatPlugin p; diff --git a/lib/formats/protobuf.cpp b/lib/formats/protobuf.cpp index 1d37e76d2..82699d1c9 100644 --- a/lib/formats/protobuf.cpp +++ b/lib/formats/protobuf.cpp @@ -1,9 +1,9 @@ -/** Protobuf IO format +/* Protobuf IO format * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -220,6 +220,7 @@ int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sa return i; } +// Register format static char n[] = "protobuf"; static char d[] = "Google Protobuf"; static FormatPlugin p; diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index 15526b922..dbec95da0 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -1,9 +1,9 @@ -/** RAW IO format +/* RAW IO format * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -13,29 +13,29 @@ typedef float flt32_t; typedef double flt64_t; -typedef long double flt128_t; /** @todo check */ +typedef long double flt128_t; // @todo check using namespace villas; using namespace villas::node; -/** Convert double to host byte order */ +// Convert double to host byte order #define SWAP_FLOAT_XTOH(o, b, n) ({ \ union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ x.i = (o) ? be ## b ## toh(x.i) : le ## b ## toh(x.i); \ x.f; \ }) -/** Convert double to big/little endian byte order */ +// Convert double to big/little endian byte order #define SWAP_FLOAT_HTOX(o, b, n) ({ \ union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ x.i = (o) ? htobe ## b (x.i) : htole ## b (x.i); \ x.f; \ }) -/** Convert integer of varying width to host byte order */ +// Convert integer of varying width to host byte order #define SWAP_INT_XTOH(o, b, n) (o ? be ## b ## toh(n) : le ## b ## toh(n)) -/** Convert integer of varying width to big/little endian byte order */ +// Convert integer of varying width to big/little endian byte order #define SWAP_INT_HTOX(o, b, n) (o ? htobe ## b (n) : htole ## b (n)) int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) @@ -43,7 +43,7 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample int o = 0; size_t nlen; - void *vbuf = (char *) buf; /* Avoid warning about invalid pointer cast */ + void *vbuf = (char *) buf; // Avoid warning about invalid pointer cast int8_t *i8 = (int8_t *) vbuf; int16_t *i16 = (int16_t *) vbuf; @@ -64,7 +64,7 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * These fields are always encoded as integers! */ if (fake) { - /* Check length */ + // Check length nlen = (o + 3) * (bits / 8); if (nlen >= len) goto out; @@ -108,7 +108,7 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample enum SignalType fmt = sample_format(smp, j); const union SignalData *data = &smp->data[j]; - /* Check length */ + // Check length nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); if (nlen >= len) goto out; @@ -118,11 +118,11 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample switch (bits) { case 8: i8 [o++] = -1; - break; /* Not supported */ + break; // Not supported case 16: i16[o++] = -1; - break; /* Not supported */ + break; // Not supported case 32: f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) data->f); @@ -193,12 +193,12 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample case SignalType::COMPLEX: switch (bits) { case 8: - i8 [o++] = -1; /* Not supported */ + i8 [o++] = -1; // Not supported i8 [o++] = -1; break; case 16: - i16[o++] = -1; /* Not supported */ + i16[o++] = -1; // Not supported i16[o++] = -1; break; @@ -234,7 +234,7 @@ out: if (wbytes) int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) { - void *vbuf = (void *) buf; /* Avoid warning about invalid pointer cast */ + void *vbuf = (void *) buf; // Avoid warning about invalid pointer cast int8_t *i8 = (int8_t *) vbuf; int16_t *i16 = (int16_t *) vbuf; @@ -258,11 +258,11 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample return -1; if (len % (bits / 8)) - return -1; /* Invalid RAW Payload length */ + return -1; // Invalid RAW Payload length if (fake) { if (nlen < o + 3) - return -1; /* Received a packet with no fake header. Skipping... */ + return -1; // Received a packet with no fake header. Skipping... switch (bits) { case 8: @@ -317,8 +317,8 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample switch (fmt) { case SignalType::FLOAT: switch (bits) { - case 8: data->f = -1; o++; break; /* Not supported */ - case 16: data->f = -1; o++; break; /* Not supported */ + case 8: data->f = -1; o++; break; // Not supported + case 16: data->f = -1; o++; break; // Not supported case 32: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]); break; case 64: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]); break; @@ -354,8 +354,8 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample case SignalType::COMPLEX: switch (bits) { - case 8: data->z = std::complex(-1, -1); o += 2; break; /* Not supported */ - case 16: data->z = std::complex(-1, -1); o += 2; break; /* Not supported */ + case 8: data->z = std::complex(-1, -1); o += 2; break; // Not supported + case 16: data->z = std::complex(-1, -1); o += 2; break; // Not supported case 32: data->z = std::complex( SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]), @@ -378,14 +378,14 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample break; case SignalType::INVALID: - return -1; /* Unsupported format in RAW payload */ + return -1; // Unsupported format in RAW payload } } smp->length = i; if (smp->length > smp->capacity) - smp->length = smp->capacity; /* Received more values than supported */ + smp->length = smp->capacity; // Received more values than supported if (rbytes) *rbytes = o * (bits / 8); @@ -433,6 +433,7 @@ void RawFormat::parse(json_t *json) BinaryFormat::parse(json); } +// Register formats static char n1[] = "raw"; static char d1[] = "Raw binary data"; static FormatPlugin p1; diff --git a/lib/formats/value.cpp b/lib/formats/value.cpp index 018bfa698..33f3b416e 100644 --- a/lib/formats/value.cpp +++ b/lib/formats/value.cpp @@ -1,9 +1,9 @@ -/** Bare text values. +/* Bare text values. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -55,7 +55,7 @@ int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sampl return -1; ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) /* There are no valid values anymore. */ + if (ret || end == ptr) // There are no valid values anymore. goto out; i++; @@ -74,6 +74,7 @@ out: smp->flags = 0; return i; } +// Register format static char n[] = "value"; static char d[] = "A bare text value without any headers"; static FormatPlugin p; diff --git a/lib/formats/villas.proto b/lib/formats/villas.proto index af9e0dec9..27a581b2b 100644 --- a/lib/formats/villas.proto +++ b/lib/formats/villas.proto @@ -1,9 +1,9 @@ /// Protobuf schema based on msg_format.h /// /// @file -/// @author Steffen Vogel -/// @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -/// @license Apache 2.0 +/// Author: Steffen Vogel +/// SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +/// SPDX-License-Identifier: Apache-2.0 //////////////////////////////////////////////////////////////////////////////////// syntax = "proto2"; diff --git a/lib/formats/villas_binary.cpp b/lib/formats/villas_binary.cpp index b74154b1c..f9e1cad5e 100644 --- a/lib/formats/villas_binary.cpp +++ b/lib/formats/villas_binary.cpp @@ -1,9 +1,9 @@ -/** Message related functions. +/* Message related functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -36,7 +36,7 @@ int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, const stru return ret; if (web) { - /** @todo convert to little endian */ + // @todo convert to little endian } else msg_hton(msg); @@ -58,7 +58,7 @@ int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struc uint8_t sid; // source_index if (len % 4 != 0) - return -1; /* Packet size is invalid: Must be multiple of 4 bytes */ + return -1; // Packet size is invalid: Must be multiple of 4 bytes for (i = 0, j = 0; i < cnt; i++) { struct Message *msg = (struct Message *) ptr; @@ -66,29 +66,29 @@ int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struc smp->signals = signals; - /* Complete buffer has been parsed */ + // Complete buffer has been parsed if (ptr == buf + len) break; - /* Check if header is still in buffer bounaries */ + // Check if header is still in buffer bounaries if (ptr + sizeof(struct Message) > buf + len) - return -2; /* Invalid msg received */ + return -2; // Invalid msg received values = web ? msg->length : ntohs(msg->length); - /* Check if remainder of message is in buffer boundaries */ + // Check if remainder of message is in buffer boundaries if (ptr + MSG_LEN(values) > buf + len) - return -3; /* Invalid msg receive */ + return -3; // Invalid msg receive if (web) { - /** @todo convert from little endian */ + // @todo convert from little endian } else msg_ntoh(msg); ret = msg_to_sample(msg, smp, signals, &sid); if (ret) - return ret; /* Invalid msg received */ + return ret; // Invalid msg received if (validate_source_index && sid != source_index) { // source index mismatch: we skip this sample @@ -128,5 +128,8 @@ void VillasBinaryFormat::parse(json_t *json) Format::parse(json); } -static VillasBinaryFormatPlugin p1; -static VillasBinaryFormatPlugin p2; +// Register formats +static +VillasBinaryFormatPlugin p1; +static +VillasBinaryFormatPlugin p2; diff --git a/lib/formats/villas_human.cpp b/lib/formats/villas_human.cpp index efacb7284..a6cb49dab 100644 --- a/lib/formats/villas_human.cpp +++ b/lib/formats/villas_human.cpp @@ -1,9 +1,9 @@ -/** The internal datastructure for a sample of simulation data. +/* The internal datastructure for a sample of simulation data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -72,14 +72,14 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample * * Please note that only the seconds and at least one value are mandatory */ - /* Mandatory: seconds */ + // Mandatory: seconds smp->ts.origin.tv_sec = (uint32_t) strtoul(ptr, &end, 10); if (ptr == end || *end == delimiter) return -1; smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - /* Optional: nano seconds */ + // Optional: nano seconds if (*end == '.') { ptr = end + 1; @@ -90,18 +90,18 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample * else smp->ts.origin.tv_nsec = 0; - /* Optional: offset / delay */ + // Optional: offset / delay if (*end == '+' || *end == '-') { ptr = end; - offset = strtof(ptr, &end); /* offset is ignored for now */ + offset = strtof(ptr, &end); // offset is ignored for now if (ptr != end) smp->flags |= (int) SampleFlags::HAS_OFFSET; else return -4; } - /* Optional: sequence */ + // Optional: sequence if (*end == '(') { ptr = end + 1; @@ -125,7 +125,7 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample * goto out; ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) /* There are no valid values anymore. */ + if (ret || end == ptr) // There are no valid values anymore. goto out; } @@ -148,7 +148,7 @@ out: if (*end == delimiter) void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) { - /* Abort if we are not supposed to, or have already printed the header */ + // Abort if we are not supposed to, or have already printed the header if (!print_header || header_printed) return; @@ -184,6 +184,7 @@ void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) LineFormat::header(f, sigs); } +// Register format static char n[] = "villas.human"; static char d[] = "VILLAS human readable format"; static LineFormatPlugin p; diff --git a/lib/hook.cpp b/lib/hook.cpp index 17bc84be8..ed61459a1 100644 --- a/lib/hook.cpp +++ b/lib/hook.cpp @@ -1,9 +1,9 @@ -/** Hook-releated functions. +/* Hook-releated functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -28,7 +28,7 @@ Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) : factory(nullptr), state(fl & (int) Hook::Flags::BUILTIN ? State::CHECKED - : State::INITIALIZED), /* We dont need to parse builtin hooks. */ + : State::INITIALIZED), // We dont need to parse builtin hooks flags(fl), priority(prio), enabled(en), @@ -97,12 +97,11 @@ void SingleSignalHook::parse(json_t *json) signalName = json_string_value(json_signal); } - void SingleSignalHook::prepare() { Hook::prepare(); - /* Setup mask */ + // Setup mask int index = signals->getIndexByName(signalName.c_str()); if (index < 0) throw RuntimeError("Failed to find signal {}", signalName); @@ -110,7 +109,7 @@ void SingleSignalHook::prepare() signalIndex = (unsigned) index; } -/* Multi Signal Hook */ +// Multi Signal Hook void MultiSignalHook::parse(json_t *json) { @@ -155,7 +154,6 @@ void MultiSignalHook::parse(json_t *json) throw ConfigError(json, "node-config-hook-signals", "Missing 'signals' setting"); } - void MultiSignalHook::prepare() { Hook::prepare(); diff --git a/lib/hook_list.cpp b/lib/hook_list.cpp index 20b7d2711..5e3452aac 100644 --- a/lib/hook_list.cpp +++ b/lib/hook_list.cpp @@ -1,9 +1,9 @@ -/** Hook-releated functions. +/* Hook-releated functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -71,7 +71,7 @@ void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) if (!m) goto skip_add; - /* Add internal hooks if they are not already in the list */ + // Add internal hooks if they are not already in the list for (auto f : plugin::registry->lookup()) { if ((f->getFlags() & m) == m) { auto h = f->make(p, n); @@ -80,10 +80,10 @@ void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) } skip_add: - /* Remove filters which are not enabled */ + // Remove filters which are not enabled remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); - /* We sort the hooks according to their priority */ + // We sort the hooks according to their priority sort([](const value_type &a, const value_type b) { return a->getPriority() < b->getPriority(); }); unsigned i = 0; diff --git a/lib/hooks/CMakeLists.txt b/lib/hooks/CMakeLists.txt index ed2f1e0f7..16c27a575 100644 --- a/lib/hooks/CMakeLists.txt +++ b/lib/hooks/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(HOOK_SRC average.cpp diff --git a/lib/hooks/average.cpp b/lib/hooks/average.cpp index db8d6bd6f..e6b77d264 100644 --- a/lib/hooks/average.cpp +++ b/lib/hooks/average.cpp @@ -1,9 +1,9 @@ -/** Average hook. +/* Average hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -27,13 +27,14 @@ public: offset(0) { } - virtual void prepare() + virtual + void prepare() { assert(state == State::CHECKED); MultiSignalHook::prepare(); - /* Add averaged signal */ + // Add averaged signal auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); if (!avg_sig) throw RuntimeError("Failed to create new signal"); @@ -43,7 +44,8 @@ public: state = State::PREPARED; } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -61,7 +63,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { double avg, sum = 0; int n = 0; @@ -81,7 +84,7 @@ public: case SignalType::INVALID: case SignalType::COMPLEX: case SignalType::BOOLEAN: - return Hook::Reason::ERROR; /* not supported */ + return Hook::Reason::ERROR; // not supported } n++; @@ -98,7 +101,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "average"; static char d[] = "Calculate average over some signals"; static HookPlugin p; diff --git a/lib/hooks/cast.cpp b/lib/hooks/cast.cpp index 6dfe0179f..8fb373830 100644 --- a/lib/hooks/cast.cpp +++ b/lib/hooks/cast.cpp @@ -1,9 +1,9 @@ -/** Cast hook. +/* Cast hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -26,7 +26,8 @@ public: new_type(SignalType::INVALID) { } - virtual void prepare() + virtual + void prepare() { assert(state == State::CHECKED); @@ -45,7 +46,8 @@ public: state = State::PREPARED; } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; @@ -73,7 +75,7 @@ public: throw RuntimeError("Invalid signal type: {}", type); } else - /* We use this constant to indicate that we dont want to change the type. */ + // We use this constant to indicate that we dont want to change the type. new_type = SignalType::INVALID; if (name) @@ -85,7 +87,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -100,11 +103,10 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "cast"; static char d[] = "Cast signals types"; static HookPlugin p; } // namespace node } // namespace villas - diff --git a/lib/hooks/decimate.cpp b/lib/hooks/decimate.cpp index e6c397400..a8124aa16 100644 --- a/lib/hooks/decimate.cpp +++ b/lib/hooks/decimate.cpp @@ -1,9 +1,9 @@ -/** Decimate hook. +/* Decimate hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -52,7 +52,7 @@ Hook::Reason DecimateHook::process(struct Sample *smp) return Reason::OK; } -/* Register hook */ +// Register hook static char n[] = "decimate"; static char d[] = "Downsamping by integer factor"; static HookPlugin p; diff --git a/lib/hooks/dp.cpp b/lib/hooks/dp.cpp index 010c77f24..c6a1c69fd 100644 --- a/lib/hooks/dp.cpp +++ b/lib/hooks/dp.cpp @@ -1,9 +1,9 @@ -/** Dynamic Phasor Interface Algorithm hook. +/* Dynamic Phasor Interface Algorithm hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -51,21 +51,21 @@ protected: for (int k = 0; k < fharmonics_len; k++) { om_k = 2.0i * M_PI * (double) fharmonics[k] / (double) N; - /* Correction for stationary phasor */ + // Correction for stationary phasor corr = std::exp(-om_k * (steps - (N + 1))); //corr = 1; #if 0 - /* Recursive update */ + // Recursive update coeffs[k] = std::exp(om) * (coeffs[k] + (newest - oldest)); out[k] = (2.0 / N) * (coeffs[i] * corr); - /* DC component */ + // DC component if (fharmonics[k] == 0) out[k] /= 2.0; #else - /* Full DFT */ + // Full DFT std::complex X_k = 0; for (int n = 0; n < N; n++) { @@ -83,7 +83,7 @@ protected: { std::complex value = 0; - /* Reconstruct the original signal */ + // Reconstruct the original signal for (int k = 0; k < fharmonics_len; k++) { double freq = fharmonics[k]; // cppcheck-suppress objectIndex @@ -113,9 +113,10 @@ public: fharmonics_len(0) { } - virtual ~DPHook() + virtual + ~DPHook() { - /* Release memory */ + // Release memory if (fharmonics) delete fharmonics; @@ -126,7 +127,8 @@ public: free(signal_name); } - virtual void start() + virtual + void start() { assert(state == State::PREPARED); @@ -141,7 +143,8 @@ public: state = State::STARTED; } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -203,7 +206,8 @@ public: state = State::PARSED; } - virtual void prepare() + virtual + void prepare() { assert(state == State::CHECKED); @@ -218,7 +222,7 @@ public: } if (inverse) { - /* Remove complex-valued coefficient signals */ + // Remove complex-valued coefficient signals for (int i = 0; i < fharmonics_len; i++) { auto orig_sig = signals->getByIndex(signal_index + i); if (!orig_sig) @@ -230,7 +234,7 @@ public: signals->erase(signals->begin() + signal_index + i); } - /* Add new real-valued reconstructed signals */ + // Add new real-valued reconstructed signals auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); if (!new_sig) throw RuntimeError("Failed to create signal"); @@ -261,7 +265,8 @@ public: state = State::PREPARED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { if (signal_index >= smp->length) return Hook::Reason::ERROR; @@ -292,7 +297,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "dp"; static char d[] = "Transform to/from dynamic phasor domain"; static HookPlugin p; diff --git a/lib/hooks/drop.cpp b/lib/hooks/drop.cpp index 0ea53ca65..516e9e3f6 100644 --- a/lib/hooks/drop.cpp +++ b/lib/hooks/drop.cpp @@ -1,9 +1,9 @@ -/** Drop hook. +/* Drop hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -21,7 +21,8 @@ protected: public: using Hook::Hook; - virtual void start() + virtual + void start() { assert(state == State::PREPARED || state == State::STOPPED); @@ -30,7 +31,8 @@ public: state = State::STARTED; } - virtual void stop() + virtual + void stop() { assert(state == State::STARTED); @@ -40,7 +42,8 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { int dist; @@ -64,7 +67,8 @@ public: return Reason::OK; } - virtual void restart() + virtual + void restart() { assert(state == State::STARTED); @@ -75,7 +79,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "drop"; static char d[] = "Drop messages with reordered sequence numbers"; static HookPlugin p; diff --git a/lib/hooks/dump.cpp b/lib/hooks/dump.cpp index 4571707eb..5dceb1fd1 100644 --- a/lib/hooks/dump.cpp +++ b/lib/hooks/dump.cpp @@ -1,9 +1,9 @@ -/** Dump hook. +/* Dump hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -16,7 +16,8 @@ class DumpHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -26,7 +27,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "dump"; static char d[] = "Dump data to stdout"; static HookPlugin p; diff --git a/lib/hooks/ebm.cpp b/lib/hooks/ebm.cpp index f2d054f40..231236efc 100644 --- a/lib/hooks/ebm.cpp +++ b/lib/hooks/ebm.cpp @@ -1,9 +1,9 @@ -/** Energy-based Metric hook. +/* Energy-based Metric hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -26,7 +26,8 @@ protected: public: using Hook::Hook; - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; @@ -60,7 +61,8 @@ public: state = State::PARSED; } - virtual void start() + virtual + void start() { assert(state == State::PREPARED); @@ -70,14 +72,16 @@ public: state = State::STARTED; } - virtual void periodic() + virtual + void periodic() { assert(state == State::STARTED); logger->info("Energy: {}", energy); } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { double P, P_last, dt; @@ -85,7 +89,7 @@ public: if (last) { for (auto phase : phases) { - /* Trapazoidal rule */ + // Trapazoidal rule dt = time_delta(&last->ts.origin, &smp->ts.origin); P = smp->data[phase.first].f * smp->data[phase.second].f; @@ -104,7 +108,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "ebm"; static char d[] = "Energy-based Metric"; static HookPlugin p; diff --git a/lib/hooks/fix.cpp b/lib/hooks/fix.cpp index 5e50ffc60..ea653a773 100644 --- a/lib/hooks/fix.cpp +++ b/lib/hooks/fix.cpp @@ -1,9 +1,9 @@ -/** Drop hook. +/* Drop hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -20,7 +20,8 @@ class FixHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -45,11 +46,10 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "fix"; static char d[] = "Fix received data by adding missing fields"; static HookPlugin p; } // namespace node } // namespace villas - diff --git a/lib/hooks/gate.cpp b/lib/hooks/gate.cpp index cd4ae43b1..347d2dc30 100644 --- a/lib/hooks/gate.cpp +++ b/lib/hooks/gate.cpp @@ -1,9 +1,9 @@ -/** Gate hook. +/* Gate hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -48,7 +48,8 @@ public: startSequence(0) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; @@ -83,13 +84,14 @@ public: state = State::PARSED; } - virtual void prepare() + virtual + void prepare() { assert(state == State::CHECKED); SingleSignalHook::prepare(); - /* Check if signal type is float */ + // Check if signal type is float auto sig = signals->getByIndex(signalIndex); if (sig->type != SignalType::FLOAT) throw RuntimeError("Gate signal must be of type float"); @@ -97,7 +99,8 @@ public: state = State::PREPARED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -150,7 +153,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "gate"; static char d[] = "Skip samples only if an enable signal is under a specified threshold"; static HookPlugin p; diff --git a/lib/hooks/jitter_calc.cpp b/lib/hooks/jitter_calc.cpp index d32b047c2..63c6ec1ee 100644 --- a/lib/hooks/jitter_calc.cpp +++ b/lib/hooks/jitter_calc.cpp @@ -1,9 +1,9 @@ -/** Calc jitter, mean and variance of GPS vs NTP TS. +/* Calc jitter, mean and variance of GPS vs NTP TS. * - * @author Umar Farooq - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Umar Farooq + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -44,15 +44,15 @@ public: curr_count(0) { } - /** - * Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. + /* Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. * * Drawbacks: No protection for out of order packets. Default positive delay assumed, * so GPS timestamp should be earlier than NTP timestamp. If difference b/w NTP and GPS ts * is high (i.e. several mins depending on GPS_NTP_DELAY_WIN_SIZE), * the variance value will overrun the 64bit value. */ - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -66,12 +66,12 @@ public: curr_delay_us = delay_sec * 1000000 + delay_nsec / 1000; delay_mov_sum = delay_mov_sum + curr_delay_us - delay_series[curr_count]; - moving_avg[curr_count] = delay_mov_sum / GPS_NTP_DELAY_WIN_SIZE; /* Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values */ + moving_avg[curr_count] = delay_mov_sum / GPS_NTP_DELAY_WIN_SIZE; // Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values delay_mov_sum_sqrd = delay_mov_sum_sqrd + (curr_delay_us * curr_delay_us) - (delay_series[curr_count] * delay_series[curr_count]); moving_var[curr_count] = (delay_mov_sum_sqrd - (delay_mov_sum * delay_mov_sum) / GPS_NTP_DELAY_WIN_SIZE) / (GPS_NTP_DELAY_WIN_SIZE - 1); - delay_series[curr_count] = curr_delay_us; /* Update the last delay value */ + delay_series[curr_count] = curr_delay_us; // Update the last delay value /* Jitter calc formula as used in Wireshark according to RFC3550 (RTP) D(i,j) = (Rj-Ri)-(Sj-Si) = (Rj-Sj)-(Ri-Si) @@ -92,7 +92,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "jitter_calc"; static char d[] = "Calc jitter, mean and variance of GPS vs NTP TS"; static HookPlugin p; diff --git a/lib/hooks/limit_rate.cpp b/lib/hooks/limit_rate.cpp index e07fe7909..4dd0a8527 100644 --- a/lib/hooks/limit_rate.cpp +++ b/lib/hooks/limit_rate.cpp @@ -1,9 +1,9 @@ -/** Rate-limiting hook. +/* Rate-limiting hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -76,7 +76,7 @@ Hook::Reason LimitRateHook::process(struct Sample *smp) return Reason::OK; } -/* Register hook */ +// Register hook static char n[] = "limit_rate"; static char d[] = "Limit sending rate"; static HookPlugin p; diff --git a/lib/hooks/limit_value.cpp b/lib/hooks/limit_value.cpp index 7b23512b1..9a4b0311d 100644 --- a/lib/hooks/limit_value.cpp +++ b/lib/hooks/limit_value.cpp @@ -1,9 +1,9 @@ -/** Limit hook. +/* Limit hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -32,7 +32,8 @@ public: max(0) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -51,7 +52,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -76,7 +78,7 @@ public: case SignalType::INVALID: case SignalType::COMPLEX: case SignalType::BOOLEAN: - return Hook::Reason::ERROR; /* not supported */ + return Hook::Reason::ERROR; // not supported } } @@ -84,7 +86,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "limit_value"; static char d[] = "Limit signal values"; static HookPlugin p; diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index d75392cd2..4219eb061 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -1,9 +1,9 @@ -/** Lua expressions hook. +/* Lua expressions hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -40,7 +40,8 @@ public: err(e) { } - virtual const char * what() const noexcept + virtual + const char * what() const noexcept { const char *msg; switch (err) { @@ -121,7 +122,7 @@ bool lua_pushsignaldata(lua_State *L, const union SignalData *data, const Signal case SignalType::COMPLEX: case SignalType::INVALID: default: - return false; /* we skip unknown types. Lua will see a nil value in the table */ + return false; // we skip unknown types. Lua will see a nil value in the table } return true; @@ -361,7 +362,7 @@ json_t * lua_tojson(lua_State *L, int index = -1) } else { const char *key = lua_tostring(L, -2); - if (key) /* Skip table entries whose keys are neither string or number! */ + if (key) // Skip table entries whose keys are neither string or number! json_object_set(json, key, val); } lua_pop(L, 1); @@ -386,7 +387,7 @@ LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) : json_error_t err; const char *expr; - /* Parse expression */ + // Parse expression ret = json_unpack_ex(json_sig, &err, 0, "{ s: s }", "expression", &expr ); @@ -405,7 +406,7 @@ void LuaSignalExpression::prepare() void LuaSignalExpression::parseExpression(const std::string &expr) { - /* Release previous expression */ + // Release previous expression if (cookie) luaL_unref(L, LUA_REGISTRYINDEX, cookie); @@ -532,7 +533,7 @@ void LuaHook::loadScript() int ret; if (script.empty()) - return; /* No script given. */ + return; // No script given ret = luaL_loadfile(L, script.c_str()); if (ret) @@ -588,10 +589,10 @@ void LuaHook::setupEnvironment() void LuaHook::prepare() { - /* Load Lua standard libraries */ + // Load Lua standard libraries luaL_openlibs(L); - /* Load our Lua script */ + // Load our Lua script logger->debug("Loading Lua script: {}", script); setupEnvironment(); @@ -604,14 +605,14 @@ void LuaHook::prepare() */ needsLocking = functions.periodic > 0; - /* Prepare Lua process() */ + // Prepare Lua process() if (functions.process) { /* We currently do not support the alteration of * signal metadata in process() */ signalsProcessed = signals; } - /* Prepare Lua expressions */ + // Prepare Lua expressions if (hasExpressions) { for (auto &expr : expressions) expr.prepare(); @@ -721,7 +722,7 @@ Hook::Reason LuaHook::process(struct Sample *smp) ? std::unique_lock(mutex) : std::unique_lock(); - /* First, run the process() function of the script */ + // First, run the process() function of the script if (functions.process) { logger->debug("Executing Lua function: process(smp)"); @@ -749,7 +750,7 @@ Hook::Reason LuaHook::process(struct Sample *smp) else reason = Reason::OK; - /* After that evaluate expressions */ + // After that evaluate expressions if (hasExpressions) { lua_pushsample(L, smp, useNames); lua_setglobal(L, "smp"); @@ -768,7 +769,7 @@ Hook::Reason LuaHook::process(struct Sample *smp) return reason; } -/* Register hook */ +// Register hook static char n[] = "lua"; static char d[] = "Implement hook functions or expressions in Lua"; static HookPlugin p; diff --git a/lib/hooks/ma.cpp b/lib/hooks/ma.cpp index baf507f21..996767ab0 100644 --- a/lib/hooks/ma.cpp +++ b/lib/hooks/ma.cpp @@ -1,9 +1,9 @@ -/** Moving average filter. +/* Moving average filter. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -34,16 +34,16 @@ public: { MultiSignalHook::prepare(); - /* Add signals */ + // Add signals for (auto index : signalIndices) { auto origSig = signals->getByIndex(index); - /* Check that signal has float type */ + // Check that signal has float type if (origSig->type != SignalType::FLOAT) throw RuntimeError("The ma hook can only operate on signals of type float!"); } - /* Initialize sample memory */ + // Initialize sample memory smpMemory.clear(); for (unsigned i = 0; i < signalIndices.size(); i++) smpMemory.emplace_back(windowSize, 0.0); @@ -77,16 +77,16 @@ public: unsigned i = 0; for (auto index : signalIndices) { - /* The new value */ + // The new value double newValue = smp->data[index].f; - /* Append the new value to the history memory */ + // Append the new value to the history memory smpMemory[i][smpMemoryPosition % windowSize] = newValue; - /* Get the old value from the history */ + // Get the old value from the history double oldValue = smpMemory[i][(smpMemoryPosition + 1) % windowSize]; - /* Update the accumulator */ + // Update the accumulator accumulator += newValue; accumulator -= oldValue; @@ -100,7 +100,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "ma"; static char d[] = "A simple moving average filter over a fixed number of past samples"; static HookPlugin p; diff --git a/lib/hooks/pmu.cpp b/lib/hooks/pmu.cpp index 491b6f004..a93ccd535 100644 --- a/lib/hooks/pmu.cpp +++ b/lib/hooks/pmu.cpp @@ -1,9 +1,9 @@ -/** PMU hook. +/* PMU hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -40,7 +40,7 @@ void PmuHook::prepare() signals->clear(); for (unsigned i = 0; i < signalIndices.size(); i++) { - /* Add signals */ + // Add signals auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad @@ -166,7 +166,6 @@ void PmuHook::parse(json_t *json) else throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); - } Hook::Reason PmuHook::process(struct Sample *smp) @@ -212,18 +211,18 @@ Hook::Reason PmuHook::process(struct Sample *smp) phasorTimestamp = (*windowsTs)[tsPos]; } - /* Update sample memory */ + // Update sample memory unsigned i = 0; for (auto index : signalIndices) windows[i++]->update(smp->data[index].f); windowsTs->update(smp->ts.origin); - /* Make sure to update phasors after window update but estimate them before */ + // Make sure to update phasors after window update but estimate them before if(run) { for (unsigned i = 0; i < signalIndices.size(); i++) { - smp->data[i * 4 + 0].f = lastPhasors[i].frequency + frequencyOffset; /* Frequency */ - smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + amplitudeOffset; /* Amplitude */ - smp->data[i * 4 + 2].f = (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; /* Phase */ + smp->data[i * 4 + 0].f = lastPhasors[i].frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; // Phase smp->data[i * 4 + 3].f = lastPhasors[i].rocof + rocofOffset; /* ROCOF */; } smp->ts.origin = phasorTimestamp; @@ -242,7 +241,7 @@ PmuHook::Phasor PmuHook::estimatePhasor(dsp::CosineWindow *window, Phaso return {0., 0., 0., 0., Status::INVALID}; } -/* Register hook */ +// Register hook static char n[] = "pmu"; static char d[] = "This hook estimates a phsor"; static HookPlugin p; diff --git a/lib/hooks/pmu_dft.cpp b/lib/hooks/pmu_dft.cpp index a5c0118bf..e0687eb00 100644 --- a/lib/hooks/pmu_dft.cpp +++ b/lib/hooks/pmu_dft.cpp @@ -1,9 +1,9 @@ -/** DFT hook. +/* DFT hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -16,7 +16,7 @@ #include #include -/* Uncomment to enable dumper of memory windows */ +// Uncomment to enable dumper of memory windows //#define DFT_MEM_DUMP namespace villas { @@ -64,7 +64,7 @@ protected: double frequency; double amplitude; double phase; - double rocof; /**< Rate of change of frequency. */ + double rocof; // Rate of change of frequency. }; enum WindowType windowType; @@ -91,9 +91,9 @@ protected: unsigned rate; unsigned ppsIndex; unsigned windowSize; - unsigned windowMultiplier; /**< Multiplyer for the window to achieve frequency resolution */ - unsigned freqCount; /**< Number of requency bins that are calculated */ - bool channelNameEnable; /**< Rename the output values with channel name or only descriptive name */ + unsigned windowMultiplier; // Multiplyer for the window to achieve frequency resolution + unsigned freqCount; // Number of requency bins that are calculated + bool channelNameEnable; // Rename the output values with channel name or only descriptive name uint64_t smpMemPos; uint64_t lastSequence; @@ -176,7 +176,8 @@ public: rocofOffset(0.0) { } - virtual void prepare() + virtual + void prepare() { MultiSignalHook::prepare(); @@ -184,7 +185,7 @@ public: signals->clear(); for (unsigned i = 0; i < signalIndices.size(); i++) { - /* Add signals */ + // Add signals auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad @@ -208,7 +209,7 @@ public: signals->push_back(rocofSig); } - /* Initialize sample memory */ + // Initialize sample memory smpMemoryData.clear(); for (unsigned i = 0; i < signalIndices.size(); i++) { smpMemoryData.emplace_back(windowSize, 0.0); @@ -224,26 +225,25 @@ public: lastResult.push_back({0,0,0,0}); } - #ifdef DFT_MEM_DUMP - /* Initialize temporary ppsMemory */ + // Initialize temporary ppsMemory ppsMemory.clear(); ppsMemory.resize(windowSize, 0.0); #endif - /* Calculate how much zero padding ist needed for a needed resolution */ + // Calculate how much zero padding ist needed for a needed resolution windowMultiplier = ceil(((double) sampleRate / windowSize) / frequencyResolution); if (windowMultiplier > 1 && estType == EstimationType::IpDFT) throw RuntimeError("Window multiplyer must be 1 if lpdft is used. Change resolution, window_size_factor or frequency range! Current window multiplyer factor is {}", windowMultiplier); freqCount = ceil((endFreqency - startFrequency) / frequencyResolution) + 1; - /* Initialize matrix of dft coeffients */ + // Initialize matrix of dft coeffients matrix.clear(); for (unsigned i = 0; i < freqCount; i++) matrix.emplace_back(windowSize * windowMultiplier, 0.0); - /* Initalize dft results matrix */ + // Initalize dft results matrix results.clear(); for (unsigned i = 0; i < signalIndices.size(); i++) { results.emplace_back(freqCount, 0.0); @@ -261,7 +261,8 @@ public: state = State::PREPARED; } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { MultiSignalHook::parse(json); int ret; @@ -354,7 +355,8 @@ public: state = State::PARSED; } - virtual void check() + virtual + void check() { assert(state == State::PARSED); @@ -367,11 +369,12 @@ public: state = State::CHECKED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); - /* Update sample memory */ + // Update sample memory unsigned i = 0; for (auto index : signalIndices) { smpMemoryData[i++][smpMemPos % windowSize] = smp->data[index].f; @@ -446,9 +449,9 @@ public: if (windowSize <= smpMemPos) { - smp->data[i * 4 + 0].f = currentResult.frequency + frequencyOffset; /* Frequency */ - smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + amplitudeOffset; /* Amplitude */ - smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; /* Phase */ + smp->data[i * 4 + 0].f = currentResult.frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; // Phase smp->data[i * 4 + 3].f = ((currentResult.frequency - lastResult[i].frequency) * (double)rate) + rocofOffset; /* ROCOF */; lastResult[i] = currentResult; } @@ -498,7 +501,7 @@ public: return Reason::SKIP_SAMPLE; } - /** + /* * This function generates the furie coeffients for the calculateDft function */ void generateDftMatrix() @@ -514,7 +517,7 @@ public: } } - /** + /* * This function calculates the discrete furie transform of the input signal */ void calculateDft(enum PaddingType padding, std::vector &ringBuffer, std::vector> &results, unsigned ringBufferPos) @@ -541,13 +544,13 @@ public: else results[i] += 0; } - else if (padding == PaddingType::SIG_REPEAT) /* Repeat samples */ + else if (padding == PaddingType::SIG_REPEAT) // Repeat samples results[i] += tmpSmpWindow[j % windowSize] * matrix[i][j]; } } } - /** + /* * This function prepares the selected window coefficents */ void calculateWindow(enum WindowType windowTypeIn) @@ -566,7 +569,7 @@ public: case WindowType::HAMMING: case WindowType::HANN: { - double a0 = 0.5; /* This is the hann window */ + double a0 = 0.5; // This is the hann window if (windowTypeIn == WindowType::HAMMING) a0 = 25./46; @@ -603,7 +606,7 @@ public: return { a_est, f_est , phase_est}; } - /** + /* * This function is calculation the IpDFT based on the following paper: * * https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7980868&tag=1 @@ -627,14 +630,13 @@ public: double a_est = abs(b.y) * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); a_est *= 2 / (windowSize * windowCorrectionFactor * multiplier); - //Phase estimation (eq 10) double phase_est = atan2(b.y.imag(), b.y.real()) - M_PI * delta; return { a_est, f_est , phase_est}; } - /** + /* * This function is calculating the mximum based on a quadratic interpolation * * This function is based on the following paper: @@ -666,7 +668,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "pmu_dft"; static char d[] = "This hook calculates the dft on a window"; static HookPlugin p; diff --git a/lib/hooks/pmu_ipdft.cpp b/lib/hooks/pmu_ipdft.cpp index 99a3a8c44..fd5275c4c 100644 --- a/lib/hooks/pmu_ipdft.cpp +++ b/lib/hooks/pmu_ipdft.cpp @@ -1,9 +1,9 @@ -/** ipDFT PMU hook. +/* ipDFT PMU hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -17,8 +17,8 @@ protected: std::vector>> dftMatrix; std::vector> dftResult; - unsigned frequencyCount; /* Number of requency bins that are calculated */ - double estimationRange; /* The range around nominalFreq used for estimation */ + unsigned frequencyCount; // Number of requency bins that are calculated + double estimationRange; // The range around nominalFreq used for estimation public: IpDftPmuHook(Path *p, Node *n, int fl, int prio, bool en = true): @@ -38,7 +38,7 @@ public: frequencyCount = ceil((endFrequency - startFrequency) / frequencyResolution); - /* Initialize matrix of dft coeffients */ + // Initialize matrix of dft coeffients dftMatrix.clear(); for (unsigned i = 0; i < frequencyCount; i++) dftMatrix.emplace_back(windowSize, 0.0); @@ -82,7 +82,7 @@ public: { PmuHook::Phasor phasor = {0}; - /* Calculate DFT */ + // Calculate DFT for (unsigned i = 0; i < frequencyCount; i++) { dftResult[i] = 0; @@ -90,9 +90,9 @@ public: for (unsigned j = 0; j < size; j++) dftResult[i] += (*window)[j] * dftMatrix[i][j]; } - /* End calculate DFT */ + // End calculate DFT - /* Find max bin */ + // Find max bin unsigned maxBin = 0; double absAmplitude = 0; @@ -102,7 +102,7 @@ public: maxBin = j; } } - /* End find max bin */ + // End find max bin if (maxBin == 0 || maxBin == (frequencyCount - 1)) { logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); @@ -116,40 +116,40 @@ public: double c = abs(dftResult[ maxBin + 1 ]); double bPhase = atan2(dftResult[maxBin].imag(), dftResult[maxBin].real()); - /* Estimate phasor */ - /* Based on https://ieeexplore.ieee.org/document/7980868 */ + // Estimate phasor + // Based on https://ieeexplore.ieee.org/document/7980868 double delta = 0; - /* Paper eq 8 */ + // Paper eq 8 if (c > a) { delta = 1. * (2. * c - b) / (b + c); } else { delta = -1. * (2. * a - b) / (b + a); } - /* Frequency estimation (eq 4) */ + // Frequency estimation (eq 4) phasor.frequency = startFrequency + ( (double) maxBin + delta) * frequencyResolution; - /* Amplitude estimation (eq 9) */ + // Amplitude estimation (eq 9) phasor.amplitude = b * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); phasor.amplitude *= 2 / (windowSize * window->getCorrectionFactor()); - /* Phase estimation (eq 10) */ + // Phase estimation (eq 10) phasor.phase = bPhase - M_PI * delta; - /* ROCOF estimation */ + // ROCOF estimation phasor.rocof = ((phasor.frequency - lastPhasor.frequency) * (double)phasorRate); - /* End estimate phasor */ + // End estimate phasor } - if (lastPhasor.frequency != 0) /* Check if we already calculated a phasor before */ + if (lastPhasor.frequency != 0) // Check if we already calculated a phasor before phasor.valid = Status::VALID; return phasor; } }; -/* Register hook */ +// Register hook static char n[] = "ip-dft-pmu"; static char d[] = "This hook calculates a phasor based on ipDFT"; static HookPlugin p; diff --git a/lib/hooks/power.cpp b/lib/hooks/power.cpp index 414fe5b49..6716f8262 100644 --- a/lib/hooks/power.cpp +++ b/lib/hooks/power.cpp @@ -1,9 +1,9 @@ -/** RMS hook. +/* RMS hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -13,14 +13,12 @@ namespace villas { namespace node { -/********************************************************************************** - * Concept: - * Based on RMS Hook +/* Concept: Based on RMS Hook * * For each window, calculate integrals for U, I, U*I * Formulas from: https://de.wikipedia.org/wiki/Scheinleistung * Calculate S and P from these - ***********************************************************************************/ + */ class PowerHook : public MultiSignalHook { protected: @@ -55,7 +53,7 @@ protected: bool calcReactivePower; bool caclApparentPower; bool calcCosPhi; - bool channelNameEnable; /**< Rename the output values with channel name or only descriptive name */ + bool channelNameEnable; // Rename the output values with channel name or only descriptive name double angleUnitFactor; enum TimeAlign timeAlignType; @@ -76,7 +74,8 @@ public: timeAlignType(TimeAlign::CENTER) { } - virtual void prepare() + virtual + void prepare() { MultiSignalHook::prepare(); @@ -98,7 +97,7 @@ public: for (auto index : signalIndices) { auto origSig = signals->getByIndex(index); - /* Check that signal has float type */ + // Check that signal has float type if (origSig->type != SignalType::FLOAT) throw RuntimeError("The power hook can only operate on signals of type float!"); } @@ -109,7 +108,7 @@ public: if (channelNameEnable) suffix = fmt::format("_{}", signalNames[i]); - /* Add signals */ + // Add signals if (calcActivePower) { auto activeSig = std::make_shared("active", "W", SignalType::FLOAT); activeSig->name += suffix; @@ -164,7 +163,8 @@ public: } // Read configuration JSON and configure hook accordingly - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { // Ensure hook is not yet running assert(state != State::STARTED); @@ -244,7 +244,8 @@ public: } // This function does the actual processing of the hook when a new sample is passed through. - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -326,7 +327,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "power"; static char d[] = "This hook calculates the Active and Reactive Power for a given signal "; static HookPlugin p; diff --git a/lib/hooks/pps_ts.cpp b/lib/hooks/pps_ts.cpp index b2541e37c..33084ffa6 100644 --- a/lib/hooks/pps_ts.cpp +++ b/lib/hooks/pps_ts.cpp @@ -1,9 +1,9 @@ -/** Timestamp hook. +/* Timestamp hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -31,10 +31,10 @@ protected: bool isSynced; bool isLocked; struct timespec tsVirt; - double timeError; /**< In seconds */ - double periodEstimate; /**< In seconds */ - double periodErrorCompensation; /**< In seconds */ - double period; /**< In seconds */ + double timeError; // In seconds + double periodEstimate; // In seconds + double periodErrorCompensation; // In seconds + double period; // In seconds uintmax_t cntEdges; uintmax_t cntSmps; uintmax_t cntSmpsTotal; @@ -65,7 +65,8 @@ public: filterWindow(horizonEstimation + 1, 0) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -102,7 +103,8 @@ public: state = State::PARSED; } - virtual villas::node::Hook::Reason process(struct Sample *smp) + virtual + villas::node::Hook::Reason process(struct Sample *smp) { switch (mode) { case Mode::SIMPLE: @@ -120,10 +122,10 @@ public: { assert(state == State::STARTED); - /* Get value of PPS signal */ + // Get value of PPS signal float value = smp->data[signalIndex].f; // TODO check if it is really float - /* Detect Edge */ + // Detect Edge bool isEdge = lastValue < threshold && value > threshold; if (isEdge) { tsVirt.tv_sec = currentSecond + 1; @@ -160,10 +162,10 @@ public: { assert(state == State::STARTED); - /* Get value of PPS signal */ + // Get value of PPS signal float value = smp->data[signalIndex].f; // TODO check if it is really float - /* Detect Edge */ + // Detect Edge bool isEdge = lastValue < threshold && value > threshold; lastValue = value; @@ -175,9 +177,8 @@ public: else timeError -= (tsVirt.tv_nsec / 1.0e9); - filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal; - /* Estimated sample period over last 'horizonEstimation' seconds */ + // Estimated sample period over last 'horizonEstimation' seconds unsigned int tmp = cntEdges < filterWindow.size() ? cntEdges : horizonEstimation; double cntSmpsAvg = (cntSmpsTotal - filterWindow[(cntEdges - tmp) % filterWindow.size()]) / tmp; periodEstimate = 1.0 / cntSmpsAvg; @@ -209,7 +210,6 @@ public: struct timespec tsPeriod = time_from_double(period); tsVirt = time_add(&tsVirt, &tsPeriod); - if ((smp->sequence - lastSequence) > 1) logger->warn("Samples missed: {} sampled missed", smp->sequence - lastSequence); @@ -219,7 +219,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "pps_ts"; static char d[] = "Timestamp samples based GPS PPS signal"; static HookPlugin p; diff --git a/lib/hooks/print.cpp b/lib/hooks/print.cpp index e93de76e0..d4c10e372 100644 --- a/lib/hooks/print.cpp +++ b/lib/hooks/print.cpp @@ -1,9 +1,9 @@ -/** Print hook. +/* Print hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -92,7 +92,7 @@ public: if (o) output_path = o; - /* Format */ + // Format auto *fmt = json_format ? FormatFactory::make(json_format) : FormatFactory::make("villas.human"); @@ -131,11 +131,10 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "print"; static char d[] = "Print the message to stdout or a file"; static HookPlugin p; } // namespace node } // namespace villas - diff --git a/lib/hooks/restart.cpp b/lib/hooks/restart.cpp index 5aad7d077..d0e07d7e4 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -1,9 +1,9 @@ -/** Path restart hook. +/* Path restart hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -22,7 +22,8 @@ protected: public: using Hook::Hook; - virtual void start() + virtual + void start() { assert(state == State::PREPARED); @@ -31,7 +32,8 @@ public: state = State::STARTED; } - virtual void stop() + virtual + void stop() { assert(state == State::STARTED); @@ -41,19 +43,20 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); if (prev) { - /* A wrap around of the sequence no should not be treated as a simulation restart */ + // A wrap around of the sequence no should not be treated as a simulation restart if (smp->sequence == 0 && prev->sequence != 0 && prev->sequence < UINT64_MAX - 16) { logger->warn("Simulation from node {} restarted (previous->sequence={}, current->sequence={})", node->getName(), prev->sequence, smp->sequence); smp->flags |= (int) SampleFlags::IS_FIRST; - /* Restart hooks */ + // Restart hooks for (auto k : node->in.hooks) k->restart(); @@ -72,7 +75,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "restart"; static char d[] = "Call restart hooks for current node"; static HookPlugin p; diff --git a/lib/hooks/rms.cpp b/lib/hooks/rms.cpp index f33efbaea..44689d24c 100644 --- a/lib/hooks/rms.cpp +++ b/lib/hooks/rms.cpp @@ -1,9 +1,9 @@ -/** RMS hook. +/* RMS hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -33,11 +33,11 @@ public: { MultiSignalHook::prepare(); - /* Add signals */ + // Add signals for (auto index : signalIndices) { auto origSig = signals->getByIndex(index); - /* Check that signal has float type */ + // Check that signal has float type if (origSig->type != SignalType::FLOAT) throw RuntimeError("The rms hook can only operate on signals of type float!"); } @@ -84,16 +84,16 @@ public: unsigned i = 0; for (auto index : signalIndices) { - /* Square the new value */ + // Square the new value double newValue = pow(smp->data[index].f, 2); - /* Get the old value from the history */ + // Get the old value from the history double oldValue = smpMemory[i][smpMemoryPosition % windowSize]; - /* Append the new value to the history memory */ + // Append the new value to the history memory smpMemory[i][smpMemoryPosition % windowSize] = newValue; - /* Update the accumulator */ + // Update the accumulator accumulator[index] += newValue; accumulator[index] -= oldValue; @@ -109,7 +109,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "rms"; static char d[] = "This hook calculates the root-mean-square (RMS) on a window"; static HookPlugin p; diff --git a/lib/hooks/round.cpp b/lib/hooks/round.cpp index 49ea6f2f0..658e7ec85 100644 --- a/lib/hooks/round.cpp +++ b/lib/hooks/round.cpp @@ -1,9 +1,9 @@ -/** Round hook. +/* Round hook. * - * @author Manuel Pitz - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,7 +24,8 @@ public: precision(1) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -42,7 +43,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { for (auto index : signalIndices) { assert(index < smp->length); @@ -67,7 +69,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "round"; static char d[] = "Round signals to a set number of digits"; static HookPlugin p; diff --git a/lib/hooks/scale.cpp b/lib/hooks/scale.cpp index d9daa6c3c..956abfcf7 100644 --- a/lib/hooks/scale.cpp +++ b/lib/hooks/scale.cpp @@ -1,9 +1,9 @@ -/** Scale hook. +/* Scale hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -26,7 +26,8 @@ public: offset(0.0) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -45,7 +46,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { for (auto index : signalIndices) { assert(index < smp->length); @@ -75,7 +77,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "scale"; static char d[] = "Scale signals by a factor and add offset"; static HookPlugin p; diff --git a/lib/hooks/shift_seq.cpp b/lib/hooks/shift_seq.cpp index a56797b88..d37c7a820 100644 --- a/lib/hooks/shift_seq.cpp +++ b/lib/hooks/shift_seq.cpp @@ -1,9 +1,9 @@ -/** Shift sequence number of samples +/* Shift sequence number of samples * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -20,7 +20,8 @@ public: using Hook::Hook; - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { json_error_t err; int ret; @@ -38,7 +39,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -48,7 +50,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "shift_seq"; static char d[] = "Shift sequence number of samples"; static HookPlugin p; diff --git a/lib/hooks/shift_ts.cpp b/lib/hooks/shift_ts.cpp index 55b6e2f69..a06ad428d 100644 --- a/lib/hooks/shift_ts.cpp +++ b/lib/hooks/shift_ts.cpp @@ -1,9 +1,9 @@ -/** Shift timestamps of samples. +/* Shift timestamps of samples. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -29,7 +29,8 @@ public: mode(SHIFT_ORIGIN) { } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { double o; const char *m = nullptr; @@ -61,7 +62,8 @@ public: state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { timespec *ts; @@ -86,7 +88,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "shift_ts"; static char d[] = "Shift timestamps of samples"; static HookPlugin p; diff --git a/lib/hooks/skip_first.cpp b/lib/hooks/skip_first.cpp index 4bff92e76..a90fc5881 100644 --- a/lib/hooks/skip_first.cpp +++ b/lib/hooks/skip_first.cpp @@ -1,9 +1,9 @@ -/** Skip first hook. +/* Skip first hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -16,9 +16,9 @@ class SkipFirstHook : public Hook { protected: 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. */ + 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 class Mode { @@ -29,7 +29,7 @@ protected: union { struct { timespec until; - timespec wait; /**< Absolute point in time from where we accept samples. */ + timespec wait; // Absolute point in time from where we accept samples. } seconds; struct { @@ -41,7 +41,8 @@ protected: public: using Hook::Hook; - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { double s; @@ -72,22 +73,25 @@ public: throw ConfigError(json, err, "node-config-hook-skip_first"); } - virtual void start() + virtual + void start() { skip_state = SkipState::STARTED; state = State::STARTED; } - virtual void restart() + virtual + void restart() { skip_state = SkipState::STARTED; } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); - /* Remember sequence no or timestamp of first sample. */ + // Remember sequence no or timestamp of first sample. if (skip_state == SkipState::STARTED) { switch (mode) { case Mode::SAMPLES: @@ -121,7 +125,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "skip_first"; static char d[] = "Skip the first samples"; static HookPlugin p; diff --git a/lib/hooks/stats.cpp b/lib/hooks/stats.cpp index 801c1784b..df5b75ac3 100644 --- a/lib/hooks/stats.cpp +++ b/lib/hooks/stats.cpp @@ -1,9 +1,9 @@ -/** Statistic hooks. +/* Statistic hooks. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -29,11 +29,12 @@ public: Hook(p, n, fl, prio, en), parent(pa) { - /* This hook has no config. We never call parse() for it */ + // This hook has no config. We never call parse() for it state = State::PARSED; } - virtual Hook::Reason process(struct Sample *smp); + virtual + Hook::Reason process(struct Sample *smp); }; class StatsReadHook : public Hook { @@ -49,11 +50,12 @@ public: last(nullptr), parent(pa) { - /* This hook has no config. We never call parse() for it */ + // This hook has no config. We never call parse() for it state = State::PARSED; } - virtual void start() + virtual + void start() { assert(state == State::PREPARED); @@ -62,7 +64,8 @@ public: state = State::STARTED; } - virtual void stop() + virtual + void stop() { assert(state == State::STARTED); @@ -72,7 +75,8 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(struct Sample *smp); + virtual + Hook::Reason process(struct Sample *smp); }; class StatsHook : public Hook { @@ -111,7 +115,7 @@ public: if (!readHook || !writeHook) throw MemoryAllocationError(); - /* Add child hooks */ + // Add child hooks if (node) { node->in.hooks.push_back(readHook); node->out.hooks.push_back(writeHook); @@ -121,7 +125,8 @@ public: StatsHook & operator=(const StatsHook&) = delete; StatsHook(const StatsHook&) = delete; - virtual void start() + virtual + void start() { assert(state == State::PREPARED); @@ -134,7 +139,8 @@ public: state = State::STARTED; } - virtual void stop() + virtual + void stop() { assert(state == State::STARTED); @@ -146,14 +152,16 @@ public: state = State::STOPPED; } - virtual void restart() + virtual + void restart() { assert(state == State::STARTED); stats->reset(); } - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { // Only call readHook if it hasnt been added to the node's hook list if (!node) @@ -162,14 +170,16 @@ public: return Hook::Reason::OK; } - virtual void periodic() + virtual + void periodic() { assert(state == State::STARTED); stats->printPeriodic(uri.empty() ? stdout : output, format, node); } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { int ret; json_error_t err; @@ -205,7 +215,8 @@ public: state = State::PARSED; } - virtual void prepare() + virtual + void prepare() { assert(state == State::CHECKED); @@ -258,11 +269,10 @@ Hook::Reason StatsReadHook::process(struct Sample *smp) return Reason::OK; } -/* Register hook */ +// Register hook static char n[] = "stats"; static char d[] = "Collect statistics for the current node"; static HookPlugin p; } // namespace node } // namespace villas - diff --git a/lib/hooks/ts.cpp b/lib/hooks/ts.cpp index bfe8ec548..85c58b28a 100644 --- a/lib/hooks/ts.cpp +++ b/lib/hooks/ts.cpp @@ -1,9 +1,9 @@ -/** Timestamp hook. +/* Timestamp hook. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -17,7 +17,8 @@ class TsHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(struct Sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -27,7 +28,7 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "ts"; static char d[] = "Overwrite origin timestamp of samples with receive timestamp"; static HookPlugin p; diff --git a/lib/kernel/if.cpp b/lib/kernel/if.cpp index e12c6ec62..8dd2eb549 100644 --- a/lib/kernel/if.cpp +++ b/lib/kernel/if.cpp @@ -1,9 +1,9 @@ -/** Interface related functions. +/* Interface related functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -54,30 +54,30 @@ int Interface::start() { logger->info("Starting interface which is used by {} nodes", nodes.size()); - /* Set affinity for network interfaces (skip _loopback_ dev) */ + // Set affinity for network interfaces (skip _loopback_ dev) if (affinity) setAffinity(affinity); - /* Assign fwmark's to nodes which have netem options */ + // Assign fwmark's to nodes which have netem options int ret, fwmark = 0; for (auto *n : nodes) { if (n->tc_qdisc && n->fwmark < 0) n->fwmark = 1 + fwmark++; } - /* Abort if no node is using netem */ + // Abort if no node is using netem if (fwmark == 0) return 0; if (getuid() != 0) throw RuntimeError("Network emulation requires super-user privileges!"); - /* Replace root qdisc */ + // Replace root qdisc ret = tc::prio(this, &tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, fwmark); if (ret) throw RuntimeError("Failed to setup priority queuing discipline: {}", nl_geterror(ret)); - /* Create netem qdisks and appropriate filter per netem node */ + // Create netem qdisks and appropriate filter per netem node for (auto *n : nodes) { if (n->tc_qdisc) { ret = tc::mark(this, &n->tc_classifier, TC_HANDLE(1, n->fwmark), n->fwmark); @@ -126,18 +126,18 @@ Interface * Interface::getEgress(struct sockaddr *sa, SuperNode *sn) auto & interfaces = sn->getInterfaces(); auto affinity = sn->getAffinity(); - /* Determine outgoing interface */ + // Determine outgoing interface link = nl::get_egress_link(sa); if (!link) throw RuntimeError("Failed to get interface for socket address '{}'", socket_print_addr(sa)); - /* Search of existing interface with correct ifindex */ + // Search of existing interface with correct ifindex for (auto *i : interfaces) { if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) return i; } - /* If not found, create a new interface */ + // If not found, create a new interface auto *i = new Interface(link, affinity); if (!i) throw MemoryAllocationError(); diff --git a/lib/kernel/nl.cpp b/lib/kernel/nl.cpp index b1f341be9..e84360b75 100644 --- a/lib/kernel/nl.cpp +++ b/lib/kernel/nl.cpp @@ -1,11 +1,11 @@ -/** Netlink related functions. +/* Netlink related functions. * * VILLASnode uses libnl3 to talk to the Linux kernel to gather networking related information * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -18,8 +18,9 @@ #include #include -/** Singleton for global netlink socket */ -static struct nl_sock *sock = nullptr; +// Singleton for global netlink socket +static +struct nl_sock *sock = nullptr; using namespace villas; using namespace villas::kernel::nl; @@ -29,7 +30,7 @@ struct nl_sock * villas::kernel::nl::init() int ret; if (!sock) { - /* Create connection to netlink */ + // Create connection to netlink sock = nl_socket_alloc(); if (!sock) throw MemoryAllocationError(); @@ -38,7 +39,7 @@ struct nl_sock * villas::kernel::nl::init() if (ret) throw RuntimeError("Failed to connect to kernel: {}", nl_geterror(ret)); - /* Fill some caches */ + // Fill some caches struct nl_cache *cache; ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); if (ret) @@ -58,7 +59,8 @@ void villas::kernel::nl::shutdown() sock = nullptr; } -static int egress_cb(struct nl_msg *msg, void *arg) +static +int egress_cb(struct nl_msg *msg, void *arg) { struct rtnl_route **route = (struct rtnl_route **) arg; @@ -76,7 +78,7 @@ int villas::kernel::nl::get_egress(struct nl_addr *addr) struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETROUTE, 0); struct rtnl_route *route = nullptr; - /* Build message */ + // Build message struct rtmsg rmsg = { .rtm_family = (unsigned char) nl_addr_get_family(addr), .rtm_dst_len = (unsigned char) nl_addr_get_prefixlen(addr), @@ -90,20 +92,20 @@ int villas::kernel::nl::get_egress(struct nl_addr *addr) if (ret) goto out; - /* Send message */ + // Send message ret = nl_send_auto(sock, msg); if (ret < 0) goto out; - /* Hook into receive chain */ + // Hook into receive chain cb = nl_cb_alloc(NL_CB_CUSTOM); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, egress_cb, &route); - /* Receive message */ + // Receive message nl_recvmsgs_report(sock, cb); nl_wait_for_ack(sock); - /* Check result */ + // Check result if (!route || rtnl_route_get_nnexthops(route) != 1) { ret = -1; goto out2; diff --git a/lib/kernel/tc.cpp b/lib/kernel/tc.cpp index 87627d20e..241f5d996 100644 --- a/lib/kernel/tc.cpp +++ b/lib/kernel/tc.cpp @@ -1,11 +1,11 @@ -/** Traffic control (tc): setup interface queuing desciplines. +/* Traffic control (tc): setup interface queuing desciplines. * * VILLASnode uses these functions to setup the network emulation feature. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -89,6 +89,6 @@ int villas::kernel::tc::reset(Interface *i) { struct nl_sock *sock = nl::init(); - /* We restore the default pfifo_fast qdisc, by deleting ours */ + // We restore the default pfifo_fast qdisc, by deleting ours return rtnl_qdisc_delete(sock, i->tc_qdisc); } diff --git a/lib/kernel/tc_netem.cpp b/lib/kernel/tc_netem.cpp index eeb59c0d1..2b4acb38a 100644 --- a/lib/kernel/tc_netem.cpp +++ b/lib/kernel/tc_netem.cpp @@ -1,11 +1,11 @@ -/** Traffic control (tc): setup network emulation qdisc +/* Traffic control (tc): setup network emulation qdisc * * VILLASnode uses these functions to setup the network emulation feature. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -24,14 +24,16 @@ using namespace villas; using namespace villas::utils; using namespace villas::kernel; -static const double max_percent_value = 0xffffffff; +static +const double max_percent_value = 0xffffffff; -/** +/* * Set the delay distribution. Latency/jitter must be set before applying. * @arg qdisc Netem qdisc. * @return 0 on success, error code on failure. */ -static int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, short *data, size_t len) +static +int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, short *data, size_t len) { struct rtnl_netem *netem; @@ -53,8 +55,9 @@ static int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, shor return 0; } -/** Customized version of rtnl_netem_set_delay_distribution() of libnl */ -static int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) +// Customized version of rtnl_netem_set_delay_distribution() of libnl +static +int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) { if (json_is_string(json)) return rtnl_netem_set_delay_distribution(qdisc, json_string_value(json)); diff --git a/lib/mapping.cpp b/lib/mapping.cpp index f7c3793ed..f4ad98fa3 100644 --- a/lib/mapping.cpp +++ b/lib/mapping.cpp @@ -1,9 +1,9 @@ -/** Sample value remapping for mux. +/* Sample value remapping for mux. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -82,7 +82,7 @@ int MappingEntry::parseString(const std::string &str) type = Type::HEADER; } - /* Only node name given.. We map all data */ + // Only node name given.. We map all data else if (!nodeName.empty()) { data.first = nullptr; data.last = nullptr; @@ -211,7 +211,7 @@ int MappingEntry::prepare(NodeList &nodes) } } else { - /* Map all signals */ + // Map all signals data.offset = 0; length = -1; goto end; @@ -229,7 +229,7 @@ int MappingEntry::prepare(NodeList &nodes) } } else - last = first; /* single element: data[5] => data[5-5] */ + last = first; // single element: data[5] => data[5-5] if (last < first) throw RuntimeError("Invalid data range indices for mapping: {} < {}", last, first); diff --git a/lib/mapping_list.cpp b/lib/mapping_list.cpp index dcbbfb1ab..504b606fb 100644 --- a/lib/mapping_list.cpp +++ b/lib/mapping_list.cpp @@ -1,10 +1,9 @@ -/** Sample value remapping for path source muxing. +/* Sample value remapping for path source muxing. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/memory.cpp b/lib/memory.cpp index 6777628b5..739ca737d 100644 --- a/lib/memory.cpp +++ b/lib/memory.cpp @@ -1,9 +1,9 @@ -/** Memory allocators. +/* Memory allocators. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -25,8 +25,10 @@ using namespace villas; using namespace villas::node; using namespace villas::node::memory; -static std::unordered_map allocations; -static Logger logger; +static +std::unordered_map allocations; +static +Logger logger; int villas::node::memory::init(int hugepages) { @@ -62,7 +64,7 @@ int villas::node::memory::lock(size_t sz) #ifndef __arm__ struct rlimit l; - /* Increase ressource limit for locked memory */ + // Increase ressource limit for locked memory ret = getrlimit(RLIMIT_MEMLOCK, &l); if (ret) return ret; @@ -88,15 +90,15 @@ int villas::node::memory::lock(size_t sz) logger->debug("Increased ressource limit of locked memory to {} bytes", sz); } -#endif /* __arm__ */ +#endif // __arm__ #ifdef _POSIX_MEMLOCK - /* Lock all current and future memory allocations */ + // Lock all current and future memory allocations ret = mlockall(MCL_CURRENT | MCL_FUTURE); if (ret) return -1; -#endif /* _POSIX_MEMLOCK */ +#endif // _POSIX_MEMLOCK -#endif /* __linux__ */ +#endif // __linux__ return 0; } @@ -125,7 +127,7 @@ int villas::node::memory::free(void *ptr) { int ret; - /* Find corresponding memory allocation entry */ + // Find corresponding memory allocation entry struct Allocation *ma = allocations[ptr]; if (!ma) return -1; @@ -136,7 +138,7 @@ int villas::node::memory::free(void *ptr) if (ret) return ret; - /* Remove allocation entry */ + // Remove allocation entry auto iter = allocations.find(ptr); if (iter == allocations.end()) return -1; diff --git a/lib/memory/heap.cpp b/lib/memory/heap.cpp index 682da1f1c..bb891324a 100644 --- a/lib/memory/heap.cpp +++ b/lib/memory/heap.cpp @@ -1,9 +1,9 @@ -/** Heap memory allocator. +/* Heap memory allocator. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -49,7 +49,7 @@ int heap_free(struct Allocation *ma, struct Type *m) return 0; } -/* List of available memory types */ +// List of available memory types struct Type villas::node::memory::heap = { .name = "heap", .flags = (int) Flags::HEAP, diff --git a/lib/memory/ib.cpp b/lib/memory/ib.cpp index f6d014804..6421488f5 100644 --- a/lib/memory/ib.cpp +++ b/lib/memory/ib.cpp @@ -1,9 +1,9 @@ -/** Infiniband memory allocator. +/* Infiniband memory allocator. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/memory/managed.cpp b/lib/memory/managed.cpp index f167500ab..e977e502a 100644 --- a/lib/memory/managed.cpp +++ b/lib/memory/managed.cpp @@ -1,9 +1,9 @@ -/** Managed memory allocator. +/* Managed memory allocator. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -28,7 +28,7 @@ using namespace villas::node::memory; static struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) { - /* Simple first-fit allocation */ + // Simple first-fit allocation struct Block *first = (struct Block *) m->_vd; struct Block *block; @@ -47,7 +47,7 @@ struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) if (rem != 0) { gap = alignment - rem; if (gap > avail) - continue; /* Next aligned address isn't in this block anymore */ + continue; // Next aligned address isn't in this block anymore cptr += gap; avail -= gap; @@ -75,7 +75,7 @@ struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) } if (avail > len + sizeof(struct Block)) { - /* Imperfect fit, so create another block for the remaining part */ + // Imperfect fit, so create another block for the remaining part struct Block *newblock = (struct Block *) (cptr + len); newblock->prev = block; newblock->next = block->next; @@ -110,7 +110,7 @@ struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) } } - /* No suitable block found */ + // No suitable block found return nullptr; } @@ -119,10 +119,10 @@ int managed_free(struct Allocation *ma, struct Type *m) { struct Block *block = ma->managed.block; - /* Try to merge it with neighbouring free blocks */ + // Try to merge it with neighbouring free blocks if (block->prev && !block->prev->used && block->next && !block->next->used) { - /* Special case first: both previous and next block are unused */ + // Special case first: both previous and next block are unused block->prev->length += block->length + block->next->length + 2 * sizeof(struct Block); block->prev->next = block->next->next; if (block->next->next) @@ -141,7 +141,7 @@ int managed_free(struct Allocation *ma, struct Type *m) block->next->prev = block; } else { - /* no neighbouring free block, so just mark it as free */ + // no neighbouring free block, so just mark it as free block->used = false; } @@ -160,7 +160,7 @@ struct Type * villas::node::memory::managed(void *ptr, size_t len) return nullptr; } - /* Initialize type */ + // Initialize type mt->name = "managed"; mt->flags = 0; mt->alloc = managed_alloc; @@ -169,7 +169,7 @@ struct Type * villas::node::memory::managed(void *ptr, size_t len) cptr += ALIGN(sizeof(struct Type), sizeof(void *)); - /* Initialize first free memory block */ + // Initialize first free memory block mb = (struct Block *) cptr; mb->prev = nullptr; mb->next = nullptr; diff --git a/lib/memory/mmap.cpp b/lib/memory/mmap.cpp index eab73ec73..5b18bb57d 100644 --- a/lib/memory/mmap.cpp +++ b/lib/memory/mmap.cpp @@ -1,9 +1,9 @@ -/** mmap memory allocator. +/* mmap memory allocator. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -14,10 +14,10 @@ #include #include -/* Required to allocate hugepages on Apple OS X */ +// Required to allocate hugepages on Apple OS X #ifdef __MACH__ #include -#endif /* __MACH__ */ +#endif // __MACH__ #include #include @@ -95,7 +95,7 @@ int villas::node::memory::mmap_init(int hugepages) return 0; } -/** Allocate memory backed by mmaps with malloc() like interface */ +// Allocate memory backed by mmaps with malloc() like interface static struct Allocation * mmap_alloc(size_t len, size_t alignment, struct Type *m) { @@ -127,7 +127,7 @@ struct Allocation * mmap_alloc(size_t len, size_t alignment, struct Type *m) sz = pgsz; } - /** We must make sure that len is a multiple of the page size + /* We must make sure that len is a multiple of the page size * * See: https://lkml.org/lkml/2014/10/22/925 */ @@ -159,7 +159,7 @@ int mmap_free(struct Allocation *ma, struct Type *m) struct Type memory::mmap = { .name = "mmap", .flags = (int) Flags::MMAP, - .alignment = 12, /* 4k page */ + .alignment = 12, // 4k page .alloc = mmap_alloc, .free = mmap_free }; @@ -167,7 +167,7 @@ struct Type memory::mmap = { struct Type memory::mmap_hugetlb = { .name = "mmap_hugetlb", .flags = (int) Flags::MMAP | (int) Flags::HUGEPAGE, - .alignment = 21, /* 2 MiB hugepage */ + .alignment = 21, // 2 MiB hugepage .alloc = mmap_alloc, .free = mmap_free }; diff --git a/lib/node.cpp b/lib/node.cpp index 54dea752f..99597b5db 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -1,9 +1,9 @@ -/** Nodes. +/* Nodes. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -35,7 +35,7 @@ #include #include #include -#endif /* WITH_NETEM */ +#endif // WITH_NETEM using namespace villas; using namespace villas::node; @@ -49,16 +49,16 @@ Node::Node(const uuid_t &id, const std::string &name) : out(NodeDirection::Direction::OUT, this), #ifdef __linux__ fwmark(-1), -#endif /* __linux__ */ +#endif // __linux__ #ifdef WITH_NETEM tc_qdisc(nullptr), tc_classifier(nullptr), -#endif /* WITH_NETEM */ +#endif // WITH_NETEM state(State::INITIALIZED), enabled(true), config(nullptr), name_short(name), - affinity(-1), /* all cores */ + affinity(-1), // all cores factory(nullptr) { if (uuid_is_null(id)) { @@ -81,7 +81,7 @@ Node::~Node() #ifdef WITH_NETEM rtnl_qdisc_put(tc_qdisc); rtnl_cls_put(tc_classifier); -#endif /* WITH_NETEM */ +#endif // WITH_NETEM factory->instances.remove(this); } @@ -132,7 +132,7 @@ int Node::parse(json_t *json) ); if (ret) return ret; -#endif /* __linux__ */ +#endif // __linux__ enabled = en; @@ -148,7 +148,7 @@ int Node::parse(json_t *json) kernel::tc::netem_parse(&tc_qdisc, json_netem); else tc_qdisc = nullptr; -#endif /* WITH_NETEM */ +#endif // WITH_NETEM } struct { @@ -164,12 +164,12 @@ int Node::parse(json_t *json) for (unsigned j = 0; j < ARRAY_LEN(dirs); j++) { json_t *json_dir = json_object_get(json, dirs[j].str); - /* Skip if direction is unused */ + // Skip if direction is unused if (!json_dir) { json_dir = json_pack("{ s: b }", "enabled", 0); } - /* Copy missing fields from main node config to direction config */ + // Copy missing fields from main node config to direction config for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { json_t *json_field_dir = json_object_get(json_dir, fields[i]); json_t *json_field_node = json_object_get(json, fields[i]); @@ -219,7 +219,7 @@ int Node::start() return ret; #ifdef __linux__ - /* Set fwmark for outgoing packets if netem is enabled for this node */ + // Set fwmark for outgoing packets if netem is enabled for this node if (fwmark >= 0) { for (int fd : getNetemFDs()) { ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); @@ -229,7 +229,7 @@ int Node::start() logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); } } -#endif /* __linux__ */ +#endif // __linux__ state = State::STARTED; sequence = sequence_init; @@ -304,7 +304,7 @@ int Node::read(struct Sample * smps[], unsigned cnt) } #ifdef WITH_HOOKS - /* Run read hooks */ + // Run read hooks int rread = in.hooks.process(smps, nread); if (rread < 0) return rread; @@ -324,7 +324,7 @@ int Node::read(struct Sample * smps[], unsigned cnt) logger->debug("Received {} samples", nread); return nread; -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS } int Node::write(struct Sample * smps[], unsigned cnt) @@ -338,11 +338,11 @@ int Node::write(struct Sample * smps[], unsigned cnt) return -1; #ifdef WITH_HOOKS - /* Run write hooks */ + // Run write hooks cnt = out.hooks.process(smps, cnt); if (cnt <= 0) return cnt; -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS vect = getFactory()->getVectorize(); if (!vect) @@ -377,7 +377,7 @@ const std::string & Node::getNameFull() if (tc_qdisc) name_full += fmt::format(", fwmark={}", fwmark); -#endif /* WITH_NETEM */ +#endif // WITH_NETEM if (out.path) { name_full += fmt::format(", #out.signals={}/{}", @@ -387,7 +387,7 @@ const std::string & Node::getNameFull() name_full += fmt::format(", out.path={}", out.path->toString()); } - /* Append node-type specific details */ + // Append node-type specific details auto details = getDetails(); if (!details.empty()) name_full += fmt::format(", {}", details); diff --git a/lib/node_capi.cpp b/lib/node_capi.cpp index 38f280482..e1241858d 100644 --- a/lib/node_capi.cpp +++ b/lib/node_capi.cpp @@ -1,11 +1,9 @@ -/** Node C-API +/* Node C-API * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -184,7 +182,6 @@ unsigned sample_length(vsample *s) return smp->length; } - vsample * sample_pack(unsigned seq, struct timespec *ts_origin, struct timespec *ts_received, unsigned len, double *values) { auto *smp = sample_alloc_mem(len); diff --git a/lib/node_compat.cpp b/lib/node_compat.cpp index d4719bc33..588ec531b 100644 --- a/lib/node_compat.cpp +++ b/lib/node_compat.cpp @@ -1,9 +1,9 @@ -/** Legacy nodes. +/* Legacy nodes. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -174,7 +174,7 @@ int NodeCompat::_write(struct Sample * smps[], unsigned cnt) : -1; } -/** Reverse local and remote socket address. +/* Reverse local and remote socket address. * * @see node_type::reverse */ diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index 9d2e55bf7..16d3d174d 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -1,9 +1,9 @@ -/** Node direction +/* Node direction * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -50,7 +50,7 @@ int NodeDirection::parse(json_t *json) throw ConfigError(json, err, "node-config-node-in"); if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::PROVIDES_SIGNALS) { - /* Do nothing.. Node-type will provide signals */ + // Do nothing.. Node-type will provide signals signals = std::make_shared(); if (!signals) throw MemoryAllocationError(); @@ -118,7 +118,7 @@ int NodeDirection::parse(json_t *json) hooks.parse(json_hooks, m, nullptr, node); } -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return 0; } @@ -130,7 +130,7 @@ void NodeDirection::check() #ifdef WITH_HOOKS hooks.check(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS } int NodeDirection::prepare() @@ -140,7 +140,7 @@ int NodeDirection::prepare() int m = builtin ? t | (int) Hook::Flags::BUILTIN : 0; hooks.prepare(signals, m, nullptr, node); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return 0; } @@ -149,7 +149,7 @@ int NodeDirection::start() { #ifdef WITH_HOOKS hooks.start(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return 0; } @@ -158,7 +158,7 @@ int NodeDirection::stop() { #ifdef WITH_HOOKS hooks.stop(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return 0; } @@ -168,7 +168,7 @@ SignalList::Ptr NodeDirection::getSignals(int after_hooks) const #ifdef WITH_HOOKS if (after_hooks && hooks.size() > 0) return hooks.getSignals(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return signals; } @@ -178,7 +178,7 @@ unsigned NodeDirection::getSignalsMaxCount() const #ifdef WITH_HOOKS if (hooks.size() > 0) return MAX(signals->size(), hooks.getSignalsMaxCount()); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return signals->size(); } diff --git a/lib/node_list.cpp b/lib/node_list.cpp index e77282191..bbd89bed9 100644 --- a/lib/node_list.cpp +++ b/lib/node_list.cpp @@ -1,10 +1,9 @@ -/** Node list +/* Node list * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/nodes/CMakeLists.txt b/lib/nodes/CMakeLists.txt index 04c4719fd..25340dda4 100644 --- a/lib/nodes/CMakeLists.txt +++ b/lib/nodes/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(NODE_SRC loopback_internal.cpp diff --git a/lib/nodes/amqp.cpp b/lib/nodes/amqp.cpp index 87aa35d2e..61f6ceb6c 100644 --- a/lib/nodes/amqp.cpp +++ b/lib/nodes/amqp.cpp @@ -1,9 +1,9 @@ -/** Node type: nanomsg +/* Node type: nanomsg * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -135,7 +135,7 @@ int villas::node::amqp_init(NodeCompat *n) { auto *a = n->getData(); - /* Default values */ + // Default values amqp_default_ssl_info(&a->ssl_info); amqp_default_connection_info(&a->connection_info); @@ -214,7 +214,7 @@ int villas::node::amqp_parse(NodeCompat *n, json_t *json) a->ssl_info.client_key = strdup(client_key); } - /* Format */ + // Format if (a->formatter) delete a->formatter; a->formatter = json_format @@ -272,23 +272,23 @@ int villas::node::amqp_start(NodeCompat *n) a->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); - /* Connect producer */ + // Connect producer a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); if (!a->producer) return -1; - /* Connect consumer */ + // Connect consumer a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); if (!a->consumer) return -1; - /* Declare exchange */ + // Declare exchange amqp_exchange_declare(a->producer, 1, a->exchange, amqp_cstring_bytes("direct"), 0, 0, 0, 0, amqp_empty_table); rep = amqp_get_rpc_reply(a->consumer); if (rep.reply_type != AMQP_RESPONSE_NORMAL) return -1; - /* Declare private queue */ + // Declare private queue r = amqp_queue_declare(a->consumer, 1, amqp_empty_bytes, 0, 0, 0, 1, amqp_empty_table); rep = amqp_get_rpc_reply(a->consumer); if (rep.reply_type != AMQP_RESPONSE_NORMAL) @@ -298,13 +298,13 @@ int villas::node::amqp_start(NodeCompat *n) if (queue.bytes == nullptr) return -1; - /* Bind queue to exchange */ + // Bind queue to exchange amqp_queue_bind(a->consumer, 1, queue, a->exchange, a->routing_key, amqp_empty_table); rep = amqp_get_rpc_reply(a->consumer); if (rep.reply_type != AMQP_RESPONSE_NORMAL) return -1; - /* Start consumer */ + // Start consumer amqp_basic_consume(a->consumer, 1, queue, amqp_empty_bytes, 0, 1, 0, amqp_empty_table); rep = amqp_get_rpc_reply(a->consumer); if (rep.reply_type != AMQP_RESPONSE_NORMAL) @@ -365,7 +365,7 @@ int villas::node::amqp_write(NodeCompat *n, struct Sample * const smps[], unsign .bytes = data }; - /* Send message */ + // Send message ret = amqp_basic_publish(a->producer, 1, a->exchange, a->routing_key, @@ -416,10 +416,11 @@ int villas::node::amqp_destroy(NodeCompat *n) return 0; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "amqp"; p.description = "Advanced Message Queueing Protoocl (rabbitmq-c)"; p.vectorize = 0; @@ -434,5 +435,6 @@ static void register_plugin() { p.write = amqp_write; p.poll_fds = amqp_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/api.cpp b/lib/nodes/api.cpp index 3c2dcd379..dfcad29ef 100644 --- a/lib/nodes/api.cpp +++ b/lib/nodes/api.cpp @@ -1,10 +1,10 @@ -/** Node type: Universal Data-exchange API (v2) +/* Node type: Universal Data-exchange API (v2) * * @see https://github.com/ERIGrid2/JRA-3.1-api - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -122,6 +122,7 @@ int APINode::parse(json_t *json) return 0; } +// Register node static char n[] = "api"; static char d[] = "A node providing a HTTP REST interface"; static NodePlugin p; diff --git a/lib/nodes/can.cpp b/lib/nodes/can.cpp index 3432e4ee5..6b1369fcb 100644 --- a/lib/nodes/can.cpp +++ b/lib/nodes/can.cpp @@ -1,9 +1,9 @@ -/** Node-type: CAN bus +/* Node-type: CAN bus * - * @author Niklas Eiling - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Niklas Eiling + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -30,8 +30,9 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -/* Forward declarations */ -static NodeCompatType p; +// Forward declarations +static +NodeCompatType p; int villas::node::can_init(NodeCompat *n) { @@ -408,7 +409,7 @@ int villas::node::can_read(NodeCompat *n, struct Sample * const smps[], unsigned n->logger->debug("Received {} signals", c->sample_buf_num); - /* Copy signal data to sample only when all signals have been received */ + // Copy signal data to sample only when all signals have been received if (c->sample_buf_num == n->getInputSignals(false)->size()) { smps[nread]->length = c->sample_buf_num; memcpy(smps[nread]->data, c->sample_buf, c->sample_buf_num*sizeof(union SignalData)); @@ -421,7 +422,7 @@ int villas::node::can_read(NodeCompat *n, struct Sample * const smps[], unsigned ret = 0; } - out: /* Set signals, because other VILLASnode parts expect us to */ + out: // Set signals, because other VILLASnode parts expect us to smps[nread]->signals = n->getInputSignals(false); return ret; @@ -432,7 +433,7 @@ int villas::node::can_write(NodeCompat *n, struct Sample * const smps[], unsigne int nbytes; unsigned nwrite; struct can_frame *frame; - size_t fsize = 0; /* number of frames in use */ + size_t fsize = 0; // number of frames in use auto *c = n->getData(); @@ -442,7 +443,7 @@ int villas::node::can_write(NodeCompat *n, struct Sample * const smps[], unsigne for (nwrite=0; nwrite < cnt; nwrite++) { for (size_t i=0; i < n->getOutputSignals()->size(); i++) { - if (c->out[i].offset != 0) /* frame is shared */ + if (c->out[i].offset != 0) // frame is shared continue; frame[fsize].can_dlc = c->out[i].size; @@ -458,7 +459,7 @@ int villas::node::can_write(NodeCompat *n, struct Sample * const smps[], unsigne } for (size_t i=0; i < n->getOutputSignals(false)->size(); i++) { - if (c->out[i].offset == 0) { /* frame already stored */ + if (c->out[i].offset == 0) { // frame already stored continue; } @@ -502,11 +503,11 @@ int villas::node::can_poll_fds(NodeCompat *n, int fds[]) fds[0] = c->socket; - return 1; /* The number of file descriptors which have been set in fds */ + return 1; // The number of file descriptors which have been set in fds } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "can"; p.description = "Receive CAN messages using the socketCAN driver"; p.vectorize = 0; @@ -524,5 +525,6 @@ static void register_plugin() { p.write = can_write; p.poll_fds = can_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index dd6f0eb05..9b40cf4eb 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -1,10 +1,10 @@ -/** Node type: comedi +/* Node type: comedi * - * @author Steffen Vogel - * @author Daniel Krebs - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Daniel Krebs + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -21,9 +21,11 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -/* Utility functions to dump a comedi_cmd graciously taken from comedilib demo */ -static char* comedi_cmd_trigger_src(unsigned int src, char *buf); -static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); +// Utility functions to dump a comedi_cmd graciously taken from comedilib demo +static +char* comedi_cmd_trigger_src(unsigned int src, char *buf); +static +void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); static int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t *json) @@ -33,7 +35,7 @@ int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t json_t *json_chans; json_error_t err; - /* Default values */ + // Default values d->subdevice = -1; d->buffer_size = 16; @@ -49,7 +51,7 @@ int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t if (!json_is_array(json_chans)) return -1; - /* Convert kilobytes to bytes */ + // Convert kilobytes to bytes d->buffer_size = d->buffer_size << 10; size_t i; @@ -101,7 +103,7 @@ int comedi_start_common(NodeCompat *n) if (!d->present) continue; - /* Sanity-check channel config and populate chanspec for later */ + // Sanity-check channel config and populate chanspec for later for (unsigned i = 0; i < d->chanlist_len; i++) { const unsigned int channel = CR_CHAN(d->chanlist[i]); const int range = CR_RANGE(d->chanlist[i]); @@ -129,7 +131,7 @@ int comedi_start_common(NodeCompat *n) const int flags = comedi_get_subdevice_flags(c->dev, d->subdevice); d->sample_size = (flags & SDF_LSAMPL) ? sizeof(lsampl_t) : sizeof(sampl_t); - /* Set buffer size */ + // Set buffer size comedi_set_buffer_size(c->dev, d->subdevice, d->buffer_size); comedi_set_max_buffer_size(c->dev, d->subdevice, d->buffer_size); ret = comedi_get_buffer_size(c->dev, d->subdevice); @@ -153,14 +155,14 @@ int comedi_start_in(NodeCompat *n) auto *c = n->getData(); struct comedi_direction *d = &c->in; - /* Try to find first analog input subdevice if not specified in config */ + // Try to find first analog input subdevice if not specified in config if (d->subdevice < 0) { d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AI, 0); if (d->subdevice < 0) throw RuntimeError("Cannot find analog input device for node '{}'"); } else { - /* Check if subdevice is usable */ + // Check if subdevice is usable ret = comedi_get_subdevice_type(c->dev, d->subdevice); if (ret != COMEDI_SUBD_AI) throw RuntimeError("Input subdevice is not an analog input"); @@ -184,28 +186,28 @@ int comedi_start_in(NodeCompat *n) * full (TODO: evaluate if this makes sense, leave as reminder) */ //cmd.flags = TRIG_WAKE_EOS; - /* Start right now */ + // Start right now cmd.start_src = TRIG_NOW; - /* Trigger scans periodically */ + // Trigger scans periodically cmd.scan_begin_src = TRIG_TIMER; cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; - /* Do conversions in serial with 1ns inter-conversion delay */ + // Do conversions in serial with 1ns inter-conversion delay cmd.convert_src = TRIG_TIMER; - cmd.convert_arg = 1; /* Inter-conversion delay in nanoseconds */ + cmd.convert_arg = 1; // Inter-conversion delay in nanoseconds - /* Terminate scan after each channel has been converted */ + // Terminate scan after each channel has been converted cmd.scan_end_src = TRIG_COUNT; cmd.scan_end_arg = d->chanlist_len; - /* Contionous sampling */ + // Contionous sampling cmd.stop_src = TRIG_NONE; cmd.chanlist = d->chanlist; cmd.chanlist_len = d->chanlist_len; - /* First run might change command, second should return successfully */ + // First run might change command, second should return successfully ret = comedi_command_test(c->dev, &cmd); ret = comedi_command_test(c->dev, &cmd); if (ret < 0) @@ -223,7 +225,7 @@ int comedi_start_in(NodeCompat *n) d->running = true; #if COMEDI_USE_READ - /* Be prepared to consume one entire buffer */ + // Be prepared to consume one entire buffer c->buf = new char[c->in.buffer_size]; c->bufptr = c->buf; if (!c->buf) @@ -244,7 +246,7 @@ int comedi_start_out(NodeCompat *n) auto *c = n->getData(); struct comedi_direction *d = &c->out; - /* Try to find first analog output subdevice if not specified in config */ + // Try to find first analog output subdevice if not specified in config if (d->subdevice < 0) { d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AO, 0); if (d->subdevice < 0) @@ -272,7 +274,7 @@ int comedi_start_out(NodeCompat *n) cmd.flags = CMDF_WRITE; - /* Wait for internal trigger, we will have to fill the buffer first */ + // Wait for internal trigger, we will have to fill the buffer first cmd.start_src = TRIG_INT; cmd.start_arg = 0; @@ -285,14 +287,14 @@ int comedi_start_out(NodeCompat *n) cmd.scan_end_src = TRIG_COUNT; cmd.scan_end_arg = d->chanlist_len; - /* Continous sampling */ + // Continous sampling cmd.stop_src = TRIG_NONE; cmd.stop_arg = 0; cmd.chanlist = d->chanlist; cmd.chanlist_len = d->chanlist_len; - /* First run might change command, second should return successfully */ + // First run might change command, second should return successfully ret = comedi_command_test(c->dev, &cmd); if (ret < 0) throw RuntimeError("Invalid command for input subdevice"); @@ -308,19 +310,19 @@ int comedi_start_out(NodeCompat *n) if (ret < 0) throw RuntimeError("Failed to issue command to input subdevice of node '{}'"); - /* Output will only start after the internal trigger */ + // Output will only start after the internal trigger d->running = false; d->last_debug = time_now(); - /* Allocate buffer for one complete VILLAS sample */ - /** @todo maybe increase buffer size according to c->vectorize */ + // Allocate buffer for one complete VILLAS sample + // @todo maybe increase buffer size according to c->vectorize const size_t local_buffer_size = d->sample_size * d->chanlist_len; d->buffer = new char[local_buffer_size]; d->bufptr = d->buffer; if (!d->buffer) throw MemoryAllocationError(); - /* Initialize local buffer used for write() syscalls */ + // Initialize local buffer used for write() syscalls for (unsigned channel = 0; channel < d->chanlist_len; channel++) { const unsigned raw = comedi_from_phys(0.0f, d->chanspecs[channel].range, d->chanspecs[channel].maxdata); @@ -332,7 +334,7 @@ int comedi_start_out(NodeCompat *n) d->bufptr += d->sample_size; } - /* Preload comedi output buffer */ + // Preload comedi output buffer for (unsigned i = 0; i < d->buffer_size / local_buffer_size; i++) { size_t written = write(comedi_fileno(c->dev), d->buffer, local_buffer_size); if (written != local_buffer_size) { @@ -445,8 +447,8 @@ int villas::node::comedi_start(NodeCompat *n) if (!c->dev) throw RuntimeError("Failed to open device: {}", comedi_strerror(comedi_errno())); - /* Enable non-blocking syscalls */ - /** @todo verify if this works with both input and output, so comment out */ + // Enable non-blocking syscalls + // @todo verify if this works with both input and output, so comment out //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); @@ -528,9 +530,9 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig ret = select(comedi_fileno(c->dev) + 1, &rdset, nullptr, nullptr, &timeout); if (ret < 0) throw RuntimeError("Failed select()"); - else if (ret == 0) /* hit timeout */ + else if (ret == 0) // hit timeout return 0; - else if (FD_ISSET(comedi_fileno(c->dev), &rdset)) { /* comedi file descriptor became ready */ + else if (FD_ISSET(comedi_fileno(c->dev), &rdset)) { // comedi file descriptor became ready const size_t buffer_bytes_free = d->buffer_size - (c->bufptr - c->buf); const size_t bytes_requested = cnt * villas_sample_size; @@ -546,7 +548,7 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig return 0; } else { - /* Sample handling here */ + // Sample handling here const size_t bytes_available = ret; const size_t raw_samples_available = bytes_available / d->sample_size; const size_t villas_samples_available = raw_samples_available / d->chanlist_len; @@ -592,21 +594,21 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig const size_t bytes_consumed = cnt * villas_sample_size; const size_t bytes_left = bytes_available - bytes_consumed; if (bytes_left > 0) { - /* Move leftover bytes to the beginning of buffer */ - /** @todo optimize? */ + // Move leftover bytes to the beginning of buffer + // @todo optimize? memmove(c->buf, c->bufptr, bytes_left); } n->logger->info("Consumed {} bytes", bytes_consumed); - /* Start at the beginning again */ + // Start at the beginning again c->bufptr = c->buf; return cnt; } } else - /* unknown file descriptor became ready */ + // unknown file descriptor became ready n->logger->warn("Unknown file descriptor ready"); return -1; @@ -660,7 +662,7 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig n->logger->info("front={} back={} bufpos={}", c->front, c->back, c->bufpos); if ((c->bufpos + bytes_available) >= d->buffer_size) { - /* Let comedi do the wraparound, only consume until end of buffer */ + // Let comedi do the wraparound, only consume until end of buffer villas_sample_count = (d->buffer_size - c->bufpos) / villas_sample_size; n->logger->warn("Reducing consumption from {} to {} bytes", ret, bytes_available); n->logger->warn("Only consume {} VILLAS samples b/c of buffer wraparound", villas_sample_count); @@ -696,7 +698,7 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig else n->logger->info("Consume {} bytes", ret); - /* Align front to whole samples */ + // Align front to whole samples c->front = c->back + samples_total_bytes; for (size_t i = 0; i < cnt; i++) { @@ -804,7 +806,7 @@ int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsi } if (!d->running) { - /* Output was not yet running, so start now */ + // Output was not yet running, so start now ret = comedi_internal_trigger(c->dev, d->subdevice, 0); if (ret < 0) throw RuntimeError("Failed to trigger-start output"); @@ -856,7 +858,7 @@ int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsi d->bufptr = d->buffer; - /* Move samples from villas into local buffer for comedi */ + // Move samples from villas into local buffer for comedi for (unsigned si = 0; si < sample->length; si++) { unsigned raw_value = 0; @@ -866,7 +868,7 @@ int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsi break; case SignalType::INTEGER: - /* Treat sample as already raw DAC value */ + // Treat sample as already raw DAC value raw_value = sample->data[si].i; break; @@ -875,7 +877,7 @@ int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsi break; case SignalType::COMPLEX: - /* We only output the real part */ + // We only output the real part raw_value = comedi_from_phys(std::real(sample->data[si].z), d->chanspecs[si].range, d->chanspecs[si].maxdata); break; @@ -892,12 +894,12 @@ int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsi d->bufptr += d->sample_size; } - /* Try to write one complete villas sample to comedi */ + // Try to write one complete villas sample to comedi size_t written = write(comedi_fileno(c->dev), d->buffer, villas_sample_size); if (written < 0) throw RuntimeError("write() failed"); else if (written == 0) - break; /* Comedi doesn't accept any more samples at the moment */ + break; // Comedi doesn't accept any more samples at the moment else if (written == villas_sample_size) villas_samples_written++; else @@ -967,10 +969,11 @@ int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) return 0; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "comedi"; p.description = "Comedi-compatible DAQ/ADC cards"; p.vectorize = 0; @@ -983,5 +986,6 @@ static void register_plugin() { p.write = comedi_write; p.poll_fds = comedi_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index c219855c4..2bd7c5a4e 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -1,11 +1,11 @@ -/** Node type: Ethercat +/* Node type: Ethercat * - * @author Niklas Eiling - * @author Steffen Vogel - * @author Divya Laxetti - * @copyright 2018-2020, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Niklas Eiling + * Author: Steffen Vogel + * Author: Divya Laxetti + * SPDX-FileCopyrightText: 2018-2020 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -18,18 +18,20 @@ using namespace villas; using namespace villas::node; -/* Forward declartions */ -static NodeCompatType p; +// Forward declartions +static +NodeCompatType p; -/* Constants */ +// Constants #define NSEC_PER_SEC (1000000000) #define FREQUENCY (NSEC_PER_SEC / PERIOD_NS) -/* Global state and config */ +// Global state and config int master_id = 0; int alias = 0; -static ec_master_t *master = nullptr; +static +ec_master_t *master = nullptr; struct coupler { int position; @@ -54,11 +56,11 @@ void ethercat_cyclic_task(NodeCompat *n) while (true) { w->task.wait(); - /* Receive process data */ + // Receive process data ecrt_master_receive(master); ecrt_domain_process(w->domain); - /* Receive process data */ + // Receive process data smp = sample_alloc(&w->pool); if (!smp) { n->logger->warn("Pool underrun"); @@ -69,7 +71,7 @@ void ethercat_cyclic_task(NodeCompat *n) smp->flags = (int) SampleFlags::HAS_DATA; smp->signals = n->getInputSignals(false); - /* Read process data */ + // Read process data for (unsigned i = 0; i < smp->length; i++) { int16_t ain_value = EC_READ_S16(w->domain_pd + w->in.offsets[i]); @@ -80,7 +82,7 @@ void ethercat_cyclic_task(NodeCompat *n) if (ret) n->logger->warn("Failed to enqueue samples"); - /* Write process data */ + // Write process data smp = w->send.exchange(nullptr); for (unsigned i = 0; i < w->out.num_channels; i++) { @@ -124,7 +126,7 @@ int villas::node::ethercat_type_start(villas::node::SuperNode *sn) if (!master) return -1; - /* Create configuration for bus coupler */ + // Create configuration for bus coupler coupler.sc = ecrt_master_slave_config(master, alias, coupler.position, coupler.vendor_id, coupler.product_code); if (!coupler.sc) return -1; @@ -187,7 +189,7 @@ int villas::node::ethercat_check(NodeCompat *n) { auto *w = n->getData(); - /* Some parts of the configuration are still hard-coded for this specific setup */ + // Some parts of the configuration are still hard-coded for this specific setup if (w->in.product_code != ETHERCAT_PID_EL3008 || w->in.vendor_id != ETHERCAT_VID_BECKHOFF || w->out.product_code != ETHERCAT_PID_EL4038 || @@ -227,7 +229,7 @@ int villas::node::ethercat_prepare(NodeCompat *n) memset(w->domain_regs, 0, (w->in.num_channels + w->out.num_channels + 1) * sizeof(ec_pdo_entry_reg_t)); - /* Prepare list of domain registers */ + // Prepare list of domain registers int o = 0; for (unsigned i = 0; i < w->out.num_channels; i++) { w->out.offsets[i] = 0; @@ -243,7 +245,7 @@ int villas::node::ethercat_prepare(NodeCompat *n) o++; }; - /* Prepare list of domain registers */ + // Prepare list of domain registers for (unsigned i = 0; i < w->in.num_channels; i++) { w->in.offsets[i] = 0; @@ -270,7 +272,7 @@ int villas::node::ethercat_start(NodeCompat *n) int ret; auto *w = n->getData(); - /* Configure analog in */ + // Configure analog in w->in.sc = ecrt_master_slave_config(master, alias, w->in.position, w->in.vendor_id, w->in.product_code); if (!w->in.sc) throw RuntimeError("Failed to get slave configuration."); @@ -279,7 +281,7 @@ int villas::node::ethercat_start(NodeCompat *n) if (ret) throw RuntimeError("Failed to configure PDOs."); - /* Configure analog out */ + // Configure analog out w->out.sc = ecrt_master_slave_config(master, alias, w->out.position, w->out.vendor_id, w->out.product_code); if (!w->out.sc) throw RuntimeError("Failed to get slave configuration."); @@ -292,7 +294,7 @@ int villas::node::ethercat_start(NodeCompat *n) if (ret) throw RuntimeError("PDO entry registration failed!"); - /** @todo Check that master is not already active... */ + // @todo Check that master is not already active... ret = ecrt_master_activate(master); if (ret) return -1; @@ -301,10 +303,10 @@ int villas::node::ethercat_start(NodeCompat *n) if (!w->domain_pd) return -1; - /* Start cyclic timer */ + // Start cyclic timer w->task.setRate(w->rate); - /* Start cyclic task */ + // Start cyclic task w->thread = std::thread(ethercat_cyclic_task, n); return 0; @@ -363,7 +365,7 @@ int villas::node::ethercat_init(NodeCompat *n) { auto *w = n->getData(); - /* Default values */ + // Default values w->rate = 1000; w->in.num_channels = 8; @@ -386,7 +388,7 @@ int villas::node::ethercat_init(NodeCompat *n) w->domain_pd = nullptr; w->domain_regs = nullptr; - /* Placement new for C++ objects */ + // Placement new for C++ objects new (&w->send) std::atomic(); new (&w->thread) std::thread(); new (&w->task) Task(CLOCK_REALTIME); @@ -418,7 +420,7 @@ int villas::node::ethercat_destroy(NodeCompat *n) w->task.~Task(); - /** @todo Destroy domain? */ + // @todo Destroy domain? return 0; } @@ -432,11 +434,11 @@ int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "ethercat"; p.description = "Send and receive samples of an ethercat connection"; - p.vectorize = 1; /* we only process a single sample per call */ + p.vectorize = 1; // we only process a single sample per call p.size = sizeof(struct ethercat); p.type.start = ethercat_type_start; p.type.stop = ethercat_type_stop; @@ -452,6 +454,6 @@ static void register_plugin() { p.write = ethercat_write; p.poll_fds = ethercat_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } - diff --git a/lib/nodes/example.cpp b/lib/nodes/example.cpp index ad421e701..f21db14a2 100644 --- a/lib/nodes/example.cpp +++ b/lib/nodes/example.cpp @@ -1,12 +1,12 @@ -/** An example get started with new implementations of new node-types +/* An example get started with new implementations of new node-types * * This example does not do any particulary useful. * It is just a skeleton to get you started with new node-types. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -42,7 +42,7 @@ int ExampleNode::prepare() int ExampleNode::parse(json_t *json) { - /* TODO: Add implementation here. The following is just an example */ + // TODO: Add implementation here. The following is just an example const char *setting2_str = nullptr; @@ -138,7 +138,7 @@ int ExampleNode::_read(struct Sample *smps[], unsigned cnt) int read; struct timespec now; - /* TODO: Add implementation here. The following is just an example */ + // TODO: Add implementation here. The following is just an example assert(cnt >= 1 && smps[0]->capacity >= 1); @@ -151,7 +151,7 @@ int ExampleNode::_read(struct Sample *smps[], unsigned cnt) smps[0]->flags = (int) SampleFlags::HAS_DATA; smps[0]->signals = getInputSignals(false); - read = 1; /* The number of samples read */ + read = 1; // The number of samples read return read; } @@ -160,14 +160,14 @@ int ExampleNode::_write(struct Sample *smps[], unsigned cnt) { int written; - /* TODO: Add implementation here. */ + // TODO: Add implementation here. - written = 0; /* The number of samples written */ + written = 0; // The number of samples written return written; } - +// Register node static char n[] = "example"; static char d[] = "An example for staring new node-type implementations"; static NodePlugin p; diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index 15a33423d..ef4269688 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -1,9 +1,9 @@ -/** Node-type for subprocess node-types. +/* Node-type for subprocess node-types. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -86,7 +86,7 @@ int ExecNode::parse(json_t *json) } if (json_env) { - /* obj is a JSON object */ + // obj is a JSON object const char *key; json_t *json_value; @@ -98,7 +98,7 @@ int ExecNode::parse(json_t *json) } } - /* Format */ + // Format auto *fmt = json_format ? FormatFactory::make(json_format) : FormatFactory::make("villas.human"); @@ -116,7 +116,7 @@ int ExecNode::prepare() { assert(state == State::CHECKED); - /* Initialize IO */ + // Initialize IO formatter->start(getInputSignals(false)); return Node::prepare(); @@ -124,7 +124,7 @@ int ExecNode::prepare() int ExecNode::start() { - /* Start subprocess */ + // Start subprocess proc = std::make_unique(command, arguments, environment, working_dir, shell); logger->debug("Started sub-process with pid={}", proc->getPid()); @@ -149,14 +149,14 @@ int ExecNode::stop() if (ret) return ret; - /* Stop subprocess */ + // Stop subprocess logger->debug("Killing sub-process with pid={}", proc->getPid()); proc->kill(SIGINT); logger->debug("Waiting for sub-process with pid={} to terminate", proc->getPid()); proc->close(); - /** @todo Check exit code of subprocess? */ + // @todo Check exit code of subprocess? return 0; } @@ -206,6 +206,7 @@ std::vector ExecNode::getPollFDs() return { proc->getFdIn() }; } +// Register node static char n[] = "exec"; static char d[] = "run subprocesses with stdin/stdout communication"; static NodePlugin p; diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index 631cd02f8..d3fbfb22c 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -1,9 +1,9 @@ -/** Node type: File +/* Node type: File * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -32,7 +32,7 @@ char * file_format_name(const char *format, struct timespec *ts) if (!buf) throw MemoryAllocationError(); - /* Convert time */ + // Convert time gmtime_r(&ts->tv_sec, &tm); strftime(buf, FILE_MAX_PATHLEN, format, &tm); @@ -43,24 +43,24 @@ char * file_format_name(const char *format, struct timespec *ts) static struct timespec file_calc_offset(const struct timespec *first, const struct timespec *epoch, enum file::EpochMode mode) { - /* Get current time */ + // Get current time struct timespec now = time_now(); struct timespec offset; - /* Set offset depending on epoch */ + // Set offset depending on epoch switch (mode) { - case file::EpochMode::DIRECT: /* read first value at now + epoch */ + case file::EpochMode::DIRECT: // read first value at now + epoch offset = time_diff(first, &now); return time_add(&offset, epoch); - case file::EpochMode::WAIT: /* read first value at now + first + epoch */ + case file::EpochMode::WAIT: // read first value at now + first + epoch offset = now; return time_add(&now, epoch); - case file::EpochMode::RELATIVE: /* read first value at first + epoch */ + case file::EpochMode::RELATIVE: // read first value at first + epoch return *epoch; - case file::EpochMode::ABSOLUTE: /* read first value at f->epoch */ + case file::EpochMode::ABSOLUTE: // read first value at f->epoch return time_diff(first, epoch); default: @@ -101,7 +101,7 @@ int villas::node::file_parse(NodeCompat *n, json_t *json) f->epoch = time_from_double(epoch_flt); f->uri_tmpl = uri_tmpl ? strdup(uri_tmpl) : nullptr; - /* Format */ + // Format if (f->formatter) delete f->formatter; f->formatter = json_format @@ -230,13 +230,13 @@ int villas::node::file_start(NodeCompat *n) struct timespec now = time_now(); int ret; - /* Prepare file name */ + // Prepare file name if (f->uri) delete[] f->uri; f->uri = file_format_name(f->uri_tmpl, &now); - /* Check if directory exists */ + // Check if directory exists struct stat sb; char *cpy = strdup(f->uri); char *dir = dirname(cpy); @@ -261,7 +261,7 @@ int villas::node::file_start(NodeCompat *n) f->formatter->start(n->getInputSignals(false)); - /* Open file */ + // Open file f->stream_out = fopen(f->uri, "a+"); if (!f->stream_out) return -1; @@ -282,10 +282,10 @@ int villas::node::file_start(NodeCompat *n) return ret; } - /* Create timer */ + // Create timer f->task.setRate(f->rate); - /* Get timestamp of first line */ + // Get timestamp of first line if (f->epoch_mode != file::EpochMode::ORIGINAL) { rewind(f->stream_in); @@ -309,7 +309,7 @@ int villas::node::file_start(NodeCompat *n) rewind(f->stream_in); - /* Fast-forward */ + // Fast-forward struct Sample *smp = sample_alloc_mem(n->getInputSignals(false)->size()); for (unsigned i = 0; i < f->skip_lines; i++) f->formatter->scan(f->stream_in, smp); @@ -351,10 +351,10 @@ retry: ret = f->formatter->scan(f->stream_in, smps, cnt); goto retry; case file::EOFBehaviour::SUSPEND: - /* We wait 10ms before fetching again. */ + // We wait 10ms before fetching again. usleep(100000); - /* Try to download more data if this is a remote file. */ + // Try to download more data if this is a remote file. clearerr(f->stream_in); goto retry; @@ -374,7 +374,7 @@ retry: ret = f->formatter->scan(f->stream_in, smps, cnt); return 0; } - /* We dont wait in FILE_EPOCH_ORIGINAL mode */ + // We dont wait in FILE_EPOCH_ORIGINAL mode if (f->epoch_mode == file::EpochMode::ORIGINAL) return cnt; @@ -390,7 +390,7 @@ retry: ret = f->formatter->scan(f->stream_in, smps, cnt); steps = f->task.wait(); } - /* Check for overruns */ + // Check for overruns if (steps == 0) throw SystemError("Failed to wait for timer"); else if (steps != 1) @@ -431,7 +431,7 @@ int villas::node::file_poll_fds(NodeCompat *n, int fds[]) return 1; } - return -1; /** @todo not supported yet */ + return -1; // @todo not supported yet } int villas::node::file_init(NodeCompat *n) @@ -440,7 +440,7 @@ int villas::node::file_init(NodeCompat *n) new (&f->task) Task(CLOCK_REALTIME); - /* Default values */ + // Default values f->rate = 0; f->eof_mode = file::EOFBehaviour::STOP; f->epoch_mode = file::EpochMode::DIRECT; @@ -469,10 +469,11 @@ int villas::node::file_destroy(NodeCompat *n) return 0; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "file"; p.description = "support for file log / replay node type"; p.vectorize = 1; @@ -487,5 +488,6 @@ static void register_plugin() { p.write = file_write; p.poll_fds = file_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index af884406e..76e44d941 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -1,9 +1,9 @@ -/** Communicate with VILLASfpga Xilinx FPGA boards +/* Communicate with VILLASfpga Xilinx FPGA boards * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -32,12 +32,16 @@ using namespace villas::node; using namespace villas::fpga; using namespace villas::utils; -/* Global state */ -static std::list> cards; -static std::map dmaMap; +// Global state +static +std::list> cards; +static +std::map dmaMap; -static std::shared_ptr pciDevices; -static std::shared_ptr vfioContainer; +static +std::shared_ptr pciDevices; +static +std::shared_ptr vfioContainer; using namespace villas; using namespace villas::node; @@ -204,7 +208,7 @@ int FpgaNode::_write(Sample *smps[], unsigned cnt) if (!state) return -1; - written = 0; /* The number of samples written */ + written = 0; // The number of samples written return written; } diff --git a/lib/nodes/iec60870.cpp b/lib/nodes/iec60870.cpp index 8c71ab4f2..437f41f80 100644 --- a/lib/nodes/iec60870.cpp +++ b/lib/nodes/iec60870.cpp @@ -1,9 +1,9 @@ -/** Node type: IEC60870-5-104 +/* Node type: IEC60870-5-104 * - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -20,14 +20,16 @@ using namespace villas::utils; using namespace villas::node::iec60870; using namespace std::literals::chrono_literals; -static CP56Time2a timespec_to_cp56time2a(timespec time) { +static +CP56Time2a timespec_to_cp56time2a(timespec time) { time_t time_ms = static_cast(time.tv_sec) * 1000 + static_cast(time.tv_nsec) / 1000000; return CP56Time2a_createFromMsTimestamp(NULL, time_ms); } -static timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { +static +timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { auto time_ms = CP56Time2a_toMsTimestamp(cp56time2a); timespec time {}; time.tv_nsec = time_ms % 1000 * 1000; @@ -798,6 +800,7 @@ int SlaveNode::stop() return Node::stop(); } +// Register node static char name[] = "iec60870-5-104"; static char description[] = "Provide values as protocol slave"; static NodePlugin p; diff --git a/lib/nodes/iec61850.cpp b/lib/nodes/iec61850.cpp index 8c380c963..33ffedc9f 100644 --- a/lib/nodes/iec61850.cpp +++ b/lib/nodes/iec61850.cpp @@ -1,9 +1,9 @@ -/** Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values) * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -25,7 +25,7 @@ using namespace villas::node; using namespace villas::utils; const struct iec61850_type_descriptor type_descriptors[] = { - /* name, iec_type, type, size, supported */ + // name, iec_type, type, size, supported { "boolean", IEC61850Type::BOOLEAN, SignalType::BOOLEAN, 1, false, false }, { "int8", IEC61850Type::INT8, SignalType::INTEGER, 1, false, false }, { "int16", IEC61850Type::INT16, SignalType::INTEGER, 2, false, false }, @@ -48,11 +48,15 @@ const struct iec61850_type_descriptor type_descriptors[] = { { "bitstring", IEC61850Type::BITSTRING, SignalType::INVALID, 4, false, false } }; -/** Each network interface needs a separate receiver */ -static struct List receivers; -static pthread_t thread; -static EthernetHandleSet hset; -static int users = 0; +// Each network interface needs a separate receiver +static +struct List receivers; +static +pthread_t thread; +static +EthernetHandleSet hset; +static +int users = 0; static void * iec61850_thread(void *ctx) @@ -106,7 +110,7 @@ int villas::node::iec61850_parse_signals(json_t *json_signals, struct List *sign "iec_type", &iec_type ); - /* Try to deduct the IEC 61850 data type from VILLAS signal format */ + // Try to deduct the IEC 61850 data type from VILLAS signal format if (!iec_type) { if (!node_signals) return -1; @@ -165,7 +169,7 @@ int villas::node::iec61850_type_start(villas::node::SuperNode *sn) { int ret; - /* Check if already initialized */ + // Check if already initialized if (users > 0) return 0; @@ -279,7 +283,7 @@ struct iec61850_receiver * villas::node::iec61850_receiver_create(enum iec61850_ { struct iec61850_receiver *r; - /* Check if there is already a SVReceiver for this interface */ + // Check if there is already a SVReceiver for this interface r = iec61850_receiver_lookup(t, intf); if (!r) { r = new struct iec61850_receiver; diff --git a/lib/nodes/iec61850_goose.cpp b/lib/nodes/iec61850_goose.cpp index 40c01efec..8a76c7fda 100644 --- a/lib/nodes/iec61850_goose.cpp +++ b/lib/nodes/iec61850_goose.cpp @@ -1,9 +1,9 @@ -/** Node type: IEC 61850 - GOOSE +/* Node type: IEC 61850 - GOOSE * - * @author Philipp Jungkamp - * @copyright 2023, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -909,6 +909,7 @@ int GooseNode::stop() return Node::stop(); } +// Register node static char name[] = "iec61850-8-1"; static char description[] = "IEC 61850-8-1 (GOOSE)"; static NodePlugin p; diff --git a/lib/nodes/iec61850_sv.cpp b/lib/nodes/iec61850_sv.cpp index 74f3e5b3f..6db86e0fb 100644 --- a/lib/nodes/iec61850_sv.cpp +++ b/lib/nodes/iec61850_sv.cpp @@ -1,9 +1,9 @@ -/** Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values) * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -139,11 +139,11 @@ int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) json_t *json_signals = nullptr; json_error_t err; - /* Default values */ + // Default values i->out.enabled = false; i->in.enabled = false; - i->out.smpmod = -1; /* do not set smpmod */ - i->out.smprate = -1; /* do not set smpmod */ + i->out.smpmod = -1; // do not set smpmod + i->out.smprate = -1; // do not set smpmod i->out.confrev = 1; i->out.vlan_priority = CONFIG_SV_DEFAULT_PRIORITY; i->out.vlan_id = CONFIG_SV_DEFAULT_VLAN_ID; @@ -231,7 +231,7 @@ char * villas::node::iec61850_sv_print(NodeCompat *n) buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, i->app_id, ether_ntoa(&i->dst_address)); - /* Publisher part */ + // Publisher part if (i->out.enabled) { strcatf(&buf, ", pub.svid=%s, pub.vlan_prio=%d, pub.vlan_id=%#x, pub.confrev=%d, pub.#fields=%zu", i->out.svid, @@ -242,7 +242,7 @@ char * villas::node::iec61850_sv_print(NodeCompat *n) ); } - /* Subscriber part */ + // Subscriber part if (i->in.enabled) strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); @@ -254,7 +254,7 @@ int villas::node::iec61850_sv_start(NodeCompat *n) int ret; auto *i = n->getData(); - /* Initialize publisher */ + // Initialize publisher if (i->out.enabled) { i->out.publisher = SVPublisher_create(nullptr, i->interface); i->out.asdu = SVPublisher_addASDU(i->out.publisher, i->out.svid, n->getNameShort().c_str(), i->out.confrev); @@ -291,24 +291,24 @@ int villas::node::iec61850_sv_start(NodeCompat *n) // if (s->out.smprate >= 0) // SV_ASDU_setSmpRate(i->out.asdu, i->out.smprate); - /* Start publisher */ + // Start publisher SVPublisher_setupComplete(i->out.publisher); } - /* Start subscriber */ + // Start subscriber if (i->in.enabled) { struct iec61850_receiver *r = iec61850_receiver_create(iec61850_receiver::Type::SAMPLED_VALUES, i->interface); i->in.receiver = r->sv; i->in.subscriber = SVSubscriber_create(i->dst_address.ether_addr_octet, i->app_id); - /* Install a callback handler for the subscriber */ + // Install a callback handler for the subscriber SVSubscriber_setListener(i->in.subscriber, iec61850_sv_listener, n); - /* Connect the subscriber to the receiver */ + // Connect the subscriber to the receiver SVReceiver_addSubscriber(i->in.receiver, i->in.subscriber); - /* Initialize pool and queue to pass samples between threads */ + // Initialize pool and queue to pass samples between threads ret = pool_init(&i->in.pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); if (ret) return ret; @@ -351,11 +351,11 @@ int villas::node::iec61850_sv_destroy(NodeCompat *n) int ret; auto *i = n->getData(); - /* Deinitialize publisher */ + // Deinitialize publisher if (i->out.enabled && i->out.publisher) SVPublisher_destroy(i->out.publisher); - /* Deinitialise subscriber */ + // Deinitialise subscriber if (i->in.enabled) { ret = queue_signalled_destroy(&i->in.queue); if (ret) @@ -461,10 +461,11 @@ int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "iec61850-9-2"; p.description = "IEC 61850-9-2 (Sampled Values)"; p.vectorize = 0; @@ -480,5 +481,6 @@ static void register_plugin() { p.write = iec61850_sv_write; p.poll_fds = iec61850_sv_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index 263f62cf6..e91c0357f 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -1,9 +1,9 @@ -/** Node type: infiniband +/* Node type: infiniband * - * @author Dennis Potter - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Dennis Potter + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -34,7 +34,7 @@ int ib_disconnect(NodeCompat *n) rdma_disconnect(ib->ctx.id); - /* If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. */ + // If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. while (ib->conn.available_recv_wrs) { wcs = ibv_poll_cq(ib->ctx.recv_cq, ib->recv_cq_size, wc); @@ -44,13 +44,13 @@ int ib_disconnect(NodeCompat *n) sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); } - /* Send Queue */ + // Send Queue while ((wcs = ibv_poll_cq(ib->ctx.send_cq, ib->send_cq_size, wc))) for (int j = 0; j < wcs; j++) if (wc[j].wr_id > 0) sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); - /* Destroy QP */ + // Destroy QP rdma_destroy_qp(ib->ctx.id); n->logger->debug("Destroyed QP"); @@ -66,7 +66,7 @@ void ib_build_ibv(NodeCompat *n) n->logger->debug("Starting to build IBV components"); - /* Create completion queues (No completion channel!) */ + // Create completion queues (No completion channel!) ib->ctx.recv_cq = ibv_create_cq(ib->ctx.id->verbs, ib->recv_cq_size, nullptr, nullptr, 0); if (!ib->ctx.recv_cq) throw RuntimeError("Could not create receive completion queue"); @@ -79,11 +79,11 @@ void ib_build_ibv(NodeCompat *n) n->logger->debug("Created send Completion Queue"); - /* Prepare remaining Queue Pair (QP) attributes */ + // Prepare remaining Queue Pair (QP) attributes ib->qp_init.send_cq = ib->ctx.send_cq; ib->qp_init.recv_cq = ib->ctx.recv_cq; - /* Create the actual QP */ + // Create the actual QP ret = rdma_create_qp(ib->ctx.id, ib->ctx.pd, &ib->qp_init); if (ret) throw RuntimeError("Failed to create Queue Pair"); @@ -103,10 +103,10 @@ int ib_addr_resolved(NodeCompat *n) n->logger->debug("Successfully resolved address"); - /* Build all components from IB Verbs */ + // Build all components from IB Verbs ib_build_ibv(n); - /* Resolve address */ + // Resolve address ret = rdma_resolve_route(ib->ctx.id, ib->conn.timeout); if (ret) throw RuntimeError("Failed to resolve route"); @@ -123,7 +123,7 @@ int ib_route_resolved(NodeCompat *n) struct rdma_conn_param cm_params; memset(&cm_params, 0, sizeof(cm_params)); - /* Send connection request */ + // Send connection request ret = rdma_connect(ib->ctx.id, &cm_params); if (ret) throw RuntimeError("Failed to connect"); @@ -147,7 +147,7 @@ int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) struct rdma_conn_param cm_params; memset(&cm_params, 0, sizeof(cm_params)); - /* Accept connection request */ + // Accept connection request ret = rdma_accept(ib->ctx.id, &cm_params); if (ret) throw RuntimeError("Failed to connect"); @@ -187,7 +187,7 @@ int villas::node::ib_parse(NodeCompat *n, json_t *json) int buffer_subtraction = 16; int use_fallback = 1; - /* Parse JSON files and copy to local variables */ + // Parse JSON files and copy to local variables json_t *json_in = nullptr; json_t *json_out = nullptr; json_error_t err; @@ -200,7 +200,6 @@ int villas::node::ib_parse(NodeCompat *n, json_t *json) if (ret) throw ConfigError(json, err, "node-config-node-ib"); - if (json_in) { ret = json_unpack_ex(json_in, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i}", "address", &local, @@ -240,19 +239,19 @@ int villas::node::ib_parse(NodeCompat *n, json_t *json) n->logger->debug("Setup as target"); } - /* Set fallback mode */ + // Set fallback mode ib->conn.use_fallback = use_fallback; - /* Set vectorize mode. Do not print, since framework will print this information */ + // Set vectorize mode. Do not print, since framework will print this information n->in.vectorize = vectorize_in; n->out.vectorize = vectorize_out; - /* Set buffer subtraction */ + // Set buffer subtraction ib->conn.buffer_subtraction = buffer_subtraction; n->logger->debug("Set buffer subtraction to {}", buffer_subtraction); - /* Translate IP:PORT to a struct addrinfo */ + // Translate IP:PORT to a struct addrinfo char *ip_adr = strtok_r(local, ":", &lasts); char *port = strtok_r(nullptr, ":", &lasts); @@ -262,7 +261,7 @@ int villas::node::ib_parse(NodeCompat *n, json_t *json) n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); - /* Translate port space */ + // Translate port space if (strcmp(transport_mode, "RC") == 0) { ib->conn.port_space = RDMA_PS_TCP; ib->qp_init.qp_type = IBV_QPT_RC; @@ -285,44 +284,43 @@ int villas::node::ib_parse(NodeCompat *n, json_t *json) n->logger->debug("Set transport mode to {}", transport_mode); - /* Set timeout */ + // Set timeout ib->conn.timeout = timeout; n->logger->debug("Set timeout to {}", timeout); - /* Set completion queue size */ + // Set completion queue size ib->recv_cq_size = recv_cq_size; ib->send_cq_size = send_cq_size; n->logger->debug("Set Completion Queue size to {} & {} (in & out)", recv_cq_size, send_cq_size); - - /* Translate inline mode */ + // Translate inline mode ib->conn.send_inline = send_inline; n->logger->debug("Set send_inline to {}", send_inline); - /* Set max. send and receive Work Requests */ + // Set max. send and receive Work Requests ib->qp_init.cap.max_send_wr = max_send_wr; ib->qp_init.cap.max_recv_wr = max_recv_wr; n->logger->debug("Set max_send_wr and max_recv_wr to {} and {}, respectively", max_send_wr, max_recv_wr); - /* Set available receive Work Requests to 0 */ + // Set available receive Work Requests to 0 ib->conn.available_recv_wrs = 0; - /* Set remaining QP attributes */ + // Set remaining QP attributes ib->qp_init.cap.max_send_sge = 4; ib->qp_init.cap.max_recv_sge = (ib->conn.port_space == RDMA_PS_UDP) ? 5 : 4; - /* Set number of bytes to be send inline */ + // Set number of bytes to be send inline ib->qp_init.cap.max_inline_data = max_inline_data; - /* If node will send data, set remote address */ + // If node will send data, set remote address if (ib->is_source) { - /* Translate address info */ + // Translate address info char *ip_adr = strtok_r(remote, ":", &lasts); char *port = strtok_r(nullptr, ":", &lasts); @@ -340,14 +338,14 @@ int villas::node::ib_check(NodeCompat *n) { auto *ib = n->getData(); - /* Check if read substraction makes sense */ + // Check if read substraction makes sense if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) throw RuntimeError("The buffer substraction value must be bigger than 2 * in.vectorize"); if (ib->conn.buffer_subtraction >= ib->qp_init.cap.max_recv_wr - n->in.vectorize) throw RuntimeError("The buffer substraction value cannot be bigger than in.max_wrs - in.vectorize"); - /* Check if the set value is a power of 2, and warn the user if this is not the case */ + // Check if the set value is a power of 2, and warn the user if this is not the case unsigned max_send_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_send_wr))); unsigned max_recv_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_recv_wr))); @@ -355,7 +353,7 @@ int villas::node::ib_check(NodeCompat *n) n->logger->warn("Max nr. of send WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", ib->qp_init.cap.max_send_wr, max_send_pow); - /* Change it now, because otherwise errors are possible in ib_start(). */ + // Change it now, because otherwise errors are possible in ib_start(). ib->qp_init.cap.max_send_wr = max_send_pow; } @@ -363,11 +361,11 @@ int villas::node::ib_check(NodeCompat *n) n->logger->warn("Max nr. of recv WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", ib->qp_init.cap.max_recv_wr, max_recv_pow); - /* Change it now, because otherwise errors are possible in ib_start(). */ + // Change it now, because otherwise errors are possible in ib_start(). ib->qp_init.cap.max_recv_wr = max_recv_pow; } - /* Check maximum size of max_recv_wr and max_send_wr */ + // Check maximum size of max_recv_wr and max_send_wr if (ib->qp_init.cap.max_send_wr > 8192) n->logger->warn("Max number of send WRs ({}) is bigger than send queue!", ib->qp_init.cap.max_send_wr); @@ -379,7 +377,7 @@ int villas::node::ib_check(NodeCompat *n) if (ib->periodic_signaling == 0) ib->periodic_signaling = ib->qp_init.cap.max_send_wr / 2; - /* Warn user if he changed the default inline value */ + // Warn user if he changed the default inline value if (ib->qp_init.cap.max_inline_data != 0) n->logger->warn("You changed the default value of max_inline_data. This might influence the maximum number " "of outstanding Work Requests in the Queue Pair and can be a reason for the Queue Pair creation to fail"); @@ -444,7 +442,7 @@ void ib_create_bind_id(NodeCompat *n) n->logger->debug("Created rdma_cm_id"); - /* Bind rdma_cm_id to the HCA */ + // Bind rdma_cm_id to the HCA ret = rdma_bind_addr(ib->ctx.id, ib->conn.src_addr->ai_addr); if (ret) throw RuntimeError("Failed to bind to local device: {}", gai_strerror(ret)); @@ -472,21 +470,21 @@ void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) n->setState(State::STARTED); - /* Acknowledge event */ + // Acknowledge event rdma_ack_cm_event(event); - /* Destroy ID */ + // Destroy ID rdma_destroy_id(ib->ctx.listen_id); - /* Create rdma_cm_id and bind to device */ + // Create rdma_cm_id and bind to device ib_create_bind_id(n); - /* Listen to id for events */ + // Listen to id for events ret = rdma_listen(ib->ctx.listen_id, 10); if (ret) throw RuntimeError("Failed to listen to rdma_cm_id"); - /* Node is not a source (and will not send data */ + // Node is not a source (and will not send data ib->is_source = 0; n->logger->info("Use listening mode"); @@ -502,10 +500,10 @@ void * ib_rdma_cm_event_thread(void *ctx) n->logger->debug("Started rdma_cm_event thread"); - /* Wait until node is completely started */ + // Wait until node is completely started while (n->getState() != State::STARTED); - /* Monitor event channel */ + // Monitor event channel while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { n->logger->debug("Received communication event: {}", rdma_event_str(event->event)); @@ -567,7 +565,7 @@ void * ib_rdma_cm_event_thread(void *ctx) break; case RDMA_CM_EVENT_ESTABLISHED: - /* If the connection is unreliable connectionless, set appropriate variables */ + // If the connection is unreliable connectionless, set appropriate variables if (ib->conn.port_space == RDMA_PS_UDP) { ib->conn.ud.ud = event->param.ud; ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); @@ -612,27 +610,27 @@ int villas::node::ib_start(NodeCompat *n) n->logger->debug("Started ib_start"); - /* Create event channel */ + // Create event channel ib->ctx.ec = rdma_create_event_channel(); if (!ib->ctx.ec) throw RuntimeError("Failed to create event channel!"); n->logger->debug("Created event channel"); - /* Create rdma_cm_id and bind to device */ + // Create rdma_cm_id and bind to device ib_create_bind_id(n); n->logger->debug("Initialized Work Completion Buffer"); - /* Resolve address or listen to rdma_cm_id */ + // Resolve address or listen to rdma_cm_id if (ib->is_source) { - /* Resolve address */ + // Resolve address ret = rdma_resolve_addr(ib->ctx.id, nullptr, ib->conn.dst_addr->ai_addr, ib->conn.timeout); if (ret) throw RuntimeError("Failed to resolve remote address after {}ms: {}", ib->conn.timeout, gai_strerror(ret)); } else { - /* Listen on rdma_cm_id for events */ + // Listen on rdma_cm_id for events ret = rdma_listen(ib->ctx.listen_id, 10); if (ret) throw RuntimeError("Failed to listen to rdma_cm_id"); @@ -640,14 +638,14 @@ int villas::node::ib_start(NodeCompat *n) n->logger->debug("Started to listen to rdma_cm_id"); } - /* Allocate protection domain */ + // Allocate protection domain ib->ctx.pd = ibv_alloc_pd(ib->ctx.id->verbs); if (!ib->ctx.pd) throw RuntimeError("Could not allocate protection domain"); n->logger->debug("Allocated Protection Domain"); - /* Allocate space for 40 Byte GHR. We don't use this. */ + // Allocate space for 40 Byte GHR. We don't use this. if (ib->conn.port_space == RDMA_PS_UDP) { ib->conn.ud.grh_ptr = new char[GRH_SIZE]; if (!ib->conn.ud.grh_ptr) @@ -661,7 +659,7 @@ int villas::node::ib_start(NodeCompat *n) */ n->logger->debug("Starting to monitor events on rdma_cm_id"); - /* Create thread to monitor rdma_cm_event channel */ + // Create thread to monitor rdma_cm_event channel ret = pthread_create(&ib->conn.rdma_cm_event_thread, nullptr, ib_rdma_cm_event_thread, n); if (ret) throw RuntimeError("Failed to create thread to monitor rdma_cm events: {}", gai_strerror(ret)); @@ -698,22 +696,22 @@ int villas::node::ib_stop(NodeCompat *n) n->logger->info("Disconnecting... Waiting for threads to join."); - /* Wait for event thread to join */ + // Wait for event thread to join ret = pthread_join(ib->conn.rdma_cm_event_thread, nullptr); if (ret) throw RuntimeError("Error while joining rdma_cm_event_thread: {}", ret); n->logger->debug("Joined rdma_cm_event_thread"); - /* Destroy RDMA CM ID */ + // Destroy RDMA CM ID rdma_destroy_id(ib->ctx.id); n->logger->debug("Destroyed rdma_cm_id"); - /* Dealloc Protection Domain */ + // Dealloc Protection Domain ibv_dealloc_pd(ib->ctx.pd); n->logger->debug("Destroyed protection domain"); - /* Destroy event channel */ + // Destroy event channel rdma_destroy_event_channel(ib->ctx.ec); n->logger->debug("Destroyed event channel"); @@ -752,13 +750,13 @@ int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); if (wcs) { - /* Get time directly after something arrived in Completion Queue */ + // Get time directly after something arrived in Completion Queue ts_receive = time_now(); n->logger->debug("Received {} Work Completions", wcs); - read_values = wcs; /* Value to return */ - max_wr_post = wcs; /* Make space free in smps[] */ + read_values = wcs; // Value to return + max_wr_post = wcs; // Make space free in smps[] break; } @@ -774,18 +772,18 @@ int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned ib->conn.available_recv_wrs += max_wr_post; // TODO: fix release logic - // *release = 0; /* While we fill the receive queue, we always use all samples */ + // *release = 0; // While we fill the receive queue, we always use all samples } - /* Get Memory Region */ + // Get Memory Region mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); for (int i = 0; i < max_wr_post; i++) { int j = 0; - /* Prepare receive Scatter/Gather element */ + // Prepare receive Scatter/Gather element - /* First 40 byte of UD data are GRH and unused in our case */ + // First 40 byte of UD data are GRH and unused in our case if (ib->conn.port_space == RDMA_PS_UDP) { sge[i][j].addr = (uint64_t) ib->conn.ud.grh_ptr; sge[i][j].length = GRH_SIZE; @@ -794,14 +792,14 @@ int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned j++; } - /* Sequence */ + // Sequence sge[i][j].addr = (uint64_t) &smps[i]->sequence; sge[i][j].length = sizeof(smps[i]->sequence); sge[i][j].lkey = mr->lkey; j++; - /* Timespec origin */ + // Timespec origin sge[i][j].addr = (uint64_t) &smps[i]->ts.origin; sge[i][j].length = sizeof(smps[i]->ts.origin); sge[i][j].lkey = mr->lkey; @@ -814,7 +812,7 @@ int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned j++; - /* Prepare a receive Work Request */ + // Prepare a receive Work Request wr[i].wr_id = (uintptr_t) smps[i]; wr[i].next = &wr[i+1]; wr[i].sg_list = sge[i]; @@ -826,17 +824,17 @@ int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned n->logger->debug("Prepared {} new receive Work Requests", max_wr_post); n->logger->debug("{} receive Work Requests in Receive Queue", ib->conn.available_recv_wrs); - /* Post list of Work Requests */ + // Post list of Work Requests ret = ibv_post_recv(ib->ctx.id->qp, &wr[0], &bad_wr); if (ret) throw RuntimeError("Was unable to post receive WR: {}, bad WR ID: {:#x}", ret, bad_wr->wr_id); n->logger->debug("Succesfully posted receive Work Requests"); - /* Doesn't start if wcs == 0 */ + // Doesn't start if wcs == 0 for (int j = 0; j < wcs; j++) { if ( !( (wc[j].opcode & IBV_WC_RECV) && wc[j].status == IBV_WC_SUCCESS) ) { - /* Drop all values, we don't know where the error occured */ + // Drop all values, we don't know where the error occured read_values = 0; } @@ -874,7 +872,7 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned struct ibv_mr *mr; int ret; - unsigned sent = 0; /* Used for first loop: prepare work requests to post to send queue */ + unsigned sent = 0; // Used for first loop: prepare work requests to post to send queue n->logger->debug("ib_write is called"); @@ -882,38 +880,38 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned // TODO: fix release logic // *release = 0; - /* First, write */ + // First, write - /* Get Memory Region */ + // Get Memory Region mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); for (sent = 0; sent < cnt; sent++) { int j = 0; - /* Set Scatter/Gather element to data of sample */ + // Set Scatter/Gather element to data of sample - /* Sequence */ + // Sequence sge[sent][j].addr = (uint64_t) &smps[sent]->sequence; sge[sent][j].length = sizeof(smps[sent]->sequence); sge[sent][j].lkey = mr->lkey; j++; - /* Timespec origin */ + // Timespec origin sge[sent][j].addr = (uint64_t) &smps[sent]->ts.origin; sge[sent][j].length = sizeof(smps[sent]->ts.origin); sge[sent][j].lkey = mr->lkey; j++; - /* Actual Payload */ + // Actual Payload sge[sent][j].addr = (uint64_t) &smps[sent]->data; sge[sent][j].length = SAMPLE_DATA_LENGTH(smps[sent]->length); sge[sent][j].lkey = mr->lkey; j++; - /* Check if connection is connected or unconnected and set appropriate values */ + // Check if connection is connected or unconnected and set appropriate values if (ib->conn.port_space == RDMA_PS_UDP) { wr[sent].wr.ud.ah = ib->conn.ud.ah; wr[sent].wr.ud.remote_qkey = ib->conn.ud.ud.qkey; @@ -932,7 +930,7 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned n->logger->debug("Sample will be send inline [0/1]: {}", send_inline); - /* Set Send Work Request */ + // Set Send Work Request wr[sent].wr_id = (uintptr_t) smps[sent]; wr[sent].sg_list = sge[sent]; wr[sent].num_sge = j; @@ -945,7 +943,7 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned n->logger->debug("Prepared {} send Work Requests", cnt); wr[cnt-1].next = nullptr; - /* Send linked list of Work Requests */ + // Send linked list of Work Requests ret = ibv_post_send(ib->ctx.id->qp, wr, &bad_wr); n->logger->debug("Posted send Work Requests"); @@ -966,8 +964,8 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned while (1) { // TODO: fix release logic // smps[*release] = smps[m]; - // (*release)++; /* Increment number of samples to be released */ - sent--; /* Decrement the number of successfully posted elements */ + // (*release)++; // Increment number of samples to be released + sent--; // Decrement the number of successfully posted elements if (++m == cnt) break; } @@ -1002,10 +1000,11 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned return sent; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "infiniband"; p.description = "Infiniband interface (libibverbs, librdmacm)"; p.vectorize = 0; @@ -1023,5 +1022,6 @@ static void register_plugin() { p.reverse = ib_reverse; p.memory_type = memory::ib; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/influxdb.cpp b/lib/nodes/influxdb.cpp index d0224f734..7080f56bb 100644 --- a/lib/nodes/influxdb.cpp +++ b/lib/nodes/influxdb.cpp @@ -1,9 +1,9 @@ -/** Node-type for InfluxDB. +/* Node-type for InfluxDB. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -70,7 +70,7 @@ int villas::node::influxdb_open(NodeCompat *n) if (ret) throw RuntimeError("Failed to lookup server: {}", gai_strerror(ret)); - /* Loop through all the results and connect to the first we can */ + // Loop through all the results and connect to the first we can for (p = servinfo; p != nullptr; p = p->ai_next) { i->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (i->sd == -1) @@ -83,7 +83,7 @@ int villas::node::influxdb_open(NodeCompat *n) continue; } - /* If we get here, we must have connected successfully */ + // If we get here, we must have connected successfully break; } @@ -116,10 +116,10 @@ int villas::node::influxdb_write(NodeCompat *n, struct Sample * const smps[], un for (unsigned k = 0; k < cnt; k++) { const struct Sample *smp = smps[k]; - /* Key */ + // Key strcatf(&buf, "%s", i->key); - /* Fields */ + // Fields for (unsigned j = 0; j < smp->length; j++) { const auto *data = &smp->data[j]; auto sig = smp->signals->getByIndex(j); @@ -164,7 +164,7 @@ int villas::node::influxdb_write(NodeCompat *n, struct Sample * const smps[], un } } - /* Timestamp */ + // Timestamp strcatf(&buf, " %lld%09lld\n", (long long) smp->ts.origin.tv_sec, (long long) smp->ts.origin.tv_nsec); } @@ -191,10 +191,11 @@ char * villas::node::influxdb_print(NodeCompat *n) return buf; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "influxdb"; p.description = "Write results to InfluxDB"; p.vectorize = 0; @@ -205,5 +206,6 @@ static void register_plugin() { p.stop = influxdb_close; p.write = influxdb_write; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/kafka.cpp b/lib/nodes/kafka.cpp index ac5d89052..5b3f81fcf 100644 --- a/lib/nodes/kafka.cpp +++ b/lib/nodes/kafka.cpp @@ -1,9 +1,9 @@ -/** Node type: kafka +/* Node type: kafka * - * @author Juan Pablo Noreña - * @copyright 2021, Universidad Nacional de Colombia - * @license Apache 2.0 - *********************************************************************************/ + * Author: Juan Pablo Noreña + * SPDX-FileCopyrightText: 2021 Universidad Nacional de Colombia + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,9 +19,12 @@ using namespace villas::node; using namespace villas::utils; // Each process has a list of clients for which a thread invokes the kafka loop -static struct List clients; -static pthread_t thread; -static Logger logger; +static +struct List clients; +static +pthread_t thread; +static +Logger logger; static void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, const char *buf) @@ -127,7 +130,7 @@ int villas::node::kafka_init(NodeCompat *n) { auto *k = n->getData(); - /* Default values */ + // Default values k->server = nullptr; k->protocol = nullptr; k->produce = nullptr; @@ -231,7 +234,7 @@ int villas::node::kafka_parse(NodeCompat *n, json_t *json) k->sasl.password = strdup(password); } - /* Format */ + // Format if (k->formatter) delete k->formatter; k->formatter = json_format @@ -273,7 +276,7 @@ char * villas::node::kafka_print(NodeCompat *n) k->protocol ); - /* Only show if not default */ + // Only show if not default if (k->produce) strcatf(&buf, ", out.produce=%s", k->produce); @@ -571,10 +574,11 @@ int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "kafka"; p.description = "Kafka event message streaming (rdkafka)"; p.vectorize = 0; @@ -595,5 +599,6 @@ static void register_plugin() { p.reverse = kafka_reverse; p.poll_fds = kafka_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/loopback.cpp b/lib/nodes/loopback.cpp index cb3e53ce8..55cd70d91 100644 --- a/lib/nodes/loopback.cpp +++ b/lib/nodes/loopback.cpp @@ -1,9 +1,9 @@ -/** Node-type for loopback connections. +/* Node-type for loopback connections. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -79,7 +79,7 @@ int LoopbackNode::_write(struct Sample * smps[], unsigned cnt) return pushed; } - /* Released unpushed samples */ + // Released unpushed samples if ((unsigned) pushed < cnt) { sample_decref_many(smps + pushed, cnt - pushed); logger->warn("Queue overrun"); @@ -134,6 +134,7 @@ int LoopbackNode::parse(json_t *json) return Node::parse(json); } +// Register node static char n[] = "loopback"; static char d[] = "loopback node-type"; static NodePlugin - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -17,7 +17,8 @@ using namespace villas; using namespace villas::node; -static InternalLoopbackNodeFactory nf; +static +InternalLoopbackNodeFactory nf; InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) : queuelen(ql), @@ -90,7 +91,7 @@ int InternalLoopbackNode::_write(struct Sample * smps[], unsigned cnt) return pushed; } - /* Released unpushed samples */ + // Released unpushed samples if ((unsigned) pushed < cnt) { sample_decref_many(smps + pushed, cnt - pushed); logger->warn("Queue overrun"); diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 5d3987d1f..13bd07beb 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -1,4 +1,4 @@ -/** A Modbus node-type supporting RTU and TCP transports. +/* A Modbus node-type supporting RTU and TCP transports. * * The modbus communication using the libmodbus library is fairly simple. * @@ -30,10 +30,10 @@ * - The special case in blockDistance makes causes the bit mappings to be grouped * first, before any adjacent registers. * - * @author Philipp Jungkamp - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -260,7 +260,6 @@ modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) }, mapping); } - modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) { return single.num_registers(); @@ -942,6 +941,7 @@ const std::string & ModbusNode::getDetails() return details; } +// Register node static char name[] = "modbus"; static char description[] = "Read and write Modbus registers"; static NodePlugin p; diff --git a/lib/nodes/mqtt.cpp b/lib/nodes/mqtt.cpp index 304b3941e..3444a9e45 100644 --- a/lib/nodes/mqtt.cpp +++ b/lib/nodes/mqtt.cpp @@ -1,9 +1,9 @@ -/** Node type: mqtt +/* Node type: mqtt * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -141,11 +141,11 @@ int villas::node::mqtt_init(NodeCompat *n) m->formatter = nullptr; - /* Default values */ + // Default values m->port = 1883; m->qos = 0; m->retain = 0; - m->keepalive = 5; /* 5 second, minimum required for libmosquitto */ + m->keepalive = 5; // 5 second, minimum required for libmosquitto m->host = nullptr; m->username = nullptr; @@ -242,7 +242,7 @@ int villas::node::mqtt_parse(NodeCompat *n, json_t *json) m->ssl.ciphers = ciphers ? strdup(ciphers) : nullptr; } - /* Format */ + // Format if (m->formatter) delete m->formatter; m->formatter = json_format @@ -301,7 +301,7 @@ char * villas::node::mqtt_print(NodeCompat *n) m->ssl.enabled ? "yes" : "no" ); - /* Only show if not default */ + // Only show if not default if (m->username) strcatf(&buf, ", username=%s", m->username); @@ -499,10 +499,11 @@ int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "mqtt"; p.description = "Message Queuing Telemetry Transport (libmosquitto)"; p.vectorize = 0; @@ -524,5 +525,6 @@ static void register_plugin() { p.reverse = mqtt_reverse; p.poll_fds = mqtt_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/nanomsg.cpp b/lib/nodes/nanomsg.cpp index 4b111d403..7abe4a3d6 100644 --- a/lib/nodes/nanomsg.cpp +++ b/lib/nodes/nanomsg.cpp @@ -1,9 +1,9 @@ -/** Node type: nanomsg +/* Node type: nanomsg * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -126,7 +126,7 @@ int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) throw RuntimeError("Invalid type for 'subscribe' setting"); } - /* Format */ + // Format if (m->formatter) delete m->formatter; m->formatter = json_format @@ -180,12 +180,12 @@ int villas::node::nanomsg_start(NodeCompat *n) if (ret < 0) throw RuntimeError("Failed to create nanomsg socket: {}", nn_strerror(errno)); - /* Subscribe to all topics */ + // Subscribe to all topics ret = nn_setsockopt(ret = m->in.socket, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); if (ret < 0) return ret; - /* Bind publisher to socket */ + // Bind publisher to socket for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { char *ep = (char *) list_at(&m->out.endpoints, i); @@ -194,7 +194,7 @@ int villas::node::nanomsg_start(NodeCompat *n) throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", ep, nn_strerror(errno)); } - /* Connect subscribers socket */ + // Connect subscribers socket for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { char *ep = (char *) list_at(&m->in.endpoints, i); @@ -235,7 +235,7 @@ int villas::node::nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsi int bytes; char data[NANOMSG_MAX_PACKET_LEN]; - /* Receive payload */ + // Receive payload bytes = nn_recv(m->in.socket, data, sizeof(data), 0); if (bytes < 0) return -1; @@ -289,10 +289,11 @@ int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "nanomsg"; p.description = "scalability protocols library (libnanomsg)"; p.vectorize = 0; @@ -310,5 +311,6 @@ static void register_plugin() { p.poll_fds = nanomsg_poll_fds; p.netem_fds = nanomsg_netem_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ngsi.cpp b/lib/nodes/ngsi.cpp index d3813afad..0353c286e 100644 --- a/lib/nodes/ngsi.cpp +++ b/lib/nodes/ngsi.cpp @@ -1,8 +1,9 @@ -/** Node type: OMA Next Generation Services Interface 9 (NGSI) (FIWARE context broker) +/* Node type: OMA Next Generation Services Interface 9 (NGSI) (FIWARE context broker) * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - **********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -27,7 +28,7 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -/* Some global settings */ +// Some global settings #if OPENSSL_VERSION_NUMBER < 0x010003000L // See: https://curl.haxx.se/libcurl/c/opensslthreadlock.html @@ -35,8 +36,10 @@ using namespace villas::utils; #endif #ifdef CURL_SSL_REQUIRES_LOCKING -/** This array will store all of the mutexes available to OpenSSL. */ -static pthread_mutex_t *mutex_buf = NULL; + +// This array will store all of the mutexes available to OpenSSL. +static +pthread_mutex_t *mutex_buf = NULL; static void handle_error(const char *file, int lineno, const char *msg) @@ -47,7 +50,7 @@ void handle_error(const char *file, int lineno, const char *msg) ERR_print_errors_fp(stderr); - /* exit(-1); */ + // exit(-1); } static @@ -64,7 +67,7 @@ unsigned long curl_ssl_thread_id_function(void) { return ((unsigned long) pthread_self()); } -#endif /* CURL_SSL_REQUIRES_LOCKING */ +#endif // CURL_SSL_REQUIRES_LOCKING enum NgsiFlags { NGSI_ENTITY_ATTRIBUTES_IN = (1 << 0), @@ -145,7 +148,7 @@ public: if (ret) throw ConfigError(json, err, "node-config-node-ngsi", "Failed to parse NGSI attribute"); - /* Copy values from node signal, if 'ngsi_attribute' settings not provided */ + // Copy values from node signal, if 'ngsi_attribute' settings not provided if (s && !nam) nam = !s->name.empty() ? s->name.c_str() : ""; @@ -167,7 +170,7 @@ public: metadata.emplace_back(json_metadata); } - /* Metadata: index(integer)=j */ + // Metadata: index(integer)=j metadata.emplace_back("index", "integer", fmt::format("{}", j)); } @@ -180,7 +183,7 @@ public: if (flags & NGSI_ENTITY_VALUES) { #if NGSI_VECTORS - /* Build value vector */ + // Build value vector json_t *json_value = json_array(); for (unsigned k = 0; k < cnt; k++) { @@ -205,7 +208,7 @@ public: json_object_set(json_attribute, "value", json_value); } - if (flags & NGSI_ENTITY_METADATA) { /* Create Metadata for attribute */ + if (flags & NGSI_ENTITY_METADATA) { // Create Metadata for attribute json_t *json_metadatas = json_array(); for (auto &meta : metadata) { @@ -299,7 +302,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const char *end; const char *value; - /* Parse JSON */ + // Parse JSON ret = json_unpack_ex(json_attr, &err, 0, "{ s: s, s: s, s: o, s?: o }", "name", &name, "type", &type, @@ -309,14 +312,14 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const if (ret) return -3; - /* Check attribute name and type */ + // Check attribute name and type attr = list_lookup_name(&i->in.signals, name); if (!attr || attr->type != type) - continue; /* skip unknown attributes */ + continue; // skip unknown attributes length++; - /* Check metadata */ + // Check metadata if (!json_is_array(json_metadata)) return -5; @@ -324,7 +327,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const json_t *json_tuple; const char *ts, *seq; - /* Check number of values */ + // Check number of values if (!json_is_array(json_value) || json_array_size(json_value) != cnt) return -6; @@ -332,7 +335,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const json_array_foreach(json_value, k, json_tuple) { struct Sample *smp = smps[k]; - /* Check sample format */ + // Check sample format if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) return -7; @@ -353,7 +356,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const if (!sig) return -11; - if (value[0] == '\0') /* No data on Orion CB? -> Use init value */ + if (value[0] == '\0') // No data on Orion CB? -> Use init value *sd = sig->init; else { signal_data_parse_str(sd, sig->type, value, &end); @@ -364,7 +367,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const #else struct Sample *smp = smps[0]; - /* Check number of values */ + // Check number of values if (!json_is_string(json_value)) return -6; @@ -375,7 +378,7 @@ int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const if (!sig) return -11; - if (value[0] == '\0') /* No data on Orion CB? -> Use init value */ + if (value[0] == '\0') // No data on Orion CB? -> Use init value *data = sig->init; else { data->parseString(sig->type, value, &end); @@ -456,7 +459,7 @@ size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, void *user struct ngsi_response *mem = (struct ngsi_response *) userp; mem->data = (char *) realloc(mem->data, mem->len + realsize + 1); - if (mem->data == nullptr) /* out of memory! */ + if (mem->data == nullptr) // out of memory! throw MemoryAllocationError(); memcpy(&(mem->data[mem->len]), contents, realsize); @@ -486,7 +489,7 @@ int ngsi_request(CURL *handle, const char *endpoint, const char *operation, json logger->debug("Request to context broker: {}\n{}", url, post); - /* We don't want to leave the handle in an invalid state */ + // We don't want to leave the handle in an invalid state pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); CURLcode ret = curl_easy_perform(handle); pthread_setcancelstate(old, nullptr); @@ -579,7 +582,7 @@ int villas::node::ngsi_type_start(villas::node::SuperNode *sn) auto logger = logging.get("curl"); logger->info("Setup libcurl/openssl locking primitives"); -#endif /* CURL_SSL_REQUIRES_LOCKING */ +#endif // CURL_SSL_REQUIRES_LOCKING return curl_global_init(CURL_GLOBAL_ALL); } @@ -597,7 +600,7 @@ int villas::node::ngsi_type_stop() pthread_mutex_destroy(&mutex_buf[i]); delete mutex_buf; -#endif /* CURL_SSL_REQUIRES_LOCKING */ +#endif // CURL_SSL_REQUIRES_LOCKING curl_global_cleanup(); @@ -674,7 +677,7 @@ int villas::node::ngsi_start(NodeCompat *n) i->headers = curl_slist_append(i->headers, buf); } - /* Create task */ + // Create task if (i->timeout > 1 / i->rate) n->logger->warn("Timeout is to large for given rate: {}", i->rate); @@ -692,7 +695,7 @@ int villas::node::ngsi_start(NodeCompat *n) curl_easy_setopt(handles[p], CURLOPT_USERAGENT, HTTP_USER_AGENT); } - /* Create entity and atributes */ + // Create entity and atributes if (i->create) { json_t *json_entity = ngsi_build_entity(n, nullptr, 0, NGSI_ENTITY_ATTRIBUTES | NGSI_ENTITY_METADATA); @@ -713,7 +716,7 @@ int villas::node::ngsi_stop(NodeCompat *n) i->task.stop(); - /* Delete complete entity (not just attributes) */ + // Delete complete entity (not just attributes) json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); ret = ngsi_request_context_update(i->out.curl, i->endpoint, "DELETE", json_entity, n->logger); @@ -790,11 +793,11 @@ int villas::node::ngsi_init(NodeCompat *n) if (ret) return ret; - /* Default values */ - i->access_token = nullptr; /* disabled by default */ - i->ssl_verify = 1; /* verify by default */ - i->timeout = 1; /* default value */ - i->rate = 1; /* default value */ + // Default values + i->access_token = nullptr; // disabled by default + i->ssl_verify = 1; // verify by default + i->timeout = 1; // default value + i->rate = 1; // default value return 0; } @@ -804,7 +807,6 @@ int villas::node::ngsi_destroy(NodeCompat *n) int ret; auto *i = n->getData(); - for (size_t j = 0; j < list_length(&i->in.signals); j++) { auto *attr = (NgsiAttribute *) list_at(&i->in.signals, j); @@ -840,15 +842,15 @@ int villas::node::ngsi_reverse(NodeCompat *n) return 0; } +static +NodeCompatType p; -static NodeCompatType p; - -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "ngsi"; p.description = "OMA Next Generation Services Interface 10 (libcurl, libjansson)"; #ifdef NGSI_VECTORS - p.vectorize = 0, /* unlimited */ + p.vectorize = 0, // unlimited #else p.vectorize = 1, #endif @@ -866,5 +868,6 @@ static void register_plugin() { p.poll_fds = ngsi_poll_fds; p.reverse = ngsi_reverse; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 1341c40cd..94d90ea6e 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -1,11 +1,11 @@ -/** Node type: OPAL (AsyncApi) +/* Node type: OPAL (AsyncApi) * * This file implements the opal subtype for nodes. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -29,22 +29,27 @@ extern "C" { #include } +// Private static storage +static +std::string asyncShmemName; // Shared Memory identifiers and size, provided via argv. +static +std::string printShmemName; // Shared Memory identifiers and size, provided via argv. +static +size_t asyncShmemSize; // Shared Memory identifiers and size, provided via argv. -/* Private static storage */ -static std::string asyncShmemName; /**< Shared Memory identifiers and size, provided via argv. */ -static std::string printShmemName; /**< Shared Memory identifiers and size, provided via argv. */ -static size_t asyncShmemSize; /**< Shared Memory identifiers and size, provided via argv. */ +static +std::vector sendIDs, recvIDs; // A dynamically allocated array of SendIDs. -static std::vector sendIDs, recvIDs; /** A dynamically allocated array of SendIDs. */ +static +Opal_GenAsyncParam_Ctrl params; // String and Float parameters, provided by the OPAL AsyncProcess block. -static Opal_GenAsyncParam_Ctrl params; /** String and Float parameters, provided by the OPAL AsyncProcess block. */ - -static pthread_mutex_t lock; /** Big Global Lock for libOpalAsync API */ +static +pthread_mutex_t lock; // Big Global Lock for libOpalAsync API using namespace villas; using namespace villas::utils; -/** A bunch of symbols which are used by the libOpal libraries +/* A bunch of symbols which are used by the libOpal libraries * and undefined by GCC. We replace them by GCC variants here. */ extern "C" { @@ -107,12 +112,12 @@ int villas::node::opal_type_start(villas::node::SuperNode *sn) pthread_mutex_init(&lock, nullptr); - /* Enable the OpalPrint function. This prints to the OpalDisplay. */ + // Enable the OpalPrint function. This prints to the OpalDisplay. err = OpalSystemCtrl_Register((char *) printShmemName.c_str()); if (err != EOK) throw RuntimeError("OpalPrint() access not available ({})", err); - /* Open Share Memory created by the model. */ + // Open Share Memory created by the model. err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str()); if (err != EOK) throw RuntimeError("Model shared memory not available ({})", err); @@ -121,7 +126,7 @@ int villas::node::opal_type_start(villas::node::SuperNode *sn) if (err != EOK) throw RuntimeError("Could not get OPAL controller parameters ({})", err); - /* Get list of Send and RecvIDs */ + // Get list of Send and RecvIDs err = OpalGetNbAsyncSendIcon(&noSendIcons); if (err != EOK) throw RuntimeError("Failed to get number of send blocks ({})", err); @@ -216,7 +221,7 @@ char * villas::node::opal_print(NodeCompat *n) { auto *o = n->getData(); - /** @todo Print send_params, recv_params */ + // @todo Print send_params, recv_params return strf("sendID=%u, recvID=%u, reply=%u", o->sendID, o->recvID, o->reply); @@ -226,7 +231,7 @@ int villas::node::opal_start(NodeCompat *n) { auto *o = n->getData(); - /* Search for valid send and recv ids */ + // Search for valid send and recv ids int sfound = 0, rfound = 0; for (auto i : sendIDs) sfound += i == o->sendID; @@ -238,7 +243,7 @@ int villas::node::opal_start(NodeCompat *n) if (!rfound) throw RuntimeError("Invalid recv_id '{}'", o->recvID); - /* Get some more informations and paramters from OPAL-RT */ + // Get some more informations and paramters from OPAL-RT OpalGetAsyncSendIconMode(&o->mode, o->sendID); OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), o->sendID); OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), o->recvID); @@ -262,7 +267,7 @@ int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigne if (cnt != 1) throw RuntimeError("The OPAL-RT node type does not support combining!"); - /* This call unblocks when the 'Data Ready' line of a send icon is asserted. */ + // This call unblocks when the 'Data Ready' line of a send icon is asserted. do { ret = OpalWaitForAsyncSendRequest(&id); if (ret != EOK) { @@ -270,14 +275,14 @@ int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigne if ((state == STATE_RESET) || (state == STATE_STOP)) throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - return -1; /* @todo correct return value */ + return -1; // @todo correct return value } } while (id != o->sendID); - /* No errors encountered yet */ + // No errors encountered yet OpalSetAsyncSendIconError(0, o->sendID); - /* Get the size of the data being sent by the unblocking SendID */ + // Get the size of the data being sent by the unblocking SendID OpalGetAsyncSendIconDataLength(&len, o->sendID); if ((unsigned) len > s->capacity * sizeof(s->data[0])) { n->logger->warn("Ignoring the last {} of {} values for OPAL (send_id={}).", @@ -286,14 +291,14 @@ int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigne len = sizeof(data); } - /* Read data from the model */ + // Read data from the model OpalGetAsyncSendIconData(data, len, o->sendID); s->sequence = htons(o->sequenceNo++); s->length = (unsigned) len / sizeof(double); for (unsigned i = 0; i < s->length; i++) - s->data[i].f = (float) data[i]; /* OPAL provides double precission */ + s->data[i].f = (float) data[i]; // OPAL provides double precission /* This next call allows the execution of the "asynchronous" process * to actually be synchronous with the model. To achieve this, you @@ -330,26 +335,27 @@ int villas::node::opal_write(NodeCompat *n, struct Sample * const smps[], unsign if ((state == STATE_RESET) || (state == STATE_STOP)) throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - OpalSetAsyncRecvIconStatus(s->sequence, o->recvID); /* Set the Status to the message ID */ - OpalSetAsyncRecvIconError(0, o->recvID); /* Set the Error to 0 */ + OpalSetAsyncRecvIconStatus(s->sequence, o->recvID); // Set the Status to the message ID + OpalSetAsyncRecvIconError(0, o->recvID); // Set the Error to 0 - /* Get the number of signals to send back to the model */ + // Get the number of signals to send back to the model OpalGetAsyncRecvIconDataLength(&len, o->recvID); if (len > (int) sizeof(data)) n->logger->warn("Node expecting more signals ({}) than values in message ({})", len / sizeof(double), s->length); for (unsigned i = 0; i < s->length; i++) - data[i] = (double) s->data[i].f; /* OPAL expects double precission */ + data[i] = (double) s->data[i].f; // OPAL expects double precission OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID); return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "opal"; p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)"; p.vectorize = 1; @@ -362,5 +368,6 @@ static void register_plugin() { p.read = opal_read; p.write = opal_write; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/redis.cpp b/lib/nodes/redis.cpp index ec33a83ca..600f01e25 100644 --- a/lib/nodes/redis.cpp +++ b/lib/nodes/redis.cpp @@ -1,9 +1,9 @@ -/** Redis node-type +/* Redis node-type * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -27,18 +27,21 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -/* Forward declartions */ -static NodeCompatType p; -static void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg); +// Forward declartions +static +NodeCompatType p; +static +void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg); -static std::unordered_map connections; +static +std::unordered_map connections; RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) : context(opts), subscriber(context.subscriber()), logger(logging.get("nodes:redis")) { - /* Enable keyspace notifications */ + // Enable keyspace notifications context.command("config", "set", "notify-keyspace-events", "K$h"); subscriber.on_message([this](const std::string &channel, const std::string &msg) { @@ -102,7 +105,7 @@ void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) void RedisConnection::start() { if (state == State::RUNNING) - return; /* Already running */ + return; // Already running state = State::RUNNING; @@ -135,7 +138,7 @@ void RedisConnection::loop() catch (const sw::redis::Error &e) { logger->error("Error: {}. Recreating subscriber", e.what()); - /* Create a new subscriber */ + // Create a new subscriber subscriber = context.subscriber(); } } @@ -384,10 +387,10 @@ int villas::node::redis_parse(NodeCompat *n, json_t *json) r->options.tls.sni = host; #else throw ConfigError(json_ssl, "node-config-node-redis-ssl", "This built of the redis++ library does not support SSL"); -#endif /* REDISPP_WITH_TLS */ +#endif // REDISPP_WITH_TLS } - /* Mode */ + // Mode if (mode) { if (!strcmp(mode, "key") || !strcmp(mode, "set-get")) r->mode = RedisMode::KEY; @@ -399,7 +402,7 @@ int villas::node::redis_parse(NodeCompat *n, json_t *json) throw ConfigError(json, "node-config-node-redis-mode", "Invalid Redis mode: {}", mode); } - /* Format */ + // Format if (r->formatter) delete r->formatter; r->formatter = json_format @@ -416,7 +419,7 @@ int villas::node::redis_parse(NodeCompat *n, json_t *json) if (notify >= 0) r->notify = notify != 0; - /* Connection options */ + // Connection options if (uri) r->options = make_redis_connection_options(uri); @@ -568,7 +571,7 @@ int villas::node::redis_read(NodeCompat *n, struct Sample * const smps[], unsign { auto *r = n->getData(); - /* Wait for new data */ + // Wait for new data if (r->notify || r->mode == RedisMode::CHANNEL) { int pulled_cnt; struct Sample *pulled_smps[cnt]; @@ -624,7 +627,7 @@ int villas::node::redis_write(NodeCompat *n, struct Sample * const smps[], unsig } case RedisMode::HASH: { - /* We only update the signals with their latest value here. */ + // We only update the signals with their latest value here. struct Sample *smp = smps[cnt - 1]; std::unordered_map kvs; @@ -656,8 +659,8 @@ int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "redis"; p.description = "Redis key-value store"; p.vectorize = 0; @@ -674,5 +677,6 @@ static void register_plugin() { p.write = redis_write; p.poll_fds = redis_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index f44eb1fab..ff8cf1d94 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -1,10 +1,10 @@ -/** Node type: Real-time Protocol (RTP) +/* Node type: Real-time Protocol (RTP) * - * @author Steffen Vogel - * @author Marvin Klimke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Marvin Klimke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -34,17 +34,20 @@ extern "C" { #ifdef WITH_NETEM #include -#endif /* WITH_NETEM */ +#endif // WITH_NETEM -static pthread_t re_pthread; +static +pthread_t re_pthread; using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -static NodeCompatType p; -static NodeCompatFactory ncp(&p); +static +NodeCompatType p; +static +NodeCompatFactory ncp(&p); static int rtp_aimd(NodeCompat *n, double loss_frac) @@ -82,7 +85,7 @@ int villas::node::rtp_init(NodeCompat *n) n->logger = villas::logging.get("node:rtp"); - /* Default values */ + // Default values r->aimd.a = 10; r->aimd.b = 0.5; r->aimd.Kp = 1; @@ -140,7 +143,7 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) if (ret) throw ConfigError(json, err, "node-config-node-rtp"); - /* AIMD */ + // AIMD if (json_aimd) { ret = json_unpack_ex(json_aimd, &err, 0, "{ s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: s, s?: s }", "a", &r->aimd.a, @@ -157,7 +160,7 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) if (ret) throw ConfigError(json_aimd, err, "node-config-node-rtp-aimd"); - /* AIMD Hook type */ + // AIMD Hook type if (!r->rtcp.enabled) r->aimd.rate_hook_type = RTPHookType::DISABLED; else if (hook_type) { @@ -175,7 +178,7 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) if (log) r->aimd.log_filename = strdup(log); - /* Format */ + // Format if (r->formatter) delete r->formatter; r->formatter = json_format @@ -184,29 +187,29 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) if (!r->formatter) throw ConfigError(json_format, "node-config-node-rtp-format", "Invalid format configuration"); - /* Remote address */ + // Remote address ret = sa_decode(&r->out.saddr_rtp, remote, strlen(remote)); if (ret) throw RuntimeError("Failed to resolve remote address '{}': {}", remote, strerror(ret)); - /* Assign even port number to RTP socket, next odd number to RTCP socket */ + // Assign even port number to RTP socket, next odd number to RTCP socket port = sa_port(&r->out.saddr_rtp) & ~1; sa_set_sa(&r->out.saddr_rtcp, &r->out.saddr_rtp.u.sa); sa_set_port(&r->out.saddr_rtp, port); sa_set_port(&r->out.saddr_rtcp, port+1); - /* Local address */ + // Local address ret = sa_decode(&r->in.saddr_rtp, local, strlen(local)); if (ret) throw RuntimeError("Failed to resolve local address '{}': {}", local, strerror(ret)); - /* Assign even port number to RTP socket, next odd number to RTCP socket */ + // Assign even port number to RTP socket, next odd number to RTCP socket port = sa_port(&r->in.saddr_rtp) & ~1; sa_set_sa(&r->in.saddr_rtcp, &r->in.saddr_rtp.u.sa); sa_set_port(&r->in.saddr_rtp, port); sa_set_port(&r->in.saddr_rtcp, port+1); - /** @todo parse * in addresses */ + /* @todo parse * in addresses */ return 0; } @@ -260,7 +263,7 @@ void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf auto *n = (NodeCompat *) arg; auto *r = n->getData(); - /* source, header not used */ + // source, header not used (void) src; (void) hdr; @@ -279,7 +282,7 @@ void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) auto *n = (NodeCompat *) arg; auto *r = n->getData(); - /* source not used */ + // source not used (void) src; n->logger->debug("RTCP: recv {}", rtcp_type_name((enum rtcp_type) msg->hdr.pt)); @@ -313,15 +316,15 @@ int villas::node::rtp_start(NodeCompat *n) int ret; auto *r = n->getData(); - /* Initialize queue */ + // Initialize queue ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); if (ret) return ret; - /* Initialize IO */ + // Initialize IO r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); - /* Initialize memory buffer for sending */ + // Initialize memory buffer for sending r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); if (!r->send_mb) return -1; @@ -330,7 +333,7 @@ int villas::node::rtp_start(NodeCompat *n) if (ret) return -1; - /* Initialize AIMD hook */ + // Initialize AIMD hook if (r->aimd.rate_hook_type != RTPHookType::DISABLED) { #ifdef WITH_HOOKS switch (r->aimd.rate_hook_type) { @@ -365,11 +368,11 @@ int villas::node::rtp_start(NodeCompat *n) r->aimd.rate_pid = villas::dsp::PID(dt, r->aimd.rate_source, r->aimd.rate_min, r->aimd.Kp, r->aimd.Ki, r->aimd.Kd); - /* Initialize RTP socket */ + // Initialize RTP socket uint16_t port = sa_port(&r->in.saddr_rtp) & ~1; ret = rtp_listen(&r->rs, IPPROTO_UDP, &r->in.saddr_rtp, port, port+1, r->rtcp.enabled, rtp_handler, rtcp_handler, n); - /* Start RTCP session */ + // Start RTCP session if (r->rtcp.enabled) { r->rtcp.num_rrs = 0; @@ -381,7 +384,7 @@ int villas::node::rtp_start(NodeCompat *n) time_t ts = time(nullptr); struct tm tm; - /* Convert time */ + // Convert time gmtime_r(&ts, &tm); strftime(fn, sizeof(fn), r->aimd.log_filename, &tm); @@ -449,12 +452,12 @@ int villas::node::rtp_type_start(villas::node::SuperNode *sn) { int ret; - /* Initialize library */ + // Initialize library ret = libre_init(); if (ret) throw RuntimeError("Error initializing libre"); - /* Add worker thread */ + // Add worker thread ret = pthread_create(&re_pthread, nullptr, (pthread_start_routine) re_main, nullptr); if (ret) throw RuntimeError("Error creating rtp node type pthread"); @@ -481,7 +484,7 @@ int villas::node::rtp_type_start(villas::node::SuperNode *sn) j->addNode(n); } } -#endif /* WITH_NETEM */ +#endif // WITH_NETEM return 0; } @@ -490,7 +493,7 @@ int villas::node::rtp_type_stop() { int ret; - /* Join worker thread */ + // Join worker thread pthread_kill(re_pthread, SIGUSR1); ret = pthread_join(re_pthread, nullptr); if (ret) @@ -507,12 +510,12 @@ int villas::node::rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned auto *r = n->getData(); struct mbuf *mb; - /* Get data from queue */ + // Get data from queue ret = queue_signalled_pull(&r->recv_queue, (void **) &mb); if (ret < 0) throw RuntimeError("Failed to pull from queue"); - /* Unpack data */ + // Unpack data ret = r->formatter->sscan((char *) mb->buf + mb->pos, mbuf_get_left(mb), nullptr, smps, cnt); mem_deref(mb); @@ -548,7 +551,7 @@ retry: mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); - /* Send dataset */ + // Send dataset ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, r->send_mb); if (ret) throw RuntimeError("Error from rtp_send, reason: {}", ret); @@ -565,8 +568,8 @@ int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "rtp"; #ifdef WITH_NETEM p.description = "real-time transport protocol (libre, libnl3 netem support)"; diff --git a/lib/nodes/shmem.cpp b/lib/nodes/shmem.cpp index 88d4bc4a7..f2252f8d8 100644 --- a/lib/nodes/shmem.cpp +++ b/lib/nodes/shmem.cpp @@ -1,10 +1,9 @@ -/** Node-type for shared memory communication. +/* Node-type for shared memory communication. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -30,7 +29,7 @@ int villas::node::shmem_init(NodeCompat *n) { auto *shm = n->getData(); - /* Default values */ + // Default values shm->conf.queuelen = -1; shm->conf.samplelen = -1; shm->conf.polling = false; @@ -164,7 +163,7 @@ int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsign sample_copy_many(smps, shared_smps, recv); sample_decref_many(shared_smps, recv); - /** @todo signal descriptions are currently not shared between processes */ + // @todo signal descriptions are currently not shared between processes for (int i = 0; i < recv; i++) smps[i]->signals = n->getInputSignals(false); @@ -174,7 +173,7 @@ int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsign int villas::node::shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { auto *shm = n->getData(); - struct Sample *shared_smps[cnt]; /* Samples need to be copied to the shared pool first */ + struct Sample *shared_smps[cnt]; // Samples need to be copied to the shared pool first int avail, pushed, copied; avail = sample_alloc_many(&shm->intf.write.shared->pool, shared_smps, cnt); @@ -212,10 +211,11 @@ char * villas::node::shmem_print(NodeCompat *n) return buf; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "shmem"; p.description = "POSIX shared memory interface with external processes"; p.vectorize = 0; @@ -229,5 +229,6 @@ static void register_plugin() { p.prepare = shmem_prepare; p.init = shmem_init; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/signal.cpp b/lib/nodes/signal.cpp index c2a9400d1..798569229 100644 --- a/lib/nodes/signal.cpp +++ b/lib/nodes/signal.cpp @@ -1,10 +1,9 @@ -/** Node-type for signal generation. +/* Node-type for signal generation. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -270,7 +269,7 @@ int SignalNode::start() for (auto sig : signals) sig.start(); - /* Setup task */ + // Setup task if (rt) task.setRate(rate); @@ -339,9 +338,9 @@ int SignalNode::_read(struct Sample *smps[], unsigned cnt) return -1; } - /* Throttle output if desired */ + // Throttle output if desired if (rt) { - /* Block until 1/p->rate seconds elapsed */ + // Block until 1/p->rate seconds elapsed steps = task.wait(); if (steps > 1 && monitor_missed) { logger->debug("Missed steps: {}", steps-1); @@ -377,6 +376,7 @@ std::vector SignalNode::getPollFDs() return {}; } +// Register node static char n[] = "signal.v2"; static char d[] = "Signal generator"; static NodePlugin p; diff --git a/lib/nodes/signal_v1.cpp b/lib/nodes/signal_v1.cpp index be94579b0..f9d17b0e6 100644 --- a/lib/nodes/signal_v1.cpp +++ b/lib/nodes/signal_v1.cpp @@ -1,10 +1,9 @@ -/** Node-type for signal generation. +/* Node-type for signal generation. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -304,7 +303,7 @@ int villas::node::signal_node_start(NodeCompat *n) for (unsigned i = 0; i < s->values; i++) s->last[i] = s->offset[i]; - /* Setup task */ + // Setup task if (s->rt) s->task.setRate(s->rate); @@ -405,9 +404,9 @@ int villas::node::signal_node_read(NodeCompat *n, struct Sample * const smps[], return -1; } - /* Throttle output if desired */ + // Throttle output if desired if (s->rt) { - /* Block until 1/p->rate seconds elapsed */ + // Block until 1/p->rate seconds elapsed steps = s->task.wait(); if (steps > 1 && s->monitor_missed) { n->logger->debug("Missed steps: {}", steps-1); @@ -446,10 +445,11 @@ int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) return 0; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "signal"; p.description = "Legacy Signal generator"; p.vectorize = 1; @@ -465,5 +465,6 @@ static void register_plugin() { p.read = signal_node_read; p.poll_fds = signal_node_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/socket.cpp b/lib/nodes/socket.cpp index ab09dd00f..2d880fa37 100644 --- a/lib/nodes/socket.cpp +++ b/lib/nodes/socket.cpp @@ -1,9 +1,9 @@ -/** The socket node-type for Layer 2, 3, 4 BSD-style sockets +/* The socket node-type for Layer 2, 3, 4 BSD-style sockets * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -21,21 +21,23 @@ #ifdef WITH_SOCKET_LAYER_ETH #include -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH #ifdef WITH_NETEM #include #include -#endif /* WITH_NETEM */ +#endif // WITH_NETEM using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -/* Forward declartions */ -static NodeCompatType p; -static NodeCompatFactory ncp(&p); +// Forward declartions +static +NodeCompatType p; +static +NodeCompatFactory ncp(&p); int villas::node::socket_type_start(villas::node::SuperNode *sn) { @@ -49,13 +51,13 @@ int villas::node::socket_type_start(villas::node::SuperNode *sn) if (s->layer == SocketLayer::UNIX) continue; - /* Determine outgoing interface */ + // Determine outgoing interface Interface *j = Interface::getEgress((struct sockaddr *) &s->out.saddr, sn); j->addNode(n); } } -#endif /* WITH_NETEM */ +#endif // WITH_NETEM return 0; } @@ -132,7 +134,7 @@ int villas::node::socket_check(NodeCompat *n) { auto *s = n->getData(); - /* Some checks on the addresses */ + // Some checks on the addresses if (s->layer != SocketLayer::UNIX) { if (s->in.saddr.sa.sa_family != s->out.saddr.sa.sa_family) throw RuntimeError("Address families of local and remote must match!"); @@ -150,7 +152,7 @@ int villas::node::socket_check(NodeCompat *n) if (ntohs(s->in.saddr.sll.sll_protocol) <= 0x5DC) throw RuntimeError("Ethertype must be large than {} or it is interpreted as an IEEE802.3 length field!", 0x5DC); } -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH if (s->multicast.enabled) { if (s->in.saddr.sa.sa_family != AF_INET) @@ -169,10 +171,10 @@ int villas::node::socket_start(NodeCompat *n) auto *s = n->getData(); int ret; - /* Initialize IO */ + // Initialize IO s->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); - /* Create socket */ + // Create socket switch (s->layer) { case SocketLayer::UDP: s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); @@ -186,7 +188,7 @@ int villas::node::socket_start(NodeCompat *n) case SocketLayer::ETH: s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, s->in.saddr.sll.sll_protocol); break; -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH case SocketLayer::UNIX: s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, 0); @@ -199,14 +201,14 @@ int villas::node::socket_start(NodeCompat *n) if (s->sd < 0) throw SystemError("Failed to create socket"); - /* Delete Unix domain socket if already existing */ + // Delete Unix domain socket if already existing if (s->layer == SocketLayer::UNIX) { ret = unlink(s->in.saddr.sun.sun_path); if (ret && errno != ENOENT) return ret; } - /* Bind socket for receiving */ + // Bind socket for receiving socklen_t addrlen = 0; switch(s->in.saddr.ss.ss_family) { case AF_INET: @@ -225,7 +227,7 @@ int villas::node::socket_start(NodeCompat *n) case AF_PACKET: addrlen = sizeof(struct sockaddr_ll); break; -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH default: addrlen = sizeof(s->in.saddr); } @@ -248,7 +250,7 @@ int villas::node::socket_start(NodeCompat *n) throw SystemError("Failed to join multicast group"); } - /* Set socket priority, QoS or TOS IP options */ + // Set socket priority, QoS or TOS IP options int prio; switch (s->layer) { case SocketLayer::UDP: @@ -270,7 +272,7 @@ int villas::node::socket_start(NodeCompat *n) break; #else { } -#endif /* __linux__ */ +#endif // __linux__ } s->out.buflen = SOCKET_INITIAL_BUFFER_LEN; @@ -333,7 +335,7 @@ int villas::node::socket_read(NodeCompat *n, struct Sample * const smps[], unsig union sockaddr_union src; socklen_t srclen = sizeof(src); - /* Receive next sample */ + // Receive next sample bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); if (bytes < 0) { if (errno == EINTR) @@ -346,7 +348,7 @@ int villas::node::socket_read(NodeCompat *n, struct Sample * const smps[], unsig ptr = s->in.buf; - /* Strip IP header from packet */ + // Strip IP header from packet if (s->layer == SocketLayer::IP) { struct ip *iphdr = (struct ip *) ptr; @@ -413,7 +415,7 @@ retry: ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt) goto retry; } - /* Send message */ + // Send message socklen_t addrlen = 0; switch(s->in.saddr.ss.ss_family) { case AF_INET: @@ -432,7 +434,7 @@ retry: ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt) case AF_PACKET: addrlen = sizeof(struct sockaddr_ll); break; -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH default: addrlen = sizeof(s->in.saddr); } @@ -467,7 +469,7 @@ int villas::node::socket_parse(NodeCompat *n, json_t *json) json_t *json_multicast = nullptr; json_t *json_format = nullptr; - /* Default values */ + // Default values s->layer = SocketLayer::UDP; s->verify_source = 0; @@ -484,7 +486,7 @@ int villas::node::socket_parse(NodeCompat *n, json_t *json) if (ret) throw ConfigError(json, err, "node-config-node-socket"); - /* Format */ + // Format if (s->formatter) delete s->formatter; s->formatter = json_format @@ -493,14 +495,14 @@ int villas::node::socket_parse(NodeCompat *n, json_t *json) if (!s->formatter) throw ConfigError(json_format, "node-config-node-socket-format", "Invalid format configuration"); - /* IP layer */ + // IP layer if (layer) { if (!strcmp(layer, "ip")) s->layer = SocketLayer::IP; #ifdef WITH_SOCKET_LAYER_ETH else if (!strcmp(layer, "eth")) s->layer = SocketLayer::ETH; -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH else if (!strcmp(layer, "udp")) s->layer = SocketLayer::UDP; else if (!strcmp(layer, "unix") || !strcmp(layer, "local")) @@ -520,7 +522,7 @@ int villas::node::socket_parse(NodeCompat *n, json_t *json) if (json_multicast) { const char *group, *interface = nullptr; - /* Default values */ + // Default values s->multicast.enabled = true; s->multicast.mreq.imr_interface.s_addr = INADDR_ANY; s->multicast.loop = 0; @@ -559,8 +561,8 @@ int villas::node::socket_fds(NodeCompat *n, int fds[]) return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "socket"; #ifdef WITH_NETEM p.description = "BSD network sockets for Ethernet / IP / UDP (libnl3, netem support)"; diff --git a/lib/nodes/stats.cpp b/lib/nodes/stats.cpp index c130dfdd1..000915f9c 100644 --- a/lib/nodes/stats.cpp +++ b/lib/nodes/stats.cpp @@ -1,9 +1,9 @@ -/** Sending statistics to another node. +/* Sending statistics to another node. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -20,7 +20,8 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static NodeList nodes; /** The global list of nodes */ +static +NodeList nodes; // The global list of nodes int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) { @@ -86,7 +87,7 @@ int villas::node::stats_node_prepare(NodeCompat *n) assert(n->getInputSignals(false)->size() == 0); - /* Generate signal list */ + // Generate signal list for (size_t i = 0; i < list_length(&s->signals); i++) { struct stats_node_signal *stats_sig = (struct stats_node_signal *) list_at(&s->signals, i); @@ -241,10 +242,11 @@ int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) return 0; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "stats"; p.description = "Send statistics to another node"; p.vectorize = 1; @@ -261,5 +263,6 @@ static void register_plugin() { p.read = stats_node_read; p.poll_fds = stats_node_poll_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/temper.cpp b/lib/nodes/temper.cpp index 25c5a76a3..20e61316f 100644 --- a/lib/nodes/temper.cpp +++ b/lib/nodes/temper.cpp @@ -1,33 +1,19 @@ -/** PCSensor / TEMPer node-type +/* PCSensor / TEMPer node-type * - * Based on pcsensor.c by Juan Carlos Perez (c) 2011 (cray@isp-sl.com) - * Based on Temper.c by Robert Kavaler (c) 2009 (relavak.com) + * The driver will work with some TEMPer usb devices from RDing (www.PCsensor.com). + * + * Based on pcsensor.c by Juan Carlos Perez + * Based on Temper.c by Robert Kavaler + * + * SPDX-FileCopyrightText: 2011 Juan Carlos Perez + * SPDX-FileCopyrightText: 2009 Robert Kavaler (relavak.com) + * SPDX-License-Identifier: BSD-1-Clause * * All rights reserved. * * 2011/08/30 Thanks to EdorFaus: bugfix to support negative temperatures * 2017/08/30 Improved by K.Cima: changed libusb-0.1 -> libusb-1.0 * https://github.com/shakemid/pcsensor - * - * Temper driver for linux. This program can be compiled either as a library - * or as a standalone program (-DUNIT_TEST). The driver will work with some - * TEMPer usb devices from RDing (www.PCsensor.com). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY Juan Carlos Perez ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL Robert kavaler BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include @@ -39,15 +25,18 @@ using namespace villas; using namespace villas::utils; using namespace villas::node; -static Logger logger; +static +Logger logger; -static std::list devices; +static +std::list devices; -static struct libusb_context *context; - -/* Forward declartions */ -static NodeCompatType p; +static +struct libusb_context *context; +// Forward declartions +static +NodeCompatType p; TEMPerDevice::TEMPerDevice(struct libusb_device *dev) : usb::Device(dev), @@ -97,7 +86,7 @@ void TEMPerDevice::read(struct Sample *smp) float temp[2]; int i = 0, al, ret; - /* Read from device */ + // Read from device unsigned char question[sizeof(question_temperature)]; memcpy(question, question_temperature, sizeof(question_temperature)); @@ -113,14 +102,14 @@ void TEMPerDevice::read(struct Sample *smp) decode(answer, temp); - /* Temperature 1 */ + // Temperature 1 smp->data[i++].f = temp[0]; - /* Temperature 2 */ + // Temperature 2 if (getNumSensors() == 2) smp->data[i++].f = temp[1]; - /* Humidity */ + // Humidity if (hasHumiditySensor()) smp->data[i++].f = temp[1]; @@ -129,7 +118,7 @@ void TEMPerDevice::read(struct Sample *smp) smp->flags |= (int) SampleFlags::HAS_DATA; } -/* Thanks to https://github.com/edorfaus/TEMPered */ +// Thanks to https://github.com/edorfaus/TEMPered void TEMPer1Device::decode(unsigned char *answer, float *temp) { int buf; @@ -250,7 +239,7 @@ int villas::node::temper_type_start(villas::node::SuperNode *sn) logger = logging.get("node:temper"); - /* Enumerate temper devices */ + // Enumerate temper devices devices.clear(); struct libusb_device **devs; @@ -347,7 +336,7 @@ int villas::node::temper_prepare(NodeCompat *n) { auto *t = n->getData(); - /* Find matching USB device */ + // Find matching USB device t->device = nullptr; for (auto *dev : devices) { if (dev->match(&t->filter)) { @@ -359,20 +348,20 @@ int villas::node::temper_prepare(NodeCompat *n) if (t->device == nullptr) throw RuntimeError("No matching TEMPer USB device found!"); - /* Create signal list */ + // Create signal list assert(n->getInputSignals(false)->size() == 0); - /* Temperature 1 */ + // Temperature 1 auto sig1 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); n->in.signals->push_back(sig1); - /* Temperature 2 */ + // Temperature 2 if (t->device->getNumSensors() == 2) { auto sig2 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); n->in.signals->push_back(sig2); } - /* Humidity */ + // Humidity if (t->device->hasHumiditySensor()) { auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); n->in.signals->push_back(sig3); @@ -410,8 +399,8 @@ int villas::node::temper_read(NodeCompat *n, struct Sample * const smps[], unsig return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "temper"; p.description = "An temper for staring new node-type implementations"; p.vectorize = 1; @@ -428,5 +417,6 @@ static void register_plugin() { p.stop = temper_stop; p.read = temper_read; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/test_rtt.cpp b/lib/nodes/test_rtt.cpp index 6280f8313..bb5ea6223 100644 --- a/lib/nodes/test_rtt.cpp +++ b/lib/nodes/test_rtt.cpp @@ -1,9 +1,9 @@ -/** Node type: Node-type for testing Round-trip Time. +/* Node type: Node-type for testing Round-trip Time. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,7 +23,8 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static NodeCompatType p; +static +NodeCompatType p; static int test_rtt_case_start(NodeCompat *n, int id) @@ -33,12 +34,12 @@ int test_rtt_case_start(NodeCompat *n, int id) n->logger->info("Starting case #{}: filename={}, rate={}, values={}, limit={}", t->current, c->filename_formatted, c->rate, c->values, c->limit); - /* Open file */ + // Open file t->stream = fopen(c->filename_formatted, "a+"); if (!t->stream) return -1; - /* Start timer. */ + // Start timer t->task.setRate(c->rate); t->counter = 0; @@ -53,7 +54,7 @@ int test_rtt_case_stop(NodeCompat *n, int id) int ret; auto *t = n->getData(); - /* Stop timer */ + // Stop timer t->task.stop(); ret = fclose(t->stream); @@ -83,7 +84,7 @@ int villas::node::test_rtt_prepare(NodeCompat *n) unsigned max_values = 0; - /* Take current for time for test case prefix */ + // Take current for time for test case prefix time_t ts = time(nullptr); struct tm tm; gmtime_r(&ts, &tm); @@ -124,7 +125,7 @@ int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) t->cooldown = 0; - /* Generate list of test cases */ + // Generate list of test cases ret = list_init(&t->cases); if (ret) return ret; @@ -142,7 +143,7 @@ int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) t->output = strdup(output); t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); - /* Initialize IO module */ + // Initialize IO module if (!json_format) json_format = json_string("villas.binary"); @@ -150,13 +151,13 @@ int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) if (!t->formatter) throw ConfigError(json, "node-config-node-test-rtt-format", "Invalid value for setting 'format'"); - /* Construct List of test cases */ + // Construct List of test cases if (!json_is_array(json_cases)) throw ConfigError(json_cases, "node-config-node-test-rtt-format", "The 'cases' setting must be an array."); json_array_foreach(json_cases, i, json_case) { int limit = -1; - double duration = -1; /* in secs */ + double duration = -1; // in secs ret = json_unpack_ex(json_case, &err, 0, "{ s: o, s: o, s?: i, s?: F }", "rates", &json_rates, @@ -219,7 +220,7 @@ int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) else if (duration > 0) c->limit = duration * c->rate; else - c->limit = 1000; /* default value */ + c->limit = 1000; // default value c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, c->values, c->rate); @@ -279,7 +280,7 @@ int villas::node::test_rtt_start(NodeCompat *n) auto *t = n->getData(); struct test_rtt_case *c = (struct test_rtt_case *) list_first(&t->cases); - /* Create folder for results if not present */ + // Create folder for results if not present ret = stat(t->output, &st); if (ret || !S_ISDIR(st.st_mode)) { ret = mkdir(t->output, 0777); @@ -321,7 +322,7 @@ int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], uns auto *t = n->getData(); - /* Handle start/stop of new cases */ + // Handle start/stop of new cases if (t->counter == -1) { if (t->current < 0) { t->current = 0; @@ -350,7 +351,7 @@ int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], uns struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, t->current); - /* Wait */ + // Wait steps = t->task.wait(); if (steps > 1) n->logger->warn("Skipped {} steps", steps - 1); @@ -370,7 +371,7 @@ int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], uns else { struct timespec now = time_now(); - /* Prepare samples */ + // Prepare samples for (i = 0; i < cnt; i++) { smps[i]->length = c->values; smps[i]->sequence = t->counter; @@ -416,8 +417,8 @@ int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) return 1; } -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "test_rtt"; p.description = "Test round-trip time with loopback"; p.vectorize = 0; @@ -433,5 +434,6 @@ static void register_plugin() { p.read = test_rtt_read; p.write = test_rtt_write; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/uldaq.cpp b/lib/nodes/uldaq.cpp index d824bdb39..f6a907913 100644 --- a/lib/nodes/uldaq.cpp +++ b/lib/nodes/uldaq.cpp @@ -1,11 +1,10 @@ -/** Node-type for uldaq connections. +/* Node-type for uldaq connections. * - * @file - * @author Manuel Pitz - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Manuel Pitz + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -20,10 +19,13 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static unsigned num_devs = ULDAQ_MAX_DEV_COUNT; -static DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; +static +unsigned num_devs = ULDAQ_MAX_DEV_COUNT; +static +DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; -static const struct { +static +const struct { const char *name; AiInputMode mode; } input_modes[] = { @@ -32,7 +34,8 @@ static const struct { { "pseudo-differential", AI_PSEUDO_DIFFERENTIAL } }; -static const struct { +static +const struct { const char *name; DaqDeviceInterface interface; } interface_types[] = { @@ -42,7 +45,8 @@ static const struct { { "any", ANY_IFC } }; -static const struct { +static +const struct { const char *name; Range range; float min, max; @@ -171,27 +175,27 @@ int uldaq_connect(NodeCompat *n) auto *u = n->getData(); UlError err; - /* Find Matching device */ + // Find Matching device if (!u->device_descriptor) { u->device_descriptor = uldaq_find_device(u); if (!u->device_descriptor) throw RuntimeError("Unable to find a matching device"); } - /* Get a handle to the DAQ device associated with the first descriptor */ + // Get a handle to the DAQ device associated with the first descriptor if (!u->device_handle) { u->device_handle = ulCreateDaqDevice(*u->device_descriptor); if (!u->device_handle) throw RuntimeError("Unable to create handle for DAQ device"); } - /* Check if device is already connected */ + // Check if device is already connected int connected; err = ulIsDaqDeviceConnected(u->device_handle, &connected); if (err != ERR_NO_ERROR) return -1; - /* Connect to device */ + // Connect to device if (!connected) { err = ulConnectDaqDevice(u->device_handle); if (err != ERR_NO_ERROR) { @@ -208,7 +212,7 @@ int villas::node::uldaq_type_start(villas::node::SuperNode *sn) { UlError err; - /* Get descriptors for all of the available DAQ devices */ + // Get descriptors for all of the available DAQ devices err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs); if (err != ERR_NO_ERROR) throw RuntimeError("Failed to retrieve DAQ device list"); @@ -488,7 +492,7 @@ void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type pthread_mutex_unlock(&u->in.mutex); - /* Signal uldaq_read() about new data */ + // Signal uldaq_read() about new data pthread_cond_signal(&u->in.cv); } @@ -502,7 +506,7 @@ int villas::node::uldaq_start(NodeCompat *n) int ret; UlError err; - /* Allocate a buffer to receive the data */ + // Allocate a buffer to receive the data u->in.buffer_len = u->in.channel_count * n->in.vectorize * 50; u->in.buffer = new double[u->in.buffer_len]; if (!u->in.buffer) @@ -516,10 +520,10 @@ int villas::node::uldaq_start(NodeCompat *n) if (err != ERR_NO_ERROR) throw RuntimeError("Failed to load input queue to DAQ device"); - /* Enable the event to be notified every time samples are available */ + // Enable the event to be notified every time samples are available err = ulEnableEvent(u->device_handle, DE_ON_DATA_AVAILABLE, n->in.vectorize, uldaq_data_available, n); - /* Start the acquisition */ + // Start the acquisition err = ulAInScan(u->device_handle, 0, 0, (AiInputMode) 0, (Range) 0, u->in.buffer_len / u->in.channel_count, &u->in.sample_rate, u->in.scan_options, u->in.flags, u->in.buffer); if (err != ERR_NO_ERROR) { char buf[ERR_MSG_LEN]; @@ -527,7 +531,7 @@ int villas::node::uldaq_start(NodeCompat *n) throw RuntimeError("Failed to start acquisition on DAQ device: {}", buf); } - /* Get the initial status of the acquisition */ + // Get the initial status of the acquisition err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); if (err != ERR_NO_ERROR) { char buf[ERR_MSG_LEN]; @@ -550,15 +554,15 @@ int villas::node::uldaq_stop(NodeCompat *n) UlError err; - /* @todo Fix deadlock */ + // @todo Fix deadlock //pthread_mutex_lock(&u->in.mutex); - /* Get the current status of the acquisition */ + // Get the current status of the acquisition err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); if (err != ERR_NO_ERROR) return -1; - /* Stop the acquisition if it is still running */ + // Stop the acquisition if it is still running if (u->in.status == SS_RUNNING) { err = ulAInScanStop(u->device_handle); if (err != ERR_NO_ERROR) @@ -589,7 +593,7 @@ int villas::node::uldaq_read(NodeCompat *n, struct Sample * const smps[], unsign size_t start_index = u->in.buffer_pos; - /* Wait for data available condition triggered by event callback */ + // Wait for data available condition triggered by event callback if (start_index + n->in.vectorize * u->in.channel_count > u->in.transfer_status.currentTotalCount) pthread_cond_wait(&u->in.cv, &u->in.mutex); @@ -617,10 +621,11 @@ int villas::node::uldaq_read(NodeCompat *n, struct Sample * const smps[], unsign return cnt; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "uldaq"; p.description = "Measurement Computing DAQ devices like UL201 (libuldaq)"; p.vectorize = 0; @@ -635,5 +640,6 @@ static void register_plugin() { p.stop = uldaq_stop; p.read = uldaq_read; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/webrtc.cpp b/lib/nodes/webrtc.cpp index 85a0d0bf4..13b61cf74 100644 --- a/lib/nodes/webrtc.cpp +++ b/lib/nodes/webrtc.cpp @@ -1,11 +1,11 @@ -/** Node-type: webrtc +/* Node-type: webrtc * - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -22,7 +22,8 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static villas::node::Web *web; +static +villas::node::Web *web; WebRTCNode::WebRTCNode(const uuid_t &id, const std::string &name) : Node(id, name), @@ -248,5 +249,5 @@ int WebRTCNodeFactory::start(SuperNode *sn) return 0; } - -static WebRTCNodeFactory p; +static +WebRTCNodeFactory p; diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index 4b66bf6f5..959a1138d 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -1,12 +1,11 @@ -/** WebRTC peer connection +/* WebRTC peer connection * - * @file - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/nodes/webrtc/signaling_client.cpp b/lib/nodes/webrtc/signaling_client.cpp index 9fb2caf1d..b132d5eab 100644 --- a/lib/nodes/webrtc/signaling_client.cpp +++ b/lib/nodes/webrtc/signaling_client.cpp @@ -1,11 +1,11 @@ -/** WebRTC signaling client +/* WebRTC signaling client * - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/nodes/webrtc/signaling_message.cpp b/lib/nodes/webrtc/signaling_message.cpp index 068bd6bc5..99a5518d9 100644 --- a/lib/nodes/webrtc/signaling_message.cpp +++ b/lib/nodes/webrtc/signaling_message.cpp @@ -1,11 +1,11 @@ -/** WebRTC signaling messages. +/* WebRTC signaling messages. * - * @author Steffen Vogel - * @author Philipp Jungkamp - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index d43f4926f..09f4d1fae 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -1,9 +1,9 @@ -/** Node type: Websockets (libwebsockets) +/* Node type: Websockets (libwebsockets) * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,16 +26,22 @@ using namespace villas::utils; #define DEFAULT_WEBSOCKET_BUFFER_SIZE (1 << 12) -/* Private static storage */ -static std::list connections; /**< List of active libwebsocket connections which receive samples from all nodes (catch all) */ -static std::mutex connections_lock; +// Private static storage +static +std::list connections; // List of active libwebsocket connections which receive samples from all nodes (catch all) +static +std::mutex connections_lock; -static villas::node::Web *web; -static villas::Logger logger = logging.get("websocket"); +static +villas::node::Web *web; +static +villas::Logger logger = logging.get("websocket"); -/* Forward declarations */ -static NodeCompatType p; -static NodeCompatFactory ncp(&p); +// Forward declarations +static +NodeCompatType p; +static +NodeCompatFactory ncp(&p); static void websocket_destination_destroy(struct websocket_destination *d) @@ -75,7 +81,7 @@ int websocket_connection_destroy(struct websocket_connection *c) assert(c->state != websocket_connection::State::DESTROYED); - /* Return all samples to pool */ + // Return all samples to pool int avail; struct Sample *smp; @@ -112,7 +118,7 @@ int websocket_connection_write(struct websocket_connection *c, struct Sample * c c->node->logger->debug("Enqueued {} samples to {}", pushed, c->toString()); - /* Client connections which are currently connecting don't have an associate c->wsi yet */ + // Client connections which are currently connecting don't have an associate c->wsi yet if (c->wsi) web->callbackOnWritable(c->wsi); else @@ -151,7 +157,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso * and format 'json'. */ - /* Get path of incoming request */ + // Get path of incoming request char *node, *format, *lasts; char uri[64]; @@ -173,7 +179,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso if (!format) format = (char *) "villas.web"; - /* Search for node whose name matches the URI. */ + // Search for node whose name matches the URI auto *n = ncp.instances.lookup(node); if (!n) { websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); @@ -226,7 +232,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); if (c->state != websocket_connection::State::CLOSING) { - /** @todo Attempt reconnect here */ + // @todo Attempt reconnect here } { @@ -280,7 +286,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso c->buffers.recv->append((char *) in, len); - /* We dont try to parse the frame yet, as we have to wait for the remaining fragments */ + // We dont try to parse the frame yet, as we have to wait for the remaining fragments if (lws_is_final_fragment(wsi)) { struct timespec ts_recv = time_now(); auto *n = c->node; @@ -301,7 +307,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso c->node->logger->debug("Received {} samples from connection: {}", recvd, c->toString()); - /* Set receive timestamp */ + // Set receive timestamp for (int i = 0; i < recvd; i++) { smps[i]->ts.received = ts_recv; smps[i]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; @@ -311,7 +317,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso if (enqueued < recvd) c->node->logger->warn("Queue overrun in connection: {}", c->toString()); - /* Release unused samples back to pool */ + // Release unused samples back to pool if (enqueued < avail) sample_decref_many(&smps[enqueued], avail - enqueued); @@ -381,7 +387,7 @@ int villas::node::websocket_start(NodeCompat *n) format = strchr(d->info.path, '.'); if (format) - format = format + 1; /* Removes "." */ + format = format + 1; // Removes "." else format = "villas.web"; @@ -399,7 +405,7 @@ int villas::node::websocket_start(NodeCompat *n) lws_client_connect_via_info(&d->info); } - /* Wait until all destinations are connected */ + // Wait until all destinations are connected if (w->wait) { unsigned connected = 0, total = list_length(&w->destinations); do { @@ -505,7 +511,7 @@ int villas::node::websocket_write(NodeCompat *n, struct Sample * const smps[], u auto *w = n->getData(); struct Sample *cpys[cnt]; - /* Make copies of all samples */ + // Make copies of all samples avail = sample_alloc_many(&w->pool, cpys, cnt); if (avail < (int) cnt) n->logger->warn("Pool underrun: avail={}", avail); @@ -536,7 +542,6 @@ int villas::node::websocket_parse(NodeCompat *n, json_t *json) json_error_t err; int wc = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b }", "destinations", &json_dests, "wait_connected", &wc @@ -619,7 +624,8 @@ int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) return 1; } -__attribute__((constructor(110))) static void UNIQUE(__ctor)() { +__attribute__((constructor(110))) static +void UNIQUE(__ctor)() { p.name = "websocket"; p.description = "Send and receive samples of a WebSocket connection (libwebsockets)"; p.vectorize = 0; diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 13163f8d7..8e72ff4dc 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -1,9 +1,9 @@ -/** Node type: ZeroMQ +/* Node type: ZeroMQ * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,20 +23,21 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static void *context; +static +void *context; -/** Read one event off the monitor socket; return value and address +/* Read one event off the monitor socket; return value and address * by reference, if not null, and event number by value. * * @returnval -1 In case of error. */ static int get_monitor_event(void *monitor, int *value, char **address) { - /* First frame in message contains event number and value */ + // First frame in message contains event number and value zmq_msg_t msg; zmq_msg_init (&msg); if (zmq_msg_recv (&msg, monitor, 0) == -1) - return -1; /* Interruped, presumably. */ + return -1; // Interruped, presumably assert(zmq_msg_more (&msg)); @@ -45,10 +46,10 @@ int get_monitor_event(void *monitor, int *value, char **address) if (value) *value = *(uint32_t *) (data + 2); - /* Second frame in message contains event address */ + // Second frame in message contains event address zmq_msg_init(&msg); if (zmq_msg_recv(&msg, monitor, 0) == -1) - return -1; /* Interruped, presumably. */ + return -1; // Interruped, presumably assert(!zmq_msg_more(&msg)); @@ -172,7 +173,7 @@ int villas::node::zeromq_parse(NodeCompat *n, json_t *json) z->in.filter = in_filter ? strdup(in_filter) : nullptr; z->out.filter = out_filter ? strdup(out_filter) : nullptr; - /* Format */ + // Format if (z->formatter) delete z->formatter; z->formatter = json_format @@ -216,7 +217,7 @@ int villas::node::zeromq_parse(NodeCompat *n, json_t *json) memcpy(z->curve.server.secret_key, secret_key, 41); } - /** @todo We should fix this. Its mostly done. */ + // @todo We should fix this. Its mostly done. if (z->curve.enabled) throw ConfigError(json_curve, "node-config-zeromq-curve", "CurveZMQ support is currently broken"); @@ -337,7 +338,7 @@ int villas::node::zeromq_start(NodeCompat *n) goto fail; } - /* Join group */ + // Join group switch (z->pattern) { #ifdef ZMQ_BUILD_DISH case zeromq::Pattern::RADIODISH: @@ -357,7 +358,7 @@ int villas::node::zeromq_start(NodeCompat *n) goto fail; if (z->curve.enabled) { - /* Publisher has server role */ + // Publisher has server role ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SECRETKEY, z->curve.server.secret_key, 41); if (ret) goto fail; @@ -371,12 +372,12 @@ int villas::node::zeromq_start(NodeCompat *n) if (ret) goto fail; - /* Create temporary client keys first */ + // Create temporary client keys first ret = zmq_curve_keypair(z->curve.client.public_key, z->curve.client.secret_key); if (ret) goto fail; - /* Subscriber has client role */ + // Subscriber has client role ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SECRETKEY, z->curve.client.secret_key, 41); if (ret) goto fail; @@ -402,24 +403,24 @@ int villas::node::zeromq_start(NodeCompat *n) if (ret) goto fail; - /* Monitor events on the server */ + // Monitor events on the server ret = zmq_socket_monitor(d->socket, mon_ep, ZMQ_EVENT_ALL); if (ret < 0) goto fail; - /* Create socket for collecting monitor events */ + // Create socket for collecting monitor events d->mon_socket = zmq_socket(context, ZMQ_PAIR); if (!d->mon_socket) { ret = -1; goto fail; } - /* Connect it to the inproc endpoints so they'll get events */ + // Connect it to the inproc endpoints so they'll get events ret = zmq_connect(d->mon_socket, mon_ep); if (ret < 0) goto fail; - /* Connect / bind sockets to endpoints */ + // Connect / bind sockets to endpoints for (size_t i = 0; i < list_length(&d->endpoints); i++) { char *ep = (char *) list_at(&d->endpoints, i); @@ -438,7 +439,7 @@ int villas::node::zeromq_start(NodeCompat *n) } } - /* Wait for all connections to be connected */ + // Wait for all connections to be connected for (auto d : dirs) { while (d->pending > 0) { int evt = d->bind ? ZMQ_EVENT_LISTENING : ZMQ_EVENT_CONNECTED; @@ -455,7 +456,7 @@ int villas::node::zeromq_start(NodeCompat *n) return ret == ZMQ_EVENT_HANDSHAKE_SUCCEEDED; } else - return 0; /* The handshake events are only emitted for CurveZMQ sessions. */ + return 0; // The handshake events are only emitted for CurveZMQ sessions #else return 0; #endif @@ -521,7 +522,7 @@ int villas::node::zeromq_read(NodeCompat *n, struct Sample * const smps[], unsig if (z->in.filter) { switch (z->pattern) { case zeromq::Pattern::PUBSUB: - /* Discard envelope */ + // Discard envelope zmq_recv(z->in.socket, nullptr, 0, 0); break; @@ -529,7 +530,7 @@ int villas::node::zeromq_read(NodeCompat *n, struct Sample * const smps[], unsig } } - /* Receive payload */ + // Receive payload ret = zmq_msg_recv(&m, z->in.socket, 0); if (ret < 0) return ret; @@ -569,7 +570,7 @@ int villas::node::zeromq_write(NodeCompat *n, struct Sample * const smps[], unsi break; #endif - case zeromq::Pattern::PUBSUB: /* Send envelope */ + case zeromq::Pattern::PUBSUB: // Send envelope zmq_send(z->out.socket, z->out.filter, strlen(z->out.filter), ZMQ_SNDMORE); break; } @@ -627,10 +628,11 @@ int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) return 1; } -static NodeCompatType p; +static +NodeCompatType p; -__attribute__((constructor(110))) -static void register_plugin() { +__attribute__((constructor(110))) static +void register_plugin() { p.name = "zeromq"; p.description = "ZeroMQ Distributed Messaging (libzmq)"; p.vectorize = 0; @@ -650,5 +652,6 @@ static void register_plugin() { p.poll_fds = zeromq_poll_fds; p.netem_fds = zeromq_netem_fds; - static NodeCompatFactory ncp(&p); + static + NodeCompatFactory ncp(&p); } diff --git a/lib/path.cpp b/lib/path.cpp index 1c2354de8..4855623b2 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -1,9 +1,9 @@ -/** Message paths. +/* Message paths. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -47,7 +47,7 @@ void * Path::runWrapper(void *arg) : p->runSingle(); } -/** Main thread function per path: +/* Main thread function per path: * read samples from source -> write samples to destinations * * This is an optimized version of runPoll() which is @@ -58,7 +58,7 @@ void * Path::runWrapper(void *arg) void * Path::runSingle() { int ret; - auto ps = sources.front(); /* there is only a single source */ + auto ps = sources.front(); // there is only a single source while (state == State::STARTED) { pthread_testcancel(); @@ -74,7 +74,7 @@ void * Path::runSingle() return nullptr; } -/** Main thread function per path: +/* Main thread function per path: * read samples from source -> write samples to destinations * * This variant of the path uses poll() to listen on an event from @@ -93,7 +93,7 @@ void * Path::runPoll() auto &pfd = pfds[i]; if (pfd.revents & POLLIN) { - /* Timeout: re-enqueue the last sample */ + // Timeout: re-enqueue the last sample if (pfd.fd == timeout.getFD()) { timeout.wait(); @@ -101,7 +101,7 @@ void * Path::runPoll() PathDestination::enqueueAll(this, &last_sample, 1); } - /* A source is ready to receive samples */ + // A source is ready to receive samples else { auto ps = sources[i]; @@ -121,7 +121,7 @@ Path::Path() : state(State::INITIALIZED), mode(Mode::ANY), timeout(CLOCK_MONOTONIC), - rate(0), /* Disabled */ + rate(0), // Disabled affinity(0), enabled(true), poll(-1), @@ -146,7 +146,7 @@ void Path::startPoll() if (fd < 0) throw RuntimeError("Failed to get file descriptor for node {}", ps->getNode()->getName()); - /* This slot is only used if it is not masked */ + // This slot is only used if it is not masked struct pollfd pfd = { .fd = fd, .events = POLLIN @@ -156,7 +156,7 @@ void Path::startPoll() } } - /* We use the last slot for the timeout timer. */ + // We use the last slot for the timeout timer if (rate > 0) { timeout.setRate(rate); @@ -183,12 +183,12 @@ void Path::prepare(NodeList &nodes) mask.reset(); signals = std::make_shared(); - /* Prepare mappings */ + // Prepare mappings ret = mappings.prepare(nodes); if (ret) throw RuntimeError("Failed to prepare mappings of path: {}", this->toString()); - /* Create path sources */ + // Create path sources std::map psm; unsigned i = 0, j = 0; for (auto me : mappings) { @@ -196,7 +196,7 @@ void Path::prepare(NodeList &nodes) PathSource::Ptr ps; if (psm.find(n) != psm.end()) - /* We already have a path source for this mapping entry */ + // We already have a path source for this mapping entry ps = psm[n]; else { /* Depending on weather the node belonging to this mapping is already @@ -207,9 +207,9 @@ void Path::prepare(NodeList &nodes) */ bool isSecondary = n->sources.size() > 0; - /* Create new path source */ + // Create new path source if (isSecondary) { - /* Get master path source */ + // Get master path source auto mps = std::dynamic_pointer_cast(n->sources.front()); if (!mps) throw RuntimeError("Failed to find master path source"); @@ -247,7 +247,7 @@ void Path::prepare(NodeList &nodes) SignalList::Ptr sigs = me->node->getInputSignals(); - /* Update signals of path */ + // Update signals of path for (unsigned j = 0; j < (unsigned) me->length; j++) { Signal::Ptr sig; @@ -260,7 +260,7 @@ void Path::prepare(NodeList &nodes) continue; } } - /* For other mappings we create new signal descriptors */ + // For other mappings we create new signal descriptors else { sig = me->toSignal(j); if (!sig) @@ -275,7 +275,7 @@ void Path::prepare(NodeList &nodes) i++; } - /* Prepare path destinations */ + // Prepare path destinations int mt_cnt = 0; for (auto pd : destinations) { auto *pd_mt = pd->node->getMemoryType(); @@ -293,11 +293,11 @@ void Path::prepare(NodeList &nodes) throw RuntimeError("Failed to prepare path destination {} of path {}", pd->node->getName(), this->toString()); } - /* Autodetect whether to use original sequence numbers or not */ + // Autodetect whether to use original sequence numbers or not if (original_sequence_no == -1) original_sequence_no = sources.size() == 1; - /* Autodetect whether to use poll() for this path or not */ + // Autodetect whether to use poll() for this path or not if (poll == -1) { if (rate > 0) poll = 1; @@ -308,18 +308,18 @@ void Path::prepare(NodeList &nodes) } #ifdef WITH_HOOKS - /* Prepare path hooks */ + // Prepare path hooks int m = builtin ? (int) Hook::Flags::PATH | (int) Hook::Flags::BUILTIN : 0; - /* Add internal hooks if they are not already in the list */ + // Add internal hooks if they are not already in the list hooks.prepare(signals, m, this, nullptr); hooks.dump(logger, fmt::format("path {}", this->toString())); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS - /* Prepare pool */ + // Prepare pool auto osigs = getOutputSignals(); unsigned pool_size = MAX(1UL, destinations.size()) * queuelen; @@ -374,7 +374,7 @@ void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) if (rev >= 0) reversed = rev != 0; - /* Optional settings */ + // Optional settings if (mode_str) { if (!strcmp(mode_str, "any")) mode = Mode::ANY; @@ -384,22 +384,22 @@ void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", mode_str); } - /* UUID */ + // UUID if (uuid_str) { ret = uuid_parse(uuid_str, uuid); if (ret) throw ConfigError(json, "node-config-path-uuid", "Failed to parse UUID: {}", uuid_str); } else - /* Generate UUID from hashed config */ + // Generate UUID from hashed config uuid::generateFromJson(uuid, json, sn_uuid); - /* Input node(s) */ + // Input node(s) ret = mappings.parse(json_in); if (ret) throw ConfigError(json_in, "node-config-path-in", "Failed to parse input mapping of path {}", this->toString()); - /* Output node(s) */ + // Output node(s) NodeList dests; if (json_out) { ret = dests.parse(json_out, nodes); @@ -424,7 +424,7 @@ void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) #ifdef WITH_HOOKS if (json_hooks) hooks.parse(json_hooks, (int) Hook::Flags::PATH, this, nullptr); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS if (json_mask) parseMask(json_mask, nodes); @@ -471,7 +471,7 @@ void Path::check() #ifdef WITH_HOOKS hooks.check(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS state = State::CHECKED; } @@ -479,17 +479,17 @@ void Path::check() void Path::checkPrepared() { if (poll == 0) { - /* Check that we do not need to multiplex between multiple sources when polling is disabled */ + // Check that we do not need to multiplex between multiple sources when polling is disabled if (sources.size() > 1) throw RuntimeError("Setting 'poll' must be active if the path has more than one source"); - /* Check that we do not use the fixed rate feature when polling is disabled */ + // Check that we do not use the fixed rate feature when polling is disabled if (rate > 0) throw RuntimeError("Setting 'poll' must be activated when used together with setting 'rate'"); } else { if (rate <= 0) { - /* Check that all path sources provide a file descriptor for polling if fixed rate is disabled */ + // Check that all path sources provide a file descriptor for polling if fixed rate is disabled for (auto ps : sources) { if (!(ps->getNode()->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_POLL)) throw RuntimeError("Node {} can not be used in polling mode with path {}", ps->getNode()->getName(), this->toString()); @@ -540,13 +540,13 @@ void Path::start() #ifdef WITH_HOOKS hooks.start(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS last_sequence = 0; received.reset(); - /* We initialize the intial sample */ + // We initialize the intial sample last_sample = sample_alloc(&pool); if (!last_sample) throw MemoryAllocationError(); @@ -615,7 +615,7 @@ void Path::stop() #ifdef WITH_HOOKS hooks.stop(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS sample_decref(last_sample); @@ -679,7 +679,7 @@ SignalList::Ptr Path::getOutputSignals(bool after_hooks) #ifdef WITH_HOOKS if (after_hooks && hooks.size() > 0) return hooks.getSignals(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return signals; } @@ -689,7 +689,7 @@ unsigned Path::getOutputSignalsMaxCount() #ifdef WITH_HOOKS if (hooks.size() > 0) return MAX(signals->size(), hooks.getSignalsMaxCount()); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS return signals->size(); } @@ -701,7 +701,7 @@ json_t * Path::toJson() const json_t *json_hooks = hooks.toJson(); #else json_t *json_hooks = json_array(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS json_t *json_sources = json_array(); json_t *json_destinations = json_array(); diff --git a/lib/path_destination.cpp b/lib/path_destination.cpp index d8d8f4d19..79685a4ee 100644 --- a/lib/path_destination.cpp +++ b/lib/path_destination.cpp @@ -1,9 +1,9 @@ -/** Path destination +/* Path destination * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -56,7 +56,7 @@ void PathDestination::enqueueAll(Path *p, const struct Sample * const smps[], un if (enqueued != cnt) p->logger->warn("Queue overrun for path {}", p->toString()); - /* Increase reference counter of these samples as they are now also owned by the queue. */ + // Increase reference counter of these samples as they are now also owned by the queue sample_incref_many(clones, cloned); p->logger->debug("Enqueued {} samples to destination {} of path {}", enqueued, pd->node->getName(), p->toString()); @@ -73,7 +73,7 @@ void PathDestination::write() struct Sample *smps[cnt]; - /* As long as there are still samples in the queue */ + // As long as there are still samples in the queue while (true) { allocated = queue_pull_many(&queue, (void **) smps, cnt); if (allocated == 0) diff --git a/lib/path_list.cpp b/lib/path_list.cpp index 57c835e08..38868f2b5 100644 --- a/lib/path_list.cpp +++ b/lib/path_list.cpp @@ -1,10 +1,9 @@ -/** Path list +/* Path list * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/path_source.cpp b/lib/path_source.cpp index 1ddd015c1..e608ad036 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -1,9 +1,9 @@ -/** Path source +/* Path source * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -52,12 +52,12 @@ int PathSource::read(int i) struct Sample *muxed_smps[cnt]; struct Sample **tomux_smps; - /* Fill smps[] free sample blocks from the pool */ + // Fill smps[] free sample blocks from the pool allocated = sample_alloc_many(&pool, read_smps, cnt); if (allocated != cnt) path->logger->warn("Pool underrun for path source {}", node->getName()); - /* Read ready samples and store them to blocks pointed by smps[] */ + // Read ready samples and store them to blocks pointed by smps[] recv = node->read(read_smps, allocated); if (recv == 0) { enqueued = 0; @@ -79,14 +79,14 @@ int PathSource::read(int i) else if (recv < allocated) path->logger->warn("Partial read for path {}: read={}, expected={}", path->toString(), recv, allocated); - /* Let the master path sources forward received samples to their secondaries */ + // Let the master path sources forward received samples to their secondaries writeToSecondaries(read_smps, recv); - if (path->mode == Path::Mode::ANY) { /* Mux all samples */ + if (path->mode == Path::Mode::ANY) { // Mux all samples tomux_smps = read_smps; tomux = recv; } - else { /* Mux only last sample and discard others */ + else { // Mux only last sample and discard others tomux_smps = read_smps + recv - 1; tomux = 1; } @@ -154,12 +154,12 @@ int PathSource::read(int i) path->logger->debug("received=0b{:b}, mask=0b{:b}", path->received.to_ullong(), path->mask.to_ullong()); if (path->mask.test(i)) { - /* Enqueue always */ + // Enqueue always if (path->mode == Path::Mode::ANY) { enqueued = toenqueue; PathDestination::enqueueAll(path, muxed_smps, toenqueue); } - /* Enqueue only if received == mask bitset */ + // Enqueue only if received == mask bitset else if (path->mode == Path::Mode::ALL) { if (path->mask == path->received) { PathDestination::enqueueAll(path, muxed_smps, toenqueue); @@ -217,6 +217,6 @@ SecondaryPathSource::SecondaryPathSource(Path *p, Node *n, NodeList &nodes, Path if (!node) throw RuntimeError("Failed to create internal loopback"); - /* Register new loopback node in node list of super node */ + // Register new loopback node in node list of super node nodes.push_back(node); } diff --git a/lib/pool.cpp b/lib/pool.cpp index 5225a40e2..a34cf839d 100644 --- a/lib/pool.cpp +++ b/lib/pool.cpp @@ -1,9 +1,9 @@ -/** Memory pool for fixed size objects. +/* Memory pool for fixed size objects. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +19,7 @@ int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct m int ret; auto logger = logging.get("pool"); - /* Make sure that we use a block size that is aligned to the size of a cache line */ + // Make sure that we use a block size that is aligned to the size of a cache line p->alignment = kernel::getCachelineSize(); p->blocksz = p->alignment * CEIL(blocksz, p->alignment); p->len = cnt * p->blocksz; diff --git a/lib/queue.cpp b/lib/queue.cpp index d0b6a2523..27d79b83a 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -1,11 +1,11 @@ -/** Lock-free Multiple-Producer Multiple-consumer (MPMC) queue. +/* Lock-free Multiple-Producer Multiple-consumer (MPMC) queue. * * Based on Dmitry Vyukov#s Bounded MPMC queue: * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * - * @author Steffen Vogel - * @copyright 2017 Steffen Vogel - * @license BSD 2-Clause License + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2017 Steffen Vogel + * SPDX-License-Identifier: BSD-2-Clause * * All rights reserved. * @@ -29,7 +29,7 @@ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *********************************************************************************/ + */ #include #include @@ -38,10 +38,10 @@ using namespace villas; -/** Initialize MPMC queue */ +// Initialize MPMC queue int villas::node::queue_init(struct CQueue *q, size_t size, struct memory::Type *m) { - /* Queue size must be 2 exponent */ + // Queue size must be 2 exponent if (!IS_POW2(size)) { size_t old_size = size; size = LOG2_CEIL(size); diff --git a/lib/queue_signalled.cpp b/lib/queue_signalled.cpp index 3bad38ebb..f8fbeaad2 100644 --- a/lib/queue_signalled.cpp +++ b/lib/queue_signalled.cpp @@ -1,10 +1,9 @@ -/** Wrapper around queue that uses POSIX CV's for signalling writes. +/* Wrapper around queue that uses POSIX CV's for signalling writes. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -69,7 +68,7 @@ int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, pthread_condattr_destroy(&cvattr); } else if (qs->mode == QueueSignalledMode::POLLING) { - /* Nothing todo */ + // Nothing todo } #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { @@ -97,7 +96,7 @@ int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) pthread_mutex_destroy(&qs->pthread.mutex); } else if (qs->mode == QueueSignalledMode::POLLING) { - /* Nothing todo */ + // Nothing todo } #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { @@ -126,7 +125,7 @@ int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) pthread_mutex_unlock(&qs->pthread.mutex); } else if (qs->mode == QueueSignalledMode::POLLING) { - /* Nothing todo */ + // Nothing todo } #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { @@ -157,7 +156,7 @@ int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, void *pt pthread_mutex_unlock(&qs->pthread.mutex); } else if (qs->mode == QueueSignalledMode::POLLING) { - /* Nothing todo */ + // Nothing todo } #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { @@ -178,7 +177,7 @@ int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) { int pulled = 0; - /* Make sure that qs->mutex is unlocked if this thread gets cancelled. */ + // Make sure that qs->mutex is unlocked if this thread gets cancelled pthread_cleanup_push(queue_signalled_cleanup, qs); if (qs->mode == QueueSignalledMode::PTHREAD) @@ -192,7 +191,7 @@ int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) if (qs->mode == QueueSignalledMode::PTHREAD) pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); else if (qs->mode == QueueSignalledMode::POLLING) - continue; /* Try again */ + continue; // Try again #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { int ret; @@ -219,7 +218,7 @@ int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, void *pt { int pulled = 0; - /* Make sure that qs->mutex is unlocked if this thread gets cancelled. */ + // Make sure that qs->mutex is unlocked if this thread gets cancelled pthread_cleanup_push(queue_signalled_cleanup, qs); if (qs->mode == QueueSignalledMode::PTHREAD) @@ -233,7 +232,7 @@ int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, void *pt if (qs->mode == QueueSignalledMode::PTHREAD) pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); else if (qs->mode == QueueSignalledMode::POLLING) - continue; /* Try again */ + continue; // Try again #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { int ret; @@ -270,7 +269,7 @@ int villas::node::queue_signalled_close(struct CQueueSignalled *qs) pthread_mutex_unlock(&qs->pthread.mutex); } else if (qs->mode == QueueSignalledMode::POLLING) { - /* Nothing todo */ + // Nothing todo } #ifdef HAS_EVENTFD else if (qs->mode == QueueSignalledMode::EVENTFD) { diff --git a/lib/sample.cpp b/lib/sample.cpp index 2c56322a0..b4ebc1015 100644 --- a/lib/sample.cpp +++ b/lib/sample.cpp @@ -1,9 +1,9 @@ -/** The internal datastructure for a sample of simulation data. +/* The internal datastructure for a sample of simulation data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -135,7 +135,7 @@ int villas::node::sample_decref(struct Sample *s) { int prev = atomic_fetch_sub(&s->refcnt, 1); - /* Did we had the last reference? */ + // Did we had the last reference? if (prev == 1) sample_free(s); @@ -208,7 +208,7 @@ int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, return -1; } - /* Compare sequence no */ + // Compare sequence no if (flags & (int) SampleFlags::HAS_SEQUENCE) { if (a->sequence != b->sequence) { printf("sequence no: %" PRIu64 " != %" PRIu64 "\n", a->sequence, b->sequence); @@ -216,7 +216,7 @@ int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, } } - /* Compare timestamp */ + // Compare timestamp if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { if (time_delta(&a->ts.origin, &b->ts.origin) > epsilon) { printf("ts.origin: %f != %f\n", time_to_double(&a->ts.origin), time_to_double(&b->ts.origin)); @@ -224,7 +224,7 @@ int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, } } - /* Compare data */ + // Compare data if (flags & (int) SampleFlags::HAS_DATA) { if (a->length != b->length) { printf("length: %u != %u\n", a->length, b->length); @@ -232,7 +232,7 @@ int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, } for (unsigned i = 0; i < a->length; i++) { - /* Compare format */ + // Compare format if (sample_format(a, i) != sample_format(b, i)) return 6; diff --git a/lib/shmem.cpp b/lib/shmem.cpp index 70712d084..8ca3a1223 100644 --- a/lib/shmem.cpp +++ b/lib/shmem.cpp @@ -1,10 +1,9 @@ -/** Shared-memory interface: The interface functions that the external program should use. +/* Shared-memory interface: The interface functions that the external program should use. * - * @file - * @author Georg Martin Reinke - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Georg Martin Reinke + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,17 +22,17 @@ using namespace villas::node; size_t villas::node::shmem_total_size(int queuelen, int samplelen) { - /* We have the constant const of the memory_type header */ + // We have the constant const of the memory_type header return sizeof(struct memory::Type) - /* and the shared struct itself */ + // and the shared struct itself + sizeof(struct ShmemShared) - /* the size of the actual queue and the queue for the pool */ + // the size of the actual queue and the queue for the pool + queuelen * (2 * sizeof(struct CQueue_cell)) - /* the size of the pool */ + // the size of the pool + queuelen * kernel::getCachelineSize() * CEIL(SAMPLE_LENGTH(samplelen), kernel::getCachelineSize()) - /* a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) */ + // a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) + 4 * sizeof(struct memory::Block) - /* and some extra buffer for alignment */ + // and some extra buffer for alignment + 1024; } @@ -48,7 +47,7 @@ int villas::node::shmem_int_open(const char *wname, const char* rname, struct Sh struct stat stat_buf; sem_t *sem_own, *sem_other; - /* Ensure both semaphores exist */ + // Ensure both semaphores exist sem_own = sem_open(wname, O_CREAT, 0600, 0); if (sem_own == SEM_FAILED) return -1; @@ -57,7 +56,7 @@ int villas::node::shmem_int_open(const char *wname, const char* rname, struct Sh if (sem_other == SEM_FAILED) return -2; - /* Open and initialize the shared region for the output queue */ + // Open and initialize the shared region for the output queue retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); if (fd < 0) { if (errno == EEXIST) { @@ -117,7 +116,7 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); sem_post(sem_own); sem_wait(sem_other); - /* Open and map the other region */ + // Open and map the other region fd = shm_open(rname, O_RDWR, 0); if (fd < 0) return -8; @@ -142,7 +141,7 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); shm->writers = 0; shm->closed = 0; - /* Unlink the semaphores; we don't need them anymore */ + // Unlink the semaphores; we don't need them anymore sem_unlink(wname); return 0; diff --git a/lib/signal.cpp b/lib/signal.cpp index 7be7139f9..65c0a3c42 100644 --- a/lib/signal.cpp +++ b/lib/signal.cpp @@ -1,9 +1,9 @@ -/** Signal meta data. +/* Signal meta data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -101,20 +101,20 @@ std::string Signal::toString(const union SignalData *d) const return ss.str(); } -/** Check if two signal names are numbered ascendingly +/* Check if two signal names are numbered ascendingly * * E.g. signal3 -> signal4 */ static bool isNextName(const std::string &a, const std::string &b) { - /* Find common prefix */ + // Find common prefix std::string::const_iterator ia, ib; for (ia = a.cbegin(), ib = b.cbegin(); ia != b.cend() && ib != b.cend() && *ia == *ib; ++ia, ++ib); - /* Suffixes */ + // Suffixes auto sa = std::string(ia, a.cend()); auto sb = std::string(ib, b.cend()); diff --git a/lib/signal_data.cpp b/lib/signal_data.cpp index 710249de8..5d7d09575 100644 --- a/lib/signal_data.cpp +++ b/lib/signal_data.cpp @@ -1,9 +1,9 @@ -/** Signal data. +/* Signal data. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/signal_list.cpp b/lib/signal_list.cpp index e64d53e31..18717d0d4 100644 --- a/lib/signal_list.cpp +++ b/lib/signal_list.cpp @@ -1,9 +1,9 @@ -/** Signal metadata list. +/* Signal metadata list. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -91,7 +91,7 @@ void SignalList::dump(Logger logger, const union SignalData *data, unsigned len) Signal::Ptr prevSig; unsigned i = 0; for (auto sig : *this) { - /* Check if this is a sequence of similar signals which can be abbreviated */ + // Check if this is a sequence of similar signals which can be abbreviated if (i >= 1 && i < size() - 1) { if (prevSig->isNext(*sig)) { abbrev = true; diff --git a/lib/signal_type.cpp b/lib/signal_type.cpp index 3766693d3..40c770822 100644 --- a/lib/signal_type.cpp +++ b/lib/signal_type.cpp @@ -1,9 +1,9 @@ -/** Signal types. +/* Signal types. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index d643661f5..b5aad4bd4 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -1,9 +1,9 @@ -/** Various functions to work with socket addresses +/* Various functions to work with socket addresses * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -16,7 +16,7 @@ #ifdef WITH_SOCKET_LAYER_ETH #include -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH using namespace villas; using namespace villas::node; @@ -29,7 +29,7 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) if (!buf) throw MemoryAllocationError(); - /* Address */ + // Address switch (sa->sa.sa_family) { case AF_INET6: inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); @@ -45,7 +45,7 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) for (int i = 1; i < sa->sll.sll_halen; i++) strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); break; -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH case AF_UNIX: snprintf(buf, 256, "%s", sa->sun.sun_path); break; @@ -54,7 +54,7 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) throw RuntimeError("Unknown address family: '{}'", sa->sa.sa_family); } - /* Port / Interface */ + // Port / Interface switch (sa->sa.sa_family) { case AF_INET6: case AF_INET: @@ -72,7 +72,7 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); break; } -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH } return buf; @@ -80,13 +80,13 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLayer layer, int flags) { - /** @todo Add support for IPv6 */ + // @todo Add support for IPv6 union sockaddr_union *sa = (union sockaddr_union *) saddr; char *copy = strdup(addr); int ret; - if (layer == SocketLayer::UNIX) { /* Format: "/path/to/socket" */ + if (layer == SocketLayer::UNIX) { // Format: "/path/to/socket" sa->sun.sun_family = AF_UNIX; if (strlen(addr) > sizeof(sa->sun.sun_path) - 1) @@ -97,21 +97,21 @@ int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, ret = 0; } #ifdef WITH_SOCKET_LAYER_ETH - else if (layer == SocketLayer::ETH) { /* Format: "ab:cd:ef:12:34:56%ifname:protocol" */ - /* Split string */ + else if (layer == SocketLayer::ETH) { // Format: "ab:cd:ef:12:34:56%ifname:protocol" + // Split string char *lasts; char *node = strtok_r(copy, "%", &lasts); char *ifname = strtok_r(nullptr, ":", &lasts); char *proto = strtok_r(nullptr, "\0", &lasts); - /* Parse link layer (MAC) address */ + // Parse link layer (MAC) address struct ether_addr *mac = ether_aton(node); if (!mac) throw RuntimeError("Failed to parse MAC address: {}", node); memcpy(&sa->sll.sll_addr, &mac->ether_addr_octet, ETHER_ADDR_LEN); - /* Get interface index from name */ + // Get interface index from name kernel::nl::init(); struct nl_cache *cache = nl_cache_mngt_require("route/link"); @@ -126,14 +126,14 @@ int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, ret = 0; } -#endif /* WITH_SOCKET_LAYER_ETH */ - else { /* Format: "192.168.0.10:12001" */ +#endif // WITH_SOCKET_LAYER_ETH + else { // Format: "192.168.0.10:12001" struct addrinfo hint = { .ai_flags = flags, .ai_family = AF_UNSPEC }; - /* Split string */ + // Split string char *lasts; char *node = strtok_r(copy, ":", &lasts); char *service = strtok_r(nullptr, "\0", &lasts); @@ -160,12 +160,12 @@ int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, throw RuntimeError("Invalid address type"); } - /* Lookup address */ + // Lookup address struct addrinfo *result; ret = getaddrinfo(node, (layer == SocketLayer::IP) ? nullptr : service, &hint, &result); if (!ret) { if (layer == SocketLayer::IP) { - /* We mis-use the sin_port field to store the IP protocol number on RAW sockets */ + // We mis-use the sin_port field to store the IP protocol number on RAW sockets struct sockaddr_in *sin = (struct sockaddr_in *) result->ai_addr; sin->sin_port = htons(result->ai_protocol); } @@ -215,7 +215,7 @@ int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) CMP(xu->sll.sll_halen, yu->sll.sll_halen); return memcmp(xu->sll.sll_addr, yu->sll.sll_addr, xu->sll.sll_halen); -#endif /* WITH_SOCKET_LAYER_ETH */ +#endif // WITH_SOCKET_LAYER_ETH default: return -1; diff --git a/lib/stats.cpp b/lib/stats.cpp index fa87ee180..e20cb9db0 100644 --- a/lib/stats.cpp +++ b/lib/stats.cpp @@ -1,9 +1,9 @@ -/** Statistic collection. +/* Statistic collection. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/lib/super_node.cpp b/lib/super_node.cpp index 471e94951..670ece9e1 100644 --- a/lib/super_node.cpp +++ b/lib/super_node.cpp @@ -1,9 +1,9 @@ -/** The super node object holding the state of the application. +/* The super node object holding the state of the application. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -56,12 +56,12 @@ SuperNode::SuperNode() : if (ret) throw SystemError("Failed to determine hostname"); - /* Default UUID is derived from hostname */ + // Default UUID is derived from hostname uuid::generateFromString(uuid, hname); #ifdef WITH_NETEM - kernel::nl::init(); /* Fill link cache */ -#endif /* WITH_NETEM */ + kernel::nl::init(); // Fill link cache +#endif // WITH_NETEM logger = logging.get("super_node"); } @@ -116,12 +116,12 @@ void SuperNode::parse(json_t *root) #ifdef WITH_WEB if (json_http) web.parse(json_http); -#endif /* WITH_WEB */ +#endif // WITH_WEB if (json_logging) logging.parse(json_logging); - /* Parse nodes */ + // Parse nodes if (json_nodes) { if (!json_is_object(json_nodes)) throw ConfigError(json_nodes, "node-config-nodes", "Setting 'nodes' must be a group with node name => group mappings."); @@ -167,7 +167,7 @@ void SuperNode::parse(json_t *root) } } - /* Parse paths */ + // Parse paths if (json_paths) { if (!json_is_array(json_paths)) logger->warn("Setting 'paths' must be a list of objects"); @@ -184,12 +184,12 @@ parse: auto *p = new Path(); paths.push_back(p); if (p->isReversed()) { - /* Only simple paths can be reversed */ + // Only simple paths can be reversed ret = p->isSimple(); if (!ret) throw RuntimeError("Complex paths can not be reversed!"); - /* Parse a second time with in/out reversed */ + // Parse a second time with in/out reversed json_path = json_copy(json_path); json_t *json_in = json_object_get(json_path, "in"); @@ -256,7 +256,7 @@ void SuperNode::startInterfaces() if (ret) throw RuntimeError("Failed to start network interface: {}", i->getName()); } -#endif /* WITH_NETEM */ +#endif // WITH_NETEM } void SuperNode::startNodes() @@ -408,7 +408,7 @@ void SuperNode::stopInterfaces() if (ret) throw RuntimeError("Failed to stop interface: {}", i->getName()); } -#endif /* WITH_NETEM */ +#endif // WITH_NETEM } void SuperNode::stop() @@ -467,7 +467,7 @@ int SuperNode::periodic() #ifdef WITH_HOOKS p->hooks.periodic(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS } } @@ -476,7 +476,7 @@ int SuperNode::periodic() #ifdef WITH_HOOKS n->in.hooks.periodic(); n->out.hooks.periodic(); -#endif /* WITH_HOOKS */ +#endif // WITH_HOOKS } } @@ -540,4 +540,4 @@ graph_t * SuperNode::getGraph() return g; } -#endif /* WITH_GRAPHVIZ */ +#endif // WITH_GRAPHVIZ diff --git a/lib/usb.cpp b/lib/usb.cpp index 222cdb9bb..d00fb463f 100644 --- a/lib/usb.cpp +++ b/lib/usb.cpp @@ -1,10 +1,9 @@ -/** Helpers for USB node-types +/* Helpers for USB node-types * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/lib/web.cpp b/lib/web.cpp index f96f79850..5c95d2455 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -1,9 +1,9 @@ -/** LWS-releated functions. +/* LWS-releated functions. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -23,10 +23,10 @@ using namespace villas; using namespace villas::node; -/* Forward declarations */ +// Forward declarations lws_callback_function villas::node::websocket_protocol_cb; -/** List of libwebsockets protocols. */ +// List of libwebsockets protocols. lws_protocols protocols[] = { { .name = "http", @@ -41,7 +41,7 @@ lws_protocols protocols[] = { .per_session_data_size = sizeof(api::Session), .rx_buffer_size = 1024 }, -#endif /* WITH_API */ +#endif // WITH_API #ifdef WITH_NODE_WEBSOCKET { .name = "live", @@ -49,7 +49,7 @@ lws_protocols protocols[] = { .per_session_data_size = sizeof(websocket_connection), .rx_buffer_size = 0 }, -#endif /* WITH_NODE_WEBSOCKET */ +#endif // WITH_NODE_WEBSOCKET #ifdef WITH_NODE_WEBRTC { .name = "webrtc-signaling", @@ -63,13 +63,14 @@ lws_protocols protocols[] = { } }; -/** List of libwebsockets mounts. */ -static lws_http_mount mounts[] = { +// List of libwebsockets mounts. +static +lws_http_mount mounts[] = { #ifdef WITH_API { - .mount_next = nullptr, /* linked-list "next" */ - .mountpoint = "/api/v2", /* mountpoint URL */ - .origin = "http-api", /* protocol */ + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v2", // mountpoint URL + .origin = "http-api", // protocol .def = nullptr, .protocol = "http-api", .cgienv = nullptr, @@ -81,14 +82,15 @@ static lws_http_mount mounts[] = { .cache_reusable = 0, .cache_revalidate = 0, .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, /* dynamic */ - .mountpoint_len = 7 /* char count */ + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7 // char count } -#endif /* WITH_API */ +#endif // WITH_API }; -/** List of libwebsockets extensions. */ -static const lws_extension extensions[] = { +// List of libwebsockets extensions. +static +const lws_extension extensions[] = { #ifdef LWS_DEFLATE_FOUND { .name = "permessage-deflate", @@ -100,7 +102,7 @@ static const lws_extension extensions[] = { .callback = lws_extension_callback_pm_deflate, .client_offer = "deflate_frame" }, -#endif /* LWS_DEFLATE_FOUND */ +#endif // LWS_DEFLATE_FOUND { nullptr /* terminator */ } }; @@ -111,7 +113,7 @@ void Web::lwsLogger(int lws_lvl, const char *msg) { if (nl) *nl = 0; - /* Decrease severity for some errors. */ + // Decrease severity for some errors if (strstr(msg, "Unable to open") == msg) lws_lvl = LLL_WARN; @@ -131,7 +133,7 @@ void Web::lwsLogger(int lws_lvl, const char *msg) { logger->info("{}", msg); break; - default: /* Everything else is debug */ + default: // Everything else is debug logger->debug("{}", msg); } } @@ -223,7 +225,7 @@ int Web::parse(json_t *json) void Web::start() { - /* Start server */ + // Start server lws_context_creation_info ctx_info; memset(&ctx_info, 0, sizeof(ctx_info)); @@ -240,7 +242,7 @@ void Web::start() ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; ctx_info.user = (void *) this; #if LWS_LIBRARY_VERSION_NUMBER <= 3000000 - /* See: https://github.com/warmcat/libwebsockets/issues/1249 */ + // See: https://github.com/warmcat/libwebsockets/issues/1249 ctx_info.max_http_header_pool = 1024; #endif ctx_info.mounts = mounts; @@ -263,7 +265,7 @@ void Web::start() if (vhost == nullptr) throw RuntimeError("Failed to initialize virtual host"); - /* Start thread */ + // Start thread running = true; thread = std::thread(&Web::worker, this); diff --git a/lua/hooks/test.lua b/lua/hooks/test.lua index 51f2a6f29..3ed71af18 100644 --- a/lua/hooks/test.lua +++ b/lua/hooks/test.lua @@ -1,5 +1,8 @@ -- Install with: luarocks install lunajson luasockets +-- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +-- SPDX-License-Identifier: Apache-2.0 + json = require 'lunajson' http = require 'socket.http' diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 06f551c05..0767f6fcd 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 if (NOT DEFINED DEPLOY_USER) set(DEPLOY_USER deploy) diff --git a/packaging/archlinux/.gitignore b/packaging/archlinux/.gitignore index 892a7abe8..a36160779 100644 --- a/packaging/archlinux/.gitignore +++ b/packaging/archlinux/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + pkg/* src/* *.tar.bz2 diff --git a/packaging/archlinux/PKGBUILD b/packaging/archlinux/PKGBUILD index c2b71ce7a..15af49b2a 100644 --- a/packaging/archlinux/PKGBUILD +++ b/packaging/archlinux/PKGBUILD @@ -1,5 +1,7 @@ # $Id$ # Maintainer: Daniel Krebs +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 pkgname=villas-node pkgdesc="Connecting real-time power grid simulation equipment" diff --git a/packaging/deps.sh b/packaging/deps.sh index cf77f6dfd..44ddebb81 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -1,4 +1,6 @@ #!/bin/bash +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Abort the script on any failed command set -e diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index 7798d0ef6..c149cd608 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -1,9 +1,8 @@ # Debian Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # You can choose between Debian and Ubuntu here ARG DISTRO=debian diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index e16bfe55d..dd3d26850 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -1,9 +1,8 @@ # Debian Multiarch Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # You can choose between Debian and Ubuntu here ARG DISTRO=debian diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 9753dc5f4..40bd67296 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -1,9 +1,8 @@ # Fedora Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 ARG DISTRO=fedora ARG FEDORA_VERSION=36 diff --git a/packaging/docker/Dockerfile.fedora-minimal b/packaging/docker/Dockerfile.fedora-minimal index 5124baca2..460beb6d2 100644 --- a/packaging/docker/Dockerfile.fedora-minimal +++ b/packaging/docker/Dockerfile.fedora-minimal @@ -1,9 +1,8 @@ # Minimal Fedora Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 ARG DISTRO=fedora ARG FEDORA_VERSION=36 diff --git a/packaging/docker/Dockerfile.rocky b/packaging/docker/Dockerfile.rocky index 329376923..ffc3ed194 100644 --- a/packaging/docker/Dockerfile.rocky +++ b/packaging/docker/Dockerfile.rocky @@ -1,9 +1,8 @@ # Rockylinux Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 ARG DISTRO=rockylinux ARG ROCKY_VERSION=9 diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 07bc6b807..21fbef364 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -1,9 +1,8 @@ # Ubuntu Dockerfile # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # You can choose between Debian and Ubuntu here ARG DISTRO=ubuntu diff --git a/packaging/libvillas.pc.in b/packaging/libvillas.pc.in index 512fbcf78..f1a9a2573 100644 --- a/packaging/libvillas.pc.in +++ b/packaging/libvillas.pc.in @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@CMAKE_INSTALL_LIBDIR@ diff --git a/packaging/live-iso/.gitignore b/packaging/live-iso/.gitignore index bb2998942..074e0fe8f 100644 --- a/packaging/live-iso/.gitignore +++ b/packaging/live-iso/.gitignore @@ -1,4 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + villas.iso build/ *.log - diff --git a/packaging/live-iso/.gitlab-ci.yml b/packaging/live-iso/.gitlab-ci.yml index c89a63d55..73c7c936a 100644 --- a/packaging/live-iso/.gitlab-ci.yml +++ b/packaging/live-iso/.gitlab-ci.yml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- variables: GIT_STRATEGY: fetch GIT_SUBMODULE_STRATEGY: recursive @@ -12,7 +15,6 @@ stages: - build # Stage: prepare -############################################################################## # Build docker image which is used to build & test VILLASnode docker: @@ -27,7 +29,6 @@ docker: - trigger # Stage: build -############################################################################## iso: stage: build diff --git a/packaging/live-iso/Dockerfile b/packaging/live-iso/Dockerfile index 43af5f7ed..c2e87cccc 100644 --- a/packaging/live-iso/Dockerfile +++ b/packaging/live-iso/Dockerfile @@ -1,9 +1,8 @@ # Dockerfile for creating VILLAS live images # -# @author Steffen Vogel -# @copyright 2017-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2017-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 FROM fedora:36 diff --git a/packaging/live-iso/Makefile b/packaging/live-iso/Makefile index a46b3f857..6b4419ffc 100644 --- a/packaging/live-iso/Makefile +++ b/packaging/live-iso/Makefile @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + NAME ?= VILLASlive RELEASEVER ?= 35 RELEASEARCH ?= x86_64 diff --git a/packaging/live-iso/README.md b/packaging/live-iso/README.md index 231525c50..7316c1409 100644 --- a/packaging/live-iso/README.md +++ b/packaging/live-iso/README.md @@ -9,3 +9,8 @@ https://villas.fein-aachen.org/docs/liveusb/ ## Contact - Steffen Vogel + +## License + +- SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +- SPDX-License-Identifier: Apache-2.0 diff --git a/packaging/live-iso/ensure_loop.sh b/packaging/live-iso/ensure_loop.sh index 875535f99..c0ade25a4 100755 --- a/packaging/live-iso/ensure_loop.sh +++ b/packaging/live-iso/ensure_loop.sh @@ -2,6 +2,8 @@ # Ensure that we have at least two usable loop devices inside our Docker container # # Source: https://github.com/jpetazzo/dind/issues/19#issuecomment-48859883 +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 ensure_loop(){ num="$1" diff --git a/packaging/live-iso/villas.ks b/packaging/live-iso/villas.ks index 0be39e752..3d3f0913a 100644 --- a/packaging/live-iso/villas.ks +++ b/packaging/live-iso/villas.ks @@ -1,6 +1,7 @@ -################################################################################ # Kickstart file for VILLAS installation -################################################################################ +# +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Configuration lang en_US.UTF-8 @@ -27,7 +28,6 @@ repo --name=fedora --mirrorlist=https://mirrors.fedoraproject.org/mirrorlist?rep repo --name=updates --mirrorlist=https://mirrors.fedoraproject.org/mirrorlist?repo=updates-released-f$releasever&arch=$basearch url --mirrorlist=https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-$releasever&arch=$basearch -################################################################################ # Install packages %packages @core @@ -129,7 +129,6 @@ librdkafka-devel %end -################################################################################ # Custom post installer %post diff --git a/packaging/nix/README.md b/packaging/nix/README.md index f7abf407d..e4454e46e 100644 --- a/packaging/nix/README.md +++ b/packaging/nix/README.md @@ -1,6 +1,10 @@ - # `villas` as a Nix Flake + + `VILLASnode` is also packaged as a Nix Flake. ## Setup Nix @@ -348,3 +352,8 @@ docker load < $(nix build --no-link --print-out-paths .#image) [`villas.nix`]: ./villas.nix [`flake.nix`]: ./flake.nix + +## License + +- SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +- SPDX-License-Identifier: Apache-2.0 diff --git a/packaging/nix/ethercat.nix b/packaging/nix/ethercat.nix index eacaf9151..f8f099139 100644 --- a/packaging/nix/ethercat.nix +++ b/packaging/nix/ethercat.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { autoconf, automake, diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index b8c8dad38..f2a91270b 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { description = "a tool for connecting real-time power grid simulation equipment"; diff --git a/packaging/nix/lib60870.nix b/packaging/nix/lib60870.nix index b1595ab44..5aac968ec 100644 --- a/packaging/nix/lib60870.nix +++ b/packaging/nix/lib60870.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { cmake, lib, diff --git a/packaging/nix/libdatachannel.nix b/packaging/nix/libdatachannel.nix index 388c845eb..436916808 100644 --- a/packaging/nix/libdatachannel.nix +++ b/packaging/nix/libdatachannel.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { cmake, lib, diff --git a/packaging/nix/libiec61850.nix b/packaging/nix/libiec61850.nix index df8426ed1..81ffdc86a 100644 --- a/packaging/nix/libiec61850.nix +++ b/packaging/nix/libiec61850.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { cmake, lib, diff --git a/packaging/nix/villas.nix b/packaging/nix/villas.nix index 0973436df..fb88cdecb 100644 --- a/packaging/nix/villas.nix +++ b/packaging/nix/villas.nix @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 { # general configuration src, diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 11134a99e..b1226a668 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Plugins link_libraries(villas) diff --git a/plugins/example_hook.cpp b/plugins/example_hook.cpp index fc96abdeb..0ab18dfca 100644 --- a/plugins/example_hook.cpp +++ b/plugins/example_hook.cpp @@ -1,9 +1,9 @@ -/** A simple example hook function which can be loaded as a plugin. +/* A simple example hook function which can be loaded as a plugin. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -16,13 +16,14 @@ class ExampleHook : public Hook { public: using Hook::Hook; - virtual void restart() + virtual + void restart() { logger->info("The path {} restarted!", path->toString()); } }; -/* Register hook */ +// Register hook static char n[] = "example"; static char d[] = "This is just a simple example hook"; static HookPlugin p; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e13cf6187..07d184453 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,9 +1,8 @@ # Makefile. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 if(DEFINED PROTOBUF_COMPILER AND PROTOBUF_FOUND) add_custom_command( diff --git a/python/README.md b/python/README.md index 113ad2b1f..9ac65417e 100644 --- a/python/README.md +++ b/python/README.md @@ -10,13 +10,9 @@ villas-file-merge testfile.dat testfile2.dat | villas-file-filter 3 5 > output.d User documentation is available here: -## Copyright - -2014-2022, Institute for Automation of Complex Power Systems, EONERC - ## License -This project is released under the terms of the [Apache 2.0 license](COPYING.md). +This project is released under the terms of the [Apache 2.0 license](../LICENSE). We kindly ask all academic publications employing components of VILLASframework to cite one of the following papers: @@ -25,6 +21,10 @@ We kindly ask all academic publications employing components of VILLASframework For other licensing options please consult [Prof. Antonello Monti](mailto:amonti@eonerc.rwth-aachen.de). +- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +- SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +- SPDX-License-Identifier: Apache-2.0 + ## Contact [![EONERC ACS Logo](doc/pictures/eonerc_logo.png)](http://www.acs.eonerc.rwth-aachen.de) diff --git a/python/examples/Shmem_CIGRE_MV.py b/python/examples/Shmem_CIGRE_MV.py index c5cb8d713..8d1cf1b0b 100644 --- a/python/examples/Shmem_CIGRE_MV.py +++ b/python/examples/Shmem_CIGRE_MV.py @@ -1,6 +1,9 @@ import time from villas.node.node import Node as VILLASnode +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + # This could be moved to the DPsim Python code later diff --git a/python/setup.py b/python/setup.py index 689ec167c..d8092dbe6 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + from setuptools import setup, find_namespace_packages from glob import glob import sys diff --git a/python/villas/node/communicate.py b/python/villas/node/communicate.py index 91996e098..d78ed5741 100644 --- a/python/villas/node/communicate.py +++ b/python/villas/node/communicate.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + import time import logging import sys diff --git a/python/villas/node/node.py b/python/villas/node/node.py index 82a8ac1b2..f88fef939 100644 --- a/python/villas/node/node.py +++ b/python/villas/node/node.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + import json import os import tempfile diff --git a/python/villas/node/sample.py b/python/villas/node/sample.py index 2f8e5914b..2bbb2f910 100644 --- a/python/villas/node/sample.py +++ b/python/villas/node/sample.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + import re from datetime import datetime from functools import total_ordering diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4993367ff..fab2f82ca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(SRCS villas-convert diff --git a/src/villas-compare.cpp b/src/villas-compare.cpp index 7006f946b..6305ede22 100644 --- a/src/villas-compare.cpp +++ b/src/villas-compare.cpp @@ -1,9 +1,9 @@ -/** Compare two data files. +/* Compare two data files. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -49,7 +49,7 @@ public: json_t *json_format; json_error_t err; - /* Try parsing format config as JSON */ + // Try parsing format config as JSON json_format = json_loads(format.c_str(), 0, &err); formatter = json_format ? FormatFactory::make(json_format) @@ -135,7 +135,7 @@ protected: void parse() { - /* Parse Arguments */ + // Parse Arguments int c; char *endptr; while ((c = getopt (argc, argv, "he:vTsf:t:Vd:")) != -1) { @@ -189,7 +189,7 @@ check: if (optarg == endptr) exit(EXIT_FAILURE); } - /* Open files */ + // Open files for (int i = 0; i < argc - optind; i++) filenames.push_back(argv[optind + i]); } @@ -203,7 +203,7 @@ check: if (optarg == endptr) if (ret) throw RuntimeError("Failed to initialize pool"); - /* Open files */ + // Open files std::vector sides; for (auto filename : filenames) { auto *s = new CompareSide(filename, format, dtypes, &pool); @@ -215,7 +215,7 @@ check: if (optarg == endptr) line = 0; while (true) { - /* Read next sample from all files */ + // Read next sample from all files retry: eofs = 0; for (auto side : sides) { ret = feof(side->stream); @@ -243,7 +243,7 @@ retry: eofs = 0; if (failed) goto retry; - /* We compare all files against the first one */ + // We compare all files against the first one for (auto side : sides) { ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags); if (ret) { diff --git a/src/villas-conf2json.cpp b/src/villas-conf2json.cpp index a0e3d4cac..aea969fc2 100644 --- a/src/villas-conf2json.cpp +++ b/src/villas-conf2json.cpp @@ -1,9 +1,9 @@ -/** Convert old style config to new JSON format. +/* Convert old style config to new JSON format. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index aa9969895..b1005cacf 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -1,10 +1,9 @@ -/** Convert between samples IO formats +/* Convert between samples IO formats * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -71,7 +70,7 @@ protected: void parse() { - /* Parse optional command line arguments */ + // Parse optional command line arguments int c; while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) { switch (c) { @@ -117,7 +116,7 @@ protected: json_error_t err; std::string format = dirs[i].format; - /* Try parsing format config as JSON */ + // Try parsing format config as JSON json_format = json_loads(format.c_str(), 0, &err); dirs[i].formatter = json_format ? FormatFactory::make(json_format) @@ -133,7 +132,7 @@ protected: auto isLine = dynamic_cast(dirs[0].formatter) != nullptr; auto cnt = isLine ? 1 : 128; - /* Initialize memory */ + // Initialize memory struct Pool pool; ret = pool_init(&pool, cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); if (ret) diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index ffd4a29fe..15f6cce4a 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -1,10 +1,9 @@ -/** Create a graph representation of the VILLASnode configuration file +/* Create a graph representation of the VILLASnode configuration file * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -23,8 +22,7 @@ struct GVC_s { char *config_path; bool config_found; - /* gvParseArgs */ - char **input_filenames; + char **input_filenames; // gvParseArgs }; namespace villas { @@ -45,7 +43,7 @@ public: if (ret) throw RuntimeError("Failed to initialize memory"); - this->argv[0] = (char *) "neato"; /* Default layout engine */ + this->argv[0] = (char *) "neato"; // Default layout engine gvc = gvContext(); } @@ -84,26 +82,26 @@ protected: configFilename = filenames.front(); } - virtual void handler(int signal, siginfo_t *siginfp, void *) + virtual + void handler(int signal, siginfo_t *siginfp, void *) { #ifndef _WIN32 switch (signal) { case SIGINT: - /* If interrupted we try to produce a partial rendering before exiting */ + // If interrupted we try to produce a partial rendering before exiting if (graph) gvRenderJobs(gvc, graph); break; - case SIGUSR1: - /* Note that we don't call gvFinalize() so that we don't start event-driven - * devices like -Tgtk or -Txlib */ + // Note that we don't call gvFinalize() so that we don't start event-driven + // devices like -Tgtk or -Txlib */ exit(gvFreeContext(gvc)); break; default: { } } -#endif /* _WIN32 */ +#endif // _WIN32 } int main() @@ -118,7 +116,7 @@ protected: graph = sn.getGraph(); - ret = gvLayoutJobs(gvc, graph); /* take layout engine from command line */ + ret = gvLayoutJobs(gvc, graph); // Take layout engine from command line if (ret) return ret; diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index 30c1797dd..240ff0a32 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -1,10 +1,9 @@ -/** Receive messages from server snd print them on stdout. +/* Receive messages from server snd print them on stdout. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -122,7 +121,7 @@ protected: int ret; std::string file; - /* Parse optional command line arguments */ + // Parse optional command line arguments int c; char *endptr; while ((c = getopt(argc, argv, "Vhv:d:f:F:t:o:c:")) != -1) { @@ -206,7 +205,7 @@ check: if (optarg == endptr) if (ret) throw RuntimeError("Failed to initilize memory pool"); - /* Initialize IO */ + // Initialize IO struct desc { std::string dir; std::string format; @@ -221,7 +220,7 @@ check: if (optarg == endptr) json_t *json_format; json_error_t err; - /* Try parsing format config as JSON */ + // Try parsing format config as JSON json_format = json_loads(d.format.c_str(), 0, &err); (*d.formatter) = json_format ? FormatFactory::make(json_format) @@ -232,7 +231,7 @@ check: if (optarg == endptr) (*d.formatter)->start(dtypes, (int) SampleFlags::HAS_ALL); } - /* Initialize hook */ + // Initialize hook auto hf = plugin::registry->lookup(hook); if (!hf) throw RuntimeError("Unknown hook function '{}'", hook); diff --git a/src/villas-node.cpp b/src/villas-node.cpp index 232e470cd..ca2212075 100644 --- a/src/villas-node.cpp +++ b/src/villas-node.cpp @@ -1,9 +1,9 @@ -/** Main routine. +/* Main routine. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -88,7 +88,7 @@ protected: << "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME" << std::endl << " This type of invocation is used by OPAL-RT Asynchronous processes." << std::endl << " See in the RT-LAB User Guide for more information." << std::endl << std::endl -#endif /* WITH_NODE_OPAL */ +#endif // WITH_NODE_OPAL << "Supported node-types:" << std::endl; for (auto p : registry->lookup()) { @@ -127,7 +127,7 @@ protected: void parse() { - /* Check arguments */ + // Check arguments #ifdef WITH_NODE_OPAL if (argc != 4) { usage(); @@ -139,7 +139,7 @@ protected: uri = "villas-node.conf"; #else - /* Parse optional command line arguments */ + // Parse optional command line arguments int c; while ((c = getopt(argc, argv, "hCVd:")) != -1) { switch (c) { @@ -170,7 +170,7 @@ protected: usage(); exit(EXIT_FAILURE); } -#endif /* ENABLE_OPAL_ASYNC */ +#endif // ENABLE_OPAL_ASYNC } int main() @@ -214,4 +214,3 @@ int main(int argc, char *argv[]) return t.run(); } - diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index 9e8d6db76..d7b2baa0d 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -1,10 +1,9 @@ -/** Receive messages from server snd print them on stdout. +/* Receive messages from server snd print them on stdout. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -63,7 +62,7 @@ public: auto loggerName = fmt::format("pipe:{}", name); logger = logging.get(loggerName); - /* Initialize memory */ + // Initialize memory unsigned pool_size = LOG2_CEIL(MAX(node->out.vectorize, node->in.vectorize)); int ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), node->getMemoryType()); @@ -133,7 +132,7 @@ public: logger->warn("Failed to read from stdin"); } - /* Fill in missing sequence numbers */ + // Fill in missing sequence numbers for (int i = 0; i < scanned; i++) { if (smps[i]->flags & (int) SampleFlags::HAS_SEQUENCE) last_sequenceno = smps[i]->sequence; @@ -254,7 +253,7 @@ public: protected: std::atomic stop; - SuperNode sn; /**< The global configuration */ + SuperNode sn; // The global configuration Format *formatter; int timeout; @@ -419,7 +418,7 @@ check: if (optarg == endptr) else logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); - /* Try parsing format config as JSON */ + // Try parsing format config as JSON json_format = json_loads(format.c_str(), 0, &err); formatter = json_format ? FormatFactory::make(json_format) @@ -440,12 +439,12 @@ check: if (optarg == endptr) throw RuntimeError("Node {} can not send data. Consider using receive-only mode by using '-r' option", nodestr); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - /* Only start web subsystem if villas-pipe is used with a websocket node */ + // Only start web subsystem if villas-pipe is used with a websocket node if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { Web *w = sn.getWeb(); w->start(); } -#endif /* WITH_NODE_WEBSOCKET */ +#endif // WITH_NODE_WEBSOCKET if (reverse) node->reverse(); @@ -474,7 +473,7 @@ check: if (optarg == endptr) recv.dir->startThread(); send.dir->startThread(); - /* Arm timeout timer */ + // Arm timeout timer alarm(timeout); while (!stop) @@ -496,12 +495,12 @@ check: if (optarg == endptr) throw RuntimeError("Failed to stop node type {}: reason={}", node->getFactory()->getName(), ret); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - /* Only start web subsystem if villas-pipe is used with a websocket node */ + // Only start web subsystem if villas-pipe is used with a websocket node if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { Web *w = sn.getWeb(); w->stop(); } -#endif /* WITH_NODE_WEBSOCKET */ +#endif // WITH_NODE_WEBSOCKET delete formatter; @@ -509,7 +508,6 @@ check: if (optarg == endptr) } }; - } // namespace tools } // namespace node } // namespace villas diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index 6f107de1b..3dc8e108a 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -1,9 +1,9 @@ -/** Simple WebSocket relay facilitating client-to-client connections. +/* Simple WebSocket relay facilitating client-to-client connections. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -65,7 +65,7 @@ RelaySession * RelaySession::get(Relay *r, lws *wsi) * Will select the session with the name 'node_1' */ - /* Get path of incoming request */ + // Get path of incoming request lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); if (strlen(uri) <= 1) throw InvalidUrlException(); @@ -218,14 +218,14 @@ Relay::Relay(int argc, char *argv[]) : hostname = hname; - /* Default UUID is derived from hostname */ + // Default UUID is derived from hostname uuid::generateFromString(uuid, hname); ret = memory::init(0); if (ret) throw RuntimeError("Failed to initialize memory"); - /* Initialize logging */ + // Initialize logging lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); protocols = { @@ -266,14 +266,14 @@ int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK, "application/json", - LWS_ILLEGAL_HTTP_CONTENT_LEN, /* no content len */ + LWS_ILLEGAL_HTTP_CONTENT_LEN, // no content len &p, end)) return 1; if (lws_finalize_write_http_header(wsi, start, &p, end)) return 1; - /* Write the body separately */ + // Write the body separately lws_callback_on_writable(wsi); return 0; @@ -441,7 +441,7 @@ check: } int Relay::main() { - /* Start server */ + // Start server lws_context_creation_info ctx_info = { 0 }; protocols[2].name = protocol.c_str(); @@ -489,14 +489,14 @@ const std::vector Relay::extensions = { lws_extension_callback_pm_deflate, "deflate_frame" }, -#endif /* LWS_DEFLATE_FOUND */ +#endif // LWS_DEFLATE_FOUND { nullptr /* terminator */ } }; const lws_http_mount Relay::mount = { - .mount_next = nullptr, /* linked-list "next" */ - .mountpoint = "/api/v1", /* mountpoint URL */ - .origin = nullptr, /* protocol */ + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v1", // mountpoint URL + .origin = nullptr, // protocol .def = nullptr, .protocol = "http-api", .cgienv = nullptr, @@ -508,8 +508,8 @@ const lws_http_mount Relay::mount = { .cache_reusable = 0, .cache_revalidate = 0, .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, /* dynamic */ - .mountpoint_len = 7, /* char count */ + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7, // char count .basic_auth_login_file = nullptr, }; @@ -523,5 +523,3 @@ int main(int argc, char *argv[]) return t.run(); } - - diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index 3b8fd6000..c33b35197 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -1,10 +1,9 @@ -/** Simple WebSocket relay facilitating client-to-client connections. +/* Simple WebSocket relay facilitating client-to-client connections. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +18,7 @@ namespace villas { namespace node { namespace tools { -/* Forward declarations */ +// Forward declarations class Relay; class RelaySession; class RelayConnection; @@ -32,7 +31,7 @@ class Frame : public std::vector { public: Frame() { reserve(LWS_PRE); - /* lws_write() requires LWS_PRE bytes in front of the payload */ + // lws_write() requires LWS_PRE bytes in front of the payload insert(end(), LWS_PRE, 0); } @@ -61,10 +60,12 @@ protected: int connects; - static std::map sessions; + static + std::map sessions; public: - static RelaySession * get(Relay *r, lws *wsi); + static + RelaySession * get(Relay *r, lws *wsi); RelaySession(Relay *r, Identifier sid); @@ -116,10 +117,10 @@ public: protected: std::atomic stop; - /** The libwebsockets server context. */ + // The libwebsockets server context. lws_context *context; - /** The libwebsockets vhost. */ + // The libwebsockets vhost. lws_vhost *vhost; bool loopback; @@ -129,19 +130,24 @@ protected: uuid_t uuid; - /** List of libwebsockets protocols. */ + // List of libwebsockets protocols. std::vector protocols; - /** List of libwebsockets extensions. */ - static const std::vector extensions; + // List of libwebsockets extensions. + static + const std::vector extensions; - static const lws_http_mount mount; + static + const lws_http_mount mount; - static void loggerCallback(int level, const char *msg); + static + void loggerCallback(int level, const char *msg); - static int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static + int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); - static int protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static + int protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); void usage(); diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index 2b8b24708..b50f34de5 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -1,10 +1,9 @@ -/** Generate random packages on stdout. +/* Generate random packages on stdout. * - * @file - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - **********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -86,7 +85,7 @@ protected: json_t * parse_cli(int argc, char *argv[]) { - /* Default values */ + // Default values double rate = 10; double frequency = 1; double amplitude = 1; @@ -102,7 +101,7 @@ protected: int values = 1; int limit = -1; - /* Parse optional command line arguments */ + // Parse optional command line arguments int c; char *endptr; while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { @@ -262,7 +261,7 @@ check: if (optarg == endptr) if (ret) throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); - /* Try parsing format config as JSON */ + // Try parsing format config as JSON json_format = json_loads(format.c_str(), 0, &err); formatter = json_format ? FormatFactory::make(json_format) diff --git a/src/villas-test-config.cpp b/src/villas-test-config.cpp index 538a5688a..e48976a00 100644 --- a/src/villas-test-config.cpp +++ b/src/villas-test-config.cpp @@ -1,9 +1,9 @@ -/** Main routine. +/* Main routine. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/src/villas-test-rtt.cpp b/src/villas-test-rtt.cpp index da66d6bb2..ffd3d09ae 100644 --- a/src/villas-test-rtt.cpp +++ b/src/villas-test-rtt.cpp @@ -1,9 +1,9 @@ -/** Measure round-trip time. +/* Measure round-trip time. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -62,17 +62,16 @@ protected: SuperNode sn; - /** File descriptor for Matlab results. + /* File descriptor for Matlab results. * This allows you to write Matlab results in a seperate log file: * * ./test etc/example.conf rtt -f 3 3>> measurement_results.m */ int fd; - /**< Amount of messages which should be sent (default: -1 for unlimited) */ + // Amount of messages which should be sent (default: -1 for unlimited) int count; - Hist::cnt_t hist_warmup; int hist_buckets; @@ -99,7 +98,7 @@ protected: void parse() { - /* Parse Arguments */ + // Parse Arguments int c; char *endptr; while ((c = getopt (argc, argv, "w:hr:f:c:b:Vd:")) != -1) { @@ -185,14 +184,14 @@ check: if (optarg == endptr) if (ret) throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); - /* Print header */ + // Print header fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev"); while (!stop && (count < 0 || count--)) { clock_gettime(CLOCK_ID, &send); - node->write(&smp_send, 1); /* Ping */ - node->read(&smp_recv, 1); /* Pong */ + node->write(&smp_send, 1); // Ping + node->read(&smp_recv, 1); // Pong clock_gettime(CLOCK_ID, &recv); diff --git a/src/villas-zmq-keygen.cpp b/src/villas-zmq-keygen.cpp index 7f7cda8a1..208b51e30 100644 --- a/src/villas-zmq-keygen.cpp +++ b/src/villas-zmq-keygen.cpp @@ -1,31 +1,9 @@ -/** - * Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file +/* Key generator for libzmq * - * This file is part of libzmq, the ZeroMQ core engine in C++. - * - * libzmq is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License (LGPL) as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * As a special exception, the Contributors give you permission to link - * this library with independent modules to produce an executable, - * regardless of the license terms of these independent modules, and to - * copy and distribute the resulting executable under terms of your choice, - * provided that you also meet, for each linked independent module, the - * terms and conditions of the license of that module. An independent - * module is a module which is not derived from or based on this library. - * If you modify this library, you must extend this exception to your - * version of the library. - * - * libzmq 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 Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9d568fb51..f60df66d0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,9 +1,8 @@ -# Makefile. +# CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 add_custom_target(tests) add_custom_target(run-tests) diff --git a/tests/benchmarks/configs/infiniband.conf b/tests/benchmarks/configs/infiniband.conf index 3a27065ac..f88ffeb11 100644 --- a/tests/benchmarks/configs/infiniband.conf +++ b/tests/benchmarks/configs/infiniband.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "infiniband", diff --git a/tests/benchmarks/configs/loopback.conf b/tests/benchmarks/configs/loopback.conf index 15001dd1f..200987e69 100644 --- a/tests/benchmarks/configs/loopback.conf +++ b/tests/benchmarks/configs/loopback.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "loopback", queuelen = 8192, diff --git a/tests/benchmarks/configs/nanomsg.conf b/tests/benchmarks/configs/nanomsg.conf index 5ec6d3804..3ded62f0f 100644 --- a/tests/benchmarks/configs/nanomsg.conf +++ b/tests/benchmarks/configs/nanomsg.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "nanomsg", diff --git a/tests/benchmarks/configs/shmem.conf b/tests/benchmarks/configs/shmem.conf index 76d09d27b..2a26e3b22 100644 --- a/tests/benchmarks/configs/shmem.conf +++ b/tests/benchmarks/configs/shmem.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "shmem", queuelen = 8192, diff --git a/tests/benchmarks/configs/socket.conf b/tests/benchmarks/configs/socket.conf index db02bcde8..724834f2c 100644 --- a/tests/benchmarks/configs/socket.conf +++ b/tests/benchmarks/configs/socket.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "socket", diff --git a/tests/benchmarks/configs/zeromq.conf b/tests/benchmarks/configs/zeromq.conf index 0921831df..83250e094 100644 --- a/tests/benchmarks/configs/zeromq.conf +++ b/tests/benchmarks/configs/zeromq.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + source_node = { type = "zeromq", pattern = "pubsub", diff --git a/tests/benchmarks/run-benchmark.sh b/tests/benchmarks/run-benchmark.sh index 72d4f24a6..804be8337 100755 --- a/tests/benchmarks/run-benchmark.sh +++ b/tests/benchmarks/run-benchmark.sh @@ -2,16 +2,13 @@ # # Integration Infiniband test using villas-node. # -# @author Dennis Potter -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Dennis Potter +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e -###################################### -# SETTINGS ########################### -###################################### +# Settings # ${NUM_VALUES}, ${RATE_SAMPLES}, and ${IB_MODES} may be a list. @@ -20,10 +17,6 @@ RATE_SAMPLES=(10) TIME_TO_RUN=5 IB_MODES=("RC") -###################################### -###################################### -###################################### - . ${SRCDIR}/tools/villas-helper.sh # Check if user is superuser. SU is used for namespace @@ -78,9 +71,7 @@ else fi fi -###################################### -# SET PATHS ########################## -###################################### +# SET PATHS # Declare location of config files CONFIG=$(mktemp /tmp/nodetype-benchmark-config-XXXX.conf) @@ -90,10 +81,7 @@ CONFIG_SOURCE=$(mktemp /tmp/nodetype-benchmark-config-source-XXXX.conf) # Initialize counter COUNT=0 - -###################################### -# START OF LOOPS THROUGH CONFIGS ##### -###################################### +# START OF LOOPS THROUGH CONFIGS echo ${CONFIG_FILES[0]} echo ${CONFIG_FILES[1]} @@ -101,9 +89,7 @@ echo ${CONFIG_FILES[1]} for NODETYPE in "${NODETYPES[@]}" do - ###################################### - # CREATE PATH CONFIG FILES ########### - ###################################### + # CREATE PATH CONFIG FILES # Set target and source config file, which is the same for both runs cat > ${CONFIG_SOURCE} < ${CONFIG} < -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 add_custom_target(run-integration-tests COMMAND diff --git a/tests/integration/README.md b/tests/integration/README.md index 85c6cbfd7..fd6684fe0 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -18,3 +18,8 @@ Example: ``` $ BUILDDIR=/VILLASnode/build/ /VILLASnode/tools/integration-tests.sh -f pipe-loopback-socket -v ``` + + diff --git a/tests/integration/api-capabilities.sh b/tests/integration/api-capabilities.sh index 25895ebd3..9085405bb 100755 --- a/tests/integration/api-capabilities.sh +++ b/tests/integration/api-capabilities.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-config.sh b/tests/integration/api-config.sh index 99e560f85..b66272bd8 100755 --- a/tests/integration/api-config.sh +++ b/tests/integration/api-config.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-nodes.sh b/tests/integration/api-nodes.sh index e62979645..774cccb4c 100755 --- a/tests/integration/api-nodes.sh +++ b/tests/integration/api-nodes.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-paths.sh b/tests/integration/api-paths.sh index 633d54f74..8a6c136f7 100755 --- a/tests/integration/api-paths.sh +++ b/tests/integration/api-paths.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-restart.sh b/tests/integration/api-restart.sh index 46d5cff78..53ff10f6e 100755 --- a/tests/integration/api-restart.sh +++ b/tests/integration/api-restart.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-shutdown.sh b/tests/integration/api-shutdown.sh index 4d97ea870..eabc57f94 100755 --- a/tests/integration/api-shutdown.sh +++ b/tests/integration/api-shutdown.sh @@ -2,10 +2,9 @@ # # Integration test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/api-stress.sh b/tests/integration/api-stress.sh index 8ce055dc8..31a56c4d5 100755 --- a/tests/integration/api-stress.sh +++ b/tests/integration/api-stress.sh @@ -2,10 +2,9 @@ # # Stress test for remote API # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e set -x diff --git a/tests/integration/compare.sh b/tests/integration/compare.sh index 5328311de..2ecd4a42a 100755 --- a/tests/integration/compare.sh +++ b/tests/integration/compare.sh @@ -2,10 +2,9 @@ # # Integration test for villas compare. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 DIR=$(mktemp -d) pushd ${DIR} diff --git a/tests/integration/convert.sh b/tests/integration/convert.sh index 258068ed4..d2f50bfb8 100755 --- a/tests/integration/convert.sh +++ b/tests/integration/convert.sh @@ -2,10 +2,9 @@ # # Integration test for villas convert tool # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-average.sh b/tests/integration/hook-average.sh index 3a7bad72a..f66011d9f 100755 --- a/tests/integration/hook-average.sh +++ b/tests/integration/hook-average.sh @@ -2,10 +2,9 @@ # # Integration test for average hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-cast.sh b/tests/integration/hook-cast.sh index 848096555..35868089e 100755 --- a/tests/integration/hook-cast.sh +++ b/tests/integration/hook-cast.sh @@ -2,10 +2,9 @@ # # Integration test for cast hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-decimate.sh b/tests/integration/hook-decimate.sh index 545767aad..58f31decd 100755 --- a/tests/integration/hook-decimate.sh +++ b/tests/integration/hook-decimate.sh @@ -2,10 +2,9 @@ # # Integration test for decimate hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-drop.sh b/tests/integration/hook-drop.sh index f9f5eb2ad..1d4127f73 100755 --- a/tests/integration/hook-drop.sh +++ b/tests/integration/hook-drop.sh @@ -2,10 +2,9 @@ # # Integration test for drop hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-gate.sh b/tests/integration/hook-gate.sh index 3249a7447..2e32de58c 100755 --- a/tests/integration/hook-gate.sh +++ b/tests/integration/hook-gate.sh @@ -2,10 +2,9 @@ # # Integration test for gate hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-limit_rate.sh b/tests/integration/hook-limit_rate.sh index 2916949c7..f546ebc45 100755 --- a/tests/integration/hook-limit_rate.sh +++ b/tests/integration/hook-limit_rate.sh @@ -2,10 +2,9 @@ # # Integration test for limit_rate hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-lua.sh b/tests/integration/hook-lua.sh index 9e7880592..d7c204b9f 100755 --- a/tests/integration/hook-lua.sh +++ b/tests/integration/hook-lua.sh @@ -2,10 +2,9 @@ # # Integration test for scale hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-lua_script.sh b/tests/integration/hook-lua_script.sh index 8dfd700ee..6c4fd832c 100755 --- a/tests/integration/hook-lua_script.sh +++ b/tests/integration/hook-lua_script.sh @@ -2,10 +2,9 @@ # # Integration test for scale hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-print.sh b/tests/integration/hook-print.sh index bc9b1f3b8..11538f09f 100755 --- a/tests/integration/hook-print.sh +++ b/tests/integration/hook-print.sh @@ -2,10 +2,9 @@ # # Integration test for print hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-scale.sh b/tests/integration/hook-scale.sh index 0199bf847..0b72f21b3 100755 --- a/tests/integration/hook-scale.sh +++ b/tests/integration/hook-scale.sh @@ -2,10 +2,9 @@ # # Integration test for scale hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-shift_seq.sh b/tests/integration/hook-shift_seq.sh index 6b994d5c4..01264daf6 100755 --- a/tests/integration/hook-shift_seq.sh +++ b/tests/integration/hook-shift_seq.sh @@ -2,10 +2,9 @@ # # Integration test for shift_seq hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-shift_ts.sh b/tests/integration/hook-shift_ts.sh index be2a738b7..a195cc12f 100755 --- a/tests/integration/hook-shift_ts.sh +++ b/tests/integration/hook-shift_ts.sh @@ -2,10 +2,9 @@ # # Integration test for shift_ts hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-skip_first.sh b/tests/integration/hook-skip_first.sh index f3f084626..0797a8630 100755 --- a/tests/integration/hook-skip_first.sh +++ b/tests/integration/hook-skip_first.sh @@ -2,10 +2,9 @@ # # Integration test for skip_first hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/hook-skip_first2.sh b/tests/integration/hook-skip_first2.sh index 7a275036f..e36d29a8b 100755 --- a/tests/integration/hook-skip_first2.sh +++ b/tests/integration/hook-skip_first2.sh @@ -2,10 +2,9 @@ # # Integration test for skip_first hook. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/missing-example-configs.sh b/tests/integration/missing-example-configs.sh index 0190582a9..b4c62826f 100755 --- a/tests/integration/missing-example-configs.sh +++ b/tests/integration/missing-example-configs.sh @@ -3,10 +3,9 @@ # # Test example configurations # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 NODE_TYPES=$(villas node -C 2>/dev/null | jq -r '.nodes | join(" ")') HOOK_TYPES=$(villas node -C 2>/dev/null | jq -r '.hooks | join(" ")') diff --git a/tests/integration/node-can.sh b/tests/integration/node-can.sh index 8f6a21172..615dadb4f 100755 --- a/tests/integration/node-can.sh +++ b/tests/integration/node-can.sh @@ -2,10 +2,9 @@ # # Integration can test using villas node. # -# @author Niklas Eiling -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Niklas Eiling +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # To set up vcan interface use the following commands # sudo modprobe vcan # sudo ip link add dev vcan0 type vcan diff --git a/tests/integration/node-example.sh b/tests/integration/node-example.sh index 481fb5fe3..c66158ff1 100755 --- a/tests/integration/node-example.sh +++ b/tests/integration/node-example.sh @@ -2,10 +2,9 @@ # # Test for the example node-type # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-hook.sh b/tests/integration/node-hook.sh index 94e35fb04..fabefa518 100755 --- a/tests/integration/node-hook.sh +++ b/tests/integration/node-hook.sh @@ -2,10 +2,9 @@ # # Test hooks in villas node # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-infiniband.sh b/tests/integration/node-infiniband.sh index 631a1743f..8e868db32 100755 --- a/tests/integration/node-infiniband.sh +++ b/tests/integration/node-infiniband.sh @@ -2,10 +2,9 @@ # # Integration Infiniband test using villas node. # -# @author Dennis Potter -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Dennis Potter +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e @@ -110,11 +109,7 @@ MODES=("RC" "UC" "UD") # Run through modes for MODE in "${MODES[@]}"; do - echo "#############################" - echo "#############################" - echo "## START ${MODE} ##" - echo "#############################" - echo "#############################" + echo "## Start ${MODE}" sed -i -e 's/MODE/'${MODE}'/g' config.json diff --git a/tests/integration/node-loopback-socket.sh b/tests/integration/node-loopback-socket.sh index 73534cd4e..488f74903 100755 --- a/tests/integration/node-loopback-socket.sh +++ b/tests/integration/node-loopback-socket.sh @@ -2,10 +2,9 @@ # # Integration loopback test using villas node. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-mapping.sh b/tests/integration/node-mapping.sh index 1864fd072..f73261087 100755 --- a/tests/integration/node-mapping.sh +++ b/tests/integration/node-mapping.sh @@ -4,10 +4,9 @@ # # Test test checks if source mapping features for a path. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-multiple-destinations.sh b/tests/integration/node-multiple-destinations.sh index 8bd63430e..e53716b41 100755 --- a/tests/integration/node-multiple-destinations.sh +++ b/tests/integration/node-multiple-destinations.sh @@ -5,10 +5,9 @@ # This test checks if a single node can be used as an input # in multiple paths. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e set -x diff --git a/tests/integration/node-multiple-sources.sh b/tests/integration/node-multiple-sources.sh index f2847a646..d25f7cf32 100755 --- a/tests/integration/node-multiple-sources.sh +++ b/tests/integration/node-multiple-sources.sh @@ -5,10 +5,9 @@ # This test checks if a single node can be used as an input # in multiple paths. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/node-multiplexing.sh b/tests/integration/node-multiplexing.sh index 53d7720b8..fe1f0eb33 100755 --- a/tests/integration/node-multiplexing.sh +++ b/tests/integration/node-multiplexing.sh @@ -2,10 +2,9 @@ # # Integration loopback test using villas node. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-rate.sh b/tests/integration/node-rate.sh index 9d9a23825..ced0c4700 100755 --- a/tests/integration/node-rate.sh +++ b/tests/integration/node-rate.sh @@ -2,10 +2,9 @@ # # Integration loopback test using villas node. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/node-stats.sh b/tests/integration/node-stats.sh index efd043d05..b26bb3f3a 100755 --- a/tests/integration/node-stats.sh +++ b/tests/integration/node-stats.sh @@ -2,10 +2,9 @@ # # Integration loopback test using villas node. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/node-test_rtt.sh b/tests/integration/node-test_rtt.sh index db5154e9d..8231fd59c 100755 --- a/tests/integration/node-test_rtt.sh +++ b/tests/integration/node-test_rtt.sh @@ -2,10 +2,9 @@ # # Integration loopback test using villas node. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test not yet supported" exit 99 diff --git a/tests/integration/pipe-loopback-amqp.sh b/tests/integration/pipe-loopback-amqp.sh index 4dcc134d8..3cb60ec2e 100755 --- a/tests/integration/pipe-loopback-amqp.sh +++ b/tests/integration/pipe-loopback-amqp.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-exec.sh b/tests/integration/pipe-loopback-exec.sh index e678790eb..6135a0ae5 100755 --- a/tests/integration/pipe-loopback-exec.sh +++ b/tests/integration/pipe-loopback-exec.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-file.sh b/tests/integration/pipe-loopback-file.sh index cb023b081..d157d3dd6 100755 --- a/tests/integration/pipe-loopback-file.sh +++ b/tests/integration/pipe-loopback-file.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-iec61850-9-2.sh b/tests/integration/pipe-loopback-iec61850-9-2.sh index 5b3d5bacb..9730e6722 100755 --- a/tests/integration/pipe-loopback-iec61850-9-2.sh +++ b/tests/integration/pipe-loopback-iec61850-9-2.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/pipe-loopback-loopback.sh b/tests/integration/pipe-loopback-loopback.sh index 166d06903..92c561580 100755 --- a/tests/integration/pipe-loopback-loopback.sh +++ b/tests/integration/pipe-loopback-loopback.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-mqtt.sh b/tests/integration/pipe-loopback-mqtt.sh index 9fef51818..2c523245a 100755 --- a/tests/integration/pipe-loopback-mqtt.sh +++ b/tests/integration/pipe-loopback-mqtt.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-nanomsg.sh b/tests/integration/pipe-loopback-nanomsg.sh index 1d248dc9e..2e7a9f991 100755 --- a/tests/integration/pipe-loopback-nanomsg.sh +++ b/tests/integration/pipe-loopback-nanomsg.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-redis.sh b/tests/integration/pipe-loopback-redis.sh index 036ab8911..ecd33f30e 100755 --- a/tests/integration/pipe-loopback-redis.sh +++ b/tests/integration/pipe-loopback-redis.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test not ready" exit 99 diff --git a/tests/integration/pipe-loopback-rtp-dual.sh b/tests/integration/pipe-loopback-rtp-dual.sh index 99783b618..32fd82cfe 100755 --- a/tests/integration/pipe-loopback-rtp-dual.sh +++ b/tests/integration/pipe-loopback-rtp-dual.sh @@ -2,11 +2,10 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @author Marvin Klimke -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# Author: Marvin Klimke +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/pipe-loopback-rtp-remote.sh b/tests/integration/pipe-loopback-rtp-remote.sh index 2991ab9a8..46df8a054 100755 --- a/tests/integration/pipe-loopback-rtp-remote.sh +++ b/tests/integration/pipe-loopback-rtp-remote.sh @@ -2,11 +2,10 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @author Marvin Klimke -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# Author: Marvin Klimke +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-rtp-tbf.sh b/tests/integration/pipe-loopback-rtp-tbf.sh index 54d8f0198..89d08b9c6 100755 --- a/tests/integration/pipe-loopback-rtp-tbf.sh +++ b/tests/integration/pipe-loopback-rtp-tbf.sh @@ -2,11 +2,10 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @author Marvin Klimke -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# Author: Marvin Klimke +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/pipe-loopback-rtp.sh b/tests/integration/pipe-loopback-rtp.sh index 922c065da..0dbe6b143 100755 --- a/tests/integration/pipe-loopback-rtp.sh +++ b/tests/integration/pipe-loopback-rtp.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/pipe-loopback-shmem.sh b/tests/integration/pipe-loopback-shmem.sh index a64f54502..5f7f01359 100755 --- a/tests/integration/pipe-loopback-shmem.sh +++ b/tests/integration/pipe-loopback-shmem.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-socket-multicast.sh b/tests/integration/pipe-loopback-socket-multicast.sh index 1a3710116..7a7178737 100755 --- a/tests/integration/pipe-loopback-socket-multicast.sh +++ b/tests/integration/pipe-loopback-socket-multicast.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-socket-netem.sh b/tests/integration/pipe-loopback-socket-netem.sh index 68809a285..460794cf6 100755 --- a/tests/integration/pipe-loopback-socket-netem.sh +++ b/tests/integration/pipe-loopback-socket-netem.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 if ! modprobe -aqn sch_prio sch_netem cls_fw; then echo "Netem / TC kernel modules are missing" diff --git a/tests/integration/pipe-loopback-socket.sh b/tests/integration/pipe-loopback-socket.sh index 00887537d..881e693a3 100755 --- a/tests/integration/pipe-loopback-socket.sh +++ b/tests/integration/pipe-loopback-socket.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-loopback-websocket.sh b/tests/integration/pipe-loopback-websocket.sh index a4de667c3..a3b0e7b81 100755 --- a/tests/integration/pipe-loopback-websocket.sh +++ b/tests/integration/pipe-loopback-websocket.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/pipe-loopback-zeromq.sh b/tests/integration/pipe-loopback-zeromq.sh index 9d840cf73..0846b2955 100755 --- a/tests/integration/pipe-loopback-zeromq.sh +++ b/tests/integration/pipe-loopback-zeromq.sh @@ -2,10 +2,9 @@ # # Integration loopback test for villas pipe. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/pipe-python-protobuf.sh b/tests/integration/pipe-python-protobuf.sh index 9b3e5ba33..129704fe0 100755 --- a/tests/integration/pipe-python-protobuf.sh +++ b/tests/integration/pipe-python-protobuf.sh @@ -2,10 +2,9 @@ # # Test protobuf serialization with Python client # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/relay.sh b/tests/integration/relay.sh index b1afde288..a02657360 100755 --- a/tests/integration/relay.sh +++ b/tests/integration/relay.sh @@ -2,10 +2,9 @@ # # Integration test for villas relay # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 echo "Test is broken" exit 99 diff --git a/tests/integration/signal.sh b/tests/integration/signal.sh index ff20b06f7..cfeb9648a 100755 --- a/tests/integration/signal.sh +++ b/tests/integration/signal.sh @@ -2,10 +2,9 @@ # # Integration test for villas signal tool # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/integration/test-config.sh b/tests/integration/test-config.sh index 74f0d9c73..761c0d03d 100755 --- a/tests/integration/test-config.sh +++ b/tests/integration/test-config.sh @@ -3,10 +3,9 @@ # # Test example configurations # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 3797af484..d8aee5f19 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists.txt. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set(TEST_SRC config_json.cpp diff --git a/tests/unit/config.cpp b/tests/unit/config.cpp index 06cd3458b..ab126d6ee 100644 --- a/tests/unit/config.cpp +++ b/tests/unit/config.cpp @@ -1,9 +1,9 @@ -/** Unit tests for config features. +/* Unit tests for config features. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/tests/unit/config_json.cpp b/tests/unit/config_json.cpp index 56fd26876..f0592f17d 100644 --- a/tests/unit/config_json.cpp +++ b/tests/unit/config_json.cpp @@ -1,9 +1,9 @@ -/** Unit tests libconfig to jansson converters. +/* Unit tests libconfig to jansson converters. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -81,7 +81,7 @@ Test(config, json_to_config) config_setting_t *cfg_root; json_t *json; - /* For config_write() */ + // For config_write() FILE *f; char str[1024]; @@ -105,4 +105,4 @@ Test(config, json_to_config) json_decref(json); } -#endif /* WITH_CONFIG */ +#endif // WITH_CONFIG diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index f3b08d0e8..04c5ecef7 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -1,9 +1,9 @@ -/** Unit tests for formatters. +/* Unit tests for formatters. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -25,7 +25,8 @@ using namespace villas; using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); #define NUM_VALUES 10 @@ -68,7 +69,7 @@ void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], unsigned c break; case SignalType::COMPLEX: { - /** @todo Port to proper C++ */ + // @todo Port to proper C++ std::complex z = { j * 0.1f, i * 100.0f }; memcpy(&data->z, &z, sizeof(data->z)); break; @@ -180,7 +181,8 @@ void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, int ParameterizedTestParameters(format, lowlevel) { - static criterion::parameters params; + static + criterion::parameters params; params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); @@ -267,7 +269,8 @@ ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) ParameterizedTestParameters(format, highlevel) { - static criterion::parameters params; + static + criterion::parameters params; params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); @@ -320,7 +323,7 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) fill_sample_data(signals, smps, p->cnt); - /* Open a file for testing the formatter */ + // Open a file for testing the formatter char *fn, dir[64]; strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir)); @@ -347,7 +350,7 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) ret = fflush(stream); cr_assert_eq(ret, 0); -#if 0 /* Show the file contents */ +#if 0 // Show the file contents char cmd[128]; if (p->fmt == "csv" || p->fmt == "json" || p->fmt == "villas.human") snprintf(cmd, sizeof(cmd), "cat %s", fn); diff --git a/tests/unit/helpers.cpp b/tests/unit/helpers.cpp index 23866e41c..8b269d036 100644 --- a/tests/unit/helpers.cpp +++ b/tests/unit/helpers.cpp @@ -1,3 +1,10 @@ +/* Unit test helpers + * + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/tests/unit/helpers.hpp b/tests/unit/helpers.hpp index 61f8cc925..496cada39 100644 --- a/tests/unit/helpers.hpp +++ b/tests/unit/helpers.hpp @@ -1,3 +1,10 @@ +/* Unit test helpers + * + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once char * cr_strdup(const char *str); diff --git a/tests/unit/json.cpp b/tests/unit/json.cpp index ce3d1afaa..659097368 100644 --- a/tests/unit/json.cpp +++ b/tests/unit/json.cpp @@ -1,10 +1,9 @@ -/** Unit tests for libjansson helpers +/* Unit tests for libjansson helpers * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ - + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,7 +25,8 @@ ParameterizedTestParameters(json, json_load_cli) { const auto d = cr_strdup; - static criterion::parameters params = { + static + criterion::parameters params = { // Combined long option { .argv = { d("dummy"), d("--option=value") }, diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 627566296..faf94c471 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -1,9 +1,9 @@ -/** Custom main() for Criterion +/* Custom main() for Criterion * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/tests/unit/mapping.cpp b/tests/unit/mapping.cpp index 79410cd4c..52417f254 100644 --- a/tests/unit/mapping.cpp +++ b/tests/unit/mapping.cpp @@ -1,9 +1,9 @@ -/** Unit tests for sample value mapping. +/* Unit tests for sample value mapping. * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/tests/unit/memory.cpp b/tests/unit/memory.cpp index ecb7b65cd..f6fa9dd32 100644 --- a/tests/unit/memory.cpp +++ b/tests/unit/memory.cpp @@ -1,9 +1,9 @@ -/** Unit tests for memory management +/* Unit tests for memory management * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +19,8 @@ using namespace villas; using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); #define PAGESIZE (1 << 12) #define HUGEPAGESIZE (1 << 21) diff --git a/tests/unit/pool.cpp b/tests/unit/pool.cpp index fdbaecd86..446b5eca5 100644 --- a/tests/unit/pool.cpp +++ b/tests/unit/pool.cpp @@ -1,9 +1,9 @@ -/** Unit tests for memory pool +/* Unit tests for memory pool * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -19,7 +19,8 @@ using namespace villas; using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); struct param { int thread_count; @@ -30,7 +31,8 @@ struct param { ParameterizedTestParameters(pool, basic) { - static std::vector params; + static + std::vector params; params.clear(); params.push_back({ 1, 4096, 150, &memory::heap }); @@ -59,7 +61,7 @@ ParameterizedTest(struct param *p, pool, basic, .init = init_memory) ptr = pool_get(&pool); cr_assert_neq(ptr, nullptr); - memset(ptr, 1, p->block_size); /* check that we dont get a seg fault */ + memset(ptr, 1, p->block_size); // check that we dont get a seg fault int i; for (i = 1; i < p->pool_size; i++) { diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index 422703b3d..1253444cc 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -1,9 +1,9 @@ -/** Unit tests for queue +/* Unit tests for queue * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -24,14 +24,17 @@ using namespace villas; using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); #define SIZE (1 << 10) -static struct CQueue q; +static +struct CQueue q; #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -static pthread_barrier_t barrier; +static +pthread_barrier_t barrier; #endif struct param { @@ -45,7 +48,7 @@ struct param { struct CQueue queue; }; -/** Get thread id as integer +/* Get thread id as integer * In contrast to pthread_t which is an opaque type */ #ifdef __linux__ #include @@ -63,13 +66,15 @@ uint64_t thread_get_id() return -1; } -/** Sleep, do nothing */ -__attribute__((always_inline)) static inline void nop() +// Sleep, do nothing +__attribute__((always_inline)) static inline +void nop() { __asm__("rep nop;"); } -static void * producer(void *ctx) +static +void * producer(void *ctx) { int ret; struct param *p = (struct param *) ctx; @@ -77,15 +82,15 @@ static void * producer(void *ctx) srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; - /* Wait for global start signal */ + // Wait for global start signal while (p->start == 0) sched_yield(); - /* Wait for a random time */ + // Wait for a random time for (size_t i = 0; i != nops; i += 1) nop(); - /* Enqueue */ + // Enqueue for (intptr_t count = 0; count < p->iter_count; count++) { do { ret = queue_push(&p->queue, (void *) count); @@ -96,7 +101,8 @@ static void * producer(void *ctx) return nullptr; } -static void * consumer(void *ctx) +static +void * consumer(void *ctx) { int ret; struct param *p = (struct param *) ctx; @@ -104,15 +110,15 @@ static void * consumer(void *ctx) srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; - /* Wait for global start signal */ + // Wait for global start signal while (p->start == 0) sched_yield(); - /* Wait for a random time */ + // Wait for a random time for (size_t i = 0; i != nops; i += 1) nop(); - /* Dequeue */ + // Dequeue for (intptr_t count = 0; count < p->iter_count; count++) { intptr_t ptr; @@ -136,11 +142,11 @@ void * producer_consumer(void *ctx) srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; - /* Wait for global start signal */ + // Wait for global start signal while (p->start == 0) sched_yield(); - /* Wait for a random time */ + // Wait for a random time for (size_t i = 0; i != nops; i += 1) nop(); @@ -150,13 +156,13 @@ void * producer_consumer(void *ctx) for (intptr_t i = 0; i < p->batch_size; i++) { void *ptr = (void *) (iter * p->batch_size + i); while (!queue_push(&p->queue, ptr)) - sched_yield(); /* queue full, let other threads proceed */ + sched_yield(); // queue full, let other threads proceed } for (intptr_t i = 0; i < p->batch_size; i++) { void *ptr; while (!queue_pull(&p->queue, &ptr)) - sched_yield(); /* queue empty, let other threads proceed */ + sched_yield(); // queue empty, let other threads proceed } } @@ -170,11 +176,11 @@ void * producer_consumer_many(void *ctx) srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; - /* Wait for global start signal */ + // Wait for global start signal while (p->start == 0) sched_yield(); - /* Wait for a random time */ + // Wait for a random time for (size_t i = 0; i != nops; i += 1) nop(); @@ -190,20 +196,20 @@ void * producer_consumer_many(void *ctx) do { pushed += queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); if (pushed != p->batch_size) - sched_yield(); /* queue full, let other threads proceed */ + sched_yield(); // queue full, let other threads proceed } while (pushed < p->batch_size); int pulled = 0; do { pulled += queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); if (pulled != p->batch_size) - sched_yield(); /* queue empty, let other threads proceed */ + sched_yield(); // queue empty, let other threads proceed } while (pulled < p->batch_size); } return 0; } -#endif /* _POSIX_BARRIERS */ +#endif // _POSIX_BARRIERS Test(queue, single_threaded, .init = init_memory) { @@ -212,7 +218,7 @@ Test(queue, single_threaded, .init = init_memory) p.iter_count = 1 << 8; p.queue_size = 1 << 10; - p.start = 1; /* we start immeadiatly */ + p.start = 1; // we start immeadiatly ret = queue_init(&p.queue, p.queue_size, &memory::heap); cr_assert_eq(ret, 0, "Failed to create queue"); @@ -229,7 +235,8 @@ Test(queue, single_threaded, .init = init_memory) #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 ParameterizedTestParameters(queue, multi_threaded) { - static struct param params[] = { + static + struct param params[] = { { .iter_count = 1 << 12, .queue_size = 1 << 9, @@ -323,7 +330,7 @@ ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, .init = ret = pthread_barrier_destroy(&barrier); cr_assert_eq(ret, 0, "Failed to destroy barrier"); } -#endif /* _POSIX_BARRIERS */ +#endif // _POSIX_BARRIERS Test(queue, init_destroy, .init = init_memory) { @@ -331,8 +338,8 @@ Test(queue, init_destroy, .init = init_memory) struct CQueue q; ret = queue_init(&q, 1024, &memory::heap); - cr_assert_eq(ret, 0); /* Should succeed */ + cr_assert_eq(ret, 0); // Should succeed ret = queue_destroy(&q); - cr_assert_eq(ret, 0); /* Should succeed */ + cr_assert_eq(ret, 0); // Should succeed } diff --git a/tests/unit/queue_signalled.cpp b/tests/unit/queue_signalled.cpp index d88712113..2398f1409 100644 --- a/tests/unit/queue_signalled.cpp +++ b/tests/unit/queue_signalled.cpp @@ -1,9 +1,9 @@ -/** Unit tests for queue_signalled +/* Unit tests for queue_signalled * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -17,7 +17,8 @@ using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); #define NUM_ELEM 1000 @@ -27,7 +28,8 @@ struct param { bool polled; }; -static void * producer(void * ctx) +static +void * producer(void * ctx) { int ret; struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; @@ -35,15 +37,16 @@ static void * producer(void * ctx) for (intptr_t i = 0; i < NUM_ELEM; i++) { ret = queue_signalled_push(q, (void *) i); if (ret != 1) - return (void *) 1; /* Indicates an error to the parent thread */ + return (void *) 1; // Indicates an error to the parent thread - usleep(0.1e-3 * 1e6); /* 1 ms */ + usleep(0.1e-3 * 1e6); // 1 ms } return nullptr; } -static void * consumer(void * ctx) +static +void * consumer(void * ctx) { int ret; struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; @@ -53,11 +56,11 @@ static void * consumer(void * ctx) for (intptr_t i = 0; i < NUM_ELEM;) { ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data)); if (ret <= 0) - return (void *) 1; /* Indicates an error to the parent thread */ + return (void *) 1; // Indicates an error to the parent thread for (intptr_t j = 0; j < ret; j++, i++) { if ((intptr_t) data[j] != i) - return (void *) 2; /* Indicates an error to the parent thread */ + return (void *) 2; // Indicates an error to the parent thread } } @@ -84,14 +87,13 @@ again: ret = poll(&pfd, 1, -1); else if (ret == 0) goto again; - void *p; ret = queue_signalled_pull(q, &p); if (ret != 1) - return (void *) 1; /* Indicates an error to the parent thread */ + return (void *) 1; // Indicates an error to the parent thread if ((intptr_t) p != i) - return (void *) 2; /* Indicates an error to the parent thread */ + return (void *) 2; // Indicates an error to the parent thread } return nullptr; @@ -99,7 +101,8 @@ again: ret = poll(&pfd, 1, -1); ParameterizedTestParameters(queue_signalled, simple) { - static struct param params[] = { + static + struct param params[] = { { QueueSignalledMode::AUTO, 0, false }, { QueueSignalledMode::PTHREAD, 0, false }, { QueueSignalledMode::PTHREAD, 0, false }, diff --git a/tests/unit/signal.cpp b/tests/unit/signal.cpp index e8c6a90bb..d674bb2b5 100644 --- a/tests/unit/signal.cpp +++ b/tests/unit/signal.cpp @@ -1,9 +1,9 @@ -/** Unit tests for memory management +/* Unit tests for memory management * - * @author Steffen Vogel - * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC - * @license Apache 2.0 - *********************************************************************************/ + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -11,7 +11,8 @@ using namespace villas::node; -extern void init_memory(); +extern +void init_memory(); // cppcheck-suppress unknownMacro Test(signal_data, parse, .init = init_memory) { diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index bcef18645..fd638841f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,9 +1,8 @@ # CMakeLists. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 install( TARGETS ${TOOLS} diff --git a/tools/docker-dev.sh b/tools/docker-dev.sh index c494a61d1..465379763 100755 --- a/tools/docker-dev.sh +++ b/tools/docker-dev.sh @@ -2,10 +2,9 @@ # # Start a Docker based development environment # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 SCRIPT=$(realpath ${BASH_SOURCE[0]}) SCRIPTPATH=$(dirname $SCRIPT) diff --git a/tools/integration-tests.sh b/tools/integration-tests.sh index 00131f195..2f61eda39 100755 --- a/tools/integration-tests.sh +++ b/tools/integration-tests.sh @@ -2,10 +2,9 @@ # # Run integration tests # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 SCRIPT=$(realpath ${BASH_SOURCE[0]}) SCRIPTPATH=$(dirname $SCRIPT) diff --git a/tools/start-fpga.sh b/tools/start-fpga.sh index 813325381..0693b2bd0 100755 --- a/tools/start-fpga.sh +++ b/tools/start-fpga.sh @@ -1,4 +1,6 @@ #!/bin/bash +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 ARGS="$@" diff --git a/tools/tc-dump.sh b/tools/tc-dump.sh index 27ba2bcb9..f0e7ff9e4 100755 --- a/tools/tc-dump.sh +++ b/tools/tc-dump.sh @@ -2,10 +2,9 @@ # # Dump Linux traffic control state to screen. # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 IF=$1 diff --git a/tools/tc-netem.sh b/tools/tc-netem.sh index ea5040641..e6aefaced 100755 --- a/tools/tc-netem.sh +++ b/tools/tc-netem.sh @@ -4,10 +4,9 @@ # # Dependencies: iptables, ebtables and iproute2 # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e # Abort on error die() { echo "$1"; exit -1; } diff --git a/tools/tc-netem2.sh b/tools/tc-netem2.sh index 2251dd07f..6f5ebed14 100755 --- a/tools/tc-netem2.sh +++ b/tools/tc-netem2.sh @@ -4,10 +4,9 @@ # # Dependencies: iptables, ebtables and iproute2 # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 set -e # Abort on error die() { echo "$1"; exit -1; } @@ -30,7 +29,7 @@ DST_IF=p5p1.11 # Network emulation settings (see http://stuff.onse.fi/man?program=tc-netem§ion=8) NETEM="delay 1000000 20000 distribution normal duplicate 4 loss 20" -############################################################################################## +### # Do not change something below this line! MARK=$RANDOM diff --git a/tools/tune-realtime.sh b/tools/tune-realtime.sh index e22c44947..8f1819df3 100755 --- a/tools/tune-realtime.sh +++ b/tools/tune-realtime.sh @@ -1,4 +1,6 @@ #!/bin/bash +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 dnf -y --refresh install \ tuned-utils \ diff --git a/tools/villas b/tools/villas index 1e90d581e..e3f95be10 100755 --- a/tools/villas +++ b/tools/villas @@ -7,10 +7,9 @@ # Install by: # $ make install # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################### +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Get a list of all available tools SUBTOOLS="api node compare pipe hook conf2json convert graph relay signal test-config test-rtt zmq-keygen" diff --git a/tools/villas-api.sh b/tools/villas-api.sh index fdaccdf87..e634af21a 100755 --- a/tools/villas-api.sh +++ b/tools/villas-api.sh @@ -1,4 +1,6 @@ #!/bin/bash +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 # Check if all required commands exist diff --git a/tools/villas-helper.sh b/tools/villas-helper.sh index 3653385bf..7833eb64b 100755 --- a/tools/villas-helper.sh +++ b/tools/villas-helper.sh @@ -2,10 +2,9 @@ # # Some helper functions for our integration test suite # -# @author Steffen Vogel -# @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC -# @license Apache 2.0 -################################################################################## +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 function villas_format_supports_vectorize() { local FORMAT=$1 diff --git a/web/webrtc.html b/web/webrtc.html index 9bb75254e..e1df0cce4 100644 --- a/web/webrtc.html +++ b/web/webrtc.html @@ -4,9 +4,9 @@ diff --git a/webrtc_a.conf b/webrtc_a.conf new file mode 100644 index 000000000..403d38827 --- /dev/null +++ b/webrtc_a.conf @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +nodes = { + webrtc = { + type = "webrtc", + + # A unique session identifier which must be shared between two nodes + session = "KUCHEN" + peer = "a" + + # Address to the websocket signaling server + server = "http://172.23.157.207:8080" + + # wait_seconds = 5 + } + + signal = { + type = "signal" + signal = "sine" + values = 1 + rate = 0.2 + } +} + +paths = ( + { + in = "signal" + out = "webrtc" + }, + { + in = "webrtc" + hooks = ("print") + } +) diff --git a/webrtc_b.conf b/webrtc_b.conf new file mode 100644 index 000000000..897d75582 --- /dev/null +++ b/webrtc_b.conf @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +nodes = { + webrtc = { + type = "webrtc", + + # A unique session identifier which must be shared between two nodes + session = "KUCHEN" + peer = "b" + + # Address to the websocket signaling server + server = "http://172.23.157.207:8080" + + # wait_seconds = 5 + } + + signal = { + type = "signal" + signal = "sine" + values = 1 + rate = 0.2 + } +} + +paths = ( + { + in = "signal" + out = "webrtc" + }, + { + in = "webrtc" + hooks = ("print") + } +) From 68654f95f280932a62c160ea8d3efc0b8bc0e8db Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 4 Sep 2023 12:21:37 +0200 Subject: [PATCH 027/100] Add periods after file headers and fix email addresses Signed-off-by: Steffen Vogel --- clients/opal/models/send_receive/include/msg.h | 2 +- clients/opal/models/send_receive/include/msg_format.h | 2 +- clients/opal/models/send_receive/src/compat.c | 2 +- include/villas/api/universal.hpp | 2 +- include/villas/capabilities.hpp | 2 +- include/villas/formats/line.hpp | 2 +- include/villas/formats/msg_format.hpp | 2 +- include/villas/formats/opal_asyncip.hpp | 2 +- include/villas/formats/protobuf.hpp | 2 +- include/villas/formats/raw.hpp | 2 +- include/villas/formats/value.hpp | 2 +- include/villas/formats/villas_binary.hpp | 2 +- include/villas/formats/villas_human.hpp | 2 +- include/villas/hook.hpp | 2 +- include/villas/hook_list.hpp | 2 +- include/villas/kernel/if.hpp | 2 +- include/villas/kernel/nl-private.h | 2 +- include/villas/kernel/tc.hpp | 2 +- include/villas/kernel/tc_netem.hpp | 2 +- include/villas/node.h | 2 +- include/villas/node.hpp | 2 +- include/villas/node_compat.hpp | 2 +- include/villas/node_compat_type.hpp | 2 +- include/villas/node_direction.hpp | 2 +- include/villas/node_list.hpp | 2 +- include/villas/nodes/amqp.hpp | 2 +- include/villas/nodes/api.hpp | 2 +- include/villas/nodes/can.hpp | 2 +- include/villas/nodes/comedi.hpp | 2 +- include/villas/nodes/ethercat.hpp | 2 +- include/villas/nodes/ethercat_config.hpp | 2 +- include/villas/nodes/example.hpp | 2 +- include/villas/nodes/file.hpp | 2 +- include/villas/nodes/fpga.hpp | 2 +- include/villas/nodes/iec60870.hpp | 2 +- include/villas/nodes/iec61850.hpp | 2 +- include/villas/nodes/iec61850_goose.hpp | 2 +- include/villas/nodes/iec61850_sv.hpp | 2 +- include/villas/nodes/infiniband.hpp | 2 +- include/villas/nodes/kafka.hpp | 2 +- include/villas/nodes/loopback_internal.hpp | 2 +- include/villas/nodes/mqtt.hpp | 2 +- include/villas/nodes/nanomsg.hpp | 2 +- include/villas/nodes/ngsi.hpp | 2 +- include/villas/nodes/opal.hpp | 2 +- include/villas/nodes/redis.hpp | 2 +- include/villas/nodes/redis_helpers.hpp | 2 +- include/villas/nodes/rtp.hpp | 2 +- include/villas/nodes/socket.hpp | 2 +- include/villas/nodes/temper.hpp | 2 +- include/villas/nodes/webrtc.hpp | 2 +- include/villas/nodes/webrtc/peer_connection.hpp | 4 ++-- include/villas/nodes/webrtc/signaling_client.hpp | 4 ++-- include/villas/nodes/webrtc/signaling_message.hpp | 2 +- include/villas/nodes/websocket.hpp | 2 +- include/villas/nodes/zeromq.hpp | 2 +- include/villas/path.hpp | 2 +- include/villas/path_destination.hpp | 2 +- include/villas/path_list.hpp | 2 +- include/villas/path_source.hpp | 2 +- include/villas/queue.h | 2 +- include/villas/socket_addr.hpp | 2 +- include/villas/usb.hpp | 2 +- lib/api/requests/universal.cpp | 2 +- lib/api/universal.cpp | 2 +- lib/capabilities.cpp | 2 +- lib/formats/line.cpp | 2 +- lib/formats/opal_asyncip.cpp | 2 +- lib/formats/protobuf.cpp | 2 +- lib/formats/raw.cpp | 2 +- lib/hooks/shift_seq.cpp | 2 +- lib/kernel/tc_netem.cpp | 2 +- lib/node_capi.cpp | 2 +- lib/node_direction.cpp | 2 +- lib/node_list.cpp | 2 +- lib/nodes/amqp.cpp | 2 +- lib/nodes/api.cpp | 2 +- lib/nodes/can.cpp | 2 +- lib/nodes/comedi.cpp | 2 +- lib/nodes/ethercat.cpp | 2 +- lib/nodes/example.cpp | 2 +- lib/nodes/file.cpp | 2 +- lib/nodes/fpga.cpp | 2 +- lib/nodes/iec60870.cpp | 2 +- lib/nodes/iec61850.cpp | 2 +- lib/nodes/iec61850_goose.cpp | 2 +- lib/nodes/iec61850_sv.cpp | 2 +- lib/nodes/infiniband.cpp | 2 +- lib/nodes/kafka.cpp | 2 +- lib/nodes/mqtt.cpp | 2 +- lib/nodes/nanomsg.cpp | 2 +- lib/nodes/ngsi.cpp | 2 +- lib/nodes/opal.cpp | 2 +- lib/nodes/redis.cpp | 2 +- lib/nodes/rtp.cpp | 2 +- lib/nodes/socket.cpp | 2 +- lib/nodes/temper.cpp | 2 +- lib/nodes/webrtc.cpp | 4 ++-- lib/nodes/webrtc/peer_connection.cpp | 4 ++-- lib/nodes/webrtc/signaling_client.cpp | 4 ++-- lib/nodes/webrtc/signaling_message.cpp | 2 +- lib/nodes/websocket.cpp | 2 +- lib/nodes/zeromq.cpp | 2 +- lib/path_destination.cpp | 2 +- lib/path_list.cpp | 2 +- lib/path_source.cpp | 2 +- lib/queue.cpp | 2 +- lib/socket_addr.cpp | 2 +- lib/usb.cpp | 2 +- src/villas-convert.cpp | 2 +- src/villas-graph.cpp | 2 +- src/villas-zmq-keygen.cpp | 2 +- tests/unit/helpers.cpp | 2 +- tests/unit/helpers.hpp | 2 +- tests/unit/json.cpp | 2 +- tests/unit/main.cpp | 2 +- tests/unit/memory.cpp | 2 +- tests/unit/pool.cpp | 2 +- tests/unit/queue.cpp | 2 +- tests/unit/queue_signalled.cpp | 2 +- tests/unit/signal.cpp | 2 +- 121 files changed, 126 insertions(+), 126 deletions(-) diff --git a/clients/opal/models/send_receive/include/msg.h b/clients/opal/models/send_receive/include/msg.h index 05d23e231..10afe45fd 100644 --- a/clients/opal/models/send_receive/include/msg.h +++ b/clients/opal/models/send_receive/include/msg.h @@ -1,4 +1,4 @@ -/* Message related functions +/* Message related functions. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index e0263456a..5a380fcb4 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -1,4 +1,4 @@ -/* Message format +/* Message format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/clients/opal/models/send_receive/src/compat.c b/clients/opal/models/send_receive/src/compat.c index d0d8f5132..e68c73b26 100644 --- a/clients/opal/models/send_receive/src/compat.c +++ b/clients/opal/models/send_receive/src/compat.c @@ -1,4 +1,4 @@ -/* Compatibility code for GCC +/* Compatibility code for GCC. * * OPAL-RT's libSystem.a links against some Intel * diff --git a/include/villas/api/universal.hpp b/include/villas/api/universal.hpp index d27e5509d..20b497ec7 100644 --- a/include/villas/api/universal.hpp +++ b/include/villas/api/universal.hpp @@ -1,7 +1,7 @@ /* Universal Data-exchange API request. * - * Author: Steffen Vogel + * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ diff --git a/include/villas/capabilities.hpp b/include/villas/capabilities.hpp index f4ec72099..48c2f58a1 100644 --- a/include/villas/capabilities.hpp +++ b/include/villas/capabilities.hpp @@ -1,4 +1,4 @@ -/* Capabilities +/* Capabilities. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index 9f8004752..45fd1dcfe 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -1,4 +1,4 @@ -/* Line-based formats +/* Line-based formats. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 7f1982495..8e2601271 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -1,4 +1,4 @@ -/* Message format +/* Message format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/opal_asyncip.hpp b/include/villas/formats/opal_asyncip.hpp index 20cc5aa83..cae90984e 100644 --- a/include/villas/formats/opal_asyncip.hpp +++ b/include/villas/formats/opal_asyncip.hpp @@ -1,4 +1,4 @@ -/* A custom format for OPAL-RTs AsyncIP example +/* A custom format for OPAL-RTs AsyncIP example. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index be5fa5c06..549ed831d 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -1,4 +1,4 @@ -/* Protobuf IO format +/* Protobuf IO format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/raw.hpp b/include/villas/formats/raw.hpp index 49ae10b36..a917e696a 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -1,4 +1,4 @@ -/* RAW IO format +/* RAW IO format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 66db86098..087f4d792 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -1,4 +1,4 @@ -/* The VILLASframework sample format +/* The VILLASframework sample format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/villas_binary.hpp b/include/villas/formats/villas_binary.hpp index 916bba8d8..e72286532 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -1,4 +1,4 @@ -/* Message related functions +/* Message related functions. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index 257b14a8f..e7a3ef2f3 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -1,4 +1,4 @@ -/* The VILLASframework sample format +/* The VILLASframework sample format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 94143f9eb..7ef81e269 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -1,4 +1,4 @@ -/* Hook functions +/* 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 diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index f9964158b..597b57ae1 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -1,4 +1,4 @@ -/* Hook list functions +/* Hook list functions. * * This file includes some examples. * diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index 3543d6b2d..1cc45502b 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -1,4 +1,4 @@ -/* Interface related functions +/* Interface related functions. * * These functions are used to manage a network interface. * Most of them make use of Linux-specific APIs. diff --git a/include/villas/kernel/nl-private.h b/include/villas/kernel/nl-private.h index c708c4ba9..b7d6ff799 100644 --- a/include/villas/kernel/nl-private.h +++ b/include/villas/kernel/nl-private.h @@ -1,4 +1,4 @@ -/* Netlink Types (Private) +/* Netlink Types (Private). * * Copied from: https://github.com/tgraf/libnl/blob/master/include/netlink-private/types.h * diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index a7f820356..540ba90e1 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -1,4 +1,4 @@ -/* Setup interface queuing desciplines for network emulation +/* Setup interface queuing desciplines for network emulation. * * We use the firewall mark to apply individual netem qdiscs * per node. Every node uses an own BSD socket. diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index 5fe4b9085..4fe586759 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -1,4 +1,4 @@ -/* Setup network emulation +/* Setup network emulation. * * We use the firewall mark to apply individual netem qdiscs * per node. Every node uses an own BSD socket. diff --git a/include/villas/node.h b/include/villas/node.h index 85572f3d4..f0f504eb4 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -1,4 +1,4 @@ -/* Node C-API +/* Node C-API. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/node.hpp b/include/villas/node.hpp index e601fa462..666210516 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -1,4 +1,4 @@ -/* Nodes +/* Nodes. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index 3b9c5dd8b..42427a8c3 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -1,4 +1,4 @@ -/* Node compatability layer for C++ +/* Node compatability layer for C++. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index 328626b57..bfb9ec120 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -1,4 +1,4 @@ -/* Nodes +/* Nodes. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp index c02506887..503865f96 100644 --- a/include/villas/node_direction.hpp +++ b/include/villas/node_direction.hpp @@ -1,4 +1,4 @@ -/* Node direction +/* Node direction. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index e954ff339..8e85c7c9c 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -1,4 +1,4 @@ -/* Node list +/* Node list. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index f710bfbcd..636ea4e3b 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -1,4 +1,4 @@ -/* Node type: amqp +/* Node type: amqp. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/api.hpp b/include/villas/nodes/api.hpp index 4185d955c..361a123a1 100644 --- a/include/villas/nodes/api.hpp +++ b/include/villas/nodes/api.hpp @@ -1,4 +1,4 @@ -/* Node type: Universal Data-exchange API (v2) +/* Node type: Universal Data-exchange API (v2). * * @see https://github.com/ERIGrid2/JRA-3.1-api * Author: Steffen Vogel diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index a8667d17e..acb5ce59a 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -1,4 +1,4 @@ -/* Node-type: CAN bus +/* Node-type: CAN bus. * * Author: Niklas Eiling * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index cd291e53c..d59c7cb9f 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -1,4 +1,4 @@ -/* Node type: comedi +/* Node type: comedi. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 7d47e9650..35cf7cbf1 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -1,4 +1,4 @@ -/* Node type: ethercat +/* Node type: ethercat. * * Author: Niklas Eiling * Author: Steffen Vogel diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index c72687cdc..148a8788e 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -1,4 +1,4 @@ -/* Configuration for Ethercat Node-type +/* Configuration for Ethercat Node-type. * * Author: Niklas Eiling * Author: Steffen Vogel diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index 1e4daf4a6..86813e20b 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -1,4 +1,4 @@ -/* An example get started with new implementations of new node-types +/* An example get started with new implementations of new node-types. * * This example does not do any particulary useful. * It is just a skeleton to get you started with new node-types. diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index a5ebad8c2..5157f82ba 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -1,4 +1,4 @@ -/* Node type: File +/* Node type: File. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 2c035716f..4f7065134 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -1,4 +1,4 @@ -/* Communicate with VILLASfpga Xilinx FPGA boards +/* Communicate with VILLASfpga Xilinx FPGA boards. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/iec60870.hpp b/include/villas/nodes/iec60870.hpp index 45fc4f879..4abeebbb0 100644 --- a/include/villas/nodes/iec60870.hpp +++ b/include/villas/nodes/iec60870.hpp @@ -1,4 +1,4 @@ -/* Node type: IEC60870-5-104 +/* Node type: IEC60870-5-104. * * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index c2182970b..2807206c9 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -1,4 +1,4 @@ -/* Some helpers to libiec61850 +/* Some helpers to libiec61850. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/iec61850_goose.hpp b/include/villas/nodes/iec61850_goose.hpp index 7e2b20bc3..4d2826d37 100644 --- a/include/villas/nodes/iec61850_goose.hpp +++ b/include/villas/nodes/iec61850_goose.hpp @@ -1,4 +1,4 @@ -/* Node type: IEC 61850 - GOOSE +/* Node type: IEC 61850 - GOOSE. * * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index 26b4e85e6..f46612834 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -1,4 +1,4 @@ -/* Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index 1b2651433..f733ffd25 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -1,4 +1,4 @@ -/* Node type: infiniband +/* Node type: infiniband. * * Author: Dennis Potter * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/kafka.hpp b/include/villas/nodes/kafka.hpp index e00149324..d4438d824 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -1,4 +1,4 @@ -/* Node type: kafka +/* Node type: kafka. * * Author: Juan Pablo Noreña * SPDX-FileCopyrightText: 2021 Universidad Nacional de Colombia diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index 7dcfc30a8..8317164a2 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -1,4 +1,4 @@ -/* Node type: internal loopback +/* Node type: internal loopback. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 7c852b163..30f421a96 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -1,4 +1,4 @@ -/* Node type: mqtt +/* Node type: mqtt. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index 05c786618..e45c1ec8a 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -1,4 +1,4 @@ -/* Node type: nanomsg +/* Node type: nanomsg. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/ngsi.hpp b/include/villas/nodes/ngsi.hpp index ff81e095d..ebcd6dbfd 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -1,4 +1,4 @@ -/* Node type: OMA Next Generation Services Interface 10 (NGSI) (FIWARE context broker) +/* Node type: OMA Next Generation Services Interface 10 (NGSI) (FIWARE context broker). * * This file implements the NGSI context interface. NGSI is RESTful HTTP is specified by * the Open Mobile Alliance (OMA). diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index 038f8767e..17117b4d4 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -1,4 +1,4 @@ -/* Node type: OPAL (libOpalAsync API) +/* Node type: OPAL (libOpalAsync API). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index 0ecb4bc8f..4a56002c2 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -1,4 +1,4 @@ -/* Redis node-type +/* Redis node-type. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index 3de183da5..e8fe617b9 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -1,4 +1,4 @@ -/* Redis node-type helpers +/* Redis node-type helpers. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index 2005c6e0b..2ef6b736c 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -1,4 +1,4 @@ -/* Node type: rtp +/* Node type: rtp. * * Author: Steffen Vogel * Author: Marvin Klimke diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index 31284b387..cd14d1f51 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -1,4 +1,4 @@ -/* The socket node-type for Layer 2, 3, 4 BSD-style sockets +/* The socket node-type for Layer 2, 3, 4 BSD-style sockets. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index 4089d7aa7..f3b144127 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -1,4 +1,4 @@ -/* An temper get started with new implementations of new node-types +/* An temper get started with new implementations of new node-types. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp index 89d359ce6..c0f327c33 100644 --- a/include/villas/nodes/webrtc.hpp +++ b/include/villas/nodes/webrtc.hpp @@ -1,6 +1,6 @@ /* Node-type webrtc. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index 9565b6eba..cb122bf30 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -1,6 +1,6 @@ -/* WebRTC peer connection +/* WebRTC peer connection. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/include/villas/nodes/webrtc/signaling_client.hpp b/include/villas/nodes/webrtc/signaling_client.hpp index e72bfc714..5d6a63e9d 100644 --- a/include/villas/nodes/webrtc/signaling_client.hpp +++ b/include/villas/nodes/webrtc/signaling_client.hpp @@ -1,6 +1,6 @@ -/* WebRTC signaling client +/* WebRTC signaling client. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/include/villas/nodes/webrtc/signaling_message.hpp b/include/villas/nodes/webrtc/signaling_message.hpp index f07b350e8..2a9039693 100644 --- a/include/villas/nodes/webrtc/signaling_message.hpp +++ b/include/villas/nodes/webrtc/signaling_message.hpp @@ -1,6 +1,6 @@ /* WebRTC signaling messages. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index 581ef2b21..c8f72ef99 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -1,4 +1,4 @@ -/* Node type: WebSockets +/* Node type: WebSockets. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/nodes/zeromq.hpp b/include/villas/nodes/zeromq.hpp index af3cb5d7e..60d7d985a 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -1,4 +1,4 @@ -/* Node type: ZeroMQ +/* Node type: ZeroMQ. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/path.hpp b/include/villas/path.hpp index a33c15042..2aaa3c88d 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -1,4 +1,4 @@ -/* Message paths +/* Message paths. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/path_destination.hpp b/include/villas/path_destination.hpp index 90117fe2c..8ea9e908d 100644 --- a/include/villas/path_destination.hpp +++ b/include/villas/path_destination.hpp @@ -1,4 +1,4 @@ -/* Path destination +/* Path destination. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 53198bfc6..8ad9e3e39 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -1,4 +1,4 @@ -/* Node list +/* Node list. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp index 28bec72fb..f5412a17b 100644 --- a/include/villas/path_source.hpp +++ b/include/villas/path_source.hpp @@ -1,4 +1,4 @@ -/* Message source +/* Message source. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/queue.h b/include/villas/queue.h index e4dc8d728..7717c82b0 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -4,7 +4,7 @@ * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2021 Steffen Vogel + * SPDX-FileCopyrightText: 2014-2021 Steffen Vogel * SPDX-License-Identifier: BSD-2-Clause * * All rights reserved. diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index adf0c1b51..a7f43b99a 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -1,4 +1,4 @@ -/* Node type: socket +/* Node type: socket. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/include/villas/usb.hpp b/include/villas/usb.hpp index 12c280896..67be5f560 100644 --- a/include/villas/usb.hpp +++ b/include/villas/usb.hpp @@ -1,4 +1,4 @@ -/* Helpers for USB node-types +/* Helpers for USB node-types. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/api/requests/universal.cpp b/lib/api/requests/universal.cpp index 481c54b7c..9ae25c389 100644 --- a/lib/api/requests/universal.cpp +++ b/lib/api/requests/universal.cpp @@ -1,4 +1,4 @@ -/* Universal Data-exchange API request +/* Universal Data-exchange API request. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/api/universal.cpp b/lib/api/universal.cpp index ed2140125..1788f09b2 100644 --- a/lib/api/universal.cpp +++ b/lib/api/universal.cpp @@ -1,6 +1,6 @@ /* API Response. * - * Author: Steffen Vogel + * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ diff --git a/lib/capabilities.cpp b/lib/capabilities.cpp index 0d19977d6..2c8f9cbb8 100644 --- a/lib/capabilities.cpp +++ b/lib/capabilities.cpp @@ -1,4 +1,4 @@ -/* Capabilities +/* Capabilities. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/formats/line.cpp b/lib/formats/line.cpp index 32a698aa3..e5ed5ad59 100644 --- a/lib/formats/line.cpp +++ b/lib/formats/line.cpp @@ -1,4 +1,4 @@ -/* Line-based formats +/* Line-based formats. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/formats/opal_asyncip.cpp b/lib/formats/opal_asyncip.cpp index 3e72fd547..e19bc1c96 100644 --- a/lib/formats/opal_asyncip.cpp +++ b/lib/formats/opal_asyncip.cpp @@ -1,4 +1,4 @@ -/* A custom format for OPAL-RTs AsyncIP example +/* A custom format for OPAL-RTs AsyncIP example. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/formats/protobuf.cpp b/lib/formats/protobuf.cpp index 82699d1c9..41828733c 100644 --- a/lib/formats/protobuf.cpp +++ b/lib/formats/protobuf.cpp @@ -1,4 +1,4 @@ -/* Protobuf IO format +/* Protobuf IO format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index dbec95da0..34c4f59e2 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -1,4 +1,4 @@ -/* RAW IO format +/* RAW IO format. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/hooks/shift_seq.cpp b/lib/hooks/shift_seq.cpp index d37c7a820..59b1fa3e9 100644 --- a/lib/hooks/shift_seq.cpp +++ b/lib/hooks/shift_seq.cpp @@ -1,4 +1,4 @@ -/* Shift sequence number of samples +/* Shift sequence number of samples. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/kernel/tc_netem.cpp b/lib/kernel/tc_netem.cpp index 2b4acb38a..b62e2d667 100644 --- a/lib/kernel/tc_netem.cpp +++ b/lib/kernel/tc_netem.cpp @@ -1,4 +1,4 @@ -/* Traffic control (tc): setup network emulation qdisc +/* Traffic control (tc): setup network emulation qdisc. * * VILLASnode uses these functions to setup the network emulation feature. * diff --git a/lib/node_capi.cpp b/lib/node_capi.cpp index e1241858d..a0fcea568 100644 --- a/lib/node_capi.cpp +++ b/lib/node_capi.cpp @@ -1,4 +1,4 @@ -/* Node C-API +/* Node C-API. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index 16d3d174d..a3c74a887 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -1,4 +1,4 @@ -/* Node direction +/* Node direction. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/node_list.cpp b/lib/node_list.cpp index bbd89bed9..10b40fbc1 100644 --- a/lib/node_list.cpp +++ b/lib/node_list.cpp @@ -1,4 +1,4 @@ -/* Node list +/* Node list. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/amqp.cpp b/lib/nodes/amqp.cpp index 61f6ceb6c..fc3cb1d04 100644 --- a/lib/nodes/amqp.cpp +++ b/lib/nodes/amqp.cpp @@ -1,4 +1,4 @@ -/* Node type: nanomsg +/* Node type: nanomsg. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/api.cpp b/lib/nodes/api.cpp index dfcad29ef..68c3b48cb 100644 --- a/lib/nodes/api.cpp +++ b/lib/nodes/api.cpp @@ -1,4 +1,4 @@ -/* Node type: Universal Data-exchange API (v2) +/* Node type: Universal Data-exchange API (v2). * * @see https://github.com/ERIGrid2/JRA-3.1-api * Author: Steffen Vogel diff --git a/lib/nodes/can.cpp b/lib/nodes/can.cpp index 6b1369fcb..2b313f04f 100644 --- a/lib/nodes/can.cpp +++ b/lib/nodes/can.cpp @@ -1,4 +1,4 @@ -/* Node-type: CAN bus +/* Node-type: CAN bus. * * Author: Niklas Eiling * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index 9b40cf4eb..249cfb597 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -1,4 +1,4 @@ -/* Node type: comedi +/* Node type: comedi. * * Author: Steffen Vogel * Author: Daniel Krebs diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index 2bd7c5a4e..65d39587a 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -1,4 +1,4 @@ -/* Node type: Ethercat +/* Node type: Ethercat. * * Author: Niklas Eiling * Author: Steffen Vogel diff --git a/lib/nodes/example.cpp b/lib/nodes/example.cpp index f21db14a2..b71cc0715 100644 --- a/lib/nodes/example.cpp +++ b/lib/nodes/example.cpp @@ -1,4 +1,4 @@ -/* An example get started with new implementations of new node-types +/* An example get started with new implementations of new node-types. * * This example does not do any particulary useful. * It is just a skeleton to get you started with new node-types. diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index d3fbfb22c..6dc986ecd 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -1,4 +1,4 @@ -/* Node type: File +/* Node type: File. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index 76e44d941..461e97e09 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -1,4 +1,4 @@ -/* Communicate with VILLASfpga Xilinx FPGA boards +/* Communicate with VILLASfpga Xilinx FPGA boards. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/iec60870.cpp b/lib/nodes/iec60870.cpp index 437f41f80..e3b213b2a 100644 --- a/lib/nodes/iec60870.cpp +++ b/lib/nodes/iec60870.cpp @@ -1,4 +1,4 @@ -/* Node type: IEC60870-5-104 +/* Node type: IEC60870-5-104. * * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/iec61850.cpp b/lib/nodes/iec61850.cpp index 33ffedc9f..33771ad48 100644 --- a/lib/nodes/iec61850.cpp +++ b/lib/nodes/iec61850.cpp @@ -1,4 +1,4 @@ -/* Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/iec61850_goose.cpp b/lib/nodes/iec61850_goose.cpp index 8a76c7fda..0bed4b5da 100644 --- a/lib/nodes/iec61850_goose.cpp +++ b/lib/nodes/iec61850_goose.cpp @@ -1,4 +1,4 @@ -/* Node type: IEC 61850 - GOOSE +/* Node type: IEC 61850 - GOOSE. * * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/iec61850_sv.cpp b/lib/nodes/iec61850_sv.cpp index 6db86e0fb..6b531aef4 100644 --- a/lib/nodes/iec61850_sv.cpp +++ b/lib/nodes/iec61850_sv.cpp @@ -1,4 +1,4 @@ -/* Node type: IEC 61850-9-2 (Sampled Values) +/* Node type: IEC 61850-9-2 (Sampled Values). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index e91c0357f..c465dc111 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -1,4 +1,4 @@ -/* Node type: infiniband +/* Node type: infiniband. * * Author: Dennis Potter * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/kafka.cpp b/lib/nodes/kafka.cpp index 5b3f81fcf..710de5fec 100644 --- a/lib/nodes/kafka.cpp +++ b/lib/nodes/kafka.cpp @@ -1,4 +1,4 @@ -/* Node type: kafka +/* Node type: kafka. * * Author: Juan Pablo Noreña * SPDX-FileCopyrightText: 2021 Universidad Nacional de Colombia diff --git a/lib/nodes/mqtt.cpp b/lib/nodes/mqtt.cpp index 3444a9e45..a20e815bf 100644 --- a/lib/nodes/mqtt.cpp +++ b/lib/nodes/mqtt.cpp @@ -1,4 +1,4 @@ -/* Node type: mqtt +/* Node type: mqtt. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/nanomsg.cpp b/lib/nodes/nanomsg.cpp index 7abe4a3d6..61acc74a5 100644 --- a/lib/nodes/nanomsg.cpp +++ b/lib/nodes/nanomsg.cpp @@ -1,4 +1,4 @@ -/* Node type: nanomsg +/* Node type: nanomsg. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/ngsi.cpp b/lib/nodes/ngsi.cpp index 0353c286e..5088ab86f 100644 --- a/lib/nodes/ngsi.cpp +++ b/lib/nodes/ngsi.cpp @@ -1,4 +1,4 @@ -/* Node type: OMA Next Generation Services Interface 9 (NGSI) (FIWARE context broker) +/* Node type: OMA Next Generation Services Interface 9 (NGSI) (FIWARE context broker). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 94d90ea6e..9b35895fb 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -1,4 +1,4 @@ -/* Node type: OPAL (AsyncApi) +/* Node type: OPAL (AsyncApi). * * This file implements the opal subtype for nodes. * diff --git a/lib/nodes/redis.cpp b/lib/nodes/redis.cpp index 600f01e25..2a07d1dfd 100644 --- a/lib/nodes/redis.cpp +++ b/lib/nodes/redis.cpp @@ -1,4 +1,4 @@ -/* Redis node-type +/* Redis node-type. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index ff8cf1d94..ad64c4f07 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -1,4 +1,4 @@ -/* Node type: Real-time Protocol (RTP) +/* Node type: Real-time Protocol (RTP). * * Author: Steffen Vogel * Author: Marvin Klimke diff --git a/lib/nodes/socket.cpp b/lib/nodes/socket.cpp index 2d880fa37..e6c1b9564 100644 --- a/lib/nodes/socket.cpp +++ b/lib/nodes/socket.cpp @@ -1,4 +1,4 @@ -/* The socket node-type for Layer 2, 3, 4 BSD-style sockets +/* The socket node-type for Layer 2, 3, 4 BSD-style sockets. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/temper.cpp b/lib/nodes/temper.cpp index 20e61316f..fcf890d0c 100644 --- a/lib/nodes/temper.cpp +++ b/lib/nodes/temper.cpp @@ -1,4 +1,4 @@ -/* PCSensor / TEMPer node-type +/* PCSensor / TEMPer node-type. * * The driver will work with some TEMPer usb devices from RDing (www.PCsensor.com). * diff --git a/lib/nodes/webrtc.cpp b/lib/nodes/webrtc.cpp index 13b61cf74..872f365d5 100644 --- a/lib/nodes/webrtc.cpp +++ b/lib/nodes/webrtc.cpp @@ -1,6 +1,6 @@ -/* Node-type: webrtc +/* Node-type: webrtc. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index 959a1138d..944de99d8 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -1,6 +1,6 @@ -/* WebRTC peer connection +/* WebRTC peer connection. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/lib/nodes/webrtc/signaling_client.cpp b/lib/nodes/webrtc/signaling_client.cpp index b132d5eab..aa3ab8fd9 100644 --- a/lib/nodes/webrtc/signaling_client.cpp +++ b/lib/nodes/webrtc/signaling_client.cpp @@ -1,6 +1,6 @@ -/* WebRTC signaling client +/* WebRTC signaling client. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/lib/nodes/webrtc/signaling_message.cpp b/lib/nodes/webrtc/signaling_message.cpp index 99a5518d9..99e61660a 100644 --- a/lib/nodes/webrtc/signaling_message.cpp +++ b/lib/nodes/webrtc/signaling_message.cpp @@ -1,6 +1,6 @@ /* WebRTC signaling messages. * - * Author: Steffen Vogel + * Author: Steffen Vogel * Author: Philipp Jungkamp * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index 09f4d1fae..f4cc122af 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -1,4 +1,4 @@ -/* Node type: Websockets (libwebsockets) +/* Node type: Websockets (libwebsockets). * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 8e72ff4dc..4d98e199b 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -1,4 +1,4 @@ -/* Node type: ZeroMQ +/* Node type: ZeroMQ. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/path_destination.cpp b/lib/path_destination.cpp index 79685a4ee..08535ad9c 100644 --- a/lib/path_destination.cpp +++ b/lib/path_destination.cpp @@ -1,4 +1,4 @@ -/* Path destination +/* Path destination. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/path_list.cpp b/lib/path_list.cpp index 38868f2b5..b2b8214da 100644 --- a/lib/path_list.cpp +++ b/lib/path_list.cpp @@ -1,4 +1,4 @@ -/* Path list +/* Path list. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/path_source.cpp b/lib/path_source.cpp index e608ad036..8e6922648 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -1,4 +1,4 @@ -/* Path source +/* Path source. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/queue.cpp b/lib/queue.cpp index 27d79b83a..c37f495cd 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -4,7 +4,7 @@ * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2017 Steffen Vogel + * SPDX-FileCopyrightText: 2017 Steffen Vogel * SPDX-License-Identifier: BSD-2-Clause * * All rights reserved. diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index b5aad4bd4..2fb720ff5 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -1,4 +1,4 @@ -/* Various functions to work with socket addresses +/* Various functions to work with socket addresses. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/usb.cpp b/lib/usb.cpp index d00fb463f..ed3cd3499 100644 --- a/lib/usb.cpp +++ b/lib/usb.cpp @@ -1,4 +1,4 @@ -/* Helpers for USB node-types +/* Helpers for USB node-types. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index b1005cacf..14d248c95 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -1,4 +1,4 @@ -/* Convert between samples IO formats +/* Convert between samples IO formats. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index 15f6cce4a..cc368c6cd 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -1,4 +1,4 @@ -/* Create a graph representation of the VILLASnode configuration file +/* Create a graph representation of the VILLASnode configuration file. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/src/villas-zmq-keygen.cpp b/src/villas-zmq-keygen.cpp index 208b51e30..c666a6c33 100644 --- a/src/villas-zmq-keygen.cpp +++ b/src/villas-zmq-keygen.cpp @@ -1,4 +1,4 @@ -/* Key generator for libzmq +/* Key generator for libzmq. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/helpers.cpp b/tests/unit/helpers.cpp index 8b269d036..a5df1d0d1 100644 --- a/tests/unit/helpers.cpp +++ b/tests/unit/helpers.cpp @@ -1,4 +1,4 @@ -/* Unit test helpers +/* Unit test helpers. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/helpers.hpp b/tests/unit/helpers.hpp index 496cada39..da2079c99 100644 --- a/tests/unit/helpers.hpp +++ b/tests/unit/helpers.hpp @@ -1,4 +1,4 @@ -/* Unit test helpers +/* Unit test helpers. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/json.cpp b/tests/unit/json.cpp index 659097368..5314948f5 100644 --- a/tests/unit/json.cpp +++ b/tests/unit/json.cpp @@ -1,4 +1,4 @@ -/* Unit tests for libjansson helpers +/* Unit tests for libjansson helpers. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index faf94c471..299241578 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -1,4 +1,4 @@ -/* Custom main() for Criterion +/* Custom main() for Criterion. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/memory.cpp b/tests/unit/memory.cpp index f6fa9dd32..8731d231a 100644 --- a/tests/unit/memory.cpp +++ b/tests/unit/memory.cpp @@ -1,4 +1,4 @@ -/* Unit tests for memory management +/* Unit tests for memory management. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/pool.cpp b/tests/unit/pool.cpp index 446b5eca5..87b7b43e1 100644 --- a/tests/unit/pool.cpp +++ b/tests/unit/pool.cpp @@ -1,4 +1,4 @@ -/* Unit tests for memory pool +/* Unit tests for memory pool. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index 1253444cc..9c5341ac5 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -1,4 +1,4 @@ -/* Unit tests for queue +/* Unit tests for queue. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/queue_signalled.cpp b/tests/unit/queue_signalled.cpp index 2398f1409..04b265328 100644 --- a/tests/unit/queue_signalled.cpp +++ b/tests/unit/queue_signalled.cpp @@ -1,4 +1,4 @@ -/* Unit tests for queue_signalled +/* Unit tests for queue_signalled. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/tests/unit/signal.cpp b/tests/unit/signal.cpp index d674bb2b5..e7f5438a9 100644 --- a/tests/unit/signal.cpp +++ b/tests/unit/signal.cpp @@ -1,4 +1,4 @@ -/* Unit tests for memory management +/* Unit tests for memory management. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University From b5f554d82856c9456030fd812d7ebb9bbf1e37f5 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 4 Sep 2023 18:14:33 +0200 Subject: [PATCH 028/100] Ignore too long lines in flake8 linter Signed-off-by: Steffen Vogel --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7bdfc7bbc..457df0b77 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -91,7 +91,7 @@ build:source: test:flake8: stage: test script: - - flake8 python/ + - flake8 --ignore=E501 python/ image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} tags: - docker From bbb3cfe240f46fc200216cfbd56befcb9ec6cd29 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 4 Sep 2023 18:16:15 +0200 Subject: [PATCH 029/100] Remove more Doxygen-style comments Signed-off-by: Steffen Vogel --- clients/opal/models/send_receive/include/msg_format.h | 7 ++----- include/villas/formats/msg_format.hpp | 7 ++----- include/villas/node/memory.hpp | 2 +- include/villas/nodes/ethercat_config.hpp | 2 +- include/villas/queue.h | 2 +- include/villas/socket_addr.hpp | 2 +- lib/formats/raw.cpp | 2 +- lib/formats/villas_binary.cpp | 4 ++-- lib/hooks/pmu_ipdft.cpp | 2 +- lib/nodes/comedi.cpp | 6 +++--- lib/nodes/ethercat.cpp | 4 ++-- lib/nodes/exec.cpp | 2 +- lib/nodes/file.cpp | 2 +- lib/nodes/opal.cpp | 4 ++-- lib/nodes/rtp.cpp | 2 +- lib/nodes/shmem.cpp | 2 +- lib/nodes/uldaq.cpp | 2 +- lib/nodes/websocket.cpp | 2 +- lib/nodes/zeromq.cpp | 2 +- lib/socket_addr.cpp | 2 +- tests/unit/format.cpp | 2 +- 21 files changed, 28 insertions(+), 34 deletions(-) diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index 5a380fcb4..95b7e769f 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -12,7 +12,7 @@ // The current version number for the message format #define MSG_VERSION 2 -// @todo Implement more message types +// TODO: Implement more message types #define MSG_TYPE_DATA 0 // Message contains float values #define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case #define MSG_TYPE_STOP 2 // Message marks the end of a simulation case @@ -41,10 +41,7 @@ .tv_nsec = (msg)->ts.nsec \ } -/* This message format is used by all clients - * - * @diafile msg_format.dia - */ +// This message format is used by all clients struct msg { #if BYTE_ORDER == BIG_ENDIAN diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 8e2601271..7512c3e24 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -12,7 +12,7 @@ // The current version number for the message format #define MSG_VERSION 2 -// @todo Implement more message types +// TODO: Implement more message types #define MSG_TYPE_DATA 0 // Message contains float / integer values #define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case #define MSG_TYPE_STOP 2 // Message marks the end of a simulation case @@ -34,10 +34,7 @@ namespace villas { namespace node { -/* This message format is used by all clients - * - * @diafile msg_format.dia - */ +// This message format is used by all clients struct Message { #if BYTE_ORDER == BIG_ENDIAN diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index fe9230584..82431c808 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -30,7 +30,7 @@ struct Block { bool used; }; -// @todo Unused for now +// TODO: Unused for now struct Allocation { struct Type *type; diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index 148a8788e..5154574d2 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -25,7 +25,7 @@ #define ETHERCAT_PID_EL3008 0x0bc03052 #define ETHERCAT_PID_FC1100 0x044c0c62 -// @todo Make PDO entry tables configurable +// TODO: Make PDO entry tables configurable /* Master 0, Slave 3, "EL4038" * Vendor ID: 0x00000002 diff --git a/include/villas/queue.h b/include/villas/queue.h index 7717c82b0..4b35d5ac0 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -70,7 +70,7 @@ struct CQueue { std::atomic head; // Queue head pointer - cacheline_pad_t _pad3; // @todo Why needed? + cacheline_pad_t _pad3; // TODO: Why needed? }; // Initialize MPMC queue diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index a7f43b99a..07e9de46d 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -57,7 +57,7 @@ char * socket_print_addr(struct sockaddr *saddr); * A IPv4 address has the follwing format: [hostname/ip]:[port/protocol] * A link layer address has the following format: [mac]%[interface]:[ethertype] * - * @todo Add support for autodetection of address type + * TODO: Add support for autodetection of address type * * @param str A string specifiying the socket address. See description for allowed formats. * @param sa A pointer to the resolved address diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index 34c4f59e2..e429c01d3 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -13,7 +13,7 @@ typedef float flt32_t; typedef double flt64_t; -typedef long double flt128_t; // @todo check +typedef long double flt128_t; // TODO: check using namespace villas; using namespace villas::node; diff --git a/lib/formats/villas_binary.cpp b/lib/formats/villas_binary.cpp index f9e1cad5e..87e233704 100644 --- a/lib/formats/villas_binary.cpp +++ b/lib/formats/villas_binary.cpp @@ -36,7 +36,7 @@ int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, const stru return ret; if (web) { - // @todo convert to little endian + // TODO: convert to little endian } else msg_hton(msg); @@ -81,7 +81,7 @@ int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struc return -3; // Invalid msg receive if (web) { - // @todo convert from little endian + // TODO: convert from little endian } else msg_ntoh(msg); diff --git a/lib/hooks/pmu_ipdft.cpp b/lib/hooks/pmu_ipdft.cpp index fd5275c4c..3faee9649 100644 --- a/lib/hooks/pmu_ipdft.cpp +++ b/lib/hooks/pmu_ipdft.cpp @@ -106,7 +106,7 @@ public: if (maxBin == 0 || maxBin == (frequencyCount - 1)) { logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); - //@todo add handling to not forward this phasor!! + //TODO: add handling to not forward this phasor!! } else { const double startFrequency = nominalFreq - estimationRange; const double frequencyResolution = (double)sampleRate / windowSize; diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index 249cfb597..5932a4d17 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -315,7 +315,7 @@ int comedi_start_out(NodeCompat *n) d->last_debug = time_now(); // Allocate buffer for one complete VILLAS sample - // @todo maybe increase buffer size according to c->vectorize + // TODO: maybe increase buffer size according to c->vectorize const size_t local_buffer_size = d->sample_size * d->chanlist_len; d->buffer = new char[local_buffer_size]; d->bufptr = d->buffer; @@ -448,7 +448,7 @@ int villas::node::comedi_start(NodeCompat *n) throw RuntimeError("Failed to open device: {}", comedi_strerror(comedi_errno())); // Enable non-blocking syscalls - // @todo verify if this works with both input and output, so comment out + // TODO: verify if this works with both input and output, so comment out //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); @@ -595,7 +595,7 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig const size_t bytes_left = bytes_available - bytes_consumed; if (bytes_left > 0) { // Move leftover bytes to the beginning of buffer - // @todo optimize? + // TODO: optimize? memmove(c->buf, c->bufptr, bytes_left); } diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index 65d39587a..5c8df874d 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -294,7 +294,7 @@ int villas::node::ethercat_start(NodeCompat *n) if (ret) throw RuntimeError("PDO entry registration failed!"); - // @todo Check that master is not already active... + // TODO: Check that master is not already active... ret = ecrt_master_activate(master); if (ret) return -1; @@ -420,7 +420,7 @@ int villas::node::ethercat_destroy(NodeCompat *n) w->task.~Task(); - // @todo Destroy domain? + // TODO: Destroy domain? return 0; } diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index ef4269688..3bfa36007 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -156,7 +156,7 @@ int ExecNode::stop() logger->debug("Waiting for sub-process with pid={} to terminate", proc->getPid()); proc->close(); - // @todo Check exit code of subprocess? + // TODO: Check exit code of subprocess? return 0; } diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index 6dc986ecd..5ae0ea762 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -431,7 +431,7 @@ int villas::node::file_poll_fds(NodeCompat *n, int fds[]) return 1; } - return -1; // @todo not supported yet + return -1; // TODO: not supported yet } int villas::node::file_init(NodeCompat *n) diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 9b35895fb..4525ff368 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -221,7 +221,7 @@ char * villas::node::opal_print(NodeCompat *n) { auto *o = n->getData(); - // @todo Print send_params, recv_params + // TODO: Print send_params, recv_params return strf("sendID=%u, recvID=%u, reply=%u", o->sendID, o->recvID, o->reply); @@ -275,7 +275,7 @@ int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigne if ((state == STATE_RESET) || (state == STATE_STOP)) throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - return -1; // @todo correct return value + return -1; // TODO: correct return value } } while (id != o->sendID); diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index ad64c4f07..f21d19ef4 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -209,7 +209,7 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) sa_set_port(&r->in.saddr_rtp, port); sa_set_port(&r->in.saddr_rtcp, port+1); - /* @todo parse * in addresses */ + /* TODO: parse * in addresses */ return 0; } diff --git a/lib/nodes/shmem.cpp b/lib/nodes/shmem.cpp index f2252f8d8..3cbb95270 100644 --- a/lib/nodes/shmem.cpp +++ b/lib/nodes/shmem.cpp @@ -163,7 +163,7 @@ int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsign sample_copy_many(smps, shared_smps, recv); sample_decref_many(shared_smps, recv); - // @todo signal descriptions are currently not shared between processes + // TODO: signal descriptions are currently not shared between processes for (int i = 0; i < recv; i++) smps[i]->signals = n->getInputSignals(false); diff --git a/lib/nodes/uldaq.cpp b/lib/nodes/uldaq.cpp index f6a907913..f0b9a9916 100644 --- a/lib/nodes/uldaq.cpp +++ b/lib/nodes/uldaq.cpp @@ -554,7 +554,7 @@ int villas::node::uldaq_stop(NodeCompat *n) UlError err; - // @todo Fix deadlock + // TODO: Fix deadlock //pthread_mutex_lock(&u->in.mutex); // Get the current status of the acquisition diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index f4cc122af..c20516efc 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -232,7 +232,7 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); if (c->state != websocket_connection::State::CLOSING) { - // @todo Attempt reconnect here + // TODO: Attempt reconnect here } { diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 4d98e199b..216dbc071 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -217,7 +217,7 @@ int villas::node::zeromq_parse(NodeCompat *n, json_t *json) memcpy(z->curve.server.secret_key, secret_key, 41); } - // @todo We should fix this. Its mostly done. + // TODO: We should fix this. Its mostly done. if (z->curve.enabled) throw ConfigError(json_curve, "node-config-zeromq-curve", "CurveZMQ support is currently broken"); diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index 2fb720ff5..faa5a6d94 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -80,7 +80,7 @@ char * villas::node::socket_print_addr(struct sockaddr *saddr) int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLayer layer, int flags) { - // @todo Add support for IPv6 + // TODO: Add support for IPv6 union sockaddr_union *sa = (union sockaddr_union *) saddr; char *copy = strdup(addr); diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index 04c5ecef7..95dbeb2f4 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -69,7 +69,7 @@ void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], unsigned c break; case SignalType::COMPLEX: { - // @todo Port to proper C++ + // TODO: Port to proper C++ std::complex z = { j * 0.1f, i * 100.0f }; memcpy(&data->z, &z, sizeof(data->z)); break; From 3cc212423ec2b186161fa3e3505feef697af536b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 4 Sep 2023 19:22:56 +0200 Subject: [PATCH 030/100] Fix more flake8 warnings Signed-off-by: Steffen Vogel --- python/examples/Shmem_CIGRE_MV.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/python/examples/Shmem_CIGRE_MV.py b/python/examples/Shmem_CIGRE_MV.py index 8d1cf1b0b..1d1640729 100644 --- a/python/examples/Shmem_CIGRE_MV.py +++ b/python/examples/Shmem_CIGRE_MV.py @@ -27,20 +27,20 @@ def get_dpsim_shmem_interface_signals(): def get_dpsim_shmem_interface_config(): return { - 'type': 'shmem', - 'in': { - 'name': '/dpsim1-villas', - 'hooks': [ - { - 'type': 'stats' - } - ], - 'signals': get_dpsim_shmem_interface_signals() - }, - 'out': { - 'name': '/villas-dpsim1' - } + 'type': 'shmem', + 'in': { + 'name': '/dpsim1-villas', + 'hooks': [ + { + 'type': 'stats' + } + ], + 'signals': get_dpsim_shmem_interface_signals() + }, + 'out': { + 'name': '/villas-dpsim1' } + } def get_villas_config(): From 626e77557a4cb93506191bca662e338349a29024 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 12:51:27 +0200 Subject: [PATCH 031/100] Apply suggestions from Philipps code review Co-authored-by: Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> Signed-off-by: Steffen Vogel --- doc/openapi/components/schemas/config/hooks/_gate.yaml | 1 + doc/openapi/components/schemas/formats/sogno-old.yaml | 1 - doc/openapi/openapi.yaml | 1 + doc/openapi/paths/capabilities.yaml | 1 + doc/openapi/paths/config.yaml | 1 + doc/openapi/paths/graph.{format}.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}.yaml | 1 + .../paths/node/node@{uuid-or-name}@file@rewind.yaml | 1 + .../paths/node/node@{uuid-or-name}@file@seek.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml | 1 + .../paths/node/node@{uuid-or-name}@restart.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}@start.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml | 1 + .../paths/node/node@{uuid-or-name}@stats@reset.yaml | 1 + doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml | 1 + doc/openapi/paths/nodes.yaml | 1 + doc/openapi/paths/path/path@{uuid}.yaml | 1 + doc/openapi/paths/path/path@{uuid}@start.yaml | 1 + doc/openapi/paths/path/path@{uuid}@stop.yaml | 1 + doc/openapi/paths/paths.yaml | 1 + doc/openapi/paths/restart.yaml | 1 + doc/openapi/paths/shutdown.yaml | 1 + doc/openapi/paths/status.yaml | 1 + doc/theme/header.html | 2 +- doc/theme/style.css | 6 +++--- include/villas/kernel/if.hpp | 2 +- include/villas/node/config.hpp.in | 2 +- include/villas/node_compat.hpp | 10 +--------- include/villas/nodes/ethercat_config.hpp | 2 +- include/villas/nodes/temper.hpp | 2 +- lib/formats/villas.proto | 1 - 32 files changed, 32 insertions(+), 19 deletions(-) diff --git a/doc/openapi/components/schemas/config/hooks/_gate.yaml b/doc/openapi/components/schemas/config/hooks/_gate.yaml index 5702f7fb8..b9d13bafa 100644 --- a/doc/openapi/components/schemas/config/hooks/_gate.yaml +++ b/doc/openapi/components/schemas/config/hooks/_gate.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/components/schemas/formats/sogno-old.yaml b/doc/openapi/components/schemas/formats/sogno-old.yaml index 77ad74657..f5badb87c 100644 --- a/doc/openapi/components/schemas/formats/sogno-old.yaml +++ b/doc/openapi/components/schemas/formats/sogno-old.yaml @@ -1,4 +1,3 @@ - # yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 diff --git a/doc/openapi/openapi.yaml b/doc/openapi/openapi.yaml index f28d7edc3..d5aa52d0c 100644 --- a/doc/openapi/openapi.yaml +++ b/doc/openapi/openapi.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/capabilities.yaml b/doc/openapi/paths/capabilities.yaml index d8b873e3c..fe0dfde7a 100644 --- a/doc/openapi/paths/capabilities.yaml +++ b/doc/openapi/paths/capabilities.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/config.yaml b/doc/openapi/paths/config.yaml index bc4a65b13..7f5a19f2d 100644 --- a/doc/openapi/paths/config.yaml +++ b/doc/openapi/paths/config.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/graph.{format}.yaml b/doc/openapi/paths/graph.{format}.yaml index 23e2b2b57..5607f9168 100644 --- a/doc/openapi/paths/graph.{format}.yaml +++ b/doc/openapi/paths/graph.{format}.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}.yaml b/doc/openapi/paths/node/node@{uuid-or-name}.yaml index ee8b5484d..5ee458410 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml index 373c0cc83..e94f3e0a4 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@file@rewind.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml index 77b329e13..6d4a59157 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@file@seek.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml index 6915f87a1..36f004609 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@pause.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml index 320d8b4b5..567399b6c 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@restart.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml index a53b819aa..bd59f1915 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@resume.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml index bf0a0182e..64b8bfcfe 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@start.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml index daef64382..f35dff857 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stats.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml index 8e279210f..142454491 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stats@reset.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml b/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml index e4182c664..4fc93abe6 100644 --- a/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml +++ b/doc/openapi/paths/node/node@{uuid-or-name}@stop.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/nodes.yaml b/doc/openapi/paths/nodes.yaml index e49dcf175..223eb5232 100644 --- a/doc/openapi/paths/nodes.yaml +++ b/doc/openapi/paths/nodes.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/path/path@{uuid}.yaml b/doc/openapi/paths/path/path@{uuid}.yaml index 5c1792cac..11a3e488a 100644 --- a/doc/openapi/paths/path/path@{uuid}.yaml +++ b/doc/openapi/paths/path/path@{uuid}.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/path/path@{uuid}@start.yaml b/doc/openapi/paths/path/path@{uuid}@start.yaml index 0898e1104..8436516e6 100644 --- a/doc/openapi/paths/path/path@{uuid}@start.yaml +++ b/doc/openapi/paths/path/path@{uuid}@start.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/path/path@{uuid}@stop.yaml b/doc/openapi/paths/path/path@{uuid}@stop.yaml index 8a4a7cb54..de808e9ee 100644 --- a/doc/openapi/paths/path/path@{uuid}@stop.yaml +++ b/doc/openapi/paths/path/path@{uuid}@stop.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/paths.yaml b/doc/openapi/paths/paths.yaml index 8bb80fe1d..7329d7220 100644 --- a/doc/openapi/paths/paths.yaml +++ b/doc/openapi/paths/paths.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/restart.yaml b/doc/openapi/paths/restart.yaml index fa4d892fd..cd2bbf621 100644 --- a/doc/openapi/paths/restart.yaml +++ b/doc/openapi/paths/restart.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/shutdown.yaml b/doc/openapi/paths/shutdown.yaml index 179721ffb..e6fe57e2e 100644 --- a/doc/openapi/paths/shutdown.yaml +++ b/doc/openapi/paths/shutdown.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/openapi/paths/status.yaml b/doc/openapi/paths/status.yaml index 65441c6a7..12bbc7f0f 100644 --- a/doc/openapi/paths/status.yaml +++ b/doc/openapi/paths/status.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema # SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University # SPDX-License-Identifier: Apache-2.0 --- diff --git a/doc/theme/header.html b/doc/theme/header.html index 93e1cd4ab..a35fab67e 100644 --- a/doc/theme/header.html +++ b/doc/theme/header.html @@ -1,9 +1,9 @@ + - diff --git a/doc/theme/style.css b/doc/theme/style.css index 2f0e4d845..4dfcc39cb 100644 --- a/doc/theme/style.css +++ b/doc/theme/style.css @@ -1,7 +1,7 @@ /* -SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -SPDX-License-Identifier: Apache-2.0 -*/ + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ #projectname { font-size: 200%; diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index 1cc45502b..d5ae1a5b1 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -48,7 +48,7 @@ protected: int affinity; // IRQ / Core Affinity of this interface. std::list irqs; // List of IRQs of the NIC. - std::list nodes; // List of nodes which use this interface. + std::list nodes; // List of nodes which use this interface. Logger logger; diff --git a/include/villas/node/config.hpp.in b/include/villas/node/config.hpp.in index 9176fa292..ab3e7c172 100644 --- a/include/villas/node/config.hpp.in +++ b/include/villas/node/config.hpp.in @@ -6,7 +6,7 @@ * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 - *********************************************************************************/ + */ #pragma once diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index 42427a8c3..b023bfb3f 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -5,10 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* - * @addtogroup node Node - * @{ - */ #pragma once @@ -144,11 +140,7 @@ public: virtual std::vector getPollFDs(); - /* Get list of socket file descriptors for configuring network emulation. - - * - * @return The number of file descriptors which have been put into \p sds. - */ + // Get list of socket file descriptors for configuring network emulation. virtual std::vector getNetemFDs(); diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index 5154574d2..ed1386b0b 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -3,7 +3,7 @@ * Author: Niklas Eiling * Author: Steffen Vogel * Author: Divya Laxetti - * SPDX-FileCopyrightText: 2018-2020 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2018-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index f3b144127..4bbecd157 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -1,4 +1,4 @@ -/* An temper get started with new implementations of new node-types. +/* TEMPer node-type. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University diff --git a/lib/formats/villas.proto b/lib/formats/villas.proto index 27a581b2b..61c01b485 100644 --- a/lib/formats/villas.proto +++ b/lib/formats/villas.proto @@ -4,7 +4,6 @@ /// Author: Steffen Vogel /// SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University /// SPDX-License-Identifier: Apache-2.0 -//////////////////////////////////////////////////////////////////////////////////// syntax = "proto2"; From bd476016300d1f48c3746cdb341705fda0724be0 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 12:41:18 +0200 Subject: [PATCH 032/100] Delete outdated CHANGELOG.md Signed-off-by: Steffen Vogel --- CHANGELOG.md | 301 --------------------------------------------------- 1 file changed, 301 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c2ea4135f..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,301 +0,0 @@ -# Changelog - - - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## [0.7.1] - 2019-01-23 - -### Fixed - - - Removed most of the static storage variables from libvillas and libvillas-common - which caused crashes with DPsim. - - Fixed compilation with Ubuntu 16.04 and GCC 7.2. - - Fixed broken `shmem` node-type since addition of signal defintions. - -### Changed - - - Node-types can now handle more than a single file-descriptor for poll() multiplexing. - - Enable network emulation sub-system also for other node-types than `socket`. - The `rtp` node-type will support it now as well. - - Improve readabilty of log output - -### Added - - - Initial rate-limiting support for `rtp` node-type based on - Additive Increase / Multiplicative Decrease (AIMD) and RTCP. - -## [0.7.0] - 2019-01-13 - -### Added - -- A new sub-command `villas-relay` implements a client-to-client WebSocket relay. - It can be used as a proxy for nodes which sit behind a NAT firewall. -- New node-types: `infiniband`, `rtp`, `uldaq` -- VILLASnode got a similarily named Python package: `villas.node`. - It can be used to interact or start an VILLASnode instance. - -### Changed - -- The syntax of the configuration file has changed in several places. - Most node configs are now separated into `in` and `out` sections. -- We ported major parts of the VILLASnode code base to C++. -- Some of the common utilities have been moved to a new repo. - VILLAScommon is used also by other related VILLAS components. - Please make sure to checkout / update the `common/` Git sub-module. -- We build and test VILLASnode now with Fedora 29. - -### Fixed - -- All unit tests are running again. Most of the integration tests run again as well. -- We added support for the ARM architecture. - -## [0.6.4] - 2018-07-18 - -### Added - -- New client User Code Model (UCM) for OPAL-RT HYPERSIM digital real-time simulator -- New node-types: - - `infiniband` is using the Infiniband IBverbs and RDMA CM APIs for a low latency interface between simualation nodes. - - `comedi` adds support for ADC and DAC cards supported by the [Comedi Linux control and measurment device interface](http://comedi.org). -- All header files can now be imported into C++ code. Missing `extern "C"` declarations have been added. - -### Changed - -- The VILLASnode project is now built with [CMake](http://cmake.org). The old Makefile have been removed. -- The VILLASnode project will be gradually ported to C++. The tools (`/tools/`), executables (`/src/`) and plugins (`/plugins/`) have already been convert to C++ code. - -## [0.6.3] - 2018-06-04 - -### Added - -- The `csv` IO format has been splitted into a similar `tsv` IO format which uses tabulators instead of commas. -- The `struct queue_signalled` supports now synchronization under Mac OS X. -- A new `poll` setting allows the user to enable/disable the usage of `poll(2)` when reading from multiple source nodes. - -### Changed - -- Started splitting the node configuration into a send and receive side. This changes will be soon also reflected in a changed configuration file syntax. -- Docker images are now based on Fedora 28. - -### Fixed - -- We now correctly determine with terminal size when executed in GDB or by the CI runner. - -## [0.6.2] - 2018-05-14 - -### Added - -- A Docker application image can now be build in a single step using `make docker`. - -### Changed - -- The IO format names have changed. They now use dots (`raw.flt32`) instead of hyphens (`raw-flt32`) in their name. Please update your configuration files accordingly. -- The configuration of many node-types is now splitted into seperate `in` and `out` sections. Please update your configuration files accordingly. - -## [0.6.1] - 2018-02-17 - -### Changed - -- Rewrite of IO formatting subsystem/ - -### Added - -- New node-types: - - `mqtt` for MQTT / Mosquitto -- A new `make help` target shows the current build configuration and available targets. - -### Fixed - -- Websocket node can now receive data from a "catch-all" connection and associate to the correct simulator - -## [0.6.0] - 2017-12-20 - -### Added - -- New node-types: - - `iec61850-9-2` for IEC 61850 Sampled Values - - `amqp` for AMQP / RabbitMQ -- New IO formats: - - Google `protobuf` -- Added support for Unix Domain Sockets to `socket` node-type -- Python example client using new Protobuf and UDP/Unix sockets -- Built-in hooks can be disabled now -- Network emulation has been improved - - can now load a delay distribution from the config instead from a separate file - - can emulate delay correlation - -### Removed - -- Moved VILLASfpga related code into external library - - `libxil` dependency is dropped - -### Changed - -- Packaging of Docker and RPM has been improved -- Upgraded Docker build containers to Fedora 27 -- Updated submodules for most dependencies -- Use "LABEL" instead of "MAINTAINER" keyword in Dockerfiles - -### Fixed - -- Socket node-type supports now arbirarily sized packets -- Sample data format conversion for RAW IO formats -- Network emulation support is working again - -## [0.5.1] - 2017-10-23 - -### Changed - -- OPAL-RT AsyncIP client is only build if libopal submodule is present - -### Fixed - -- Build warnings and errors on Ubuntu 16.04 - -## [0.5.0] - 2017-10-18 - -### Added - -- Changelog -- InfluxDB node-type -- Support for "add" / "any" path register modes - -### Fixed - -- Netem support is working again - -### Changed - -- `villas-pipe` now automatically generates correct seqeunce numbers - -## [0.4.5] - 2017-09-24 - -### Fixed - -- RPM packaging to include debug symbols in `-debuginfo` package - -## [0.4.4] - 2017-09-24 - -### Fixed - -- Invalid sequence numbers due to broken workaround - -## [0.4.3] - 2017-09-24 - -### Changed - -- Do not abort execution of socket node fails with `sendto: invalid argument` - -### Fixed - -- Several fixes for the mux / demux re-mapping feature - -## [0.4.2] - 2017-09-19 - -### Fixed - -- Improved stability of HTTP API - -## [0.4.1] - 2017-09-16 - -## [0.4.0] - 2017-09-16 - -### Added - -- API action to request status of node -- Javascript configuration example -- Pluggable IO format subsystem with plugins for: - - `csv`: Comma-separated values - - `json`: Javascript Object Notation - - `raw`: 8/16/32/64 but binary floating point and integer data - - `villas-human`: VILLAS human-readable format - - `villas-binary`: VILLAS binary wire protocol - -## [0.3.5] - 2017-08-10 - -### Added - -- API action to restart node with new configuration -- API action to terminate node - -### Fixed - -- VILLASnode compiles now on Ubuntu 16.04 - -## [0.3.4] - 2017-07-28 - -### Fixed - -- Several compiler warnings on CLang - -## [0.3.3] - 2017-07-14 - -### Changed - -- Paths do not require output nodes anymore - -### Added - -- Loopback node-type - -### Fixed - -- OPAL-RT AsyncIP model for RT-LAB 11.1.x - -## [0.3.2] - 2017-07-07 - -### Added - -- Signal generator node-type -- Valgrind test cases - -## [0.3.1] - 2017-06-29 - -### Added - -- ZeroMQ node-type -- nanomsg node-type -- Multicast support for socket node-type -- RTDS GTNET-SKT examples - -## [0.3.0] - 2017-05-08 - - -Major changes in all parts of the software - -### Added - -- Pluggable node-types with plugins for: - - `file`: File / Log recording & replay - - `fpga`: VILLASfpga interface to Xilinx VC707 FPGA board via PCIexpress - - `ngsi`: FI-WARE NGSI-10 Open RESTful API for Orion Context Broker - - `websocket`: WebSocket support for VILLASweb - - `socket`: BSD network sockets - - `shmem`: POSIX shared memory -- Web-mockup for demonstration of the `websocket` node-type - -### Removed - -- User documentation has been moved to separate repository: http://git.rwth-aachen.de/acs/public/villas/documentation - -## [0.2.0] - 2015-09-22 - -### Added - -- OPAL-RT RT-LAB example demonstrating usage of AsyncIP -- Scripts and configuration files for creating LiveUSB Fedora images -- Travis-CI configuration -- More user documentation - -## [0.1.0] - 2014-06-10 - -### Added - -- Doxygen is now used to build documentation From 527a87d9ed90ccda282a7eeeea5bc605f8a678f9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 12:42:12 +0200 Subject: [PATCH 033/100] Add missing RWTH copyright to main README.md Signed-off-by: Steffen Vogel --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f43f0275..238f6f9e8 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ We kindly ask all academic publications employing components of VILLASframework For other licensing options please consult [Prof. Antonello Monti](mailto:amonti@eonerc.rwth-aachen.de). +- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University - SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH - SPDX-License-Identifier: Apache-2.0 From e2ae1089d9932f52c73bd49ac73b9dda4b2b70d8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 12:45:12 +0200 Subject: [PATCH 034/100] Move SPDX comment behind DOCTYPE tag Signed-off-by: Steffen Vogel --- doc/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.html b/doc/index.html index abf11b59a..b98e83715 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,8 +1,8 @@ + - API Reference | ReDoc From de3f95c8e44d62f619c97f0681ea9b1281e271d0 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 12:52:01 +0200 Subject: [PATCH 035/100] Remove accidentially committed example configs Signed-off-by: Steffen Vogel --- webrtc_a.conf | 35 ----------------------------------- webrtc_b.conf | 35 ----------------------------------- 2 files changed, 70 deletions(-) delete mode 100644 webrtc_a.conf delete mode 100644 webrtc_b.conf diff --git a/webrtc_a.conf b/webrtc_a.conf deleted file mode 100644 index 403d38827..000000000 --- a/webrtc_a.conf +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - -nodes = { - webrtc = { - type = "webrtc", - - # A unique session identifier which must be shared between two nodes - session = "KUCHEN" - peer = "a" - - # Address to the websocket signaling server - server = "http://172.23.157.207:8080" - - # wait_seconds = 5 - } - - signal = { - type = "signal" - signal = "sine" - values = 1 - rate = 0.2 - } -} - -paths = ( - { - in = "signal" - out = "webrtc" - }, - { - in = "webrtc" - hooks = ("print") - } -) diff --git a/webrtc_b.conf b/webrtc_b.conf deleted file mode 100644 index 897d75582..000000000 --- a/webrtc_b.conf +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - -nodes = { - webrtc = { - type = "webrtc", - - # A unique session identifier which must be shared between two nodes - session = "KUCHEN" - peer = "b" - - # Address to the websocket signaling server - server = "http://172.23.157.207:8080" - - # wait_seconds = 5 - } - - signal = { - type = "signal" - signal = "sine" - values = 1 - rate = 0.2 - } -} - -paths = ( - { - in = "signal" - out = "webrtc" - }, - { - in = "webrtc" - hooks = ("print") - } -) From bee65579d7e9e238e0aa8e43704340b36510549e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 13:02:47 +0200 Subject: [PATCH 036/100] Use #-style comments in .conf files Signed-off-by: Steffen Vogel --- etc/loopback.conf | 61 +++++++++++++++++++-------------------- etc/websocket-client.conf | 19 ++++++------ etc/websocket-demo.conf | 19 ++++++------ 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/etc/loopback.conf b/etc/loopback.conf index 11b1b5eb6..75a470151 100644 --- a/etc/loopback.conf +++ b/etc/loopback.conf @@ -1,34 +1,33 @@ -/** This is an example for a minimal loopback configuration. - * - * All messages will be sent back to the origin using UDP packets. - * - * You can use this configuration in conjunction with the 'send', 'receive' and 'random' - * utilities as shown below (run all three steps in parallel). - * - * 0. Overview: - * - * villas signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe - * - * 1. Start server: - * - * $ villas node etc/loopback.conf - * - * 2. Send random data to server: - * - * $ villas signal random -r 10 -v 4 | villas pipe etc/loopback.conf node1 - * - * 3. Receive data from server: - * - * $ villas pipe etc/loopback.conf node2 - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University - * SPDX-License-Identifier: Apache-2.0 - *********************************************************************************/ +# This is an example for a minimal loopback configuration. +# +# All messages will be sent back to the origin using UDP packets. +# +# You can use this configuration in conjunction with the 'send', 'receive' and 'random' +# utilities as shown below (run all three steps in parallel). +# +# 0. Overview: +# +# villas signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe +# +# 1. Start server: +# +# $ villas node etc/loopback.conf +# +# 2. Send random data to server: +# +# $ villas signal random -r 10 -v 4 | villas pipe etc/loopback.conf node1 +# +# 3. Receive data from server: +# +# $ villas pipe etc/loopback.conf node2 +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 nodes = { node1 = { diff --git a/etc/websocket-client.conf b/etc/websocket-client.conf index 4bb7cce9b..7b8744b99 100644 --- a/etc/websocket-client.conf +++ b/etc/websocket-client.conf @@ -1,13 +1,12 @@ -/** Example configuration file for VILLASnode. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University - * SPDX-License-Identifier: Apache-2.0 - *********************************************************************************/ +# Example configuration file for VILLASnode. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 nodes = { sig = { diff --git a/etc/websocket-demo.conf b/etc/websocket-demo.conf index 114f954cd..879d54758 100644 --- a/etc/websocket-demo.conf +++ b/etc/websocket-demo.conf @@ -1,13 +1,12 @@ -/** Example configuration file for VILLASnode. - * - * The syntax of this file is similar to JSON. - * A detailed description of the format can be found here: - * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files - * - * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University - * SPDX-License-Identifier: Apache-2.0 - *********************************************************************************/ +# Example configuration file for VILLASnode. +# +# The syntax of this file is similar to JSON. +# A detailed description of the format can be found here: +# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 nodes = { sig = { From a9805327aec6990716365855b00535b3bcfb038f Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 13:06:51 +0200 Subject: [PATCH 037/100] Removed Doxygen from repo Signed-off-by: Steffen Vogel --- CMakeLists.txt | 6 - doc/CMakeLists.txt | 55 - doc/Doxyfile.in | 2405 ----------------------------------------- doc/theme/header.html | 70 -- doc/theme/layout.xml | 196 ---- doc/theme/style.css | 21 - 6 files changed, 2753 deletions(-) delete mode 100644 doc/CMakeLists.txt delete mode 100644 doc/Doxyfile.in delete mode 100644 doc/theme/header.html delete mode 100644 doc/theme/layout.xml delete mode 100644 doc/theme/style.css diff --git a/CMakeLists.txt b/CMakeLists.txt index c4fae12ee..f4d4c7f49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,7 +175,6 @@ cmake_dependent_option(WITH_DEFAULTS "Defaults for non required build opt cmake_dependent_option(WITH_API "Build with remote control API" "${WITH_DEFAULTS}" "" OFF) cmake_dependent_option(WITH_CLIENTS "Build client applications" "${WITH_DEFAULTS}" "TOPLEVEL_PROJECT" OFF) cmake_dependent_option(WITH_CONFIG "Build with support for libconfig configuration syntax" "${WITH_DEFAULTS}" "LIBCONFIG_FOUND" OFF) -cmake_dependent_option(WITH_DOC "Build documentation" "${WITH_DEFAULTS}" "TOPLEVEL_PROJECT" OFF) cmake_dependent_option(WITH_FPGA "Build with support for VILLASfpga" "${WITH_DEFAULTS}" "FOUND_SUBMODULE_FPGA" OFF) cmake_dependent_option(WITH_GRAPHVIZ "Build with Graphviz" "${WITH_DEFAULTS}" "CGRAPH_FOUND; GVC_FOUND" OFF) cmake_dependent_option(WITH_HOOKS "Build with support for processing hook plugins" "${WITH_DEFAULTS}" "" OFF) @@ -265,10 +264,6 @@ if(WITH_PLUGINS) add_subdirectory(plugins) endif() -if(WITH_DOC AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.9.0") - add_subdirectory(doc) -endif() - if(WITH_CLIENTS) add_subdirectory(clients) endif() @@ -286,7 +281,6 @@ configure_file( add_feature_info(API WITH_API "Build with remote control API") add_feature_info(CLIENTS WITH_CLIENTS "Build client applications") add_feature_info(CONFIG WITH_CONFIG "Build with support for libconfig configuration syntax") -add_feature_info(DOC WITH_DOC "Build documentation") add_feature_info(FPGA WITH_FPGA "Build with FPGA support") add_feature_info(GRAPHVIZ WITH_GRAPHVIZ "Build with Graphviz support") add_feature_info(HOOKS WITH_HOOKS "Build with support for processing hook plugins") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt deleted file mode 100644 index ec7d18766..000000000 --- a/doc/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -# CMakeLists.txt. -# -# Author: Steffen Vogel -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - -find_package(Doxygen) - -if(DOXYGEN_FOUND) - set(DOXYGEN_PROJECT_LOGO doc/pictures/villas_node.svg) - set(DOXYGEN_WARN_LOGFILE ${CMAKE_CURRENT_BINARY_DIR}/warnings.log) - set(DOXYGEN_TAB_SIZE 8) - set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES) - set(DOXYGEN_LAYOUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/theme/layout.xml) - set(DOXYGEN_RECURSIVE YES) - set(DOXYGEN_EXAMPLE_PATH etc/) - set(DOXYGEN_EXAMPLE_RECURSIVE YES) - set(DOXYGEN_IMAGE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/pictures) - set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${PROJECT_SOURCE_DIR}/README.md) - set(DOXYGEN_SOURCE_BROWSER YES) - set(DOXYGEN_REFERENCED_BY_RELATION YES) - set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/theme/header.html) - set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/theme/style.css) - set(DOXYGEN_HTML_EXTRA_FILES doc${CMAKE_CURRENT_SOURCE_DIR}/pictures/acs_eonerc_logo.svg) - set(DOXYGEN_HTML_COLORSTYLE_HUE 209) - set(DOXYGEN_HTML_COLORSTYLE_SAT 88) - set(DOXYGEN_HTML_TIMESTAMP YES) - set(DOXYGEN_HTML_DYNAMIC_SECTIONS YES) - set(DOXYGEN_GENERATE_TREEVIEW YES) - set(DOXYGEN_TREEVIEW_WIDTH 280) - set(DOXYGEN_UML_LOOK YES) - set(DOXYGEN_CALL_GRAPH YES) - set(DOXYGEN_CALLER_GRAPH YES) - set(DOXYGEN_DOT_IMAGE_FORMAT svg) - set(DOXYGEN_INTERACTIVE_SVG YES) - set(DOXYGEN_DIAFILE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/figures/) - - doxygen_add_docs(doc - README.md CONTRIBUTING.md LICENSE src/ lib/ tests/ include/ doc/ - WORKING_DIRECTORY ${PROJECT_DIR} - ) - - # Ensure that documentation is built before installing it - install(CODE "execute_process( - COMMAND ${CMAKE_COMMAND} --build \"${CMAKE_CURRENT_BINARY_DIR}\" --target doc - WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\" - )" - ) - - install( - DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/villas/node - COMPONENT doc - ) -endif() diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in deleted file mode 100644 index a4fcdfe26..000000000 --- a/doc/Doxyfile.in +++ /dev/null @@ -1,2405 +0,0 @@ -# Doxyfile 1.8.10 -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "VILLASnode" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "Connecting real-time power grid simulation equipment" - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = doc/pictures/villas_node.svg - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = doc/theme/layout.xml - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = doc/warnings.log - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = README.md CONTRIBUTING.md LICENSE src/ lib/ tests/ include/ doc/ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, -# *.vhdl, *.ucf, *.qsf, *.as and *.js. - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = etc/ - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = YES - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = doc/pictures - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = README.md - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# compiled with the --with-libclang option. -# The default value is: NO. - -#CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -#CLANG_OPTIONS = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = doc/theme/header.html - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = doc/theme/style.css - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = doc/pictures/acs_eonerc_logo.svg - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 209 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 88 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = YES - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 280 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /
- - - - - - - - - - - - - - - - - - - - - - - -
-
$projectname -  $projectnumber -
-
$projectbrief
-
-
$projectbrief
-
$searchbox
- - - diff --git a/doc/theme/layout.xml b/doc/theme/layout.xml deleted file mode 100644 index bc43e0556..000000000 --- a/doc/theme/layout.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/theme/style.css b/doc/theme/style.css deleted file mode 100644 index 4dfcc39cb..000000000 --- a/doc/theme/style.css +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University - * SPDX-License-Identifier: Apache-2.0 - */ - -#projectname { - font-size: 200%; -} - -#projectlogo img { - height: 3.5em; - margin: 0.25em; -} - -#institutelogo img { - height: 3em; - margin: 0.5em; - position: absolute; - right: 0; - top: 0; -} From 45b6f602dc2b7840987c28cad2b6930c4793ca97 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 13:13:55 +0200 Subject: [PATCH 038/100] Fix file header of queue.hpp Signed-off-by: Steffen Vogel --- include/villas/queue.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index d5b50046c..f04835619 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -1,4 +1,4 @@ -/* Wrapper around queue that uses POSIX CV's for signalling writes. +/* A simple queue protected by mutexes. * * Author: Georg Martin Reinke * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University From 57d5ed8e557644d8f5aa414607384b4dce6ccad2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 5 Sep 2023 13:21:01 +0200 Subject: [PATCH 039/100] Move SPDX header to top of README file Signed-off-by: Steffen Vogel --- tests/integration/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/README.md b/tests/integration/README.md index fd6684fe0..d07ef7833 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -1,6 +1,11 @@ # Integration Tests -Run tests: + + +## Run tests ``` $ BUILDDIR=/VILLASnode/build/ /VILLASnode/tools/integration-tests.sh @@ -18,8 +23,3 @@ Example: ``` $ BUILDDIR=/VILLASnode/build/ /VILLASnode/tools/integration-tests.sh -f pipe-loopback-socket -v ``` - - From 82975ddaaa640df2ae8ff3ccb2dadbd81e0fe4a9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 6 Sep 2023 09:45:19 +0200 Subject: [PATCH 040/100] Fixup whitespaces Signed-off-by: Steffen Vogel --- include/villas/kernel/if.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index d5ae1a5b1..fce1038bb 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -48,7 +48,7 @@ protected: int affinity; // IRQ / Core Affinity of this interface. std::list irqs; // List of IRQs of the NIC. - std::list nodes; // List of nodes which use this interface. + std::list nodes; // List of nodes which use this interface. Logger logger; From 66923380fb19438dda1c7d2e53cb4ae05a6451fc Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 6 Sep 2023 09:46:23 +0200 Subject: [PATCH 041/100] Update VILLAScommon sub-module Signed-off-by: Steffen Vogel --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 413a0ba31..0edfc697b 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 413a0ba31971730f60664ef69709b70d64c9de80 +Subproject commit 0edfc697b75715742957cd0eb88bd364f22f2e72 From 73ca4b5c8da556de812837f1ea0c40f2479fef1a Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 6 Sep 2023 17:08:16 +0200 Subject: [PATCH 042/100] Replace remaining C style comments Signed-off-by: Philipp Jungkamp --- lib/hooks/reorder_ts.cpp | 10 +++++----- lib/nodes/infiniband.cpp | 2 +- lib/nodes/rtp.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index 53fff9bd2..76048bde6 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -1,9 +1,9 @@ -/** Reorder samples hook. +/* Reorder samples hook. * * @author Philipp Jungkamp * @copyright 2023, OPAL-RT Germany GmbH * @license Apache 2.0 - *********************************************************************************/ + */ #include #include @@ -151,10 +151,10 @@ public: } }; -/* Register hook */ +// Register hook static char n[] = "reorder_ts"; static char d[] = "Reorder messages by their timestamp"; static HookPlugin p; -} /* namespace node */ -} /* namespace villas */ +} // namespace node +} // namespace villas diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index c465dc111..48c161567 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -980,7 +980,7 @@ int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned // TODO: fix release logic // n->logger->debug("{} samples will be released (before WC)", *release); - /* Try to grab as many CQEs from CQ as there is space in *smps[] */ + // Try to grab as many CQEs from CQ as there is space in *smps[] // ret = ibv_poll_cq(ib->ctx.send_cq, cnt - *release, wc); for (int i = 0; i < ret; i++) { diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index f21d19ef4..dc68965fb 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -209,7 +209,7 @@ int villas::node::rtp_parse(NodeCompat *n, json_t *json) sa_set_port(&r->in.saddr_rtp, port); sa_set_port(&r->in.saddr_rtcp, port+1); - /* TODO: parse * in addresses */ + // TODO: parse * in addresses return 0; } From 7d2f073075ebee2b5ba2d9efecd799141f4edae7 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 09:53:18 +0200 Subject: [PATCH 043/100] Fix REUSE compliance for reorder hook Signed-off-by: Steffen Vogel --- .../components/schemas/config/hooks/_reorder_ts.yaml | 4 ++++ doc/openapi/components/schemas/config/hooks/reorder_ts.yaml | 3 ++- etc/examples/hooks/reorder_ts.conf | 3 +++ lib/hooks/reorder_ts.cpp | 6 +++--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml b/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml index a562b1945..29cd52d64 100644 --- a/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/_reorder_ts.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 +--- allOf: - $ref: ../hook_obj.yaml - $ref: reorder_ts.yaml diff --git a/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml b/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml index 7d284700f..244782cf9 100644 --- a/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml +++ b/doc/openapi/components/schemas/config/hooks/reorder_ts.yaml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 --- - allOf: - type: object properties: diff --git a/etc/examples/hooks/reorder_ts.conf b/etc/examples/hooks/reorder_ts.conf index 7d639f744..405aaaa98 100644 --- a/etc/examples/hooks/reorder_ts.conf +++ b/etc/examples/hooks/reorder_ts.conf @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + @include "hook-nodes.conf" paths = ( diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index 76048bde6..1dbbd4481 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -1,8 +1,8 @@ /* Reorder samples hook. * - * @author Philipp Jungkamp - * @copyright 2023, OPAL-RT Germany GmbH - * @license Apache 2.0 + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023, OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 */ #include From fd0480f3c7cb53aa217ee4f02cce03f0b66b40aa Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 10:10:45 +0200 Subject: [PATCH 044/100] Remove "make doc" from Dockerfiles Signed-off-by: Steffen Vogel --- packaging/docker/Dockerfile.debian | 1 - packaging/docker/Dockerfile.debian-multiarch | 1 - packaging/docker/Dockerfile.fedora | 1 - packaging/docker/Dockerfile.fedora-minimal | 1 - packaging/docker/Dockerfile.rocky | 1 - packaging/docker/Dockerfile.ubuntu | 1 - 6 files changed, 6 deletions(-) diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index c149cd608..ed0008bd1 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -78,7 +78,6 @@ COPY . /villas/ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} .. && \ - make -j$(nproc) doc && \ make -j$(nproc) install && \ ldconfig diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index dd3d26850..6e62fba40 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -112,7 +112,6 @@ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} ${CMAKE_EXTRA_OPTS} .. && \ - make -j$(nproc) doc && \ make -j$(nproc) install FROM --platform=${TARGETPLATFORM} ${DISTRO}:${DEBIAN_VERSION} AS app diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 40bd67296..04f6c3975 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -108,7 +108,6 @@ COPY . /villas/ WORKDIR /villas/build RUN --mount=type=cache,id=${DISTRO}-${FEDORA_VERSION}-${ARCH}-${REF},target=/villas/build \ cmake ${CMAKE_OPTS} .. && \ - make -j$(nproc) doc && \ make -j$(nproc) install && \ ldconfig diff --git a/packaging/docker/Dockerfile.fedora-minimal b/packaging/docker/Dockerfile.fedora-minimal index 460beb6d2..6af3e6722 100644 --- a/packaging/docker/Dockerfile.fedora-minimal +++ b/packaging/docker/Dockerfile.fedora-minimal @@ -39,7 +39,6 @@ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} -DCPACK_GENERATOR=RPM .. && \ - make -j$(nproc) doc && \ make -j$(nproc) package FROM ${DISTRO}:${FEDORA_VERSION} as app diff --git a/packaging/docker/Dockerfile.rocky b/packaging/docker/Dockerfile.rocky index ffc3ed194..5f170d314 100644 --- a/packaging/docker/Dockerfile.rocky +++ b/packaging/docker/Dockerfile.rocky @@ -78,7 +78,6 @@ COPY . /villas/ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} .. && \ - make -j$(nproc) doc && \ make -j$(nproc) install && \ ldconfig diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 21fbef364..178912bd6 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -80,7 +80,6 @@ COPY . /villas/ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} .. && \ - make -j$(nproc) doc && \ make -j$(nproc) install && \ ldconfig From 6db1ab53ef67a5bac1dacfa392a276cacb69495b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 10:58:35 +0200 Subject: [PATCH 045/100] Revert update fpga submodule Signed-off-by: Steffen Vogel --- fpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga b/fpga index 14b425fc9..1cac3fafd 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 14b425fc9893ef63527d6230c1ec87ab10366850 +Subproject commit 1cac3fafde6ef3098a145f9d5d936a2dc6b7d7c0 From 37dec5c55dcf76ed4cc7e79b824f0e77a8450669 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 11:22:59 +0200 Subject: [PATCH 046/100] Install clang-format and clangd in Devcontainers Signed-off-by: Steffen Vogel --- packaging/docker/Dockerfile.debian | 3 ++- packaging/docker/Dockerfile.debian-multiarch | 3 ++- packaging/docker/Dockerfile.fedora | 3 ++- packaging/docker/Dockerfile.rocky | 3 ++- packaging/docker/Dockerfile.ubuntu | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index ed0008bd1..ad8398c90 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -22,7 +22,8 @@ RUN apt-get update && \ autoconf automake autogen libtool \ texinfo git curl tar wget diffutils \ flex bison \ - protobuf-compiler protobuf-c-compiler + protobuf-compiler protobuf-c-compiler \ + clang-format clangd # Dependencies RUN apt-get update && \ diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index 6e62fba40..d776dbe3b 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -31,7 +31,8 @@ RUN apt-get update && \ autoconf automake autogen libtool \ texinfo git curl tar wget diffutils \ flex bison \ - protobuf-compiler protobuf-c-compiler + protobuf-compiler protobuf-c-compiler \ + clang-format clangd # Build-time dependencies RUN apt-get update && \ diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 04f6c3975..88d86d39c 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -19,7 +19,8 @@ RUN dnf -y install \ autoconf automake autogen libtool \ texinfo git curl tar \ flex bison \ - protobuf-compiler protobuf-c-compiler + protobuf-compiler protobuf-c-compiler \ + clang-tools-extra # Several tools only needed for developement and testing RUN dnf -y install \ diff --git a/packaging/docker/Dockerfile.rocky b/packaging/docker/Dockerfile.rocky index 5f170d314..96b2cd9f6 100644 --- a/packaging/docker/Dockerfile.rocky +++ b/packaging/docker/Dockerfile.rocky @@ -24,7 +24,8 @@ RUN dnf --allowerasing -y install \ autoconf automake libtool \ flex bison \ texinfo git curl tar \ - protobuf-compiler protobuf-c-compiler + protobuf-compiler protobuf-c-compiler \ + clang-tools-extra # Dependencies RUN dnf -y install \ diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 178912bd6..0bfb82217 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -23,7 +23,8 @@ RUN apt-get update && \ autoconf automake autogen libtool \ texinfo git curl tar wget diffutils \ flex bison \ - protobuf-compiler protobuf-c-compiler + protobuf-compiler protobuf-c-compiler \ + clang-tools-extra clangd # Dependencies RUN apt-get update && \ From bc3ad552f552394f483d4e8d3f9daf77aa2a0f0e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 11:23:20 +0200 Subject: [PATCH 047/100] Make editorconfig compatible with clang-format Signed-off-by: Steffen Vogel --- .editorconfig | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 35447f7c9..08e375e0b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,24 +7,21 @@ root = true # Unix-style newlines with a newline ending every file [*] +charset = utf-8 end_of_line = lf insert_final_newline = true +trim_trailing_whitespace=true # Matches multiple files with brace expansion notation # Set default charset [{etc,include,lib,plugins,src,tests,tools,common}/**.{c,h,proto,cpp,hpp,h.in,hpp.in}] -charset = utf-8 -indent_style = tab -indent_size = 8 -trim_trailing_whitespace=true +indent_style = space +indent_size = 2 [*.conf] -charset = utf-8 indent_style = tab indent_size = 8 [*.nix] -charset = utf-8 indent_style = space indent_size = 2 -trim_trailing_whitespace=true From 8da1e68b0f8a14c42f5ec411301cebcb1fcf9dc6 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 11:23:32 +0200 Subject: [PATCH 048/100] Add clang-format config Signed-off-by: Steffen Vogel --- .clang-format | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..537bac562 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +--- +BasedOnStyle: LLVM + +# Disable automatic line-breaks in comments +# as this breaks SPDX headers +ReflowComments: false From 02a2aa4f94e4851ec714425029f9f31f1a5f7fc7 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 11:46:39 +0200 Subject: [PATCH 049/100] Apply clang-format changes Signed-off-by: Steffen Vogel --- .../opal/models/send_receive/include/config.h | 12 +- .../models/send_receive/include/msg_format.h | 78 +- .../opal/models/send_receive/include/socket.h | 10 +- clients/opal/models/send_receive/src/compat.c | 28 +- clients/opal/models/send_receive/src/main.c | 472 +++--- clients/opal/models/send_receive/src/msg.c | 59 +- clients/opal/models/send_receive/src/socket.c | 252 +-- clients/opal/models/send_receive/src/utils.c | 27 +- clients/shmem/villas-shmem.cpp | 141 +- include/villas/api.hpp | 80 +- include/villas/api/request.hpp | 173 +-- include/villas/api/requests/node.hpp | 7 +- include/villas/api/requests/path.hpp | 7 +- include/villas/api/requests/universal.hpp | 9 +- include/villas/api/response.hpp | 75 +- include/villas/api/session.hpp | 81 +- include/villas/api/universal.hpp | 31 +- include/villas/capabilities.hpp | 4 +- include/villas/config_class.hpp | 79 +- include/villas/config_helper.hpp | 12 +- include/villas/dumper.hpp | 30 +- include/villas/format.hpp | 149 +- include/villas/formats/column.hpp | 49 +- include/villas/formats/iotagent_ul.hpp | 10 +- include/villas/formats/json.hpp | 45 +- include/villas/formats/json_edgeflex.hpp | 8 +- include/villas/formats/json_kafka.hpp | 17 +- include/villas/formats/json_reserve.hpp | 8 +- include/villas/formats/line.hpp | 85 +- include/villas/formats/msg.hpp | 8 +- include/villas/formats/msg_format.hpp | 66 +- include/villas/formats/opal_asyncip.hpp | 61 +- include/villas/formats/protobuf.hpp | 12 +- include/villas/formats/raw.hpp | 45 +- include/villas/formats/value.hpp | 10 +- include/villas/formats/villas_binary.hpp | 73 +- include/villas/formats/villas_human.hpp | 11 +- include/villas/hook.hpp | 300 ++-- include/villas/hook_list.hpp | 29 +- include/villas/hooks/decimate.hpp | 38 +- include/villas/hooks/limit_rate.hpp | 35 +- include/villas/hooks/lua.hpp | 138 +- include/villas/hooks/pmu.hpp | 95 +- include/villas/kernel/if.hpp | 55 +- include/villas/kernel/nl-private.h | 55 +- include/villas/kernel/nl.hpp | 6 +- include/villas/kernel/tc.hpp | 5 +- include/villas/kernel/tc_netem.hpp | 7 +- include/villas/log_opal_sink.hpp | 35 +- include/villas/mapping.hpp | 93 +- include/villas/mapping_list.hpp | 9 +- include/villas/memory/ib.h | 6 +- include/villas/node.h | 24 +- include/villas/node.hpp | 472 +++--- include/villas/node/exceptions.hpp | 50 +- include/villas/node/memory.hpp | 45 +- include/villas/node/memory_type.hpp | 43 +- include/villas/node_compat.hpp | 143 +- include/villas/node_compat_type.hpp | 94 +- include/villas/node_direction.hpp | 47 +- include/villas/node_list.hpp | 16 +- include/villas/nodes/amqp.hpp | 36 +- include/villas/nodes/api.hpp | 37 +- include/villas/nodes/can.hpp | 30 +- include/villas/nodes/comedi.hpp | 59 +- include/villas/nodes/ethercat.hpp | 57 +- include/villas/nodes/ethercat_config.hpp | 170 +- include/villas/nodes/example.hpp | 78 +- include/villas/nodes/exec.hpp | 57 +- include/villas/nodes/file.hpp | 65 +- include/villas/nodes/fpga.hpp | 99 +- include/villas/nodes/iec60870.hpp | 276 ++-- include/villas/nodes/iec61850.hpp | 91 +- include/villas/nodes/iec61850_goose.hpp | 328 ++-- include/villas/nodes/iec61850_sv.hpp | 60 +- include/villas/nodes/infiniband.hpp | 108 +- include/villas/nodes/influxdb.hpp | 14 +- include/villas/nodes/kafka.hpp | 58 +- include/villas/nodes/loopback.hpp | 32 +- include/villas/nodes/loopback_internal.hpp | 64 +- include/villas/nodes/modbus.hpp | 294 ++-- include/villas/nodes/mqtt.hpp | 56 +- include/villas/nodes/nanomsg.hpp | 18 +- include/villas/nodes/ngsi.hpp | 38 +- include/villas/nodes/opal.hpp | 22 +- include/villas/nodes/redis.hpp | 77 +- include/villas/nodes/redis_helpers.hpp | 232 ++- include/villas/nodes/rtp.hpp | 76 +- include/villas/nodes/shmem.hpp | 18 +- include/villas/nodes/signal.hpp | 104 +- include/villas/nodes/signal_old.hpp | 67 +- include/villas/nodes/socket.hpp | 43 +- include/villas/nodes/stats.hpp | 18 +- include/villas/nodes/temper.hpp | 119 +- include/villas/nodes/test_rtt.hpp | 38 +- include/villas/nodes/uldaq.hpp | 50 +- include/villas/nodes/webrtc.hpp | 105 +- .../villas/nodes/webrtc/peer_connection.hpp | 99 +- .../villas/nodes/webrtc/signaling_client.hpp | 115 +- .../villas/nodes/webrtc/signaling_message.hpp | 43 +- include/villas/nodes/websocket.hpp | 123 +- include/villas/nodes/zeromq.hpp | 56 +- include/villas/path.hpp | 214 ++- include/villas/path_destination.hpp | 29 +- include/villas/path_list.hpp | 8 +- include/villas/path_source.hpp | 65 +- include/villas/pool.hpp | 25 +- include/villas/queue.h | 28 +- include/villas/queue.hpp | 39 +- include/villas/queue_signalled.h | 58 +- include/villas/queue_signalled.hpp | 33 +- include/villas/sample.hpp | 84 +- include/villas/shmem.hpp | 40 +- include/villas/signal.hpp | 29 +- include/villas/signal_data.hpp | 52 +- include/villas/signal_list.hpp | 37 +- include/villas/signal_type.hpp | 10 +- include/villas/socket_addr.hpp | 36 +- include/villas/stats.hpp | 120 +- include/villas/super_node.hpp | 172 +-- include/villas/usb.hpp | 102 +- include/villas/web.hpp | 79 +- lib/api.cpp | 99 +- lib/api/request.cpp | 55 +- lib/api/requests/capabiltities.cpp | 23 +- lib/api/requests/config.cpp | 28 +- lib/api/requests/graph.cpp | 132 +- lib/api/requests/node.cpp | 35 +- lib/api/requests/node_action.cpp | 38 +- lib/api/requests/node_file.cpp | 41 +- lib/api/requests/node_info.cpp | 42 +- lib/api/requests/node_stats.cpp | 32 +- lib/api/requests/node_stats_reset.cpp | 35 +- lib/api/requests/nodes.cpp | 30 +- lib/api/requests/path.cpp | 26 +- lib/api/requests/path_action.cpp | 32 +- lib/api/requests/path_info.cpp | 28 +- lib/api/requests/paths.cpp | 30 +- lib/api/requests/restart.cpp | 147 +- lib/api/requests/shutdown.cpp | 22 +- lib/api/requests/status.cpp | 141 +- lib/api/requests/universal.cpp | 12 +- lib/api/requests/universal/channel.cpp | 204 ++- lib/api/requests/universal/channels.cpp | 50 +- lib/api/requests/universal/info.cpp | 33 +- lib/api/requests/universal/status.cpp | 26 +- lib/api/response.cpp | 101 +- lib/api/session.cpp | 360 +++-- lib/api/universal.cpp | 201 ++- lib/capabilities.cpp | 62 +- lib/config.cpp | 499 +++--- lib/config_helper.cpp | 486 +++--- lib/dumper.cpp | 179 +-- lib/format.cpp | 189 ++- lib/formats/column.cpp | 249 +-- lib/formats/iotagent_ul.cpp | 57 +- lib/formats/json.cpp | 502 +++--- lib/formats/json_edgeflex.cpp | 123 +- lib/formats/json_kafka.cpp | 235 ++- lib/formats/json_reserve.cpp | 206 ++- lib/formats/line.cpp | 226 +-- lib/formats/msg.cpp | 177 ++- lib/formats/opal_asyncip.cpp | 143 +- lib/formats/protobuf.cpp | 309 ++-- lib/formats/raw.cpp | 715 +++++---- lib/formats/value.cpp | 91 +- lib/formats/villas_binary.cpp | 168 +- lib/formats/villas_human.cpp | 259 ++-- lib/hook.cpp | 208 ++- lib/hook_list.cpp | 259 ++-- lib/hooks/average.cpp | 113 +- lib/hooks/cast.cpp | 118 +- lib/hooks/decimate.cpp | 52 +- lib/hooks/dp.cpp | 384 +++-- lib/hooks/drop.cpp | 85 +- lib/hooks/dump.cpp | 20 +- lib/hooks/ebm.cpp | 119 +- lib/hooks/fix.cpp | 42 +- lib/hooks/gate.cpp | 202 ++- lib/hooks/jitter_calc.cpp | 98 +- lib/hooks/limit_rate.cpp | 96 +- lib/hooks/limit_value.cpp | 95 +- lib/hooks/lua.cpp | 1090 +++++++------ lib/hooks/ma.cpp | 124 +- lib/hooks/pmu.cpp | 379 ++--- lib/hooks/pmu_dft.cpp | 1059 ++++++------- lib/hooks/pmu_ipdft.cpp | 210 +-- lib/hooks/power.cpp | 495 +++--- lib/hooks/pps_ts.cpp | 317 ++-- lib/hooks/print.cpp | 162 +- lib/hooks/reorder_ts.cpp | 186 +-- lib/hooks/restart.cpp | 80 +- lib/hooks/rms.cpp | 136 +- lib/hooks/round.cpp | 80 +- lib/hooks/scale.cpp | 89 +- lib/hooks/shift_seq.cpp | 45 +- lib/hooks/shift_ts.cpp | 102 +- lib/hooks/skip_first.cpp | 162 +- lib/hooks/stats.cpp | 322 ++-- lib/hooks/ts.cpp | 24 +- lib/kernel/if.cpp | 255 +-- lib/kernel/nl.cpp | 194 +-- lib/kernel/tc.cpp | 101 +- lib/kernel/tc_netem.cpp | 370 ++--- lib/mapping.cpp | 509 +++--- lib/mapping_list.cpp | 94 +- lib/memory.cpp | 174 ++- lib/memory/heap.cpp | 59 +- lib/memory/ib.cpp | 107 +- lib/memory/managed.cpp | 247 ++- lib/memory/mmap.cpp | 193 ++- lib/node.cpp | 672 ++++---- lib/node_capi.cpp | 269 ++-- lib/node_compat.cpp | 391 ++--- lib/node_direction.cpp | 216 ++- lib/node_list.cpp | 115 +- lib/nodes/amqp.cpp | 599 ++++--- lib/nodes/api.cpp | 145 +- lib/nodes/can.cpp | 748 +++++---- lib/nodes/comedi.cpp | 1350 ++++++++-------- lib/nodes/ethercat.cpp | 616 ++++---- lib/nodes/example.cpp | 124 +- lib/nodes/exec.cpp | 273 ++-- lib/nodes/file.cpp | 692 ++++----- lib/nodes/fpga.cpp | 323 ++-- lib/nodes/iec60870.cpp | 1302 ++++++++-------- lib/nodes/iec61850.cpp | 435 +++--- lib/nodes/iec61850_goose.cpp | 1294 ++++++++-------- lib/nodes/iec61850_sv.cpp | 685 ++++---- lib/nodes/infiniband.cpp | 1372 ++++++++--------- lib/nodes/influxdb.cpp | 276 ++-- lib/nodes/kafka.cpp | 859 +++++------ lib/nodes/loopback.cpp | 159 +- lib/nodes/loopback_internal.cpp | 118 +- lib/nodes/modbus.cpp | 1353 ++++++++-------- lib/nodes/mqtt.cpp | 728 +++++---- lib/nodes/nanomsg.cpp | 407 +++-- lib/nodes/ngsi.cpp | 1161 +++++++------- lib/nodes/opal.cpp | 526 +++---- lib/nodes/redis.cpp | 944 ++++++------ lib/nodes/rtp.cpp | 799 +++++----- lib/nodes/shmem.cpp | 292 ++-- lib/nodes/signal.cpp | 546 ++++--- lib/nodes/signal_v1.cpp | 683 ++++---- lib/nodes/socket.cpp | 846 +++++----- lib/nodes/stats.cpp | 326 ++-- lib/nodes/temper.cpp | 551 ++++--- lib/nodes/test_rtt.cpp | 604 ++++---- lib/nodes/uldaq.cpp | 939 ++++++----- lib/nodes/webrtc.cpp | 320 ++-- lib/nodes/webrtc/peer_connection.cpp | 644 ++++---- lib/nodes/webrtc/signaling_client.cpp | 282 ++-- lib/nodes/webrtc/signaling_message.cpp | 320 ++-- lib/nodes/websocket.cpp | 914 +++++------ lib/nodes/zeromq.cpp | 909 ++++++----- lib/path.cpp | 971 ++++++------ lib/path_destination.cpp | 136 +- lib/path_list.cpp | 26 +- lib/path_source.cpp | 302 ++-- lib/pool.cpp | 98 +- lib/queue.cpp | 239 +-- lib/queue_signalled.cpp | 411 +++-- lib/sample.cpp | 430 +++--- lib/shmem.cpp | 270 ++-- lib/signal.cpp | 167 +- lib/signal_data.cpp | 395 +++-- lib/signal_list.cpp | 211 ++- lib/signal_type.cpp | 100 +- lib/socket_addr.cpp | 307 ++-- lib/stats.cpp | 391 +++-- lib/super_node.cpp | 707 ++++----- lib/usb.cpp | 175 +-- lib/web.cpp | 371 +++-- plugins/example_hook.cpp | 12 +- src/villas-compare.cpp | 389 +++-- src/villas-conf2json.cpp | 86 +- src/villas-convert.cpp | 223 ++- src/villas-graph.cpp | 142 +- src/villas-hook.cpp | 440 +++--- src/villas-node.cpp | 280 ++-- src/villas-pipe.cpp | 732 ++++----- src/villas-relay.cpp | 674 ++++---- src/villas-relay.hpp | 142 +- src/villas-signal.cpp | 461 +++--- src/villas-test-config.cpp | 137 +- src/villas-test-rtt.cpp | 327 ++-- src/villas-zmq-keygen.cpp | 57 +- tests/unit/config.cpp | 82 +- tests/unit/config_json.cpp | 122 +- tests/unit/format.cpp | 549 +++---- tests/unit/helpers.cpp | 11 +- tests/unit/helpers.hpp | 2 +- tests/unit/json.cpp | 104 +- tests/unit/main.cpp | 7 +- tests/unit/mapping.cpp | 117 +- tests/unit/memory.cpp | 117 +- tests/unit/pool.cpp | 81 +- tests/unit/queue.cpp | 456 +++--- tests/unit/queue_signalled.cpp | 186 ++- tests/unit/signal.cpp | 91 +- 300 files changed, 30949 insertions(+), 33000 deletions(-) diff --git a/clients/opal/models/send_receive/include/config.h b/clients/opal/models/send_receive/include/config.h index 1b28c4cfc..6136864ea 100644 --- a/clients/opal/models/send_receive/include/config.h +++ b/clients/opal/models/send_receive/include/config.h @@ -8,18 +8,18 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define PROGNAME "VILLASnode-OPAL-UDP" -#define VERSION "0.7" +#define PROGNAME "VILLASnode-OPAL-UDP" +#define VERSION "0.7" -#define MAX_VALUES 64 +#define MAX_VALUES 64 // List of protocols -#define VILLAS 1 -#define GTNET_SKT 2 +#define VILLAS 1 +#define GTNET_SKT 2 // Default protocol #ifndef PROTOCOL - #define PROTOCOL VILLAS +#define PROTOCOL VILLAS #endif // PROTOCOL #endif // _CONFIG_H_ diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index 95b7e769f..c3a9cf08a 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -10,65 +10,63 @@ #include // The current version number for the message format -#define MSG_VERSION 2 +#define MSG_VERSION 2 // TODO: Implement more message types -#define MSG_TYPE_DATA 0 // Message contains float values -#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case -#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case +#define MSG_TYPE_DATA 0 // Message contains float values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case // The total size in bytes of a message -#define MSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) +#define MSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) // The length of \p values values in bytes -#define MSG_DATA_LEN(values) (sizeof(float) * (values)) +#define MSG_DATA_LEN(values) (sizeof(float) * (values)) // The offset to the first data value in a message -#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, data)) +#define MSG_DATA_OFFSET(msg) ((char *)(msg) + offsetof(struct msg, data)) // Initialize a message with default values -#define MSG_INIT(len, seq) (struct msg) {\ - .version = MSG_VERSION, \ - .type = MSG_TYPE_DATA, \ - .length = len, \ - .sequence = seq, \ - .id = 0 \ -} +#define MSG_INIT(len, seq) \ + (struct msg) { \ + .version = MSG_VERSION, .type = MSG_TYPE_DATA, .length = len, \ + .sequence = seq, .id = 0 \ + } // 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) \ + (struct timespec) { .tv_sec = (msg)->ts.sec, .tv_nsec = (msg)->ts.nsec } // This message format is used by all clients -struct msg -{ +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 reserved1 : 2; // Reserved bits + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - 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) + 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 +#error Invalid byte-order #endif // BYTEORDER - uint8_t id; // 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 + uint8_t id; // 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 - // A timestamp per message - struct { - uint32_t sec; // Seconds since 1970-01-01 00:00:00 - uint32_t nsec; // Nanoseconds of the current second - } ts; + // A timestamp per message + struct { + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second + } ts; - // The message payload - union { - float f; // Floating point values - uint32_t i; // Integer values - } data[]; + // The message payload + union { + float f; // Floating point values + uint32_t i; // Integer values + } data[]; } __attribute__((packed)); diff --git a/clients/opal/models/send_receive/include/socket.h b/clients/opal/models/send_receive/include/socket.h index 372ad6ce2..427ce28a9 100644 --- a/clients/opal/models/send_receive/include/socket.h +++ b/clients/opal/models/send_receive/include/socket.h @@ -13,13 +13,13 @@ #define RT #include "OpalGenAsyncParamCtrl.h" -#define UDP_PROTOCOL 1 -#define TCP_PROTOCOL 2 +#define UDP_PROTOCOL 1 +#define TCP_PROTOCOL 2 struct socket { - struct sockaddr_in send_ad; // Send address - struct sockaddr_in recv_ad; // Receive address - int sd; // socket descriptor + struct sockaddr_in send_ad; // Send address + struct sockaddr_in recv_ad; // Receive address + int sd; // socket descriptor }; int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct); diff --git a/clients/opal/models/send_receive/src/compat.c b/clients/opal/models/send_receive/src/compat.c index e68c73b26..d127fcca3 100644 --- a/clients/opal/models/send_receive/src/compat.c +++ b/clients/opal/models/send_receive/src/compat.c @@ -9,27 +9,21 @@ #include -size_t __intel_sse2_strlen(const char *s) -{ - return strlen(s); +size_t __intel_sse2_strlen(const char *s) { return strlen(s); } + +void *_intel_fast_memset(void *b, int c, size_t len) { + return memset(b, c, len); } -void * _intel_fast_memset(void *b, int c, size_t len) -{ - return memset(b, c, len); +void *_intel_fast_memcpy(void *restrict dst, const void *restrict src, + size_t n) { + return memcpy(dst, src, n); } -void * _intel_fast_memcpy(void *restrict dst, const void *restrict src, size_t n) -{ - return memcpy(dst, src, n); +int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) { + return memcmp(s1, s2, n); } -int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) -{ - return memcmp(s1, s2, n); -} - -void * _intel_fast_memmove(void *dest, const void *src, size_t num) -{ - return memmove(dest, src, num); +void *_intel_fast_memmove(void *dest, const void *src, size_t num) { + return memmove(dest, src, num); } diff --git a/clients/opal/models/send_receive/src/main.c b/clients/opal/models/send_receive/src/main.c index 5714a4f86..147196f80 100644 --- a/clients/opal/models/send_receive/src/main.c +++ b/clients/opal/models/send_receive/src/main.c @@ -6,22 +6,22 @@ */ // Standard ANSI C headers needed for this program -#include -#include -#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ #define RTLAB -#include "OpalPrint.h" #include "AsyncApi.h" +#include "OpalPrint.h" // This is the message format #include "config.h" @@ -29,322 +29,334 @@ #include "utils.h" #if PROTOCOL == VILLAS - #include "msg.h" - #include "msg_format.h" +#include "msg.h" +#include "msg_format.h" #endif /* This is just for initializing the shared memory access to communicate * with the RT-LAB model. It's easier to remember the arguments like this */ -#define ASYNC_SHMEM_NAME argv[1] -#define ASYNC_SHMEM_SIZE atoi(argv[2]) -#define PRINT_SHMEM_NAME argv[3] +#define ASYNC_SHMEM_NAME argv[1] +#define ASYNC_SHMEM_SIZE atoi(argv[2]) +#define PRINT_SHMEM_NAME argv[3] // Global Variables struct socket skt; -static -void * SendToIPPort(void *arg) -{ - unsigned int ModelState, SendID, Sequence = 0; - int nbSend = 0, ret, cnt, len; +static void *SendToIPPort(void *arg) { + unsigned int ModelState, SendID, Sequence = 0; + int nbSend = 0, ret, cnt, len; - // Data from OPAL-RT model - double mdldata[MAX_VALUES]; - int mdldata_size; + // Data from OPAL-RT model + double mdldata[MAX_VALUES]; + int mdldata_size; #if PROTOCOL == VILLAS - char buf[MSG_LEN(MAX_VALUES)]; - struct msg *msg = (struct msg *) buf; + char buf[MSG_LEN(MAX_VALUES)]; + struct msg *msg = (struct msg *)buf; #elif PROTOCOL == GTNET_SKT - char buf[MAX_VALUES * sizeof(float)]; - float *msg = (float *) buf; + char buf[MAX_VALUES * sizeof(float)]; + float *msg = (float *)buf; #endif - OpalPrint("%s: SendToIPPort thread started\n", PROGNAME); + OpalPrint("%s: SendToIPPort thread started\n", PROGNAME); - OpalGetNbAsyncSendIcon(&nbSend); - if (nbSend < 1) { - OpalPrint("%s: SendToIPPort: No transimission block for this controller. Stopping thread.\n", PROGNAME); - return NULL; - } + OpalGetNbAsyncSendIcon(&nbSend); + if (nbSend < 1) { + OpalPrint("%s: SendToIPPort: No transimission block for this controller. " + "Stopping thread.\n", + PROGNAME); + return NULL; + } - do { - // This call unblocks when the 'Data Ready' line of a send icon is asserted. - ret = OpalWaitForAsyncSendRequest(&SendID); - if (ret != EOK) { - ModelState = OpalGetAsyncModelState(); - if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { - OpalSetAsyncSendIconError(ret, SendID); - OpalPrint("%s: OpalWaitForAsyncSendRequest(), errno %d\n", PROGNAME, ret); - } + do { + // This call unblocks when the 'Data Ready' line of a send icon is asserted. + ret = OpalWaitForAsyncSendRequest(&SendID); + if (ret != EOK) { + ModelState = OpalGetAsyncModelState(); + if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { + OpalSetAsyncSendIconError(ret, SendID); + OpalPrint("%s: OpalWaitForAsyncSendRequest(), errno %d\n", PROGNAME, + ret); + } - continue; - } + continue; + } - // No errors encountered yet - OpalSetAsyncSendIconError(0, SendID); + // No errors encountered yet + OpalSetAsyncSendIconError(0, SendID); - // Get the size of the data being sent by the unblocking SendID - OpalGetAsyncSendIconDataLength(&mdldata_size, SendID); - cnt = mdldata_size / sizeof(double); - if (cnt > MAX_VALUES) { - OpalPrint("%s: Number of signals for SendID=%d exceeds allowed maximum (%d). Limiting...\n", - PROGNAME, SendID, MAX_VALUES); - cnt = MAX_VALUES; - } + // Get the size of the data being sent by the unblocking SendID + OpalGetAsyncSendIconDataLength(&mdldata_size, SendID); + cnt = mdldata_size / sizeof(double); + if (cnt > MAX_VALUES) { + OpalPrint("%s: Number of signals for SendID=%d exceeds allowed maximum " + "(%d). Limiting...\n", + PROGNAME, SendID, MAX_VALUES); + cnt = MAX_VALUES; + } - // Read data from the model - OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID); + // Read data from the model + OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID); #if PROTOCOL == VILLAS - // Get current time - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); + // Get current time + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); - msg->version = MSG_VERSION; - msg->type = MSG_TYPE_DATA; - msg->reserved1 = 0; - msg->id = SendID; - msg->length = cnt; - msg->sequence = Sequence++; - msg->ts.sec = now.tv_sec; - msg->ts.nsec = now.tv_nsec; + msg->version = MSG_VERSION; + msg->type = MSG_TYPE_DATA; + msg->reserved1 = 0; + msg->id = SendID; + msg->length = cnt; + msg->sequence = Sequence++; + msg->ts.sec = now.tv_sec; + msg->ts.nsec = now.tv_nsec; - for (int i = 0; i < msg->length; i++) - msg->data[i].f = (float) mdldata[i]; + for (int i = 0; i < msg->length; i++) + msg->data[i].f = (float)mdldata[i]; - len = MSG_LEN(msg->length); + len = MSG_LEN(msg->length); - msg_hton(msg); + msg_hton(msg); #elif PROTOCOL == GTNET_SKT - uint32_t *imsg = (uint32_t *) msg; - for (int i = 0; i < cnt; i++) { - msg[i] = (float) mdldata[i]; - imsg[i] = htonl(imsg[i]); - } + uint32_t *imsg = (uint32_t *)msg; + for (int i = 0; i < cnt; i++) { + msg[i] = (float)mdldata[i]; + imsg[i] = htonl(imsg[i]); + } - len = cnt * sizeof(float); + len = cnt * sizeof(float); #else - #error Unknown protocol +#error Unknown protocol #endif - // Perform the actual write to the ip port - ret = socket_send(&skt, (char *) msg, len); - if (ret < 0) - OpalSetAsyncSendIconError(errno, SendID); - else - OpalSetAsyncSendIconError(0, SendID); + // Perform the actual write to the ip port + ret = socket_send(&skt, (char *)msg, len); + if (ret < 0) + OpalSetAsyncSendIconError(errno, SendID); + else + OpalSetAsyncSendIconError(0, SendID); - /* This next call allows the execution of the "asynchronous" process + /* This next call allows the execution of the "asynchronous" process * to actually be synchronous with the model. To achieve this, you * should set the "Sending Mode" in the Async_Send block to * NEED_REPLY_BEFORE_NEXT_SEND or NEED_REPLY_NOW. This will force * the model to wait for this process to call this * OpalAsyncSendRequestDone function before continuing. */ - OpalAsyncSendRequestDone(SendID); + OpalAsyncSendRequestDone(SendID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - ModelState = OpalGetAsyncModelState(); - } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); + ModelState = OpalGetAsyncModelState(); + } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); - OpalPrint("%s: SendToIPPort: Finished\n", PROGNAME); + OpalPrint("%s: SendToIPPort: Finished\n", PROGNAME); - return NULL; + return NULL; } -static -void * RecvFromIPPort(void *arg) -{ - unsigned int ModelState, RecvID; - int nbRecv = 0, ret, cnt; +static void *RecvFromIPPort(void *arg) { + unsigned int ModelState, RecvID; + int nbRecv = 0, ret, cnt; - // Data from OPAL-RT model - double mdldata[MAX_VALUES]; - int mdldata_size; + // Data from OPAL-RT model + double mdldata[MAX_VALUES]; + int mdldata_size; #if PROTOCOL == VILLAS - char buf[MSG_LEN(MAX_VALUES)]; - struct msg *msg = (struct msg *) buf; + char buf[MSG_LEN(MAX_VALUES)]; + struct msg *msg = (struct msg *)buf; #elif PROTOCOL == GTNET_SKT - char buf[MAX_VALUES * sizeof(float)]; - float *msg = (float *) buf; + char buf[MAX_VALUES * sizeof(float)]; + float *msg = (float *)buf; #else - #error Unknown protocol +#error Unknown protocol #endif - OpalPrint("%s: RecvFromIPPort thread started\n", PROGNAME); + OpalPrint("%s: RecvFromIPPort thread started\n", PROGNAME); - OpalGetNbAsyncRecvIcon(&nbRecv); - if (nbRecv < 1) { - OpalPrint("%s: RecvFromIPPort: No reception block for this controller. Stopping thread.\n", PROGNAME); - return NULL; - } + OpalGetNbAsyncRecvIcon(&nbRecv); + if (nbRecv < 1) { + OpalPrint("%s: RecvFromIPPort: No reception block for this controller. " + "Stopping thread.\n", + PROGNAME); + return NULL; + } - // Get list of RecvIds - unsigned int RecvIDs[nbRecv]; - ret = OpalGetAsyncRecvIDList(RecvIDs, sizeof(RecvIDs)); - if (ret != EOK) { - OpalPrint("%s: Failed to get list of RecvIDs\n", PROGNAME); - return NULL; - } + // Get list of RecvIds + unsigned int RecvIDs[nbRecv]; + ret = OpalGetAsyncRecvIDList(RecvIDs, sizeof(RecvIDs)); + if (ret != EOK) { + OpalPrint("%s: Failed to get list of RecvIDs\n", PROGNAME); + return NULL; + } - do { - // Receive message - ret = socket_recv(&skt, (char *) msg, sizeof(buf), 1.0); - if (ret < 1) { - ModelState = OpalGetAsyncModelState(); - if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { - if (ret == 0) // timeout, so we continue silently - OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno); - if (ret == -1) // a more serious error, so we print it - OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno); + do { + // Receive message + ret = socket_recv(&skt, (char *)msg, sizeof(buf), 1.0); + if (ret < 1) { + ModelState = OpalGetAsyncModelState(); + if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { + if (ret == 0) // timeout, so we continue silently + OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno); + if (ret == -1) // a more serious error, so we print it + OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno); - continue; - } - break; - } + continue; + } + break; + } #if PROTOCOL == VILLAS - RecvID = msg->id; + RecvID = msg->id; #elif PROTOCOL == GTNET_SKT - RecvID = 1; + RecvID = 1; #else - #error Unknown protocol +#error Unknown protocol #endif - // Check if this RecvID exists - for (int i = 0; i < nbRecv; i++) { - if (RecvIDs[i] == RecvID) - goto found; - } + // Check if this RecvID exists + for (int i = 0; i < nbRecv; i++) { + if (RecvIDs[i] == RecvID) + goto found; + } - OpalPrint("%s: Received message with non-existent RecvID=%d. Changing to RecvID=%d...\n", PROGNAME, RecvID, RecvIDs[0]); - RecvID = RecvIDs[0]; + OpalPrint("%s: Received message with non-existent RecvID=%d. Changing to " + "RecvID=%d...\n", + PROGNAME, RecvID, RecvIDs[0]); + RecvID = RecvIDs[0]; -found: // Get the number of signals to send back to the model - OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID); - cnt = mdldata_size / sizeof(double); - if (cnt > MAX_VALUES) { - OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds allowed maximum (%d)\n", - PROGNAME, RecvID, cnt, MAX_VALUES); - return NULL; - } + found: // Get the number of signals to send back to the model + OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID); + cnt = mdldata_size / sizeof(double); + if (cnt > MAX_VALUES) { + OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds allowed " + "maximum (%d)\n", + PROGNAME, RecvID, cnt, MAX_VALUES); + return NULL; + } #if PROTOCOL == VILLAS - msg_ntoh(msg); + msg_ntoh(msg); - ret = msg_verify(msg); - if (ret) { - OpalPrint("%s: Skipping invalid packet\n", PROGNAME); - continue; - } + ret = msg_verify(msg); + if (ret) { + OpalPrint("%s: Skipping invalid packet\n", PROGNAME); + continue; + } - if (cnt > msg->length) { - OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds what was received (%d)\n", - PROGNAME, RecvID, cnt, msg->length); - } + if (cnt > msg->length) { + OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds what was " + "received (%d)\n", + PROGNAME, RecvID, cnt, msg->length); + } - for (int i = 0; i < msg->length; i++) - mdldata[i] = (double) msg->data[i].f; + for (int i = 0; i < msg->length; i++) + mdldata[i] = (double)msg->data[i].f; - // Update OPAL model - OpalSetAsyncRecvIconStatus(msg->sequence, RecvID); // Set the Status to the message ID + // Update OPAL model + OpalSetAsyncRecvIconStatus(msg->sequence, + RecvID); // Set the Status to the message ID #elif PROTOCOL == GTNET_SKT - uint32_t *imsg = (uint32_t *) msg; - for (int i = 0; i < cnt; i++) { - imsg[i] = ntohl(imsg[i]); - mdldata[i] = (double) msg[i]; - } + uint32_t *imsg = (uint32_t *)msg; + for (int i = 0; i < cnt; i++) { + imsg[i] = ntohl(imsg[i]); + mdldata[i] = (double)msg[i]; + } #else - #error Unknown protocol +#error Unknown protocol #endif - OpalSetAsyncRecvIconError(0, RecvID); // Set the Error to 0 + OpalSetAsyncRecvIconError(0, RecvID); // Set the Error to 0 - OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); + OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - ModelState = OpalGetAsyncModelState(); - } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); + ModelState = OpalGetAsyncModelState(); + } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); - OpalPrint("%s: RecvFromIPPort: Finished\n", PROGNAME); + OpalPrint("%s: RecvFromIPPort: Finished\n", PROGNAME); - return NULL; + return NULL; } -int main(int argc, char *argv[]) -{ - int ret; +int main(int argc, char *argv[]) { + int ret; - Opal_GenAsyncParam_Ctrl IconCtrlStruct; + Opal_GenAsyncParam_Ctrl IconCtrlStruct; - pthread_t tid_send, tid_recv; + pthread_t tid_send, tid_recv; - OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION); + OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION); - // Check for the proper arguments to the program - if (argc < 4) { - printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize 3-PrintShmemName\n"); - exit(0); - } + // Check for the proper arguments to the program + if (argc < 4) { + printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize " + "3-PrintShmemName\n"); + exit(0); + } - // Enable the OpalPrint function. This prints to the OpalDisplay. - ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME); - if (ret != EOK) { - printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Enable the OpalPrint function. This prints to the OpalDisplay. + ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME); + if (ret != EOK) { + printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME); + exit(EXIT_FAILURE); + } - // Open Share Memory created by the model. - ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); - if (ret != EOK) { - OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Open Share Memory created by the model. + ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); + if (ret != EOK) { + OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME); + exit(EXIT_FAILURE); + } - AssignProcToCpu0(); + AssignProcToCpu0(); - /* Get IP Controler Parameters (ie: ip address, port number...) and + /* Get IP Controler Parameters (ie: ip address, port number...) and * initialize the device on the QNX node. */ - memset(&IconCtrlStruct, 0, sizeof(IconCtrlStruct)); + memset(&IconCtrlStruct, 0, sizeof(IconCtrlStruct)); - ret = OpalGetAsyncCtrlParameters(&IconCtrlStruct, sizeof(IconCtrlStruct)); - if (ret != EOK) { - OpalPrint("%s: ERROR: Could not get controller parameters (%d).\n", PROGNAME, ret); - exit(EXIT_FAILURE); - } + ret = OpalGetAsyncCtrlParameters(&IconCtrlStruct, sizeof(IconCtrlStruct)); + if (ret != EOK) { + OpalPrint("%s: ERROR: Could not get controller parameters (%d).\n", + PROGNAME, ret); + exit(EXIT_FAILURE); + } - // Initialize socket - ret = socket_init(&skt, IconCtrlStruct); - if (ret != EOK) { - OpalPrint("%s: ERROR: Failed to create socket.\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Initialize socket + ret = socket_init(&skt, IconCtrlStruct); + if (ret != EOK) { + OpalPrint("%s: ERROR: Failed to create socket.\n", PROGNAME); + exit(EXIT_FAILURE); + } - // Start send/receive threads - ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL); - if (ret < 0) - OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", PROGNAME, errno); + // Start send/receive threads + ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL); + if (ret < 0) + OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", + PROGNAME, errno); - ret = pthread_create(&tid_recv, NULL, RecvFromIPPort, NULL); - if (ret < 0) - OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", PROGNAME, errno); + ret = pthread_create(&tid_recv, NULL, RecvFromIPPort, NULL); + if (ret < 0) + OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", + PROGNAME, errno); - // Wait for both threads to finish - ret = pthread_join(tid_send, NULL); - if (ret) - OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, ret); + // Wait for both threads to finish + ret = pthread_join(tid_send, NULL); + if (ret) + OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, + ret); - ret = pthread_join(tid_recv, NULL); - if (ret) - OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, ret); + ret = pthread_join(tid_recv, NULL); + if (ret) + OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, + ret); - // Close the ip port and shared memories - socket_close(&skt, IconCtrlStruct); + // Close the ip port and shared memories + socket_close(&skt, IconCtrlStruct); - OpalCloseAsyncMem (ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); - OpalSystemCtrl_UnRegister(PRINT_SHMEM_NAME); + OpalCloseAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); + OpalSystemCtrl_UnRegister(PRINT_SHMEM_NAME); - return 0; + return 0; } diff --git a/clients/opal/models/send_receive/src/msg.c b/clients/opal/models/send_receive/src/msg.c index d07252191..d966b5fb4 100644 --- a/clients/opal/models/send_receive/src/msg.c +++ b/clients/opal/models/send_receive/src/msg.c @@ -10,46 +10,41 @@ #include "msg.h" #include "msg_format.h" -void msg_ntoh(struct msg *m) -{ - msg_hdr_ntoh(m); +void msg_ntoh(struct msg *m) { + msg_hdr_ntoh(m); - for (int i = 0; i < m->length; i++) - m->data[i].i = ntohl(m->data[i].i); + for (int i = 0; i < m->length; i++) + m->data[i].i = ntohl(m->data[i].i); } -void msg_hton(struct msg *m) -{ - for (int i = 0; i < m->length; i++) - m->data[i].i = htonl(m->data[i].i); +void msg_hton(struct msg *m) { + for (int i = 0; i < m->length; i++) + m->data[i].i = htonl(m->data[i].i); - msg_hdr_hton(m); + msg_hdr_hton(m); } -void msg_hdr_hton(struct msg *m) -{ - m->length = htons(m->length); - m->sequence = htonl(m->sequence); - m->ts.sec = htonl(m->ts.sec); - m->ts.nsec = htonl(m->ts.nsec); +void msg_hdr_hton(struct msg *m) { + m->length = htons(m->length); + m->sequence = htonl(m->sequence); + m->ts.sec = htonl(m->ts.sec); + m->ts.nsec = htonl(m->ts.nsec); } -void msg_hdr_ntoh(struct msg *m) -{ - m->length = ntohs(m->length); - m->sequence = ntohl(m->sequence); - m->ts.sec = ntohl(m->ts.sec); - m->ts.nsec = ntohl(m->ts.nsec); +void msg_hdr_ntoh(struct msg *m) { + m->length = ntohs(m->length); + m->sequence = ntohl(m->sequence); + m->ts.sec = ntohl(m->ts.sec); + m->ts.nsec = ntohl(m->ts.nsec); } -int msg_verify(struct msg *m) -{ - if (m->version != MSG_VERSION) - return -1; - else if (m->type != MSG_TYPE_DATA) - return -2; - else if (m->reserved1 != 0) - return -3; - else - return 0; +int msg_verify(struct msg *m) { + if (m->version != MSG_VERSION) + return -1; + else if (m->type != MSG_TYPE_DATA) + return -2; + else if (m->reserved1 != 0) + return -3; + else + return 0; } diff --git a/clients/opal/models/send_receive/src/socket.c b/clients/opal/models/send_receive/src/socket.c index a4d314b3e..77cc5ec3b 100644 --- a/clients/opal/models/send_receive/src/socket.c +++ b/clients/opal/models/send_receive/src/socket.c @@ -5,165 +5,177 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ #define RTLAB -#include "OpalPrint.h" #include "AsyncApi.h" +#include "OpalPrint.h" #include "config.h" #include "socket.h" -int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) -{ - struct ip_mreq mreq; // Multicast group structure - unsigned char TTL = 1, LOOP = 0; - int rc, proto, ret; +int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) { + struct ip_mreq mreq; // Multicast group structure + unsigned char TTL = 1, LOOP = 0; + int rc, proto, ret; - proto = (int) IconCtrlStruct.FloatParam[0]; - if (proto != UDP_PROTOCOL) { - OpalPrint("%s: This version of %s only supports UDP\n", PROGNAME, PROGNAME); - return EIO; - } + proto = (int)IconCtrlStruct.FloatParam[0]; + if (proto != UDP_PROTOCOL) { + OpalPrint("%s: This version of %s only supports UDP\n", PROGNAME, PROGNAME); + return EIO; + } - OpalPrint("%s: Version : %s\n", PROGNAME, VERSION); - OpalPrint("%s: Remote Address : %s\n", PROGNAME, IconCtrlStruct.StringParam[0]); - OpalPrint("%s: Remote Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[1]); + OpalPrint("%s: Version : %s\n", PROGNAME, VERSION); + OpalPrint("%s: Remote Address : %s\n", PROGNAME, + IconCtrlStruct.StringParam[0]); + OpalPrint("%s: Remote Port : %d\n", PROGNAME, + (int)IconCtrlStruct.FloatParam[1]); - // Initialize the socket - s->sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s->sd < 0) { - OpalPrint("%s: ERROR: Could not open socket\n", PROGNAME); - return EIO; - } + // Initialize the socket + s->sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s->sd < 0) { + OpalPrint("%s: ERROR: Could not open socket\n", PROGNAME); + return EIO; + } - // Set the structure for the remote port and address - memset(&s->send_ad, 0, sizeof(s->send_ad)); - s->send_ad.sin_family = AF_INET; - s->send_ad.sin_addr.s_addr = inet_addr(IconCtrlStruct.StringParam[0]); - s->send_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[1]); + // Set the structure for the remote port and address + memset(&s->send_ad, 0, sizeof(s->send_ad)); + s->send_ad.sin_family = AF_INET; + s->send_ad.sin_addr.s_addr = inet_addr(IconCtrlStruct.StringParam[0]); + s->send_ad.sin_port = htons((u_short)IconCtrlStruct.FloatParam[1]); - // Set the structure for the local port and address - memset(&s->recv_ad, 0, sizeof(s->recv_ad)); - s->recv_ad.sin_family = AF_INET; - s->recv_ad.sin_addr.s_addr = INADDR_ANY; - s->recv_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[2]); + // Set the structure for the local port and address + memset(&s->recv_ad, 0, sizeof(s->recv_ad)); + s->recv_ad.sin_family = AF_INET; + s->recv_ad.sin_addr.s_addr = INADDR_ANY; + s->recv_ad.sin_port = htons((u_short)IconCtrlStruct.FloatParam[2]); - // Bind local port and address to socket. - ret = bind(s->sd, (struct sockaddr *) &s->recv_ad, sizeof(struct sockaddr_in)); - if (ret < 0) { - OpalPrint("%s: ERROR: Could not bind local port to socket\n", PROGNAME); - return EIO; - } - else - OpalPrint("%s: Local Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[2]); + // Bind local port and address to socket. + ret = bind(s->sd, (struct sockaddr *)&s->recv_ad, sizeof(struct sockaddr_in)); + if (ret < 0) { + OpalPrint("%s: ERROR: Could not bind local port to socket\n", PROGNAME); + return EIO; + } else + OpalPrint("%s: Local Port : %d\n", PROGNAME, + (int)IconCtrlStruct.FloatParam[2]); - // If sending to a multicast address - if ((inet_addr(IconCtrlStruct.StringParam[0]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not set TTL for multicast send (%d)\n", PROGNAME, errno); - return EIO; - } + // If sending to a multicast address + if ((inet_addr(IconCtrlStruct.StringParam[0]) & inet_addr("240.0.0.0")) == + inet_addr("224.0.0.0")) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, + sizeof(TTL)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not set TTL for multicast send (%d)\n", + PROGNAME, errno); + return EIO; + } - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&LOOP, sizeof(LOOP)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not set loopback for multicast send (%d)\n", PROGNAME, errno); - return EIO; - } + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&LOOP, + sizeof(LOOP)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not set loopback for multicast send (%d)\n", + PROGNAME, errno); + return EIO; + } - OpalPrint("%s: Configured socket for sending to multicast address\n", PROGNAME); - } + OpalPrint("%s: Configured socket for sending to multicast address\n", + PROGNAME); + } - // If receiving from a multicast group, register for it. - if (inet_addr(IconCtrlStruct.StringParam[1]) > 0) { - if ((inet_addr(IconCtrlStruct.StringParam[1]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { - mreq.imr_multiaddr.s_addr = inet_addr(IconCtrlStruct.StringParam[1]); - mreq.imr_interface.s_addr = INADDR_ANY; + // If receiving from a multicast group, register for it. + if (inet_addr(IconCtrlStruct.StringParam[1]) > 0) { + if ((inet_addr(IconCtrlStruct.StringParam[1]) & inet_addr("240.0.0.0")) == + inet_addr("224.0.0.0")) { + mreq.imr_multiaddr.s_addr = inet_addr(IconCtrlStruct.StringParam[1]); + mreq.imr_interface.s_addr = INADDR_ANY; - // Have the multicast socket join the multicast group - ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not join multicast group (%d)\n", PROGNAME, errno); - return EIO; - } + // Have the multicast socket join the multicast group + ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, + sizeof(mreq)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not join multicast group (%d)\n", PROGNAME, + errno); + return EIO; + } - OpalPrint("%s: Added process to multicast group (%s)\n", PROGNAME, IconCtrlStruct.StringParam[1]); - } - else - OpalPrint("%s: WARNING: IP address for multicast group is not in multicast range. Ignored\n", PROGNAME); - } + OpalPrint("%s: Added process to multicast group (%s)\n", PROGNAME, + IconCtrlStruct.StringParam[1]); + } else + OpalPrint("%s: WARNING: IP address for multicast group is not in " + "multicast range. Ignored\n", + PROGNAME); + } - return EOK; + return EOK; } -int socket_close(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) -{ - int ret; +int socket_close(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) { + int ret; - ret = shutdown(s->sd, SHUT_RDWR); - if (ret) - return ret; + ret = shutdown(s->sd, SHUT_RDWR); + if (ret) + return ret; - ret = close(s->sd); - if (ret) - return ret; + ret = close(s->sd); + if (ret) + return ret; - return 0; + return 0; } -int socket_send(struct socket *s, char *data, int len) -{ - return sendto(s->sd, data, len, 0, (struct sockaddr *) &s->send_ad, sizeof(s->send_ad)); +int socket_send(struct socket *s, char *data, int len) { + return sendto(s->sd, data, len, 0, (struct sockaddr *)&s->send_ad, + sizeof(s->send_ad)); } -int socket_recv(struct socket *s, char *data, int len, double timeout) -{ - int ret; - struct sockaddr_in client_ad; - struct timeval tv; - socklen_t client_ad_size = sizeof(client_ad); - fd_set sd_set; +int socket_recv(struct socket *s, char *data, int len, double timeout) { + int ret; + struct sockaddr_in client_ad; + struct timeval tv; + socklen_t client_ad_size = sizeof(client_ad); + fd_set sd_set; - // Set the descriptor set for the select() call - FD_ZERO(&sd_set); - FD_SET(s->sd, &sd_set); + // Set the descriptor set for the select() call + FD_ZERO(&sd_set); + FD_SET(s->sd, &sd_set); - // Set the tv structure to the correct timeout value - tv.tv_sec = (int) timeout; - tv.tv_usec = (int) ((timeout - tv.tv_sec) * 1000000); + // Set the tv structure to the correct timeout value + tv.tv_sec = (int)timeout; + tv.tv_usec = (int)((timeout - tv.tv_sec) * 1000000); - /* Wait for a packet. We use select() to have a timeout. This is + /* Wait for a packet. We use select() to have a timeout. This is * necessary when reseting the model so we don't wait indefinitely * and prevent the process from exiting and freeing the port for * a future instance (model load). */ - ret = select(s->sd + 1, &sd_set, (fd_set *) 0, (fd_set *) 0, &tv); - switch (ret) { - case -1: // Error - return -1; - case 0: // We hit the timeout - return 0; - default: - if (!(FD_ISSET(s->sd, &sd_set))) { - /* We received something, but it's not on "sd". Since sd is the only + ret = select(s->sd + 1, &sd_set, (fd_set *)0, (fd_set *)0, &tv); + switch (ret) { + case -1: // Error + return -1; + case 0: // We hit the timeout + return 0; + default: + if (!(FD_ISSET(s->sd, &sd_set))) { + /* We received something, but it's not on "sd". Since sd is the only * descriptor in the set... */ - OpalPrint("%s: RecvPacket: God, is that You trying to reach me?\n", PROGNAME); - return -1; - } - } + OpalPrint("%s: RecvPacket: God, is that You trying to reach me?\n", + PROGNAME); + return -1; + } + } - // Clear the data array (in case we receive an incomplete packet) - memset(data, 0, len); + // Clear the data array (in case we receive an incomplete packet) + memset(data, 0, len); - // Perform the reception - return recvfrom(s->sd, data, len, 0, (struct sockaddr *) &client_ad, &client_ad_size); + // Perform the reception + return recvfrom(s->sd, data, len, 0, (struct sockaddr *)&client_ad, + &client_ad_size); } diff --git a/clients/opal/models/send_receive/src/utils.c b/clients/opal/models/send_receive/src/utils.c index 3015fc344..76e1daa7e 100644 --- a/clients/opal/models/send_receive/src/utils.c +++ b/clients/opal/models/send_receive/src/utils.c @@ -18,20 +18,19 @@ #include "config.h" #include "utils.h" -int AssignProcToCpu0(void) -{ - int ret; - cpu_set_t bindSet; - - CPU_ZERO(&bindSet); - CPU_SET(0, &bindSet); +int AssignProcToCpu0(void) { + int ret; + cpu_set_t bindSet; - // Changing process cpu affinity - ret = sched_setaffinity(0, sizeof(cpu_set_t), &bindSet); - if (ret) { - OpalPrint("Unable to bind the process to CPU 0: %d\n", errno); - return EINVAL; - } + CPU_ZERO(&bindSet); + CPU_SET(0, &bindSet); - return 0; + // Changing process cpu affinity + ret = sched_setaffinity(0, sizeof(cpu_set_t), &bindSet); + if (ret) { + OpalPrint("Unable to bind the process to CPU 0: %d\n", errno); + return EINVAL; + } + + return 0; } diff --git a/clients/shmem/villas-shmem.cpp b/clients/shmem/villas-shmem.cpp index 289970905..0f2f05ca2 100644 --- a/clients/shmem/villas-shmem.cpp +++ b/clients/shmem/villas-shmem.cpp @@ -8,19 +8,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include +#include #include +#include +#include #include #include #include -#include #include -#include #include -#include namespace villas { namespace node { @@ -29,101 +29,94 @@ namespace tools { class Shmem : public Tool { public: - Shmem(int argc, char *argv[]) : - Tool(argc, argv, "shmem"), - stop(false) - { } + Shmem(int argc, char *argv[]) : Tool(argc, argv, "shmem"), stop(false) {} protected: - std::atomic stop; + std::atomic stop; - 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; + 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; - printCopyright(); - } + printCopyright(); + } - void handler(int, siginfo_t *, void *) - { - stop = true; - } + void handler(int, siginfo_t *, void *) { stop = true; } - int main() - { - int ret, readcnt, writecnt, avail; + int main() { + int ret, readcnt, writecnt, avail; - struct ShmemInterface shm; - struct ShmemConfig conf = { - .polling = 0, - .queuelen = DEFAULT_SHMEM_QUEUELEN, - .samplelen = DEFAULT_SHMEM_SAMPLELEN - }; + struct ShmemInterface shm; + struct ShmemConfig conf = {.polling = 0, + .queuelen = DEFAULT_SHMEM_QUEUELEN, + .samplelen = DEFAULT_SHMEM_SAMPLELEN}; - if (argc != 4) { - usage(); - return 1; - } + if (argc != 4) { + usage(); + return 1; + } - std::string wname = argv[1]; - std::string rname = argv[2]; - int vectorize = atoi(argv[3]); + 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"); + 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]; + struct Sample *insmps[vectorize], *outsmps[vectorize]; - while (!stop) { - readcnt = shmem_int_read(&shm, insmps, vectorize); - if (readcnt == -1) { - logger->info("Node stopped, exiting"); - break; - } + 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: {} / {}", avail, readcnt); + avail = shmem_int_alloc(&shm, outsmps, readcnt); + if (avail < readcnt) + logger->warn("Pool underrun: {} / {}", avail, readcnt); - for (int i = 0; i < avail; i++) { - outsmps[i]->sequence = insmps[i]->sequence; - outsmps[i]->ts = insmps[i]->ts; + 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)); + int len = MIN(insmps[i]->length, outsmps[i]->capacity); + memcpy(outsmps[i]->data, insmps[i]->data, SAMPLE_DATA_LENGTH(len)); - outsmps[i]->length = len; - } + outsmps[i]->length = len; + } - for (int i = 0; i < readcnt; i++) - sample_decref(insmps[i]); + 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"); + writecnt = shmem_int_write(&shm, outsmps, avail); + if (writecnt < avail) + logger->warn("Short write"); - logger->info("Read / Write: {}/{}", readcnt, writecnt); - } + logger->info("Read / Write: {}/{}", readcnt, writecnt); + } - ret = shmem_int_close(&shm); - if (ret) - throw RuntimeError("Failed to close shared-memory interface"); + ret = shmem_int_close(&shm); + if (ret) + throw RuntimeError("Failed to close shared-memory interface"); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Shmem t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Shmem t(argc, argv); - return t.run(); + return t.run(); } diff --git a/include/villas/api.hpp b/include/villas/api.hpp index 59622799f..7ced72a0a 100644 --- a/include/villas/api.hpp +++ b/include/villas/api.hpp @@ -11,15 +11,15 @@ #include #include -#include #include +#include #include -#include #include -#include #include +#include +#include namespace villas { namespace node { @@ -35,41 +35,35 @@ class Request; class Error : public RuntimeError { public: + template + Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, + const std::string &msg = "Invalid API request", Args &&...args) + : RuntimeError(msg, std::forward(args)...), code(c), json(nullptr) { + } - template - Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", Args&&... args) : - RuntimeError(msg, std::forward(args)...), - code(c), - json(nullptr) - { } + template + Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, + const std::string &msg = "Invalid API request", + const char *fmt = nullptr, Args &&...args) + : RuntimeError(msg), code(c), + json(fmt ? json_pack(fmt, std::forward(args)...) : nullptr) {} - template - Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", const char *fmt = nullptr, Args&&... args) : - RuntimeError(msg), - code(c), - json(fmt - ? json_pack(fmt, std::forward(args)...) - : nullptr - ) - { } - - int code; - json_t *json; + int code; + json_t *json; }; class BadRequest : public Error { public: - template - BadRequest(const std::string &msg = "Bad API request", Args&&... args) : - Error(HTTP_STATUS_BAD_REQUEST, msg, std::forward(args)...) - { } + template + BadRequest(const std::string &msg = "Bad API request", Args &&...args) + : Error(HTTP_STATUS_BAD_REQUEST, msg, std::forward(args)...) {} }; class InvalidMethod : public BadRequest { public: - InvalidMethod(Request *req); + InvalidMethod(Request *req); }; } // namespace api @@ -80,36 +74,34 @@ class SuperNode; class Api { protected: - Logger logger; + Logger logger; - enum State state; + enum State state; - std::thread thread; - std::atomic running; // Atomic flag for signalizing thread termination. + std::thread thread; + std::atomic running; // Atomic flag for signalizing thread termination. - SuperNode *super_node; + SuperNode *super_node; - void run(); - void worker(); + void run(); + void worker(); public: - /* Initialize the API. + /* Initialize the API. * * Save references to list of paths / nodes for command execution. */ - Api(SuperNode *sn); - ~Api(); + Api(SuperNode *sn); + ~Api(); - void start(); - void stop(); + void start(); + void stop(); - SuperNode * getSuperNode() - { - return super_node; - } + SuperNode *getSuperNode() { return super_node; } - std::list sessions; // List of currently active connections - villas::QueueSignalled pending; // A queue of api_sessions which have pending requests. + std::list sessions; // List of currently active connections + villas::QueueSignalled + pending; // A queue of api_sessions which have pending requests. }; } // namespace node diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index 45fcb0d5e..69bdcd0b7 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -7,17 +7,19 @@ #pragma once -#include -#include #include +#include +#include -#include +#include #include +#include #include #include -#include -#define RE_UUID "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" +#define RE_UUID \ + "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{" \ + "12}" namespace villas { namespace node { @@ -30,152 +32,107 @@ class RequestFactory; class Request { - friend Session; - friend RequestFactory; - friend Response; + friend Session; + friend RequestFactory; + friend Response; protected: - Session *session; + Session *session; - Logger logger; - Buffer buffer; + Logger logger; + Buffer buffer; public: - std::vector matches; - Session::Method method; - unsigned long contentLength; - json_t *body; + std::vector matches; + Session::Method method; + unsigned long contentLength; + json_t *body; - RequestFactory *factory; + RequestFactory *factory; - Request(Session *s) : - session(s), - method(Session::Method::UNKNOWN), - contentLength(0), - body(nullptr), - factory(nullptr) - { } + Request(Session *s) + : session(s), method(Session::Method::UNKNOWN), contentLength(0), + body(nullptr), factory(nullptr) {} - virtual - ~Request() - { - if (body) - json_decref(body); - } + virtual ~Request() { + if (body) + json_decref(body); + } - virtual - void prepare() - { } + virtual void prepare() {} - virtual - Response * execute() = 0; + virtual Response *execute() = 0; - virtual - void decode(); + virtual void decode(); - const std::string & getMatch(int idx) const - { - return matches[idx]; - } + const std::string &getMatch(int idx) const { return matches[idx]; } - std::string getQueryArg(const std::string &arg) - { - char buf[1024]; - const char *val; + std::string getQueryArg(const std::string &arg) { + char buf[1024]; + const char *val; - val = lws_get_urlarg_by_name(session->wsi, (arg + "=").c_str(), buf, sizeof(buf)); + val = lws_get_urlarg_by_name(session->wsi, (arg + "=").c_str(), buf, + sizeof(buf)); - return val ? std::string(val) : std::string(); - } + return val ? std::string(val) : std::string(); + } - std::string getHeader(enum lws_token_indexes hdr) - { - char buf[1024]; + std::string getHeader(enum lws_token_indexes hdr) { + char buf[1024]; - lws_hdr_copy(session->wsi, buf, sizeof(buf), hdr); + lws_hdr_copy(session->wsi, buf, sizeof(buf), hdr); - return std::string(buf); - } + return std::string(buf); + } - virtual - std::string toString(); + virtual std::string toString(); }; class RequestFactory : public plugin::Plugin { public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - bool match(const std::string &uri, std::smatch &m) const = 0; + virtual bool match(const std::string &uri, std::smatch &m) const = 0; - virtual - Request * make(Session *s) = 0; + virtual Request *make(Session *s) = 0; - static - Request * create(Session *s, const std::string &uri, Session::Method meth, unsigned long ct); + static Request *create(Session *s, const std::string &uri, + Session::Method meth, unsigned long ct); - virtual - void init(Request *r) - { - r->logger = getLogger(); - } + virtual void init(Request *r) { r->logger = getLogger(); } - virtual - std::string - getType() const - { - return "api:request"; - } + virtual std::string getType() const { return "api:request"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; -template +template class RequestPlugin : public RequestFactory { protected: - std::regex regex; + std::regex regex; public: - RequestPlugin() : - RequestFactory(), - regex(re) - { } + RequestPlugin() : RequestFactory(), regex(re) {} - virtual - Request * make(Session *s) - { - auto *r = new T(s); + virtual Request *make(Session *s) { + auto *r = new T(s); - init(r); + init(r); - return r; - } + return r; + } - // Get plugin name - virtual - std::string getName() const - { - return name; - } + // Get plugin name + virtual std::string getName() const { return name; } - // Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + // Get plugin description + virtual std::string getDescription() const { return desc; } - virtual - bool match(const std::string &uri, std::smatch &match) const - { - return std::regex_match(uri, match, regex); - } + virtual bool match(const std::string &uri, std::smatch &match) const { + return std::regex_match(uri, match, regex); + } }; } // namespace api diff --git a/include/villas/api/requests/node.hpp b/include/villas/api/requests/node.hpp index dda48a628..831a7ba43 100644 --- a/include/villas/api/requests/node.hpp +++ b/include/villas/api/requests/node.hpp @@ -20,13 +20,12 @@ namespace api { class NodeRequest : public Request { protected: - Node *node; + Node *node; public: - using Request::Request; + using Request::Request; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/path.hpp b/include/villas/api/requests/path.hpp index 260aaf385..2ea23f6c1 100644 --- a/include/villas/api/requests/path.hpp +++ b/include/villas/api/requests/path.hpp @@ -18,13 +18,12 @@ namespace api { class PathRequest : public Request { protected: - class Path *path; + class Path *path; public: - using Request::Request; + using Request::Request; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/universal.hpp b/include/villas/api/requests/universal.hpp index c5772c6a6..2452c8e7e 100644 --- a/include/villas/api/requests/universal.hpp +++ b/include/villas/api/requests/universal.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -21,13 +21,12 @@ namespace api { class UniversalRequest : public NodeRequest { protected: - APINode *api_node; + APINode *api_node; public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/response.hpp b/include/villas/api/response.hpp index ebf1286ef..2fc9e3ec3 100644 --- a/include/villas/api/response.hpp +++ b/include/villas/api/response.hpp @@ -11,11 +11,11 @@ #include -#include +#include #include #include +#include #include -#include namespace villas { namespace node { @@ -28,71 +28,60 @@ class Request; class Response { public: - friend Session; + friend Session; - Response(Session *s, int c = HTTP_STATUS_OK, const std::string &ct = "text/html; charset=UTF-8", const Buffer &b = Buffer()); + Response(Session *s, int c = HTTP_STATUS_OK, + const std::string &ct = "text/html; charset=UTF-8", + const Buffer &b = Buffer()); - virtual - ~Response() - { } + virtual ~Response() {} - virtual - void encodeBody() - { } + virtual void encodeBody() {} - int - writeBody(struct lws *wsi); + int writeBody(struct lws *wsi); - int - writeHeaders(struct lws *wsi); + int writeHeaders(struct lws *wsi); - void - setHeader(const std::string &key, const std::string &value) - { - headers[key] = value; - } + void setHeader(const std::string &key, const std::string &value) { + headers[key] = value; + } protected: - Session *session; - Logger logger; - Buffer buffer; + Session *session; + Logger logger; + Buffer buffer; - int code; - std::string contentType; - std::map headers; + int code; + std::string contentType; + std::map headers; }; class JsonResponse : public Response { protected: - json_t *response; + json_t *response; public: - JsonResponse(Session *s, int c, json_t *r) : - Response(s, c, "application/json"), - response(r) - { } + JsonResponse(Session *s, int c, json_t *r) + : Response(s, c, "application/json"), response(r) {} - virtual - ~JsonResponse(); + virtual ~JsonResponse(); - virtual - void encodeBody(); + virtual void encodeBody(); }; class ErrorResponse : public JsonResponse { public: - ErrorResponse(Session *s, const RuntimeError &e) : - JsonResponse(s, HTTP_STATUS_INTERNAL_SERVER_ERROR, json_pack("{ s: s }", "error", e.what())) - { } + ErrorResponse(Session *s, const RuntimeError &e) + : JsonResponse(s, HTTP_STATUS_INTERNAL_SERVER_ERROR, + json_pack("{ s: s }", "error", e.what())) {} - ErrorResponse(Session *s, const Error &e) : - JsonResponse(s, e.code, json_pack("{ s: s }", "error", e.what())) - { - if (e.json) - json_object_update(response, e.json); - } + ErrorResponse(Session *s, const Error &e) + : JsonResponse(s, e.code, json_pack("{ s: s }", "error", e.what())) { + if (e.json) + json_object_update(response, e.json); + } }; } // namespace api diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index 901d727a1..005374221 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -9,9 +9,9 @@ #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -33,72 +33,53 @@ class RequestFactory; class Session { public: - friend Request; // Requires access to wsi for getting URL args and headers - friend StatusRequest; // Requires access to wsi for context status - friend RequestFactory; + friend Request; // Requires access to wsi for getting URL args and headers + friend StatusRequest; // Requires access to wsi for context status + friend RequestFactory; - enum State { - ESTABLISHED, - SHUTDOWN - }; + enum State { ESTABLISHED, SHUTDOWN }; - enum Version { - UNKNOWN_VERSION = 0, - VERSION_1 = 1, - VERSION_2 = 2 - }; + enum Version { UNKNOWN_VERSION = 0, VERSION_1 = 1, VERSION_2 = 2 }; - enum Method { - UNKNOWN, - GET, - POST, - DELETE, - OPTIONS, - PUT, - PATCH - }; + enum Method { UNKNOWN, GET, POST, DELETE, OPTIONS, PUT, PATCH }; protected: - enum State state; - enum Version version; + enum State state; + enum Version version; - lws *wsi; + lws *wsi; - Web *web; - Api *api; + Web *web; + Api *api; - Logger logger; + Logger logger; - std::unique_ptr request; - std::unique_ptr response; + std::unique_ptr request; + std::unique_ptr response; - bool headersSent; + bool headersSent; public: - Session(struct lws *w); - ~Session(); + Session(struct lws *w); + ~Session(); - std::string getName() const; + std::string getName() const; - SuperNode * getSuperNode() const - { - return api->getSuperNode(); - } + SuperNode *getSuperNode() const { return api->getSuperNode(); } - void open(void *in, size_t len); - int writeable(); - void body(void *in, size_t len); - void bodyComplete(); - void execute(); - void shutdown(); + void open(void *in, size_t len); + int writeable(); + void body(void *in, size_t len); + void bodyComplete(); + void execute(); + void shutdown(); - static - int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - Method getRequestMethod() const; + Method getRequestMethod() const; - static - std::string methodToString(Method meth); + static std::string methodToString(Method meth); }; } // namespace api diff --git a/include/villas/api/universal.hpp b/include/villas/api/universal.hpp index 20b497ec7..96ac12447 100644 --- a/include/villas/api/universal.hpp +++ b/include/villas/api/universal.hpp @@ -8,9 +8,9 @@ #pragma once +#include #include #include -#include #include @@ -21,33 +21,30 @@ namespace node { namespace api { namespace universal { -enum PayloadType { - SAMPLES = 0, - EVENTS = 1 -}; +enum PayloadType { SAMPLES = 0, EVENTS = 1 }; // Channel (uAPI) is a synonym for signal (VILLAS) class Channel { public: - std::string description; - PayloadType payload; - double range_min; - double range_max; - std::vector range_options; - double rate; - bool readable; - bool writable; + std::string description; + PayloadType payload; + double range_min; + double range_max; + std::vector range_options; + double rate; + bool readable; + bool writable; - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - void parse(json_t *json); - json_t * toJson(Signal::Ptr sig) const; + void parse(json_t *json); + json_t *toJson(Signal::Ptr sig) const; }; class ChannelList : public std::vector { public: - void parse(json_t *json, bool readable, bool writable); + void parse(json_t *json, bool readable, bool writable); }; } // namespace universal diff --git a/include/villas/capabilities.hpp b/include/villas/capabilities.hpp index 48c2f58a1..9420c1d2a 100644 --- a/include/villas/capabilities.hpp +++ b/include/villas/capabilities.hpp @@ -12,7 +12,7 @@ namespace villas { namespace node { -json_t * getCapabilities(); +json_t *getCapabilities(); } // namespace node -} // namepace vilals +} // namespace villas diff --git a/include/villas/config_class.hpp b/include/villas/config_class.hpp index 68dbf6445..60acdc251 100644 --- a/include/villas/config_class.hpp +++ b/include/villas/config_class.hpp @@ -8,17 +8,17 @@ #pragma once #include -#include #include +#include #include #include -#include #include +#include #ifdef WITH_CONFIG - #include +#include #endif namespace villas { @@ -27,65 +27,66 @@ namespace node { class Config { protected: - using str_walk_fcn_t = std::function; + using str_walk_fcn_t = std::function; - Logger logger; + Logger logger; - std::list includeDirectories; + std::list includeDirectories; - // Check if file exists on local system. - static - bool isLocalFile(const std::string &uri) - { - return access(uri.c_str(), F_OK) != -1; - } + // Check if file exists on local system. + static bool isLocalFile(const std::string &uri) { + return access(uri.c_str(), F_OK) != -1; + } - // Decode configuration file. - json_t * decode(FILE *f); + // Decode configuration file. + json_t *decode(FILE *f); #ifdef WITH_CONFIG - // Convert libconfig .conf file to libjansson .json file. - json_t * libconfigDecode(FILE *f); + // Convert libconfig .conf file to libjansson .json file. + json_t *libconfigDecode(FILE *f); - static - const char ** includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error); + static const char **includeFuncStub(config_t *cfg, const char *include_dir, + const char *path, const char **error); - const char ** includeFunc(config_t *cfg, const char *include_dir, const char *path, const char **error); + const char **includeFunc(config_t *cfg, const char *include_dir, + const char *path, const char **error); #endif // WITH_CONFIG - // Load configuration from standard input (stdim). - FILE * loadFromStdio(); + // Load configuration from standard input (stdim). + FILE *loadFromStdio(); - // Load configuration from local file. - FILE * loadFromLocalFile(const std::string &u); + // Load configuration from local file. + FILE *loadFromLocalFile(const std::string &u); - std::list resolveIncludes(const std::string &name); + std::list resolveIncludes(const std::string &name); - void resolveEnvVars(std::string &text); + void resolveEnvVars(std::string &text); - // Resolve custom include directives. - json_t * expandIncludes(json_t *in); + // Resolve custom include directives. + json_t *expandIncludes(json_t *in); - // To shell-like subsitution of environment variables in strings. - json_t * expandEnvVars(json_t *in); + // To shell-like subsitution of environment variables in strings. + json_t *expandEnvVars(json_t *in); - // Run a callback function for each string in the config - json_t * walkStrings(json_t *in, str_walk_fcn_t cb); + // Run a callback function for each string in the config + json_t *walkStrings(json_t *in, str_walk_fcn_t cb); - // Get the include dirs - std::list getIncludeDirectories(FILE *f) const; + // Get the include dirs + std::list getIncludeDirectories(FILE *f) const; public: - json_t *root; + json_t *root; - Config(); - Config(const std::string &u); + Config(); + Config(const std::string &u); - ~Config(); + ~Config(); - json_t * load(std::FILE *f, bool resolveIncludes = true, bool resolveEnvVars = true); + json_t *load(std::FILE *f, bool resolveIncludes = true, + bool resolveEnvVars = true); - json_t * load(const std::string &u, bool resolveIncludes = true, bool resolveEnvVars = true); + json_t *load(const std::string &u, bool resolveIncludes = true, + bool resolveEnvVars = true); }; } // namespace node diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index 6a1ea189c..1fa578891 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -8,7 +8,7 @@ #pragma once #ifdef WITH_CONFIG - #include +#include #endif #include @@ -22,7 +22,7 @@ namespace node { #ifdef WITH_CONFIG // Convert a libconfig object to a jansson object -json_t * config_to_json(struct config_setting_t *cfg); +json_t *config_to_json(struct config_setting_t *cfg); // Convert a jansson object into a libconfig object. int json_to_config(json_t *json, struct config_setting_t *parent); @@ -31,14 +31,16 @@ int json_to_config(json_t *json, struct config_setting_t *parent); int json_object_extend_str(json_t *orig, const char *str); -void json_object_extend_key_value(json_t *obj, const char *key, const char *value); +void json_object_extend_key_value(json_t *obj, const char *key, + const char *value); -void json_object_extend_key_value_token(json_t *obj, const char *key, const char *value); +void json_object_extend_key_value_token(json_t *obj, const char *key, + const char *value); // Merge two JSON objects recursively. int json_object_extend(json_t *orig, json_t *merge); -json_t * json_load_cli(int argc, const char *argv[]); +json_t *json_load_cli(int argc, const char *argv[]); } // namespace node } // namespace villas diff --git a/include/villas/dumper.hpp b/include/villas/dumper.hpp index 9eb34fea0..61fa61c03 100644 --- a/include/villas/dumper.hpp +++ b/include/villas/dumper.hpp @@ -17,25 +17,25 @@ namespace node { class Dumper { protected: - bool active; - int socketFd; - std::string socketPath; - bool supressRepeatedWarning; - uint64_t warningCounter; - Logger logger; + bool active; + int socketFd; + std::string socketPath; + bool supressRepeatedWarning; + uint64_t warningCounter; + Logger logger; public: - Dumper(); - ~Dumper(); + Dumper(); + ~Dumper(); - int openSocket(); - int closeSocket(); - bool isActive(); - int setActive(); + int openSocket(); + int closeSocket(); + bool isActive(); + int setActive(); - int setPath(const std::string &socketPathIn); - void writeDataCSV(unsigned len, double *yData, double *xData = nullptr); - void writeDataBinary(unsigned len, double *yData, double *xData = nullptr); + int setPath(const std::string &socketPathIn); + void writeDataCSV(unsigned len, double *yData, double *xData = nullptr); + void writeDataBinary(unsigned len, double *yData, double *xData = nullptr); }; } // namespace node diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 4d570a8e7..4f670ce3a 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -22,58 +22,46 @@ class FormatFactory; class Format { - friend FormatFactory; + friend FormatFactory; public: - using Ptr = std::unique_ptr; + using Ptr = std::unique_ptr; protected: + int flags; // A set of flags which is automatically used. + int real_precision; // Number of digits used for floatint point numbers - int flags; // A set of flags which is automatically used. - int real_precision; // Number of digits used for floatint point numbers + Logger logger; - Logger logger; + struct { + char *buffer; + size_t buflen; + } in, out; - struct { - char *buffer; - size_t buflen; - } in, out; - - SignalList::Ptr signals; // Signal meta data for parsed samples by Format::scan() + SignalList::Ptr + signals; // Signal meta data for parsed samples by Format::scan() public: - Format(int fl); + Format(int fl); - virtual - ~Format(); + virtual ~Format(); - const SignalList::Ptr getSignals() const - { - return signals; - } + const SignalList::Ptr getSignals() const { return signals; } - int getFlags() const - { - return flags; - } + int getFlags() const { return flags; } - void start(const SignalList::Ptr sigs, int fl = (int) SampleFlags::HAS_ALL); - void start(const std::string &dtypes, int fl = (int) SampleFlags::HAS_ALL); + void start(const SignalList::Ptr sigs, int fl = (int)SampleFlags::HAS_ALL); + void start(const std::string &dtypes, int fl = (int)SampleFlags::HAS_ALL); - virtual - void start() - { } + virtual void start() {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); - /* Print \p cnt samples from \p smps into buffer \p buf of length \p len. + /* Print \p cnt samples from \p smps into buffer \p buf of length \p len. * * @param buf[out] The buffer which should be filled with serialized data. * @param len[in] The length of the buffer \p buf. @@ -84,10 +72,10 @@ public: * @retval >=0 The number of samples from \p smps which have been written into \p buf. * @retval <0 Something went wrong. */ - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) = 0; + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) = 0; - /* Parse samples from the buffer \p buf with a length of \p len bytes. + /* Parse samples from the buffer \p buf with a length of \p len bytes. * * @param buf[in] The buffer of data which should be parsed / de-serialized. * @param len[in] The length of the buffer \p buf. @@ -98,98 +86,65 @@ public: * @retval >=0 The number of samples which have been parsed from \p buf and written into \p smps. * @retval <0 Something went wrong. */ - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) = 0; + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) = 0; - // Wrappers for sending a (un)parsing single samples + // Wrappers for sending a (un)parsing single samples - int print(FILE *f, const struct Sample *smp) - { - return print(f, &smp, 1); - } + int print(FILE *f, const struct Sample *smp) { return print(f, &smp, 1); } - int scan(FILE *f, struct Sample *smp) - { - return scan(f, &smp, 1); - } + int scan(FILE *f, struct Sample *smp) { return scan(f, &smp, 1); } - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample *smp) - { - return sprint(buf, len, wbytes, &smp, 1); - } + int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample *smp) { + return sprint(buf, len, wbytes, &smp, 1); + } - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample *smp) - { - return sscan(buf, len, rbytes, &smp, 1); - } + int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample *smp) { + return sscan(buf, len, rbytes, &smp, 1); + } }; class BinaryFormat : public Format { public: - using Format::Format; + using Format::Format; }; class FormatFactory : public plugin::Plugin { public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - Format * make() = 0; + virtual Format *make() = 0; - static - Format * make(json_t *json); + static Format *make(json_t *json); - static - Format * make(const std::string &format); + static Format *make(const std::string &format); - virtual - void init(Format *f) - { - f->logger = getLogger(); - } + virtual void init(Format *f) { f->logger = getLogger(); } - virtual - std::string getType() const - { - return "format"; - } + virtual std::string getType() const { return "format"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; template class FormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - auto *f = new T(flags); + virtual Format *make() { + auto *f = new T(flags); - init(f); + init(f); - return f; - } + return f; + } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/column.hpp b/include/villas/formats/column.hpp index 528b68091..2c47ed1fa 100644 --- a/include/villas/formats/column.hpp +++ b/include/villas/formats/column.hpp @@ -20,51 +20,36 @@ struct Sample; class ColumnLineFormat : public LineFormat { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp); - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp); + virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp); + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp); - char separator; // Column separator + char separator; // Column separator public: - ColumnLineFormat(int fl, char delim, char sep) : - LineFormat(fl, delim), - separator(sep) - { } + ColumnLineFormat(int fl, char delim, char sep) + : LineFormat(fl, delim), separator(sep) {} - virtual - void header(FILE *f, const SignalList::Ptr sigs); + virtual void header(FILE *f, const SignalList::Ptr sigs); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class ColumnLineFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new ColumnLineFormat(flags, delimiter, separator); - } + virtual Format *make() { + return new ColumnLineFormat(flags, delimiter, separator); + } - /// Get plugin name - virtual - std::string getName() const - { - return name; - } + /// Get plugin name + virtual std::string getName() const { return name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + /// Get plugin description + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/iotagent_ul.hpp b/include/villas/formats/iotagent_ul.hpp index d7ec53fc1..e7398fd57 100644 --- a/include/villas/formats/iotagent_ul.hpp +++ b/include/villas/formats/iotagent_ul.hpp @@ -18,14 +18,14 @@ struct Sample; class IotAgentUltraLightFormat : public Format { protected: - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); public: - using Format::Format; + using Format::Format; }; } // namespace node diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 234ffb47e..1183948b1 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -20,41 +20,32 @@ struct Sample; class JsonFormat : public Format { protected: - static - enum SignalType detect(const json_t *val); + static enum SignalType detect(const json_t *val); - json_t * packTimestamps(const struct Sample *smp); - int unpackTimestamps(json_t *json_ts, struct Sample *smp); + json_t *packTimestamps(const struct Sample *smp); + int unpackTimestamps(json_t *json_ts, struct Sample *smp); - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int packSamples(json_t **j, const struct Sample * const smps[], unsigned cnt); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); - virtual - int unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int packSamples(json_t **j, const struct Sample *const smps[], + unsigned cnt); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int unpackSamples(json_t *json_smps, struct Sample *const smps[], + unsigned cnt); - int dump_flags; + int dump_flags; public: - JsonFormat(int fl) : - Format(fl), - dump_flags(0) - { } + JsonFormat(int fl) : Format(fl), dump_flags(0) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; } // namespace node diff --git a/include/villas/formats/json_edgeflex.hpp b/include/villas/formats/json_edgeflex.hpp index 05c897ecb..ebb544532 100644 --- a/include/villas/formats/json_edgeflex.hpp +++ b/include/villas/formats/json_edgeflex.hpp @@ -15,13 +15,11 @@ namespace node { class JsonEdgeflexFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); public: - using JsonFormat::JsonFormat; + using JsonFormat::JsonFormat; }; } // namespace node diff --git a/include/villas/formats/json_kafka.hpp b/include/villas/formats/json_kafka.hpp index 492b4da6b..3edc0a566 100644 --- a/include/villas/formats/json_kafka.hpp +++ b/include/villas/formats/json_kafka.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -16,20 +16,17 @@ namespace node { class JsonKafkaFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); - const char * villasToKafkaType(enum SignalType vt); + const char *villasToKafkaType(enum SignalType vt); - json_t *json_schema; + json_t *json_schema; public: - JsonKafkaFormat(int fl); + JsonKafkaFormat(int fl); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; } // namespace node diff --git a/include/villas/formats/json_reserve.hpp b/include/villas/formats/json_reserve.hpp index f90ee2feb..46efe15c3 100644 --- a/include/villas/formats/json_reserve.hpp +++ b/include/villas/formats/json_reserve.hpp @@ -15,13 +15,11 @@ namespace node { class JsonReserveFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); public: - using JsonFormat::JsonFormat; + using JsonFormat::JsonFormat; }; } // namespace node diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index 45fd1dcfe..f4b1c0aeb 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -15,77 +15,54 @@ namespace node { class LineFormat : public Format { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp) = 0; - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; + virtual size_t sprintLine(char *buf, size_t len, + const struct Sample *smp) = 0; + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; - char delimiter; // Newline delimiter. - char comment; // Prefix for comment lines. + char delimiter; // Newline delimiter. + char comment; // Prefix for comment lines. - bool skip_first_line; // While reading, the first line is skipped (header) - bool print_header; // Before any data, a header line is printed + bool skip_first_line; // While reading, the first line is skipped (header) + bool print_header; // Before any data, a header line is printed - bool first_line_skipped; - bool header_printed; + bool first_line_skipped; + bool header_printed; public: - LineFormat(int fl, char delim = '\n', char com = '#') : - Format(fl), - delimiter(delim), - comment(com), - skip_first_line(false), - print_header(true), - first_line_skipped(false), - header_printed(false) - { } + LineFormat(int fl, char delim = '\n', char com = '#') + : Format(fl), delimiter(delim), comment(com), skip_first_line(false), + print_header(true), first_line_skipped(false), header_printed(false) {} - // Print a header - virtual - void header(FILE *f, const SignalList::Ptr sigs) - { - header_printed = true; - } + // Print a header + virtual void header(FILE *f, const SignalList::Ptr sigs) { + header_printed = true; + } - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class LineFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new T(flags, delimiter); - } + virtual Format *make() { return new T(flags, delimiter); } - /// Get plugin name - virtual - std::string getName() const - { - return name; - } + /// Get plugin name + virtual std::string getName() const { return name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + /// Get plugin description + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/msg.hpp b/include/villas/formats/msg.hpp index 0dac505aa..8b125577b 100644 --- a/include/villas/formats/msg.hpp +++ b/include/villas/formats/msg.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace villas { @@ -43,10 +43,12 @@ void msg_hdr_ntoh(struct Message *m); int msg_verify(const struct Message *m); // Copy fields from \p msg into \p smp. -int msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalList::Ptr sigs, uint8_t *source_index); +int msg_to_sample(const struct Message *msg, struct Sample *smp, + const SignalList::Ptr sigs, uint8_t *source_index); // Copy fields form \p smp into \p msg. -int msg_from_sample(struct Message *msg, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index); +int msg_from_sample(struct Message *msg, const struct Sample *smp, + const SignalList::Ptr sigs, uint8_t source_index); } // namespace node } // namespace villas diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 7512c3e24..2b58d3c8f 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -10,60 +10,62 @@ #include // The current version number for the message format -#define MSG_VERSION 2 +#define MSG_VERSION 2 // TODO: Implement more message types -#define MSG_TYPE_DATA 0 // Message contains float / integer values -#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case -#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case +#define MSG_TYPE_DATA 0 // Message contains float / integer values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case // The total size in bytes of a message -#define MSG_LEN(values) (sizeof(struct Message) + MSG_DATA_LEN(values)) +#define MSG_LEN(values) (sizeof(struct Message) + MSG_DATA_LEN(values)) // The length of \p values values in bytes. -#define MSG_DATA_LEN(values) (sizeof(float) * (values)) +#define MSG_DATA_LEN(values) (sizeof(float) * (values)) // The offset to the first data value in a message. -#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct Message, data)) +#define MSG_DATA_OFFSET(msg) ((char *)(msg) + offsetof(struct Message, data)) // The timestamp of a message in struct timespec format -#define MSG_TS(msg, i) \ - i.tv_sec = (msg)->ts.sec; \ - i.tv_nsec = (msg)->ts.nsec; +#define MSG_TS(msg, i) \ + i.tv_sec = (msg)->ts.sec; \ + i.tv_nsec = (msg)->ts.nsec; namespace villas { namespace node { // This message format is used by all clients -struct Message -{ +struct Message { #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 reserved1 : 2; // Reserved bits + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - 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) + 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 +#error Invalid byte-order #endif - uint8_t source_index; // 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. + uint8_t source_index; // 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. - // A timestamp per message. - struct { - uint32_t sec; // Seconds since 1970-01-01 00:00:00 - uint32_t nsec; // Nanoseconds of the current second - } ts; + // A timestamp per message. + struct { + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second + } ts; - // The message payload. - union { - float f; // Floating point values - uint32_t i; // Integer values - } data[]; + // The message payload. + union { + float f; // Floating point values + uint32_t i; // Integer values + } data[]; } __attribute__((packed)); } // namespace node diff --git a/include/villas/formats/opal_asyncip.hpp b/include/villas/formats/opal_asyncip.hpp index cae90984e..4be7cecb1 100644 --- a/include/villas/formats/opal_asyncip.hpp +++ b/include/villas/formats/opal_asyncip.hpp @@ -20,56 +20,45 @@ struct Sample; class OpalAsyncIPFormat : public BinaryFormat { protected: - const unsigned MAXSIZE = 64; + const unsigned MAXSIZE = 64; - struct Payload { - int16_t dev_id; // (2 bytes) Sender device ID - int32_t msg_id; // (4 bytes) Message ID - int16_t msg_len; // (2 bytes) Message length (data only) - double data[]; // Up to MAXSIZE doubles (8 bytes each) - } __attribute__((packed)); + struct Payload { + int16_t dev_id; // (2 bytes) Sender device ID + int32_t msg_id; // (4 bytes) Message ID + int16_t msg_len; // (2 bytes) Message length (data only) + double data[]; // Up to MAXSIZE doubles (8 bytes each) + } __attribute__((packed)); - int16_t dev_id; + int16_t dev_id; public: - OpalAsyncIPFormat(int fl, uint8_t did = 0) : - BinaryFormat(fl), - dev_id(did) - { } + OpalAsyncIPFormat(int fl, uint8_t did = 0) : BinaryFormat(fl), dev_id(did) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; class OpalAsyncIPFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new OpalAsyncIPFormat((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA); - } + virtual Format *make() { + return new OpalAsyncIPFormat((int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA); + } - /// Get plugin name - virtual - std::string getName() const - { - return "opal.asyncip"; - } + /// Get plugin name + virtual std::string getName() const { return "opal.asyncip"; } - /// Get plugin description - virtual - std::string getDescription() const - { - return "OPAL-RTs AsyncIP example format"; - } + /// Get plugin description + virtual std::string getDescription() const { + return "OPAL-RTs AsyncIP example format"; + } }; } // namespace node diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index 549ed831d..09048ad72 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -23,15 +23,15 @@ struct Sample; class ProtobufFormat : public BinaryFormat { protected: - enum SignalType detect(const Villas__Node__Value *val); + enum SignalType detect(const Villas__Node__Value *val); public: - using BinaryFormat::BinaryFormat; + using BinaryFormat::BinaryFormat; - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/formats/raw.hpp b/include/villas/formats/raw.hpp index a917e696a..42d8632d2 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -7,14 +7,14 @@ #pragma once -#include #include +#include #include // float128 is currently not yet supported as htole128() functions a missing #if 0 && defined(__GNUC__) && defined(__linux__) - #define HAS_128BIT +#define HAS_128BIT #endif namespace villas { @@ -26,43 +26,32 @@ struct Sample; class RawFormat : public BinaryFormat { public: - enum Endianess { - BIG, - LITTLE - }; + enum Endianess { BIG, LITTLE }; protected: - - enum Endianess endianess; - int bits; - bool fake; + enum Endianess endianess; + int bits; + bool fake; public: - RawFormat(int fl, int b = 32, enum Endianess e = Endianess::LITTLE) : - BinaryFormat(fl), - endianess(e), - bits(b), - fake(false) - { - if (fake) - flags |= (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - } + RawFormat(int fl, int b = 32, enum Endianess e = Endianess::LITTLE) + : BinaryFormat(fl), endianess(e), bits(b), fake(false) { + if (fake) + flags |= (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + } - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; class GtnetRawFormat : public RawFormat { public: - GtnetRawFormat(int fl) : - RawFormat(fl, 32, Endianess::BIG) - { } + GtnetRawFormat(int fl) : RawFormat(fl, 32, Endianess::BIG) {} }; } // namespace node diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 087f4d792..f2ca9c68d 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -17,12 +17,12 @@ namespace node { class ValueFormat : public Format { public: - using Format::Format; + using Format::Format; - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/formats/villas_binary.hpp b/include/villas/formats/villas_binary.hpp index e72286532..4597aca4b 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -20,63 +20,56 @@ struct Sample; class VillasBinaryFormat : public BinaryFormat { protected: - uint8_t source_index; - bool web; - bool validate_source_index; + uint8_t source_index; + bool web; + bool validate_source_index; public: - VillasBinaryFormat(int fl, bool w, uint8_t sid = 0) : - BinaryFormat(fl), - source_index(sid), - web(w), - validate_source_index(false) - { } + VillasBinaryFormat(int fl, bool w, uint8_t sid = 0) + : BinaryFormat(fl), source_index(sid), web(w), + validate_source_index(false) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class VillasBinaryFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new VillasBinaryFormat((int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA, web); - } + virtual Format *make() { + return new VillasBinaryFormat((int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA, + web); + } - /// Get plugin name - virtual - std::string getName() const - { - std::stringstream ss; + /// Get plugin name + virtual std::string getName() const { + std::stringstream ss; - ss << "villas." << (web ? "web" : "binary"); + ss << "villas." << (web ? "web" : "binary"); - return ss.str(); - } + return ss.str(); + } - /// Get plugin description - virtual - std::string getDescription() const - { - std::stringstream ss; + /// Get plugin description + virtual std::string getDescription() const { + std::stringstream ss; - ss << "VILLAS binary network format"; + ss << "VILLAS binary network format"; - if (web) - ss << " for WebSockets"; + if (web) + ss << " for WebSockets"; - return ss.str(); - } + return ss.str(); + } }; } // namespace node diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index e7a3ef2f3..fbf620174 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -17,16 +17,13 @@ namespace node { class VILLASHumanFormat : public LineFormat { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp); - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp); + virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp); + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp); public: - using LineFormat::LineFormat; + using LineFormat::LineFormat; - virtual - void header(FILE *f, const SignalList::Ptr sigs); + virtual void header(FILE *f, const SignalList::Ptr sigs); }; } // namespace node diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 7ef81e269..a83b1d9fe 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -11,12 +11,12 @@ #pragma once +#include #include -#include -#include #include #include -#include +#include +#include namespace villas { namespace node { @@ -29,285 +29,195 @@ class HookFactory; class Hook { - friend HookFactory; + friend HookFactory; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - 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 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 = 0, - ERROR, - SKIP_SAMPLE, - STOP_PROCESSING - }; + enum class Reason { OK = 0, ERROR, SKIP_SAMPLE, STOP_PROCESSING }; protected: - Logger logger; + Logger logger; - HookFactory *factory; + HookFactory *factory; - enum State state; + enum State state; - int flags; - unsigned priority; // A priority to change the order of execution within one type of hook. - bool enabled; // Is this hook active? + int flags; + unsigned + priority; // A priority to change the order of execution within one type of hook. + bool enabled; // Is this hook active? - Path *path; - Node *node; + Path *path; + Node *node; - SignalList::Ptr signals; + SignalList::Ptr signals; - json_t *config; // A JSON object containing the configuration of the hook. + json_t *config; // A JSON object containing the configuration of the hook. public: - Hook(Path *p, Node *n, int fl, int prio, bool en = true); + Hook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - ~Hook() - { } + virtual ~Hook() {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - void prepare(SignalList::Ptr sigs); + void prepare(SignalList::Ptr sigs); - Logger getLogger() - { - return logger; - } + Logger getLogger() { return logger; } - // Called whenever a hook is started; before threads are created. - virtual - void start() - { - assert(state == State::PREPARED); + // Called whenever a hook is started; before threads are created. + virtual void start() { + 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); + // Called whenever a hook is stopped; after threads are destoyed. + virtual void stop() { + assert(state == State::STARTED); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - void check() - { - assert(state == State::PARSED); + virtual void check() { + assert(state == State::PARSED); - state = State::CHECKED; - } + state = State::CHECKED; + } - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - state = State::PREPARED; - } + state = State::PREPARED; + } - // Called periodically. Period is set by global 'stats' option in the configuration file. - virtual - void periodic() - { - assert(state == State::STARTED); - } + // Called periodically. Period is set by global 'stats' option in the configuration file. + virtual void periodic() { 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); - } + // 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); } - // Called whenever a sample is processed. - virtual - Reason process(struct Sample *smp) - { - return Reason::OK; - }; + // Called whenever a sample is processed. + virtual Reason process(struct Sample *smp) { return Reason::OK; }; - unsigned getPriority() const - { - return priority; - } + unsigned getPriority() const { return priority; } - int getFlags() const - { - return flags; - } + int getFlags() const { return flags; } - virtual - SignalList::Ptr getSignals() const - { - return signals; - } + virtual SignalList::Ptr getSignals() const { return signals; } - json_t * getConfig() const - { - return config; - } + json_t *getConfig() const { return config; } - HookFactory * getFactory() const - { - return factory; - } + HookFactory *getFactory() const { return factory; } - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } }; class SingleSignalHook : public Hook { protected: - unsigned signalIndex; - std::string signalName; + unsigned signalIndex; + std::string signalName; public: - SingleSignalHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - signalIndex(0) - { } + SingleSignalHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), signalIndex(0) {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); }; class MultiSignalHook : public Hook { protected: - std::list signalIndices; - std::vector signalNames; + std::list signalIndices; + std::vector signalNames; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); - virtual - void check(); + virtual void check(); }; class LimitHook : public Hook { public: - using Ptr = std::shared_ptr; - using Hook::Hook; + using Ptr = std::shared_ptr; + using Hook::Hook; - virtual - void setRate(double rate, double maxRate = -1) = 0; + virtual void setRate(double rate, double maxRate = -1) = 0; - virtual - void parse() - { - assert(state == State::INITIALIZED); + virtual void parse() { + assert(state == State::INITIALIZED); - state = State::PARSED; - } + state = State::PARSED; + } - void init() - { - parse(); - check(); - prepare(); - start(); - } + void init() { + parse(); + check(); + prepare(); + start(); + } }; class HookFactory : public plugin::Plugin { protected: - virtual - void init(Hook::Ptr h) - { - h->logger = getLogger(); - h->factory = this; - } + virtual void init(Hook::Ptr h) { + h->logger = getLogger(); + h->factory = this; + } public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - Hook::Ptr make(Path *p, Node *n) = 0; + virtual Hook::Ptr make(Path *p, Node *n) = 0; - virtual - int getFlags() const = 0; + virtual int getFlags() const = 0; - virtual - unsigned getPriority() const = 0; + virtual unsigned getPriority() const = 0; - virtual - std::string getType() const - { - return "hook"; - } + virtual std::string getType() const { return "hook"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; -template +template class HookPlugin : public HookFactory { public: - using HookFactory::HookFactory; + using HookFactory::HookFactory; - virtual - Hook::Ptr make(Path *p, Node *n) - { - auto h = std::make_shared(p, n, getFlags(), getPriority()); + virtual Hook::Ptr make(Path *p, Node *n) { + auto h = std::make_shared(p, n, getFlags(), getPriority()); - init(h); + init(h); - return h; - } + return h; + } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } - virtual - int getFlags() const - { - return flags; - } + virtual int getFlags() const { return flags; } - virtual - unsigned getPriority() const - { - return prio; - } + virtual unsigned getPriority() const { return prio; } }; } // namespace node diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index 597b57ae1..daa1bc86e 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -24,10 +24,9 @@ struct Sample; class HookList : public std::list { public: - HookList() - { } + HookList() {} - /* Parses an object of hooks + /* Parses an object of hooks * * Example: * @@ -41,25 +40,25 @@ public: * hooks = [ "print" ] * } */ - void parse(json_t *json, int mask, Path *p, Node *n); + void parse(json_t *json, int mask, Path *p, Node *n); - void check(); + void check(); - void prepare(SignalList::Ptr sigs, int mask, Path *p, Node *n); + void prepare(SignalList::Ptr sigs, int mask, Path *p, Node *n); - int process(struct Sample *smps[], unsigned cnt); - void periodic(); - void start(); - void stop(); + int process(struct Sample *smps[], unsigned cnt); + void periodic(); + void start(); + void stop(); - void dump(villas::Logger logger, std::string subject) const; + void dump(villas::Logger logger, std::string subject) const; - SignalList::Ptr getSignals() const; + SignalList::Ptr getSignals() const; - // Get the maximum number of signals which is used by any of the hooks in the list. - unsigned getSignalsMaxCount() const; + // Get the maximum number of signals which is used by any of the hooks in the list. + unsigned getSignalsMaxCount() const; - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/hooks/decimate.hpp b/include/villas/hooks/decimate.hpp index 01a5388f2..c9e3767a1 100644 --- a/include/villas/hooks/decimate.hpp +++ b/include/villas/hooks/decimate.hpp @@ -15,38 +15,30 @@ namespace node { class DecimateHook : public LimitHook { protected: - int ratio; - bool renumber; - unsigned counter; + int ratio; + bool renumber; + unsigned counter; public: - using LimitHook::LimitHook; + using LimitHook::LimitHook; - virtual - void setRate(double rate, double maxRate = -1) - { - assert(maxRate > 0); + virtual void setRate(double rate, double maxRate = -1) { + assert(maxRate > 0); - int ratio = maxRate / rate; - if (ratio == 0) - ratio = 1; + int ratio = maxRate / rate; + if (ratio == 0) + ratio = 1; - setRatio(ratio); - } + setRatio(ratio); + } - void setRatio(int r) - { - ratio = r; - } + void setRatio(int r) { ratio = r; } - virtual - void start(); + virtual void start(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/limit_rate.hpp b/include/villas/hooks/limit_rate.hpp index 2ee99b3a3..3ee606069 100644 --- a/include/villas/hooks/limit_rate.hpp +++ b/include/villas/hooks/limit_rate.hpp @@ -15,35 +15,24 @@ namespace node { class LimitRateHook : public LimitHook { protected: - // The timestamp which should be used for limiting. - enum { - LIMIT_RATE_LOCAL, - LIMIT_RATE_RECEIVED, - LIMIT_RATE_ORIGIN - } mode; + // The timestamp which should be used for limiting. + enum { LIMIT_RATE_LOCAL, LIMIT_RATE_RECEIVED, LIMIT_RATE_ORIGIN } mode; - double deadtime; - timespec last; + double deadtime; + timespec last; public: - LimitRateHook(Path *p, Node *n, int fl, int prio, bool en = true) : - LimitHook(p, n, fl, prio, en), - mode(LIMIT_RATE_LOCAL), - deadtime(0), - last({0, 0}) - { } + LimitRateHook(Path *p, Node *n, int fl, int prio, bool en = true) + : LimitHook(p, n, fl, prio, en), mode(LIMIT_RATE_LOCAL), deadtime(0), + last({0, 0}) {} - virtual - void setRate(double rate, double maxRate = -1) - { - deadtime = 1.0 / rate; - } + virtual void setRate(double rate, double maxRate = -1) { + deadtime = 1.0 / rate; + } - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/lua.hpp b/include/villas/hooks/lua.hpp index 85b3365ee..42ba1bece 100644 --- a/include/villas/hooks/lua.hpp +++ b/include/villas/hooks/lua.hpp @@ -7,13 +7,13 @@ #pragma once -#include #include +#include #include extern "C" { - #include "lua.h" +#include "lua.h" }; namespace villas { @@ -26,115 +26,105 @@ enum SignalType; class LuaSignalExpression { protected: - int cookie; - lua_State *L; + int cookie; + lua_State *L; - std::string expression; + std::string expression; - json_t *cfg; + json_t *cfg; public: - LuaSignalExpression(lua_State *L, json_t *json_sig); + LuaSignalExpression(lua_State *L, json_t *json_sig); - void prepare(); + void prepare(); - void parseExpression(const std::string &expr); + void parseExpression(const std::string &expr); - void evaluate(union SignalData *data, enum SignalType type); + void evaluate(union SignalData *data, enum SignalType type); }; class LuaHook : public Hook { - friend LuaSignalExpression; + friend LuaSignalExpression; private: - static - const int SELF_REFERENCE = 55; + static const int SELF_REFERENCE = 55; protected: - std::string script; - std::vector expressions; + std::string script; + std::vector expressions; - SignalList::Ptr signalsProcessed; // Signals as emited by Lua process() function - SignalList::Ptr signalsExpressions; // Signals as emited by Lua expressions + SignalList::Ptr + signalsProcessed; // Signals as emited by Lua process() function + SignalList::Ptr signalsExpressions; // Signals as emited by Lua expressions - lua_State *L; - std::mutex mutex; + lua_State *L; + std::mutex mutex; - bool useNames; - bool hasExpressions; - bool needsLocking; + bool useNames; + bool hasExpressions; + bool needsLocking; - // Function indices - struct { - int start; - int stop; - int restart; - int process; - int periodic; - int prepare; - } functions; + // Function indices + struct { + int start; + int stop; + int restart; + int process; + int periodic; + int prepare; + } functions; - void parseExpressions(json_t *json_sigs); + void parseExpressions(json_t *json_sigs); - void loadScript(); - void lookupFunctions(); - void setupEnvironment(); + void loadScript(); + void lookupFunctions(); + void setupEnvironment(); - // Lua functions + // Lua functions - int luaInfo(lua_State *L); - int luaWarn(lua_State *L); - int luaError(lua_State *L); - int luaDebug(lua_State *L); + int luaInfo(lua_State *L); + int luaWarn(lua_State *L); + int luaError(lua_State *L); + int luaDebug(lua_State *L); - int luaRegisterApiHandler(lua_State *L); + int luaRegisterApiHandler(lua_State *L); - typedef int (LuaHook::*mem_func)(lua_State * L); + typedef int (LuaHook::*mem_func)(lua_State *L); - // This template wraps a member function into a C-style "free" function compatible with lua. - template - static - int dispatch(lua_State * L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); - void *vptr = lua_touserdata(L, -1); - lua_pop(L, 1); + // This template wraps a member function into a C-style "free" function compatible with lua. + template static int dispatch(lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + void *vptr = lua_touserdata(L, -1); + lua_pop(L, 1); - LuaHook *ptr = static_cast(vptr); - return ((*ptr).*func)(L); - } + LuaHook *ptr = static_cast(vptr); + return ((*ptr).*func)(L); + } public: - LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); + LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - ~LuaHook(); + virtual ~LuaHook(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); - // Periodically called by the main thread. - virtual - void periodic(); + // Periodically called by the main thread. + virtual void periodic(); - // Called whenever a hook is started; before threads are created. - virtual - void start(); + // Called whenever a hook is started; before threads are created. + virtual void start(); - // Called whenever a hook is stopped; after threads are destoyed. - virtual - void stop(); + // Called whenever a hook is stopped; after threads are destoyed. + virtual void stop(); - // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. - virtual - void restart(); + // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. + virtual void restart(); - // Called whenever a sample is processed. - virtual - Reason process(struct Sample *smp); + // Called whenever a sample is processed. + virtual Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/pmu.hpp b/include/villas/hooks/pmu.hpp index e530c2632..4b0fd2b0a 100644 --- a/include/villas/hooks/pmu.hpp +++ b/include/villas/hooks/pmu.hpp @@ -15,72 +15,59 @@ namespace node { class PmuHook : public MultiSignalHook { protected: - enum class Status { - INVALID, - VALID - }; + enum class Status { INVALID, VALID }; - struct Phasor { - double frequency; - double amplitude; - double phase; - double rocof; // Rate of change of frequency. - Status valid; - }; + struct Phasor { + double frequency; + double amplitude; + double phase; + double rocof; // Rate of change of frequency. + Status valid; + }; - enum class WindowType { - NONE, - FLATTOP, - HANN, - HAMMING, - NUTTAL, - BLACKMAN - }; + enum class WindowType { NONE, FLATTOP, HANN, HAMMING, NUTTAL, BLACKMAN }; - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - std::vector*> windows; - dsp::Window *windowsTs; - std::vector lastPhasors; + std::vector *> windows; + dsp::Window *windowsTs; + std::vector lastPhasors; - enum TimeAlign timeAlignType; - enum WindowType windowType; + enum TimeAlign timeAlignType; + enum WindowType windowType; - unsigned sampleRate; - double phasorRate; - double nominalFreq; - double numberPlc; - unsigned windowSize; - bool channelNameEnable; - double angleUnitFactor; - uint64_t lastSequence; - timespec nextRun; - bool init; - unsigned initSampleCount; - // Correction factors. - double phaseOffset; - double amplitudeOffset; - double frequencyOffset; - double rocofOffset; + unsigned sampleRate; + double phasorRate; + double nominalFreq; + double numberPlc; + unsigned windowSize; + bool channelNameEnable; + double angleUnitFactor; + uint64_t lastSequence; + timespec nextRun; + bool init; + unsigned initSampleCount; + // Correction factors. + double phaseOffset; + double amplitudeOffset; + double frequencyOffset; + double rocofOffset; public: - PmuHook(Path *p, Node *n, int fl, int prio, bool en = true); + PmuHook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - void prepare(); + virtual void prepare(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); - virtual - Phasor estimatePhasor(dsp::CosineWindow *window, Phasor lastPhasor); + virtual Phasor estimatePhasor(dsp::CosineWindow *window, + Phasor lastPhasor); }; } // namespace node diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index fce1038bb..a295e80f7 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -12,13 +12,14 @@ #include -#include #include +#include #include #ifndef SO_MARK - #define SO_MARK 36 // Workaround: add missing constant for OPAL-RT Redhawk target +#define SO_MARK \ + 36 // Workaround: add missing constant for OPAL-RT Redhawk target #endif // Forward declarations @@ -33,7 +34,7 @@ namespace node { class Node; class SuperNode; -} +} // namespace node namespace kernel { @@ -41,23 +42,24 @@ namespace kernel { class Interface { public: - struct rtnl_link *nl_link; // libnl3: Handle of interface. - struct rtnl_qdisc *tc_qdisc; // libnl3: Root priority queuing discipline (qdisc). + struct rtnl_link *nl_link; // libnl3: Handle of interface. + struct rtnl_qdisc + *tc_qdisc; // libnl3: Root priority queuing discipline (qdisc). protected: - int affinity; // IRQ / Core Affinity of this interface. + int affinity; // IRQ / Core Affinity of this interface. - std::list irqs; // List of IRQs of the NIC. - std::list nodes; // List of nodes which use this interface. + std::list irqs; // List of IRQs of the NIC. + std::list nodes; // List of nodes which use this interface. - Logger logger; + Logger logger; public: - // Add a new interface to the global list and lookup name, irqs... - Interface(struct rtnl_link *link, int affinity = 0); - ~Interface(); + // Add a new interface to the global list and lookup name, irqs... + Interface(struct rtnl_link *link, int affinity = 0); + ~Interface(); - /* Start interface. + /* Start interface. * * This setups traffic controls queue discs, network emulation and * maps interface IRQs according to affinity. @@ -66,9 +68,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int start(); + int start(); - /* Stop interface + /* Stop interface * * This resets traffic qdiscs ant network emulation * and maps interface IRQs to all CPUs. @@ -77,16 +79,14 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int stop(); + int stop(); - /* Find existing or create new interface instance on which packets for a certain destination + /* Find existing or create new interface instance on which packets for a certain destination * will leave the system. */ - static - Interface * - getEgress(struct sockaddr *sa, node::SuperNode *sn); + static Interface *getEgress(struct sockaddr *sa, node::SuperNode *sn); - /* Get all IRQs for this interface. + /* Get all IRQs for this interface. * * Only MSI IRQs are determined by looking at: * /sys/class/net/{ifname}/device/msi_irqs/ @@ -95,23 +95,20 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int getIRQs(); + int getIRQs(); - /* Change the SMP affinity of NIC interrupts. + /* Change the SMP affinity of NIC interrupts. * * @param i A pointer to the interface structure * @param affinity A mask specifying which cores should handle this interrupt. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int setAffinity(int affinity); + int setAffinity(int affinity); - std::string getName() const; + std::string getName() const; - void addNode(node::Node *n) - { - nodes.push_back(n); - } + void addNode(node::Node *n) { nodes.push_back(n); } }; } // namespace kernel diff --git a/include/villas/kernel/nl-private.h b/include/villas/kernel/nl-private.h index b7d6ff799..37d185cfa 100644 --- a/include/villas/kernel/nl-private.h +++ b/include/villas/kernel/nl-private.h @@ -16,44 +16,39 @@ extern "C" { #define SCH_NETEM_ATTR_DIST 0x2000 -struct rtnl_netem_corr -{ - uint32_t nmc_delay; - uint32_t nmc_loss; - uint32_t nmc_duplicate; +struct rtnl_netem_corr { + uint32_t nmc_delay; + uint32_t nmc_loss; + uint32_t nmc_duplicate; }; -struct rtnl_netem_reo -{ - uint32_t nmro_probability; - uint32_t nmro_correlation; +struct rtnl_netem_reo { + uint32_t nmro_probability; + uint32_t nmro_correlation; }; -struct rtnl_netem_crpt -{ - uint32_t nmcr_probability; - uint32_t nmcr_correlation; +struct rtnl_netem_crpt { + uint32_t nmcr_probability; + uint32_t nmcr_correlation; }; -struct rtnl_netem_dist -{ - int16_t * dist_data; - size_t dist_size; +struct rtnl_netem_dist { + int16_t *dist_data; + size_t dist_size; }; -struct rtnl_netem -{ - uint32_t qnm_latency; - uint32_t qnm_limit; - uint32_t qnm_loss; - uint32_t qnm_gap; - uint32_t qnm_duplicate; - uint32_t qnm_jitter; - uint32_t qnm_mask; - struct rtnl_netem_corr qnm_corr; - struct rtnl_netem_reo qnm_ro; - struct rtnl_netem_crpt qnm_crpt; - struct rtnl_netem_dist qnm_dist; +struct rtnl_netem { + uint32_t qnm_latency; + uint32_t qnm_limit; + uint32_t qnm_loss; + uint32_t qnm_gap; + uint32_t qnm_duplicate; + uint32_t qnm_jitter; + uint32_t qnm_mask; + struct rtnl_netem_corr qnm_corr; + struct rtnl_netem_reo qnm_ro; + struct rtnl_netem_crpt qnm_crpt; + struct rtnl_netem_dist qnm_dist; }; void *rtnl_tc_data(struct rtnl_tc *tc); diff --git a/include/villas/kernel/nl.hpp b/include/villas/kernel/nl.hpp index 2317a347b..94d4af69d 100644 --- a/include/villas/kernel/nl.hpp +++ b/include/villas/kernel/nl.hpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace villas { namespace kernel { @@ -32,10 +32,10 @@ int get_egress(struct nl_addr *addr); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -struct rtnl_link * get_egress_link(struct sockaddr *sa); +struct rtnl_link *get_egress_link(struct sockaddr *sa); // Get or create global netlink socket. -struct nl_sock * init(); +struct nl_sock *init(); // Close and free global netlink socket. void shutdown(); diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index 540ba90e1..923f0062b 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -14,8 +14,8 @@ #include -#include #include +#include #include @@ -47,7 +47,8 @@ int reset(Interface *i); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, int bands); +int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, + int bands); /* Add a new filter based on the netfilter mark. * diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index 4fe586759..a119fcd09 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -14,8 +14,8 @@ #include -#include #include +#include #include @@ -43,7 +43,7 @@ int netem_parse(struct rtnl_qdisc **ne, json_t *json); * @param tc A pointer to the libnl3 qdisc object where settings will be read from. * @return A pointer to a string which must be freed() by the caller. */ -char * netem_print(struct rtnl_qdisc *ne); +char *netem_print(struct rtnl_qdisc *ne); /* Add a new network emulator (netem) discipline. * @@ -54,7 +54,8 @@ char * netem_print(struct rtnl_qdisc *ne); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent); +int netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, + tc_hdl_t parent); int netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json); diff --git a/include/villas/log_opal_sink.hpp b/include/villas/log_opal_sink.hpp index e0e85eb79..76520091e 100644 --- a/include/villas/log_opal_sink.hpp +++ b/include/villas/log_opal_sink.hpp @@ -9,44 +9,41 @@ #include -#include #include +#include -#include #include +#include extern "C" { - /* Define RTLAB before including OpalPrint.h for messages to be sent +/* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ - #define RTLAB - #include +#define RTLAB +#include } namespace villas { namespace node { -template -class OpalSink : public spdlog::sinks::base_sink -{ +template +class OpalSink : public spdlog::sinks::base_sink { protected: - void sink_it_(const spdlog::details::log_msg &msg) override - { + void sink_it_(const spdlog::details::log_msg &msg) override { #ifdef WITH_NODE_OPAL - fmt::memory_buffer formatted; + fmt::memory_buffer formatted; - sink::formatter_->format(msg, formatted); + sink::formatter_->format(msg, formatted); - auto str = fmt::to_string(formatted).c_str(); + auto str = fmt::to_string(formatted).c_str(); - OpalPrint(PROJECT_NAME ": %s\n", str); + OpalPrint(PROJECT_NAME ": %s\n", str); #endif - } + } - void flush_() override - { - // nothing to do - } + void flush_() override { + // nothing to do + } }; using OpalSink_mt = OpalSink; diff --git a/include/villas/mapping.hpp b/include/villas/mapping.hpp index d347cb959..5a04b9c3e 100644 --- a/include/villas/mapping.hpp +++ b/include/villas/mapping.hpp @@ -11,18 +11,21 @@ #include #include -#include #include +#include #define RE_MAPPING_INDEX "[a-zA-Z0-9_]+" #define RE_MAPPING_RANGE "(" RE_MAPPING_INDEX ")(?:-(" RE_MAPPING_INDEX "))?" #define RE_MAPPING_STATS "stats\\.([a-z]+)\\.([a-z]+)" -#define RE_MAPPING_HDR "hdr\\.(sequence|length)" -#define RE_MAPPING_TS "ts\\.(origin|received)" +#define RE_MAPPING_HDR "hdr\\.(sequence|length)" +#define RE_MAPPING_TS "ts\\.(origin|received)" #define RE_MAPPING_DATA1 "data\\[" RE_MAPPING_RANGE "\\]" #define RE_MAPPING_DATA2 "(?:data\\.)?(" RE_MAPPING_INDEX ")" -#define RE_MAPPING "(?:(" RE_NODE_NAME ")\\.(?:" RE_MAPPING_STATS "|" RE_MAPPING_HDR "|" RE_MAPPING_TS "|" RE_MAPPING_DATA1 "|" RE_MAPPING_DATA2 ")|(" RE_NODE_NAME ")(?:\\[" RE_MAPPING_RANGE "\\])?)" +#define RE_MAPPING \ + "(?:(" RE_NODE_NAME ")\\.(?:" RE_MAPPING_STATS "|" RE_MAPPING_HDR \ + "|" RE_MAPPING_TS "|" RE_MAPPING_DATA1 "|" RE_MAPPING_DATA2 \ + ")|(" RE_NODE_NAME ")(?:\\[" RE_MAPPING_RANGE "\\])?)" namespace villas { namespace node { @@ -35,74 +38,62 @@ class Signal; class MappingEntry { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - enum class Type { - UNKNOWN, - DATA, - STATS, - HEADER, - TIMESTAMP - }; + enum class Type { UNKNOWN, DATA, STATS, HEADER, TIMESTAMP }; - enum class HeaderType { - LENGTH, - SEQUENCE - }; + enum class HeaderType { LENGTH, SEQUENCE }; - enum class TimestampType { - ORIGIN, - RECEIVED - }; + enum class TimestampType { ORIGIN, RECEIVED }; - Node *node; // The node to which this mapping refers. - enum Type type; // The mapping type. Selects one of the union fields below. + Node *node; // The node to which this mapping refers. + enum Type type; // The mapping type. Selects one of the union fields below. - /* The number of values which is covered by this mapping entry. + /* The number of values which is covered by this mapping entry. * * A value of 0 indicates that all remaining values starting from the offset of a sample should be mapped. */ - int length; - unsigned offset; // Offset of this mapping entry within sample::data + int length; + unsigned offset; // Offset of this mapping entry within sample::data - union { - struct { - int offset; - Signal *signal; + union { + struct { + int offset; + Signal *signal; - char *first; - char *last; - } data; + char *first; + char *last; + } data; - struct { - enum Stats::Metric metric; - enum Stats::Type type; - } stats; + struct { + enum Stats::Metric metric; + enum Stats::Type type; + } stats; - struct { - enum HeaderType type; - } header; + struct { + enum HeaderType type; + } header; - struct { - enum TimestampType type; - } timestamp; - }; + struct { + enum TimestampType type; + } timestamp; + }; - std::string nodeName; // Used for between parse and prepare only. + std::string nodeName; // Used for between parse and prepare only. - MappingEntry(); + MappingEntry(); - int prepare(NodeList &nodes); + int prepare(NodeList &nodes); - int update(struct Sample *remapped, const struct Sample *original) const; + int update(struct Sample *remapped, const struct Sample *original) const; - int parse(json_t *json); + int parse(json_t *json); - int parseString(const std::string &str); + int parseString(const std::string &str); - std::string toString(unsigned index) const; + std::string toString(unsigned index) const; - Signal::Ptr toSignal(unsigned index) const; + Signal::Ptr toSignal(unsigned index) const; }; } // namespace node diff --git a/include/villas/mapping_list.hpp b/include/villas/mapping_list.hpp index 47218ef6e..10f228af7 100644 --- a/include/villas/mapping_list.hpp +++ b/include/villas/mapping_list.hpp @@ -18,13 +18,14 @@ namespace node { class MappingList : public std::list { public: - int parse(json_t *json); + int parse(json_t *json); - int prepare(NodeList &nodes); + int prepare(NodeList &nodes); - int remap(struct Sample *remapped, const struct Sample *original) const; + int remap(struct Sample *remapped, const struct Sample *original) const; - int update(const MappingEntry::Ptr me, struct Sample *remapped, const struct Sample *original); + int update(const MappingEntry::Ptr me, struct Sample *remapped, + const struct Sample *original); }; } // namespace node diff --git a/include/villas/memory/ib.h b/include/villas/memory/ib.h index 56e2a559c..26c313cf8 100644 --- a/include/villas/memory/ib.h +++ b/include/villas/memory/ib.h @@ -14,11 +14,11 @@ namespace node { namespace memory { struct IB { - struct ibv_pd *pd; - struct Type *parent; + struct ibv_pd *pd; + struct Type *parent; }; -struct ibv_mr * ib_get_mr(void *ptr); +struct ibv_mr *ib_get_mr(void *ptr); } // namespace memory } // namespace node diff --git a/include/villas/node.h b/include/villas/node.h index f0f504eb4..333670f66 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -14,7 +14,7 @@ typedef void *vnode; typedef void *vsample; -vnode * node_new(const char *id_str, const char *json_str); +vnode *node_new(const char *id_str, const char *json_str); int node_prepare(vnode *n); @@ -32,13 +32,13 @@ int node_restart(vnode *n); int node_destroy(vnode *n); -const char * node_name(vnode *n); +const char *node_name(vnode *n); -const char * node_name_short(vnode *n); +const char *node_name_short(vnode *n); -const char * node_name_full(vnode *n); +const char *node_name_full(vnode *n); -const char * node_details(vnode *n); +const char *node_details(vnode *n); unsigned node_input_signals_max_cnt(vnode *n); @@ -58,18 +58,22 @@ bool node_is_valid_name(const char *name); bool node_is_enabled(const vnode *n); -json_t * node_to_json(const vnode *n); +json_t *node_to_json(const vnode *n); -const char * node_to_json_str(vnode *n); +const char *node_to_json_str(vnode *n); -vsample * sample_alloc(unsigned len); +vsample *sample_alloc(unsigned len); unsigned sample_length(vsample *smp); void sample_decref(vsample *smp); -vsample * sample_pack(unsigned seq, struct timespec *ts_origin, struct timespec *ts_received, unsigned len, double *values); +vsample *sample_pack(unsigned seq, struct timespec *ts_origin, + struct timespec *ts_received, unsigned len, + double *values); -void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, struct timespec *ts_received, int *flags, unsigned *len, double *values); +void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, + struct timespec *ts_received, int *flags, unsigned *len, + double *values); int memory_init(int hugepages); diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 666210516..73c7dd491 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -8,31 +8,31 @@ #pragma once #include -#include #include +#include -#include -#include -#include -#include -#include -#include #include #include -#include +#include #include -#include -#include +#include +#include +#include #include +#include +#include +#include +#include +#include #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) - #define WITH_NETEM +#define WITH_NETEM #endif // LIBNL3_ROUTE_FOUND // Forward declarations #ifdef WITH_NETEM - struct rtnl_qdisc; - struct rtnl_cls; +struct rtnl_qdisc; +struct rtnl_cls; #endif // WITH_NETEM #define RE_NODE_NAME "[a-z0-9_-]{2,32}" @@ -51,123 +51,102 @@ class SuperNode; */ class Node { - friend NodeFactory; + friend NodeFactory; public: - Logger logger; + Logger logger; - uint64_t sequence_init; - uint64_t sequence; // This is a counter of received samples, in case the node-type does not generate sequence numbers itself. + uint64_t sequence_init; + uint64_t + sequence; // This is a counter of received samples, in case the node-type does not generate sequence numbers itself. - NodeDirection in, out; + NodeDirection in, out; - PathSourceList sources; // A list of path sources which reference this node. - PathDestinationList destinations; // A list of path destinations which reference this node. + PathSourceList sources; // A list of path sources which reference this node. + PathDestinationList + destinations; // A list of path destinations which reference this node. #ifdef __linux__ - int fwmark; // Socket mark for netem, routing and filtering + int fwmark; // Socket mark for netem, routing and filtering #ifdef WITH_NETEM - struct rtnl_qdisc *tc_qdisc; // libnl3: Network emulator queuing discipline - struct rtnl_cls *tc_classifier; // libnl3: Firewall mark classifier -#endif // WITH_NETEM -#endif // __linux__ + struct rtnl_qdisc *tc_qdisc; // libnl3: Network emulator queuing discipline + struct rtnl_cls *tc_classifier; // libnl3: Firewall mark classifier +#endif // WITH_NETEM +#endif // __linux__ protected: - enum State state; + enum State state; - uuid_t uuid; + uuid_t uuid; - bool enabled; + bool enabled; - Stats::Ptr stats; // Statistic counters. This is a pointer to the statistic hooks private data. + Stats::Ptr + stats; // Statistic counters. This is a pointer to the statistic hooks private data. - json_t *config; // A JSON object containing the configuration of the node. + json_t *config; // A JSON object containing the configuration of the node. - std::string name_short; // A short identifier of the node, only used for configuration and logging - std::string name_long; // Singleton: A string used to print to screen. - std::string name_full; // Singleton: A string used to print to screen. - std::string details; + std::string + name_short; // A short identifier of the node, only used for configuration and logging + std::string name_long; // Singleton: A string used to print to screen. + std::string name_full; // Singleton: A string used to print to screen. + std::string details; - int affinity; // CPU Affinity of this node + int affinity; // CPU Affinity of this node - NodeFactory *factory; // The factory which created this instance + NodeFactory *factory; // The factory which created this instance - virtual - int _read(struct Sample * smps[], unsigned cnt) - { - return -1; - } + virtual int _read(struct Sample *smps[], unsigned cnt) { return -1; } - virtual - int _write(struct Sample * smps[], unsigned cnt) - { - return -1; - } + virtual int _write(struct Sample *smps[], unsigned cnt) { return -1; } - virtual - json_t * _readStatus() const - { - return nullptr; - } + virtual json_t *_readStatus() const { return nullptr; } public: - // Initialize node with default values - Node(const uuid_t &id = {}, const std::string &name = ""); + // Initialize node with default values + Node(const uuid_t &id = {}, const std::string &name = ""); - // Destroy node by freeing dynamically allocated memory. - virtual - ~Node(); + // Destroy node by freeing dynamically allocated memory. + virtual ~Node(); - // Do initialization after parsing the configuration - virtual - int prepare(); + // Do initialization after parsing the configuration + virtual int prepare(); - /* Parse settings of a node. + /* Parse settings of a node. * * @param json A JSON object containing the configuration of the node. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Validate node configuration. - virtual - int check(); + // Validate node configuration. + virtual int check(); - // Start operation of a node. - virtual - int start(); + // Start operation of a node. + virtual int start(); - // Stops operation of a node. - virtual - int stop(); + // Stops operation of a node. + virtual int stop(); - // Pauses operation of a node. - virtual - int pause() - { - if (state != State::STARTED) - return -1; + // Pauses operation of a node. + virtual int pause() { + if (state != State::STARTED) + return -1; - logger->info("Pausing node"); + logger->info("Pausing node"); - return 0; - } + return 0; + } - // Resumes operation of a node. - virtual - int resume() - { - return 0; - } + // Resumes operation of a node. + virtual int resume() { return 0; } - // Restarts operation of a node. - virtual - int restart(); + // Restarts operation of a node. + virtual int restart(); - /* Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -181,9 +160,9 @@ public: * @param cnt The number of samples that are allocated by the calling function. * @return The number of messages actually received. */ - int read(struct Sample * smps[], unsigned cnt); + int read(struct Sample *smps[], unsigned cnt); - /* Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -196,290 +175,193 @@ public: * @param cnt The number of samples that are allocated by the calling function. * @return The number of messages actually sent. */ - int write(struct Sample * smps[], unsigned cnt); + int write(struct Sample *smps[], unsigned cnt); - // Reverse local and remote socket address. - virtual - int reverse() - { - return -1; - } + // Reverse local and remote socket address. + virtual int reverse() { return -1; } - /* Get a list of file descriptors on which the path should poll + /* Get a list of file descriptors on which the path should poll * to detect the availability of new samples which can be read. */ - virtual - std::vector getPollFDs() - { - return {}; - } + virtual std::vector getPollFDs() { return {}; } - /* Get a list of socket file descriptors which are used by the node + /* Get a list of socket file descriptors which are used by the node * To perform network IO. We use those to selectively apply network emulation */ - virtual - std::vector getNetemFDs() - { - return {}; - } + virtual std::vector getNetemFDs() { return {}; } - /* Get the memory type which this node-type expects. + /* Get the memory type which this node-type expects. * * This is useful for special node-types like Infiniband, GPUs & FPGAs * which require DMA-backed memory. */ - virtual - struct villas::node::memory::Type * getMemoryType() - { - return villas::node::memory::default_type; - } + virtual struct villas::node::memory::Type *getMemoryType() { + return villas::node::memory::default_type; + } - // Get the factory which was used to construct this node. - villas::node::NodeFactory * getFactory() const - { - return factory; - } + // Get the factory which was used to construct this node. + villas::node::NodeFactory *getFactory() const { return factory; } - /* Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ - std::string getNameShort() const - { - return name_short; - } + std::string getNameShort() const { return name_short; } - // Return a pointer to a string which should be used to print this node. - const std::string & getName() const - { - return name_long; - } + // Return a pointer to a string which should be used to print this node. + const std::string &getName() const { return name_long; } - // Get the full name including type and details of the node. - const std::string & getNameFull(); + // Get the full name including type and details of the node. + const std::string &getNameFull(); - // Just get the config details of this node as a string - virtual - const std::string & getDetails() - { - static - std::string empty; + // Just get the config details of this node as a string + virtual const std::string &getDetails() { + static std::string empty; - return empty; - } + return empty; + } - /* Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ - const std::string & getNameLong(); + const std::string &getNameLong(); - /* Return a list of signals which are sent to this node. + /* Return a list of signals which are sent to this node. * * This list is derived from the path which uses the node as destination. */ - SignalList::Ptr getOutputSignals(bool after_hooks = true) const; - SignalList::Ptr getInputSignals(bool after_hooks = true) const; + SignalList::Ptr getOutputSignals(bool after_hooks = true) const; + SignalList::Ptr getInputSignals(bool after_hooks = true) const; - // Get the number of input signals (received by this node) - unsigned getInputSignalsMaxCount() const; + // Get the number of input signals (received by this node) + unsigned getInputSignalsMaxCount() const; - // Get the number of output signals (send out via this node) - unsigned getOutputSignalsMaxCount() const; + // Get the number of output signals (send out via this node) + unsigned getOutputSignalsMaxCount() const; - void swapSignals(); + void swapSignals(); - // Get the node configuration as JSON. - json_t * getConfig() - { - return config; - } + // Get the node configuration as JSON. + json_t *getConfig() { return config; } - // Get the state of this node. - enum State getState() const - { - return state; - } + // Get the state of this node. + enum State getState() const { return state; } - // Set the state of this node. - void setState(enum State s) - { - state = s; - } + // Set the state of this node. + void setState(enum State s) { state = s; } - // Get the UUID of this node. - const uuid_t & getUuid() const - { - return uuid; - } + // Get the UUID of this node. + const uuid_t &getUuid() const { return uuid; } - std::shared_ptr getStats() - { - return stats; - } + std::shared_ptr getStats() { return stats; } - void setStats(std::shared_ptr sts) - { - stats = sts; - } + void setStats(std::shared_ptr sts) { stats = sts; } - void setEnabled(bool en) - { - enabled = en; - } + void setEnabled(bool en) { enabled = en; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Node &n) - { - os << n.getName(); + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const Node &n) { + os << n.getName(); - return os; - } + return os; + } - json_t * toJson() const; + json_t *toJson() const; - static - bool isValidName(const std::string &name); + static bool isValidName(const std::string &name); - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } }; class NodeFactory : public villas::plugin::Plugin { - friend Node; + friend Node; protected: - virtual - void init(Node *n) - { - n->logger = getLogger(); - n->factory = this; + virtual void init(Node *n) { + n->logger = getLogger(); + n->factory = this; - n->name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", n->name_short, getName()); + n->name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", + n->name_short, getName()); - instances.push_back(n); - } + instances.push_back(n); + } - State state; + State state; public: - enum class Flags { - SUPPORTS_POLL = (1 << 0), - SUPPORTS_READ = (1 << 1), - SUPPORTS_WRITE = (1 << 2), - REQUIRES_WEB = (1 << 3), - PROVIDES_SIGNALS = (1 << 4), - INTERNAL = (1 << 5), - HIDDEN = (1 << 6) - }; + enum class Flags { + SUPPORTS_POLL = (1 << 0), + SUPPORTS_READ = (1 << 1), + SUPPORTS_WRITE = (1 << 2), + REQUIRES_WEB = (1 << 3), + PROVIDES_SIGNALS = (1 << 4), + INTERNAL = (1 << 5), + HIDDEN = (1 << 6) + }; - NodeList instances; + NodeList instances; - NodeFactory() : - Plugin() - { - state = State::INITIALIZED; - } + NodeFactory() : Plugin() { state = State::INITIALIZED; } - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") = 0; + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") = 0; - static - Node * make(json_t *json, const uuid_t &id, const std::string &name = ""); + static Node *make(json_t *json, const uuid_t &id, + const std::string &name = ""); - static - Node * make(const std::string &type, const uuid_t &id = {}, const std::string &name = ""); + static Node *make(const std::string &type, const uuid_t &id = {}, + const std::string &name = ""); - virtual - std::string getType() const - { - return "node"; - } + virtual std::string getType() const { return "node"; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const NodeFactory &f) - { - os << f.getName(); + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const NodeFactory &f) { + os << f.getName(); - return os; - } + return os; + } - virtual - int getFlags() const - { - return 0; - } + virtual int getFlags() const { return 0; } - virtual - int getVectorize() const - { - return 0; - } + virtual int getVectorize() const { return 0; } - bool isInternal() const - { - return getFlags() & (int) Flags::INTERNAL; - } + bool isInternal() const { return getFlags() & (int)Flags::INTERNAL; } - bool isHidden() const - { - return isInternal() || getFlags() & (int) Flags::HIDDEN; - } + bool isHidden() const { + return isInternal() || getFlags() & (int)Flags::HIDDEN; + } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); - virtual - int stop(); + virtual int stop(); - State getState() const - { - return state; - } + State getState() const { return state; } }; -template +template class NodePlugin : public NodeFactory { public: - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - T* n = new T(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + T *n = new T(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return flags; - } + virtual int getFlags() const { return flags; } - virtual - int getVectorize() const - { - return vectorize; - } + virtual int getVectorize() const { return vectorize; } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/node/exceptions.hpp b/include/villas/node/exceptions.hpp index 0093585f8..e84eba2a9 100644 --- a/include/villas/node/exceptions.hpp +++ b/include/villas/node/exceptions.hpp @@ -7,11 +7,11 @@ #pragma once -#include #include +#include #ifdef WITH_CONFIG - #include +#include #endif namespace villas { @@ -20,54 +20,40 @@ namespace node { class ParseError : public RuntimeError { protected: - std::string text; - std::string file; - int line; - int column; + std::string text; + std::string file; + int line; + int column; public: - ParseError(const std::string &t, const std::string &f, int l, int c = 0) : - RuntimeError("Failed to parse configuration: {} in {}:{}", t, f, l), - text(t), - file(f), - line(l), - column(c) - { } + ParseError(const std::string &t, const std::string &f, int l, int c = 0) + : RuntimeError("Failed to parse configuration: {} in {}:{}", t, f, l), + text(t), file(f), line(l), column(c) {} }; #ifdef WITH_CONFIG class LibconfigParseError : public ParseError { protected: - const config_t *config; + const config_t *config; public: - LibconfigParseError(const config_t *c) : - ParseError( - config_error_text(c), - config_error_file(c) ? config_error_file(c) : "", - config_error_line(c) - ), - config(c) - { } + LibconfigParseError(const config_t *c) + : ParseError(config_error_text(c), + config_error_file(c) ? config_error_file(c) : "", + config_error_line(c)), + config(c) {} }; #endif // WITH_CONFIG class JanssonParseError : public ParseError { protected: - json_error_t error; + json_error_t error; public: - JanssonParseError(json_error_t e) : - ParseError( - e.text, - e.source, - e.line, - e.column - ), - error(e) - { } + JanssonParseError(json_error_t e) + : ParseError(e.text, e.source, e.line, e.column), error(e) {} }; } // namespace node diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index 82431c808..1fcdc8c54 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -8,7 +8,7 @@ #pragma once #ifdef IBVERBS_FOUND - #include +#include #endif // IBVERBS_FOUND #include @@ -24,36 +24,36 @@ namespace memory { /* Descriptor of a memory block. Associated block always starts at * &m + sizeof(struct Block). */ struct Block { - struct Block *prev; - struct Block *next; - size_t length; // Length of the block; doesn't include the descriptor itself - bool used; + struct Block *prev; + struct Block *next; + size_t length; // Length of the block; doesn't include the descriptor itself + bool used; }; // TODO: Unused for now struct Allocation { - struct Type *type; + struct Type *type; - struct Allocation *parent; + struct Allocation *parent; - void *address; - size_t alignment; - size_t length; + void *address; + size_t alignment; + size_t length; - union { + union { #ifdef IBVERBS_FOUND - struct { - struct ibv_mr *mr; - } ib; + struct { + struct ibv_mr *mr; + } ib; #endif - struct { - struct Block *block; - } managed; - }; + struct { + struct Block *block; + } managed; + }; }; // Initilialize memory subsystem -int init(int hugepages) __attribute__ ((warn_unused_result)); +int init(int hugepages) __attribute__((warn_unused_result)); int lock(size_t lock); @@ -62,13 +62,14 @@ int lock(size_t lock); * @retval nullptr If allocation failed. * @retval <>0 If allocation was successful. */ -void * alloc(size_t len, struct Type *m = default_type); +void *alloc(size_t len, struct Type *m = default_type); -void * alloc_aligned(size_t len, size_t alignment, struct Type *m = default_type); +void *alloc_aligned(size_t len, size_t alignment, + struct Type *m = default_type); int free(void *ptr); -struct Allocation * get_allocation(void *ptr); +struct Allocation *get_allocation(void *ptr); } // namespace memory } // namespace node diff --git a/include/villas/node/memory_type.hpp b/include/villas/node/memory_type.hpp index 553a94483..6f832dd51 100644 --- a/include/villas/node/memory_type.hpp +++ b/include/villas/node/memory_type.hpp @@ -20,41 +20,38 @@ namespace memory { struct Type; -typedef struct Allocation * (*allocator_t)(size_t len, size_t alignment, struct Type *mem); -typedef int (*deallocator_t)(struct Allocation * ma, struct Type *mem); +typedef struct Allocation *(*allocator_t)(size_t len, size_t alignment, + struct Type *mem); +typedef int (*deallocator_t)(struct Allocation *ma, struct Type *mem); enum class Flags { - MMAP = (1 << 0), - DMA = (1 << 1), - HUGEPAGE = (1 << 2), - HEAP = (1 << 3) + MMAP = (1 << 0), + DMA = (1 << 1), + HUGEPAGE = (1 << 2), + HEAP = (1 << 3) }; struct Type { - const char *name; - int flags; + const char *name; + int flags; - size_t alignment; + size_t alignment; - allocator_t alloc; - deallocator_t free; + allocator_t alloc; + deallocator_t free; - void *_vd; // Virtual data for internal state + void *_vd; // Virtual data for internal state }; -extern -struct Type heap; -extern -struct Type mmap; -extern -struct Type mmap_hugetlb; -extern -struct Type *default_type; +extern struct Type heap; +extern struct Type mmap; +extern struct Type mmap_hugetlb; +extern struct Type *default_type; -struct Type * ib(NodeCompat *n, struct Type *parent); -struct Type * managed(void *ptr, size_t len); +struct Type *ib(NodeCompat *n, struct Type *parent); +struct Type *managed(void *ptr, size_t len); -int mmap_init(int hugepages) __attribute__ ((warn_unused_result)); +int mmap_init(int hugepages) __attribute__((warn_unused_result)); } // namespace memory } // namespace node diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index b023bfb3f..00e8b4016 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -5,14 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ - #pragma once #include -#include #include #include +#include namespace villas { namespace node { @@ -23,174 +22,132 @@ class NodeCompatFactory; class NodeCompat : public Node { protected: - struct NodeCompatType *_vt; // Virtual functions (C++ OOP style) - void *_vd; // Virtual data (used by struct vnode::_vt functions) + struct NodeCompatType *_vt; // Virtual functions (C++ OOP style) + void *_vd; // Virtual data (used by struct vnode::_vt functions) - std::string _details; + std::string _details; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - NodeCompat *node; - json_t *cfg; + NodeCompat *node; + json_t *cfg; - NodeCompat(struct NodeCompatType *vt, const uuid_t &id, const std::string &name); - NodeCompat(const NodeCompat& n); + NodeCompat(struct NodeCompatType *vt, const uuid_t &id, + const std::string &name); + NodeCompat(const NodeCompat &n); - NodeCompat& operator=(const NodeCompat& other); + NodeCompat &operator=(const NodeCompat &other); - virtual - ~NodeCompat(); + virtual ~NodeCompat(); - template - T * getData() - { - return static_cast(_vd); - } + template T *getData() { return static_cast(_vd); } - virtual - NodeCompatType * getType() const - { - return _vt; - } + virtual NodeCompatType *getType() const { return _vt; } - /* Parse node connection details. + /* Parse node connection details. * * @param json A JSON object containing the configuration of the node. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Returns a string with a textual represenation of this node. - virtual - const std::string & getDetails(); + // Returns a string with a textual represenation of this node. + virtual const std::string &getDetails(); - /* Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * @retval 0 Success. Node configuration is good. * @retval <0 Error. The node configuration is bogus. */ - virtual - int check(); + virtual int check(); - virtual - int prepare(); + virtual int prepare(); - /* Start this node. + /* Start this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int start(); + virtual int start(); - /* Stop this node. + /* Stop this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int stop(); + virtual int stop(); - /* Restart this node. + /* Restart this node. * * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int restart(); + virtual int restart(); - /* Pause this node. + /* Pause this node. * * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int pause(); + virtual int pause(); - /* Resume this node. + /* Resume this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int resume(); + virtual int resume(); - /* Reverse source and destination of a node. + /* Reverse source and destination of a node. */ - virtual - int reverse(); + virtual int reverse(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - // Get list of socket file descriptors for configuring network emulation. - virtual - std::vector getNetemFDs(); + // Get list of socket file descriptors for configuring network emulation. + virtual std::vector getNetemFDs(); - // Return a memory allocator which should be used for sample pools passed to this node. - virtual - struct memory::Type * getMemoryType(); + // Return a memory allocator which should be used for sample pools passed to this node. + virtual struct memory::Type *getMemoryType(); }; class NodeCompatFactory : public NodeFactory { protected: - struct NodeCompatType *_vt; + struct NodeCompatType *_vt; public: - NodeCompatFactory(struct NodeCompatType *vt) : - NodeFactory(), - _vt(vt) - { } + NodeCompatFactory(struct NodeCompatType *vt) : NodeFactory(), _vt(vt) {} - virtual - Node * make(const uuid_t &id = {}, const std::string &name = ""); + virtual Node *make(const uuid_t &id = {}, const std::string &name = ""); - /// Get plugin name - virtual - std::string getName() const - { - return _vt->name; - } + /// Get plugin name + virtual std::string getName() const { return _vt->name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return _vt->description; - } + /// Get plugin description + virtual std::string getDescription() const { return _vt->description; } - virtual - int getFlags() const; + virtual int getFlags() const; - virtual - int getVectorize() const - { - return _vt->vectorize; - } + virtual int getVectorize() const { return _vt->vectorize; } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); - virtual - int stop(); + virtual int stop(); }; } // namespace node diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index bfb9ec120..72877456b 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -11,8 +11,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -25,18 +25,19 @@ class SuperNode; class NodeCompatType { public: - const char *name; - const char *description; + const char *name; + const char *description; - unsigned vectorize; // Maximal vector length supported by this node type. Zero is unlimited. - int flags; + 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. - size_t size; // Size of private data bock. @see node::_vd + size_t size; // Size of private data bock. @see node::_vd - struct { - /* Global initialization per node type. + struct { + /* Global initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -44,9 +45,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(SuperNode *sn); + int (*start)(SuperNode *sn); - /* Global de-initialization per node type. + /* Global de-initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -54,27 +55,27 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*stop)(); - } type; + int (*stop)(); + } type; - /* Initialize a new node instance. + /* Initialize a new node instance. * * This callback is optional. It will only be called if non-null. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*init)(NodeCompat *n); + int (*init)(NodeCompat *n); - /* Free memory of an instance of this type. + /* Free memory of an instance of this type. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. */ - int (*destroy)(NodeCompat *n); + int (*destroy)(NodeCompat *n); - /* Parse node connection details. + /* Parse node connection details. * * This callback is optional. It will only be called if non-null. * @@ -83,9 +84,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*parse)(NodeCompat *n, json_t *json); + int (*parse)(NodeCompat *n, json_t *json); - /* Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * This callback is optional. It will only be called if non-null. * @@ -93,20 +94,20 @@ public: * @retval 0 Success. Node configuration is good. * @retval <0 Error. The node configuration is bogus. */ - int (*check)(NodeCompat *n); + int (*check)(NodeCompat *n); - int (*prepare)(NodeCompat *n); + int (*prepare)(NodeCompat *n); - /* Returns a string with a textual represenation of this node. + /* Returns a string with a textual represenation of this node. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. * @return A pointer to a dynamically allocated string. Must be freed(). */ - char * (*print)(NodeCompat *n); + char *(*print)(NodeCompat *n); - /* Start this node. + /* Start this node. * * This callback is optional. It will only be called if non-null. * @@ -114,9 +115,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(NodeCompat *n); + int (*start)(NodeCompat *n); - /* Restart this node. + /* Restart this node. * * This callback is optional. It will only be called if non-null. * @@ -124,9 +125,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*restart)(NodeCompat *n); + int (*restart)(NodeCompat *n); - /* Stop this node. + /* Stop this node. * * This callback is optional. It will only be called if non-null. * @@ -134,9 +135,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*stop)(NodeCompat *n); + int (*stop)(NodeCompat *n); - /* Pause this node. + /* Pause this node. * * This callback is optional. It will only be called if non-null. * @@ -144,9 +145,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*pause)(NodeCompat *n); + int (*pause)(NodeCompat *n); - /* Resume this node. + /* Resume this node. * * This callback is optional. It will only be called if non-null. * @@ -154,9 +155,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*resume)(NodeCompat *n); + int (*resume)(NodeCompat *n); - /* Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -172,9 +173,9 @@ public: * @param release The number of samples that should be released after read is called. * @return The number of messages actually received. */ - int (*read)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + int (*read)(NodeCompat *n, struct Sample *const smps[], unsigned cnt); - /* Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -189,34 +190,35 @@ public: * @param release The number of samples that should be released after write is called * @return The number of messages actually sent. */ - int (*write)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + int (*write)(NodeCompat *n, struct Sample *const smps[], unsigned cnt); - /* Reverse source and destination of a node. + /* Reverse source and destination of a node. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. */ - int (*reverse)(NodeCompat *n); + int (*reverse)(NodeCompat *n); - /* Get list of file descriptors which can be used by poll/select to detect the availability of new data. + /* Get list of file descriptors which can be used by poll/select to detect the availability of new data. * * This callback is optional. It will only be called if non-null. * * @return The number of file descriptors which have been put into \p fds. */ - int (*poll_fds)(NodeCompat *n, int fds[]); + int (*poll_fds)(NodeCompat *n, int fds[]); - /* Get list of socket file descriptors for configuring network emulation. + /* Get list of socket file descriptors for configuring network emulation. * * This callback is optional. It will only be called if non-null. * * @return The number of file descriptors which have been put into \p sds. */ - int (*netem_fds)(NodeCompat *n, int sds[]); + int (*netem_fds)(NodeCompat *n, int sds[]); - // Return a memory allocator which should be used for sample pools passed to this node. - struct memory::Type * (*memory_type)(NodeCompat *n, struct memory::Type *parent); + // Return a memory allocator which should be used for sample pools passed to this node. + struct memory::Type *(*memory_type)(NodeCompat *n, + struct memory::Type *parent); }; } // namespace node diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp index 503865f96..2a3a97167 100644 --- a/include/villas/node_direction.hpp +++ b/include/villas/node_direction.hpp @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include namespace villas { namespace node { @@ -22,42 +22,43 @@ class Node; class Path; class NodeDirection { - friend Node; + friend Node; public: - enum class Direction { - IN, // VILLASnode is receiving/reading - OUT // VILLASnode is sending/writing - } direction; + enum class Direction { + IN, // VILLASnode is receiving/reading + OUT // VILLASnode is sending/writing + } direction; - /* The path which uses this node as a source/destination. + /* The path which uses this node as a source/destination. * * Usually every node should be used only by a single path as destination. * Otherwise samples from different paths would be interleaved. */ - Path *path; - Node *node; + Path *path; + Node *node; - int enabled; - int builtin; // This node should use built-in hooks by default. - unsigned vectorize; // Number of messages to send / recv at once (scatter / gather) + int enabled; + int builtin; // This node should use built-in hooks by default. + unsigned + vectorize; // Number of messages to send / recv at once (scatter / gather) - HookList hooks; // List of read / write hooks (struct hook). - SignalList::Ptr signals; // Signal description. + HookList hooks; // List of read / write hooks (struct hook). + SignalList::Ptr signals; // Signal description. - json_t *config; // A JSON object containing the configuration of the node. + json_t *config; // A JSON object containing the configuration of the node. - NodeDirection(enum NodeDirection::Direction dir, Node *n); + NodeDirection(enum NodeDirection::Direction dir, Node *n); - int parse(json_t *json); - void check(); - int prepare(); - int start(); - int stop(); + int parse(json_t *json); + void check(); + int prepare(); + int start(); + int stop(); - SignalList::Ptr getSignals(int after_hooks = true) const; + SignalList::Ptr getSignals(int after_hooks = true) const; - unsigned getSignalsMaxCount() const; + unsigned getSignalsMaxCount() const; }; } // namespace node diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index 8e85c7c9c..c164e66be 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,13 +22,13 @@ class Node; class NodeList : public std::list { public: - // Lookup a node from the list based on its name - Node * lookup(const std::string &name); + // Lookup a node from the list based on its name + Node *lookup(const std::string &name); - // Lookup a node from the list based on its UUID - Node * lookup(const uuid_t &uuid); + // Lookup a node from the list based on its UUID + Node *lookup(const uuid_t &uuid); - /* Parse an array or single node and checks if they exist in the "nodes" section. + /* Parse an array or single node and checks if they exist in the "nodes" section. * * Examples: * out = [ "sintef", "scedu" ] @@ -38,9 +38,9 @@ public: * @param nodes The nodes will be added to this list. * @param all This list contains all valid nodes. */ - int parse(json_t *json, NodeList &all); + int parse(json_t *json, NodeList &all); - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index 636ea4e3b..8d6ca9cfb 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -15,8 +15,8 @@ #include #endif -#include #include +#include namespace villas { namespace node { @@ -25,30 +25,30 @@ namespace node { class NodeCompat; struct amqp_ssl_info { - int verify_peer; - int verify_hostname; - char *ca_cert; - char *client_cert; - char *client_key; + int verify_peer; + int verify_hostname; + char *ca_cert; + char *client_cert; + char *client_key; }; struct amqp { - char *uri; + char *uri; - struct amqp_connection_info connection_info; - struct amqp_ssl_info ssl_info; + struct amqp_connection_info connection_info; + struct amqp_ssl_info ssl_info; - amqp_bytes_t routing_key; - amqp_bytes_t exchange; + amqp_bytes_t routing_key; + amqp_bytes_t exchange; - // We need to create two connection because rabbitmq-c is not thread-safe! - amqp_connection_state_t producer; - amqp_connection_state_t consumer; + // We need to create two connection because rabbitmq-c is not thread-safe! + amqp_connection_state_t producer; + amqp_connection_state_t consumer; - Format *formatter; + Format *formatter; }; -char * amqp_print(NodeCompat *n); +char *amqp_print(NodeCompat *n); int amqp_parse(NodeCompat *n, json_t *json); @@ -62,9 +62,9 @@ int amqp_poll_fds(NodeCompat *n, int fds[]); int amqp_stop(NodeCompat *n); -int amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int amqp_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int amqp_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/api.hpp b/include/villas/nodes/api.hpp index 361a123a1..3e1c7f8ab 100644 --- a/include/villas/nodes/api.hpp +++ b/include/villas/nodes/api.hpp @@ -8,9 +8,9 @@ #pragma once -#include -#include #include +#include +#include namespace villas { namespace node { @@ -21,33 +21,28 @@ struct Sample; class APINode : public Node { public: - APINode(const uuid_t &id = {}, const std::string &name = ""); + APINode(const uuid_t &id = {}, const std::string &name = ""); - struct Direction { - Sample *sample; - api::universal::ChannelList channels; - pthread_cond_t cv; - pthread_mutex_t mutex; - }; + struct Direction { + Sample *sample; + api::universal::ChannelList channels; + pthread_cond_t cv; + pthread_mutex_t mutex; + }; - // Accessed by api::universal::SignalRequest - Direction read, write; + // Accessed by api::universal::SignalRequest + Direction read, write; - virtual - int prepare(); + virtual int prepare(); - virtual - int check(); + virtual int check(); protected: - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index acb5ce59a..5c398357a 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -19,22 +19,22 @@ class NodeCompat; union SignalData; struct can_signal { - uint32_t id; - int offset; - int size; + uint32_t id; + int offset; + int size; }; struct can { - // Settings - char *interface_name; - struct can_signal *in; - struct can_signal *out; + // Settings + char *interface_name; + struct can_signal *in; + struct can_signal *out; - // States - int socket; - union SignalData *sample_buf; - size_t sample_buf_num; - struct timespec start_time; + // States + int socket; + union SignalData *sample_buf; + size_t sample_buf_num; + struct timespec start_time; }; int can_init(NodeCompat *n); @@ -43,7 +43,7 @@ int can_destroy(NodeCompat *n); int can_parse(NodeCompat *n, json_t *json); -char * can_print(NodeCompat *n); +char *can_print(NodeCompat *n); int can_check(NodeCompat *n); @@ -53,9 +53,9 @@ int can_start(NodeCompat *n); int can_stop(NodeCompat *n); -int can_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int can_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int can_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int can_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index d59c7cb9f..b922b466a 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -23,47 +23,46 @@ class NodeCompat; //#define COMEDI_USE_READ (0) struct comedi_chanspec { - unsigned int maxdata; - comedi_range *range; + unsigned int maxdata; + comedi_range *range; }; struct comedi_direction { - int subdevice; ///< Comedi subdevice - int buffer_size; ///< Comedi's kernel buffer size in kB - int sample_size; ///< Size of a single measurement sample - int sample_rate_hz; ///< Sample rate in Hz - bool present; ///< Config present - bool enabled; ///< Card is started successfully - bool running; ///< Card is actively transfering samples - struct timespec started; ///< Timestamp when sampling started - struct timespec last_debug; ///< Timestamp of last debug output - size_t counter; ///< Number of villas samples transfered - struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels - unsigned *chanlist; ///< Channel list in comedi's packed format - size_t chanlist_len; ///< Number of channels for this direction + int subdevice; ///< Comedi subdevice + int buffer_size; ///< Comedi's kernel buffer size in kB + int sample_size; ///< Size of a single measurement sample + int sample_rate_hz; ///< Sample rate in Hz + bool present; ///< Config present + bool enabled; ///< Card is started successfully + bool running; ///< Card is actively transfering samples + struct timespec started; ///< Timestamp when sampling started + struct timespec last_debug; ///< Timestamp of last debug output + size_t counter; ///< Number of villas samples transfered + struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels + unsigned *chanlist; ///< Channel list in comedi's packed format + size_t chanlist_len; ///< Number of channels for this direction - char* buffer; - char* bufptr; + char *buffer; + char *bufptr; }; struct comedi { - char *device; - struct comedi_direction in, out; - comedi_t *dev; + char *device; + struct comedi_direction in, out; + comedi_t *dev; #if COMEDI_USE_READ - char *buf; - char *bufptr; + char *buf; + char *bufptr; #else - char *map; - size_t bufpos; - size_t front; - size_t back; + char *map; + size_t bufpos; + size_t front; + size_t back; #endif - }; -char * comedi_print(NodeCompat *n); +char *comedi_print(NodeCompat *n); int comedi_parse(NodeCompat *n, json_t *json); @@ -73,9 +72,9 @@ int comedi_stop(NodeCompat *n); int comedi_poll_fds(NodeCompat *n, int fds[]); -int comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int comedi_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int comedi_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 35cf7cbf1..bd16c7b65 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -11,12 +11,12 @@ #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include namespace villas { namespace node { @@ -29,37 +29,38 @@ class SuperNode; #include extern "C" { - #include +#include } -#define DEFAULT_ETHERCAT_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) +#define DEFAULT_ETHERCAT_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) // Internal data per ethercat node struct ethercat { - // Settings - double rate; + // Settings + double rate; - struct { - unsigned num_channels; - double range; - unsigned position; - unsigned product_code; // Product ID of EtherCAT slave - unsigned vendor_id; // Vendor ID of EtherCAT slave + struct { + unsigned num_channels; + double range; + unsigned position; + unsigned product_code; // Product ID of EtherCAT slave + unsigned vendor_id; // Vendor ID of EtherCAT slave - ec_slave_config_t *sc; - unsigned *offsets; // Offsets for PDO entries - } in, out; + ec_slave_config_t *sc; + unsigned *offsets; // Offsets for PDO entries + } in, out; - ec_domain_t *domain; - ec_pdo_entry_reg_t *domain_regs; - uint8_t *domain_pd; // Process data + ec_domain_t *domain; + ec_pdo_entry_reg_t *domain_regs; + uint8_t *domain_pd; // Process data - std::thread thread; // Cyclic task thread - struct Task task; // Periodic timer - struct Pool pool; - struct CQueueSignalled queue; // For samples which are received from WebSockets + std::thread thread; // Cyclic task thread + struct Task task; // Periodic timer + struct Pool pool; + struct CQueueSignalled + queue; // For samples which are received from WebSockets - std::atomic send; // Last sample to be sent via EtherCAT + std::atomic send; // Last sample to be sent via EtherCAT }; // Internal datastructures @@ -84,11 +85,11 @@ int ethercat_stop(NodeCompat *n); int ethercat_poll_fds(NodeCompat *n, int fds[]); -char * ethercat_print(NodeCompat *n); +char *ethercat_print(NodeCompat *n); -int ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ethercat_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ethercat_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index ed1386b0b..4b1c2816f 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -33,8 +33,7 @@ * Revision number: 0x00140000 */ -static -ec_pdo_entry_info_t slave_3_pdo_entries[] = { +static ec_pdo_entry_info_t slave_3_pdo_entries[] = { {0x7000, 0x01, 16}, // Analog output {0x7010, 0x01, 16}, // Analog output {0x7020, 0x01, 16}, // Analog output @@ -45,8 +44,7 @@ ec_pdo_entry_info_t slave_3_pdo_entries[] = { {0x7070, 0x01, 16}, // Analog output }; -static -ec_pdo_info_t slave_3_pdos[] = { +static ec_pdo_info_t slave_3_pdos[] = { {0x1600, 1, slave_3_pdo_entries + 0}, // AO RxPDO-Map Outputs Ch.1 {0x1601, 1, slave_3_pdo_entries + 1}, // AO RxPDO-Map Outputs Ch.2 {0x1602, 1, slave_3_pdo_entries + 2}, // AO RxPDO-Map Outputs Ch.3 @@ -57,14 +55,12 @@ ec_pdo_info_t slave_3_pdos[] = { {0x1607, 1, slave_3_pdo_entries + 7}, // AO RxPDO-Map Outputs Ch.8 }; -static -ec_sync_info_t slave_3_syncs[] = { +static ec_sync_info_t slave_3_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 8, slave_3_pdos + 0, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, - {0xff} -}; + {0xff}}; /* Master 0, Slave 4, "EL3008" * Vendor ID: 0x00000002 @@ -72,93 +68,91 @@ ec_sync_info_t slave_3_syncs[] = { * Revision number: 0x00150000 */ -static -ec_pdo_entry_info_t slave_4_pdo_entries[] = { - {0x6000, 0x01, 1}, // Underrange - {0x6000, 0x02, 1}, // Overrange - {0x6000, 0x03, 2}, // Limit 1 - {0x6000, 0x05, 2}, // Limit 2 - {0x6000, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6000, 0x0f, 1}, // TxPDO State - {0x6000, 0x10, 1}, // TxPDO Toggle +static ec_pdo_entry_info_t slave_4_pdo_entries[] = { + {0x6000, 0x01, 1}, // Underrange + {0x6000, 0x02, 1}, // Overrange + {0x6000, 0x03, 2}, // Limit 1 + {0x6000, 0x05, 2}, // Limit 2 + {0x6000, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6000, 0x0f, 1}, // TxPDO State + {0x6000, 0x10, 1}, // TxPDO Toggle {0x6000, 0x11, 16}, // Value - {0x6010, 0x01, 1}, // Underrange - {0x6010, 0x02, 1}, // Overrange - {0x6010, 0x03, 2}, // Limit 1 - {0x6010, 0x05, 2}, // Limit 2 - {0x6010, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6010, 0x0f, 1}, // TxPDO State - {0x6010, 0x10, 1}, // TxPDO Toggle + {0x6010, 0x01, 1}, // Underrange + {0x6010, 0x02, 1}, // Overrange + {0x6010, 0x03, 2}, // Limit 1 + {0x6010, 0x05, 2}, // Limit 2 + {0x6010, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6010, 0x0f, 1}, // TxPDO State + {0x6010, 0x10, 1}, // TxPDO Toggle {0x6010, 0x11, 16}, // Value - {0x6020, 0x01, 1}, // Underrange - {0x6020, 0x02, 1}, // Overrange - {0x6020, 0x03, 2}, // Limit 1 - {0x6020, 0x05, 2}, // Limit 2 - {0x6020, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6020, 0x0f, 1}, // TxPDO State - {0x6020, 0x10, 1}, // TxPDO Toggle + {0x6020, 0x01, 1}, // Underrange + {0x6020, 0x02, 1}, // Overrange + {0x6020, 0x03, 2}, // Limit 1 + {0x6020, 0x05, 2}, // Limit 2 + {0x6020, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6020, 0x0f, 1}, // TxPDO State + {0x6020, 0x10, 1}, // TxPDO Toggle {0x6020, 0x11, 16}, // Value - {0x6030, 0x01, 1}, // Underrange - {0x6030, 0x02, 1}, // Overrange - {0x6030, 0x03, 2}, // Limit 1 - {0x6030, 0x05, 2}, // Limit 2 - {0x6030, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6030, 0x0f, 1}, // TxPDO State - {0x6030, 0x10, 1}, // TxPDO Toggle + {0x6030, 0x01, 1}, // Underrange + {0x6030, 0x02, 1}, // Overrange + {0x6030, 0x03, 2}, // Limit 1 + {0x6030, 0x05, 2}, // Limit 2 + {0x6030, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6030, 0x0f, 1}, // TxPDO State + {0x6030, 0x10, 1}, // TxPDO Toggle {0x6030, 0x11, 16}, // Value - {0x6040, 0x01, 1}, // Underrange - {0x6040, 0x02, 1}, // Overrange - {0x6040, 0x03, 2}, // Limit 1 - {0x6040, 0x05, 2}, // Limit 2 - {0x6040, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6040, 0x0f, 1}, // TxPDO State - {0x6040, 0x10, 1}, // TxPDO Toggle + {0x6040, 0x01, 1}, // Underrange + {0x6040, 0x02, 1}, // Overrange + {0x6040, 0x03, 2}, // Limit 1 + {0x6040, 0x05, 2}, // Limit 2 + {0x6040, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6040, 0x0f, 1}, // TxPDO State + {0x6040, 0x10, 1}, // TxPDO Toggle {0x6040, 0x11, 16}, // Value - {0x6050, 0x01, 1}, // Underrange - {0x6050, 0x02, 1}, // Overrange - {0x6050, 0x03, 2}, // Limit 1 - {0x6050, 0x05, 2}, // Limit 2 - {0x6050, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6050, 0x0f, 1}, // TxPDO State - {0x6050, 0x10, 1}, // TxPDO Toggle + {0x6050, 0x01, 1}, // Underrange + {0x6050, 0x02, 1}, // Overrange + {0x6050, 0x03, 2}, // Limit 1 + {0x6050, 0x05, 2}, // Limit 2 + {0x6050, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6050, 0x0f, 1}, // TxPDO State + {0x6050, 0x10, 1}, // TxPDO Toggle {0x6050, 0x11, 16}, // Value - {0x6060, 0x01, 1}, // Underrange - {0x6060, 0x02, 1}, // Overrange - {0x6060, 0x03, 2}, // Limit 1 - {0x6060, 0x05, 2}, // Limit 2 - {0x6060, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6060, 0x0f, 1}, // TxPDO State - {0x6060, 0x10, 1}, // TxPDO Toggle + {0x6060, 0x01, 1}, // Underrange + {0x6060, 0x02, 1}, // Overrange + {0x6060, 0x03, 2}, // Limit 1 + {0x6060, 0x05, 2}, // Limit 2 + {0x6060, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6060, 0x0f, 1}, // TxPDO State + {0x6060, 0x10, 1}, // TxPDO Toggle {0x6060, 0x11, 16}, // Value - {0x6070, 0x01, 1}, // Underrange - {0x6070, 0x02, 1}, // Overrange - {0x6070, 0x03, 2}, // Limit 1 - {0x6070, 0x05, 2}, // Limit 2 - {0x6070, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6070, 0x0f, 1}, // TxPDO State - {0x6070, 0x10, 1}, // TxPDO Toggle + {0x6070, 0x01, 1}, // Underrange + {0x6070, 0x02, 1}, // Overrange + {0x6070, 0x03, 2}, // Limit 1 + {0x6070, 0x05, 2}, // Limit 2 + {0x6070, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6070, 0x0f, 1}, // TxPDO State + {0x6070, 0x10, 1}, // TxPDO Toggle {0x6070, 0x11, 16}, // Value }; -static -ec_pdo_info_t slave_4_pdos[] = { - {0x1a00, 10, slave_4_pdo_entries + 0}, // AI TxPDO-Map Standard Ch.1 +static ec_pdo_info_t slave_4_pdos[] = { + {0x1a00, 10, slave_4_pdo_entries + 0}, // AI TxPDO-Map Standard Ch.1 {0x1a02, 10, slave_4_pdo_entries + 10}, // AI TxPDO-Map Standard Ch.2 {0x1a04, 10, slave_4_pdo_entries + 20}, // AI TxPDO-Map Standard Ch.3 {0x1a06, 10, slave_4_pdo_entries + 30}, // AI TxPDO-Map Standard Ch.4 @@ -168,11 +162,9 @@ ec_pdo_info_t slave_4_pdos[] = { {0x1a0e, 10, slave_4_pdo_entries + 70}, // AI TxPDO-Map Standard Ch.8 }; -static -ec_sync_info_t slave_4_syncs[] = { +static ec_sync_info_t slave_4_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 8, slave_4_pdos + 0, EC_WD_DISABLE}, - {0xff} -}; + {0xff}}; diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index 86813e20b..55129bbb4 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -10,8 +10,8 @@ #pragma once -#include #include +#include #include namespace villas { @@ -23,72 +23,64 @@ struct Sample; class ExampleNode : public Node { protected: - // Place any configuration and per-node state here + // Place any configuration and per-node state here - // Settings - int setting1; + // Settings + int setting1; - std::string setting2; + std::string setting2; - // States - int state1; - struct timespec start_time; + // States + int state1; + struct timespec start_time; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - ExampleNode(const uuid_t &id = {}, const std::string &name = ""); + ExampleNode(const uuid_t &id = {}, const std::string &name = ""); - /* All of the following virtual-declared functions are optional. + /* All of the following virtual-declared functions are optional. * Have a look at node.hpp/node.cpp for the default behaviour. */ - virtual - ~ExampleNode(); + virtual ~ExampleNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Validate node configuration - virtual - int check(); + // Validate node configuration + virtual int check(); - virtual - int start(); + virtual int start(); - // virtual - // int stop(); + // virtual + // int stop(); - // virtual - // int pause(); + // virtual + // int pause(); - // virtual - // int resume(); + // virtual + // int resume(); - // virtual - // int restart(); + // virtual + // int restart(); - // virtual - // int reverse(); + // virtual + // int reverse(); - // virtual - // std::vector getPollFDs(); + // virtual + // std::vector getPollFDs(); - // virtual - // std::vector getNetemFDs(); + // virtual + // std::vector getNetemFDs(); - // virtual - // struct villas::node::memory::Type * getMemoryType(); + // virtual + // struct villas::node::memory::Type * getMemoryType(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; } // namespace node diff --git a/include/villas/nodes/exec.hpp b/include/villas/nodes/exec.hpp index 000222a57..0c061b866 100644 --- a/include/villas/nodes/exec.hpp +++ b/include/villas/nodes/exec.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include namespace villas { namespace node { @@ -20,55 +20,42 @@ struct Sample; class ExecNode : public Node { protected: - std::unique_ptr proc; - std::unique_ptr formatter; + std::unique_ptr proc; + std::unique_ptr formatter; - FILE *stream_in, *stream_out; + FILE *stream_in, *stream_out; - bool flush; - bool shell; + bool flush; + bool shell; - std::string working_dir; - std::string command; + std::string working_dir; + std::string command; - villas::utils::Popen::arg_list arguments; - villas::utils::Popen::env_map environment; + villas::utils::Popen::arg_list arguments; + villas::utils::Popen::env_map environment; - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - ExecNode(const uuid_t &id = {}, const std::string &name = "") : - Node(id, name), - stream_in(nullptr), - stream_out(nullptr), - flush(true), - shell(false) - { } + ExecNode(const uuid_t &id = {}, const std::string &name = "") + : Node(id, name), stream_in(nullptr), stream_out(nullptr), flush(true), + shell(false) {} - virtual - ~ExecNode(); + virtual ~ExecNode(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; } // namespace node diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index 5157f82ba..f148ac364 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -18,43 +18,48 @@ namespace node { // Forward declarations class NodeCompat; -#define FILE_MAX_PATHLEN 512 +#define FILE_MAX_PATHLEN 512 struct file { - Format *formatter; - FILE *stream_in; - FILE *stream_out; + Format *formatter; + FILE *stream_in; + FILE *stream_out; - char *uri_tmpl; // Format string for file name. - char *uri; // Real file name. + char *uri_tmpl; // Format string for file name. + char *uri; // Real file name. - unsigned skip_lines; // Skip the first n-th lines/samples of the file. - int flush; // Flush / upload file contents after each write. - struct Task task; // Timer file descriptor. Blocks until 1 / rate seconds are elapsed. - double rate; // The read rate. - 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. + unsigned skip_lines; // Skip the first n-th lines/samples of the file. + int flush; // Flush / upload file contents after each write. + struct Task + task; // Timer file descriptor. Blocks until 1 / rate seconds are elapsed. + double rate; // The read rate. + 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 class EpochMode { - DIRECT, - WAIT, - RELATIVE, - ABSOLUTE, - ORIGINAL - } epoch_mode; // Specifies how file::offset is calculated. + enum class EpochMode { + DIRECT, + WAIT, + RELATIVE, + ABSOLUTE, + ORIGINAL + } epoch_mode; // Specifies how file::offset is calculated. - enum class EOFBehaviour { - STOP, // Terminate when EOF is reached. - REWIND, // Rewind the file when EOF is reached. - SUSPEND // Blocking wait when EOF is reached. - } eof_mode; + enum class EOFBehaviour { + STOP, // Terminate when EOF is reached. + REWIND, // Rewind the file when EOF is reached. + SUSPEND // Blocking wait when EOF is reached. + } eof_mode; - struct timespec first; // The first timestamp in the file file::{read,write}::uri - struct timespec epoch; // The epoch timestamp from the configuration. - struct timespec offset; // An offset between the timestamp in the input file and the current time + struct timespec + first; // The first timestamp in the file file::{read,write}::uri + struct timespec epoch; // The epoch timestamp from the configuration. + struct timespec + offset; // An offset between the timestamp in the input file and the current time }; -char * file_print(NodeCompat *n); +char *file_print(NodeCompat *n); int file_parse(NodeCompat *n, json_t *json); @@ -68,9 +73,9 @@ int file_destroy(NodeCompat *n); int file_poll_fds(NodeCompat *n, int fds[]); -int file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int file_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int file_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 4f7065134..7a25dbf7f 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -7,15 +7,15 @@ #pragma once -#include -#include #include +#include +#include #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -26,89 +26,68 @@ namespace node { class FpgaNode : public Node { protected: - int irqFd; - int coalesce; - bool polling; + int irqFd; + int coalesce; + bool polling; - std::shared_ptr card; + std::shared_ptr card; - std::shared_ptr dma; - std::shared_ptr intf; + std::shared_ptr dma; + std::shared_ptr intf; - std::unique_ptr blockRx; - std::unique_ptr blockTx; + std::unique_ptr blockRx; + std::unique_ptr blockTx; - // Config only - std::string cardName; - std::string intfName; - std::string dmaName; + // Config only + std::string cardName; + std::string intfName; + std::string dmaName; protected: - virtual - int _read(Sample *smps[], unsigned cnt); + virtual int _read(Sample *smps[], unsigned cnt); - virtual - int _write(Sample *smps[], unsigned cnt); + virtual int _write(Sample *smps[], unsigned cnt); public: - FpgaNode(const uuid_t &id = {}, const std::string &name = ""); + FpgaNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~FpgaNode(); + virtual ~FpgaNode(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int check(); + virtual int check(); - virtual - int prepare(); + virtual int prepare(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; class FpgaNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - auto *n = new FpgaNode(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + auto *n = new FpgaNode(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL; + } - virtual - std::string getName() const - { - return "fpga"; - } + virtual std::string getName() const { return "fpga"; } - virtual - std::string getDescription() const - { - return "VILLASfpga"; - } + virtual std::string getDescription() const { return "VILLASfpga"; } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); }; } // namespace node diff --git a/include/villas/nodes/iec60870.hpp b/include/villas/nodes/iec60870.hpp index 4abeebbb0..4ac89bc2e 100644 --- a/include/villas/nodes/iec60870.hpp +++ b/include/villas/nodes/iec60870.hpp @@ -7,18 +7,18 @@ #pragma once -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -27,167 +27,185 @@ namespace iec60870 { /// A supported CS101 information data type class ASDUData { public: - enum Type { - SINGLE_POINT = M_SP_NA_1, // SinglePointInformation - SINGLE_POINT_WITH_TIMESTAMP = M_SP_TB_1, // SinglePointWithCP56Time2a - DOUBLE_POINT = M_DP_NA_1, // DoublePointInformation - DOUBLE_POINT_WITH_TIMESTAMP = M_DP_TB_1, // DoublePointWithCP56Time2a - SCALED_INT = M_ME_NB_1, // MeasuredValueScaled - SCALED_INT_WITH_TIMESTAMP = M_ME_TE_1, // MeasuredValueScaledWithCP56Time2a - NORMALIZED_FLOAT = M_ME_NA_1, // MeasuredValueNormalized - NORMALIZED_FLOAT_WITH_TIMESTAMP = M_ME_TD_1, // MeasuredValueNormalizedWithCP56Time2a - SHORT_FLOAT = M_ME_NC_1, // MeasuredValueShort - SHORT_FLOAT_WITH_TIMESTAMP = M_ME_TF_1, // MeasuredValueShortWithCP56Time2a - }; + enum Type { + SINGLE_POINT = M_SP_NA_1, // SinglePointInformation + SINGLE_POINT_WITH_TIMESTAMP = M_SP_TB_1, // SinglePointWithCP56Time2a + DOUBLE_POINT = M_DP_NA_1, // DoublePointInformation + DOUBLE_POINT_WITH_TIMESTAMP = M_DP_TB_1, // DoublePointWithCP56Time2a + SCALED_INT = M_ME_NB_1, // MeasuredValueScaled + SCALED_INT_WITH_TIMESTAMP = M_ME_TE_1, // MeasuredValueScaledWithCP56Time2a + NORMALIZED_FLOAT = M_ME_NA_1, // MeasuredValueNormalized + NORMALIZED_FLOAT_WITH_TIMESTAMP = + M_ME_TD_1, // MeasuredValueNormalizedWithCP56Time2a + SHORT_FLOAT = M_ME_NC_1, // MeasuredValueShort + SHORT_FLOAT_WITH_TIMESTAMP = M_ME_TF_1, // MeasuredValueShortWithCP56Time2a + }; - struct Sample { - SignalData signal_data; - QualityDescriptor quality; - std::optional timestamp; - }; + struct Sample { + SignalData signal_data; + QualityDescriptor quality; + std::optional timestamp; + }; - // Parse the config json - static - ASDUData parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence); + // Parse the config json + static ASDUData parse(json_t *json_signal, std::optional last_data, + bool duplicate_ioa_is_sequence); - // Does this data include a timestamp - bool hasTimestamp() const; + // Does this data include a timestamp + bool hasTimestamp() const; - // The IEC104 type - ASDUData::Type type() const; + // The IEC104 type + ASDUData::Type type() const; - // The config file identifier for this type - char const * name() const; + // The config file identifier for this type + char const *name() const; - // Get equivalent IEC104 type without timestamp (e.g. for general interrogation response) - ASDUData::Type typeWithoutTimestamp() const; + // Get equivalent IEC104 type without timestamp (e.g. for general interrogation response) + ASDUData::Type typeWithoutTimestamp() const; - // Get equivalent ASDUData without timestamp (e.g. for general interrogation response) - ASDUData withoutTimestamp() const; + // Get equivalent ASDUData without timestamp (e.g. for general interrogation response) + ASDUData withoutTimestamp() const; - // Corresponding signal type - SignalType signalType() const; + // Corresponding signal type + SignalType signalType() const; - // Check if ASDU contains this data - std::optional checkASDU(CS101_ASDU const &asdu) const; + // Check if ASDU contains this data + std::optional checkASDU(CS101_ASDU const &asdu) const; - // Add SignalData to an ASDU, returns false when sample couldn't be added (insufficient space in ASDU) - bool addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const; + // Add SignalData to an ASDU, returns false when sample couldn't be added (insufficient space in ASDU) + bool addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const; - // Every value in an ASDU has an associated "information object address" (ioa) - int ioa; + // Every value in an ASDU has an associated "information object address" (ioa) + int ioa; + + // Start of the ioa sequence + int ioa_sequence_start; - // Start of the ioa sequence - int ioa_sequence_start; private: - struct Descriptor { - ASDUData::Type type; - char const *name; - char const *type_id; - bool has_timestamp; - ASDUData::Type type_without_timestamp; - SignalType signal_type; - }; + struct Descriptor { + ASDUData::Type type; + char const *name; + char const *type_id; + bool has_timestamp; + ASDUData::Type type_without_timestamp; + SignalType signal_type; + }; - inline static - std::array const descriptors { - ASDUData::Descriptor { Type::SINGLE_POINT, "single-point", "M_SP_NA_1", false, Type::SINGLE_POINT, SignalType::BOOLEAN }, - ASDUData::Descriptor { Type::SINGLE_POINT_WITH_TIMESTAMP, "single-point", "M_SP_TB_1", true, Type::SINGLE_POINT, SignalType::BOOLEAN }, - ASDUData::Descriptor { Type::DOUBLE_POINT, "double-point", "M_DP_NA_1", false, Type::DOUBLE_POINT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::DOUBLE_POINT_WITH_TIMESTAMP, "double-point", "M_DP_TB_1", true, Type::DOUBLE_POINT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::SCALED_INT, "scaled-int", "M_ME_NB_1", false, Type::SCALED_INT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::SCALED_INT_WITH_TIMESTAMP, "scaled-int", "M_ME_TE_1", true, Type::SCALED_INT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::NORMALIZED_FLOAT, "normalized-float", "M_ME_NA_1", false, Type::NORMALIZED_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::NORMALIZED_FLOAT_WITH_TIMESTAMP, "normalized-float", "M_ME_TD_1", true, Type::NORMALIZED_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::SHORT_FLOAT, "short-float", "M_ME_NC_1", false, Type::SHORT_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::SHORT_FLOAT_WITH_TIMESTAMP, "short-float", "M_ME_TF_1", true, Type::SHORT_FLOAT, SignalType::FLOAT }, - }; + inline static std::array const descriptors{ + ASDUData::Descriptor{Type::SINGLE_POINT, "single-point", "M_SP_NA_1", + false, Type::SINGLE_POINT, SignalType::BOOLEAN}, + ASDUData::Descriptor{Type::SINGLE_POINT_WITH_TIMESTAMP, "single-point", + "M_SP_TB_1", true, Type::SINGLE_POINT, + SignalType::BOOLEAN}, + ASDUData::Descriptor{Type::DOUBLE_POINT, "double-point", "M_DP_NA_1", + false, Type::DOUBLE_POINT, SignalType::INTEGER}, + ASDUData::Descriptor{Type::DOUBLE_POINT_WITH_TIMESTAMP, "double-point", + "M_DP_TB_1", true, Type::DOUBLE_POINT, + SignalType::INTEGER}, + ASDUData::Descriptor{Type::SCALED_INT, "scaled-int", "M_ME_NB_1", false, + Type::SCALED_INT, SignalType::INTEGER}, + ASDUData::Descriptor{Type::SCALED_INT_WITH_TIMESTAMP, "scaled-int", + "M_ME_TE_1", true, Type::SCALED_INT, + SignalType::INTEGER}, + ASDUData::Descriptor{Type::NORMALIZED_FLOAT, "normalized-float", + "M_ME_NA_1", false, Type::NORMALIZED_FLOAT, + SignalType::FLOAT}, + ASDUData::Descriptor{Type::NORMALIZED_FLOAT_WITH_TIMESTAMP, + "normalized-float", "M_ME_TD_1", true, + Type::NORMALIZED_FLOAT, SignalType::FLOAT}, + ASDUData::Descriptor{Type::SHORT_FLOAT, "short-float", "M_ME_NC_1", false, + Type::SHORT_FLOAT, SignalType::FLOAT}, + ASDUData::Descriptor{Type::SHORT_FLOAT_WITH_TIMESTAMP, "short-float", + "M_ME_TF_1", true, Type::SHORT_FLOAT, + SignalType::FLOAT}, + }; - ASDUData(ASDUData::Descriptor const *descriptor, int ioa, int ioa_sequence_start); + ASDUData(ASDUData::Descriptor const *descriptor, int ioa, + int ioa_sequence_start); - // Lookup datatype for config key asdu_type - static - std::optional lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start); + // Lookup datatype for config key asdu_type + static std::optional lookupName(char const *name, + bool with_timestamp, int ioa, + int ioa_sequence_start); - // Lookup datatype for config key asdu_type_id - static - std::optional lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start); + // Lookup datatype for config key asdu_type_id + static std::optional lookupTypeId(char const *type_id, int ioa, + int ioa_sequence_start); - // Lookup datatype for numeric type identifier - static - std::optional lookupType(int type, int ioa, int ioa_sequence_start); + // Lookup datatype for numeric type identifier + static std::optional lookupType(int type, int ioa, + int ioa_sequence_start); - // Descriptor within the descriptors table above - ASDUData::Descriptor const *descriptor; + // Descriptor within the descriptors table above + ASDUData::Descriptor const *descriptor; }; class SlaveNode : public Node { protected: - struct Server { - // Slave state - enum { NONE, STOPPED, READY } state; + struct Server { + // Slave state + enum { NONE, STOPPED, READY } state; - // Config (use explicit defaults) - std::string local_address; - int local_port; - int common_address; - int low_priority_queue; - int high_priority_queue; + // Config (use explicit defaults) + std::string local_address; + int local_port; + int common_address; + int low_priority_queue; + int high_priority_queue; - // Config (use lib60870 defaults if std::nullopt) - std::optional apci_t0; - std::optional apci_t1; - std::optional apci_t2; - std::optional apci_t3; - std::optional apci_k; - std::optional apci_w; + // Config (use lib60870 defaults if std::nullopt) + std::optional apci_t0; + std::optional apci_t1; + std::optional apci_t2; + std::optional apci_t3; + std::optional apci_k; + std::optional apci_w; - // Lib60870 - CS104_Slave slave; - CS101_AppLayerParameters asdu_app_layer_parameters; - } server; + // Lib60870 + CS104_Slave slave; + CS101_AppLayerParameters asdu_app_layer_parameters; + } server; - struct Output { - bool enabled = false; - std::vector mapping; - std::vector asdu_types; + struct Output { + bool enabled = false; + std::vector mapping; + std::vector asdu_types; - mutable std::mutex last_values_mutex; - std::vector last_values; - } output; + mutable std::mutex last_values_mutex; + std::vector last_values; + } output; - void createSlave() noexcept; - void destroySlave() noexcept; + void createSlave() noexcept; + void destroySlave() noexcept; - void startSlave() noexcept(false); - void stopSlave() noexcept; + void startSlave() noexcept(false); + void stopSlave() noexcept; - void debugPrintMessage(IMasterConnection connection, uint8_t *message, int message_size, bool sent) const noexcept; - void debugPrintConnection(IMasterConnection connection, CS104_PeerConnectionEvent event) const noexcept; + void debugPrintMessage(IMasterConnection connection, uint8_t *message, + int message_size, bool sent) const noexcept; + void debugPrintConnection(IMasterConnection connection, + CS104_PeerConnectionEvent event) const noexcept; - bool onClockSync(IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) const noexcept; - bool onInterrogation(IMasterConnection connection, CS101_ASDU asdu, uint8_t _of_inter) const noexcept; - bool onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept; + bool onClockSync(IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) const noexcept; + bool onInterrogation(IMasterConnection connection, CS101_ASDU asdu, + uint8_t _of_inter) const noexcept; + bool onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept; - void sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false); + void sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false); - virtual - int _write(struct Sample *smps[], unsigned cnt) override; + virtual int _write(struct Sample *smps[], unsigned cnt) override; public: - SlaveNode(const uuid_t &id = {}, const std::string &name = ""); + SlaveNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~SlaveNode() override; + virtual ~SlaveNode() override; - virtual - int parse(json_t *json) override; + virtual int parse(json_t *json) override; - virtual - int start() override; + virtual int start() override; - virtual - int stop() override; + virtual int stop() override; }; } // namespace iec60870 diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index 2807206c9..0e4931bc2 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -11,8 +11,8 @@ #include -#include #include +#include #include #include @@ -20,7 +20,8 @@ #include #ifndef CONFIG_GOOSE_DEFAULT_DST_ADDRESS - #define CONFIG_GOOSE_DEFAULT_DST_ADDRESS {0x01, 0x0c, 0xcd, 0x01, 0x00, 0x01} +#define CONFIG_GOOSE_DEFAULT_DST_ADDRESS \ + { 0x01, 0x0c, 0xcd, 0x01, 0x00, 0x01 } #endif namespace villas { @@ -30,67 +31,67 @@ namespace node { class NodeCompat; enum class IEC61850Type { - // According to IEC 61850-7-2 - BOOLEAN, - INT8, - INT16, - INT32, - INT64, - INT8U, - INT16U, - INT32U, - INT64U, - FLOAT32, - FLOAT64, - ENUMERATED, - CODED_ENUM, - OCTET_STRING, - VISIBLE_STRING, - OBJECTNAME, - OBJECTREFERENCE, - TIMESTAMP, - ENTRYTIME, + // According to IEC 61850-7-2 + BOOLEAN, + INT8, + INT16, + INT32, + INT64, + INT8U, + INT16U, + INT32U, + INT64U, + FLOAT32, + FLOAT64, + ENUMERATED, + CODED_ENUM, + OCTET_STRING, + VISIBLE_STRING, + OBJECTNAME, + OBJECTREFERENCE, + TIMESTAMP, + ENTRYTIME, - // According to IEC 61850-8-1 - BITSTRING + // According to IEC 61850-8-1 + BITSTRING }; struct iec61850_type_descriptor { - const char *name; - enum IEC61850Type iec_type; - enum SignalType type; - unsigned size; - bool publisher; - bool subscriber; + const char *name; + enum IEC61850Type iec_type; + enum SignalType type; + unsigned size; + bool publisher; + bool subscriber; }; struct iec61850_receiver { - char *interface; + char *interface; - EthernetSocket socket; + EthernetSocket socket; - enum class Type { - GOOSE, - SAMPLED_VALUES - } type; + enum class Type { GOOSE, SAMPLED_VALUES } type; - union { - SVReceiver sv; - GooseReceiver goose; - }; + union { + SVReceiver sv; + GooseReceiver goose; + }; }; int iec61850_type_start(villas::node::SuperNode *sn); int iec61850_type_stop(); -const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); +const struct iec61850_type_descriptor *iec61850_lookup_type(const char *name); -int iec61850_parse_signals(json_t *json_signals, struct List *signals, SignalList::Ptr node_signals); +int iec61850_parse_signals(json_t *json_signals, struct List *signals, + SignalList::Ptr 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); @@ -98,7 +99,7 @@ int iec61850_receiver_stop(struct iec61850_receiver *r); int iec61850_receiver_destroy(struct iec61850_receiver *r); -const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); +const struct iec61850_type_descriptor *iec61850_lookup_type(const char *name); } // namespace node } // namespace villas diff --git a/include/villas/nodes/iec61850_goose.hpp b/include/villas/nodes/iec61850_goose.hpp index 4d2826d37..d613f25b7 100644 --- a/include/villas/nodes/iec61850_goose.hpp +++ b/include/villas/nodes/iec61850_goose.hpp @@ -8,21 +8,21 @@ #pragma once #include -#include #include #include #include #include +#include #include #include #include +#include #include #include -#include -#include #include +#include #include #include #include @@ -34,82 +34,89 @@ namespace iec61850 { // A GooseSignal is a SignalData value with attached Metadata for the MmsType and SignalType class GooseSignal { public: - union Meta { - int size; - }; + union Meta { + int size; + }; - struct Descriptor { - std::string name; - SignalType signal_type; - MmsType mms_type; - Meta default_meta; - }; + struct Descriptor { + std::string name; + SignalType signal_type; + MmsType mms_type; + Meta default_meta; + }; - using Type = Descriptor const *; + using Type = Descriptor const *; - // The config file identifier for this type - std::string const & name() const; + // The config file identifier for this type + std::string const &name() const; - // The type of this value - Type type() const; + // The type of this value + Type type() const; - // Corresponding mms type - MmsType mmsType() const; + // Corresponding mms type + MmsType mmsType() const; - // Corresponding signal type - SignalType signalType() const; + // Corresponding signal type + SignalType signalType() const; - // Create a GooseSignal from an MmsValue - static - std::optional fromMmsValue(MmsValue *mms_value); + // Create a GooseSignal from an MmsValue + static std::optional fromMmsValue(MmsValue *mms_value); - // Create a GooseSignal from type name and SignalData value - static - std::optional fromNameAndValue(char const *name, SignalData value, std::optional meta = std::nullopt); + // Create a GooseSignal from type name and SignalData value + static std::optional + fromNameAndValue(char const *name, SignalData value, + std::optional meta = std::nullopt); - // Create a MmsValue from this GooseSignal - MmsValue * toMmsValue() const; + // Create a MmsValue from this GooseSignal + MmsValue *toMmsValue() const; - static - std::optional lookupMmsType(int mms_type); + static std::optional lookupMmsType(int mms_type); - static - std::optional lookupMmsTypeName(char const *name); + static std::optional lookupMmsTypeName(char const *name); - GooseSignal(Type type, SignalData value, std::optional meta = std::nullopt); + GooseSignal(Type type, SignalData value, + std::optional meta = std::nullopt); + + SignalData signal_data; + Meta meta; - SignalData signal_data; - Meta meta; private: - inline static - std::array const descriptors { - Descriptor { "boolean", SignalType::BOOLEAN, MmsType::MMS_BOOLEAN }, - Descriptor { "int8", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 8 } }, - Descriptor { "int16", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 16 } }, - Descriptor { "int32", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 32 } }, - Descriptor { "int64", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 64 } }, - Descriptor { "int8u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 8 } }, - Descriptor { "int16u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 16 } }, - Descriptor { "int32u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 32 } }, - Descriptor { "bitstring", SignalType::INTEGER, MmsType::MMS_BIT_STRING, {.size = 32 } }, - Descriptor { "float32", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 32 } }, - Descriptor { "float64", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 64 } }, - }; + inline static std::array const descriptors{ + Descriptor{"boolean", SignalType::BOOLEAN, MmsType::MMS_BOOLEAN}, + Descriptor{ + "int8", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 8}}, + Descriptor{ + "int16", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 16}}, + Descriptor{ + "int32", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 32}}, + Descriptor{ + "int64", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 64}}, + Descriptor{ + "int8u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 8}}, + Descriptor{ + "int16u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 16}}, + Descriptor{ + "int32u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 32}}, + Descriptor{"bitstring", + SignalType::INTEGER, + MmsType::MMS_BIT_STRING, + {.size = 32}}, + Descriptor{ + "float32", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 32}}, + Descriptor{ + "float64", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 64}}, + }; - static - MmsValue * newMmsInteger(int64_t i, int size); + static MmsValue *newMmsInteger(int64_t i, int size); - static - MmsValue * newMmsUnsigned(uint64_t i, int size); + static MmsValue *newMmsUnsigned(uint64_t i, int size); - static - MmsValue * newMmsBitString(uint32_t i, int size); + static MmsValue *newMmsBitString(uint32_t i, int size); - static - MmsValue * newMmsFloat(double i, int size); + static MmsValue *newMmsFloat(double i, int size); - // Descriptor within the descriptors table above - Descriptor const *descriptor; + // Descriptor within the descriptors table above + Descriptor const *descriptor; }; bool operator==(GooseSignal &lhs, GooseSignal &rhs); @@ -117,141 +124,134 @@ bool operator!=(GooseSignal &lhs, GooseSignal &rhs); class GooseNode : public Node { protected: - enum InputTrigger { - CHANGE, - ALWAYS, - }; + enum InputTrigger { + CHANGE, + ALWAYS, + }; - struct InputMapping { - std::string subscriber; - unsigned int index; - GooseSignal::Type type; - }; + struct InputMapping { + std::string subscriber; + unsigned int index; + GooseSignal::Type type; + }; - struct SubscriberConfig { - std::string go_cb_ref; - InputTrigger trigger; - std::optional> dst_address; - std::optional app_id; - }; + struct SubscriberConfig { + std::string go_cb_ref; + InputTrigger trigger; + std::optional> dst_address; + std::optional app_id; + }; - struct InputEventContext { - SubscriberConfig subscriber_config; + struct InputEventContext { + SubscriberConfig subscriber_config; - GooseNode *node; - std::vector> values; - int last_state_num; - }; + GooseNode *node; + std::vector> values; + int last_state_num; + }; - struct Input { - enum { NONE, STOPPED, READY } state; - GooseReceiver receiver; - CQueueSignalled queue; - Pool pool; + struct Input { + enum { NONE, STOPPED, READY } state; + GooseReceiver receiver; + CQueueSignalled queue; + Pool pool; - std::map contexts; - std::vector mappings; - std::string interface_id; - bool with_timestamp; - unsigned int queue_length; - } input; + std::map contexts; + std::vector mappings; + std::string interface_id; + bool with_timestamp; + unsigned int queue_length; + } input; - struct OutputData { - std::optional signal; - GooseSignal default_value; - }; + struct OutputData { + std::optional signal; + GooseSignal default_value; + }; - struct PublisherConfig { - std::string go_id; - std::string go_cb_ref; - std::string data_set_ref; - std::array dst_address; - uint16_t app_id; - uint32_t conf_rev; - uint32_t time_allowed_to_live; - int burst; - std::vector data; - }; + struct PublisherConfig { + std::string go_id; + std::string go_cb_ref; + std::string data_set_ref; + std::array dst_address; + uint16_t app_id; + uint32_t conf_rev; + uint32_t time_allowed_to_live; + int burst; + std::vector data; + }; - struct OutputContext { - PublisherConfig config; - std::vector values; + struct OutputContext { + PublisherConfig config; + std::vector values; - GoosePublisher publisher; - }; + GoosePublisher publisher; + }; - struct Output { - enum { NONE, STOPPED, READY } state; - std::vector contexts; - std::string interface_id; - double resend_interval; + struct Output { + enum { NONE, STOPPED, READY } state; + std::vector contexts; + std::string interface_id; + double resend_interval; - std::mutex send_mutex; - bool changed; - bool resend_thread_stop; - std::optional resend_thread; - std::condition_variable resend_thread_cv; - } output; + std::mutex send_mutex; + bool changed; + bool resend_thread_stop; + std::optional resend_thread; + std::condition_variable resend_thread_cv; + } output; - void createReceiver() noexcept; - void destroyReceiver() noexcept; + void createReceiver() noexcept; + void destroyReceiver() noexcept; - void startReceiver() noexcept(false); - void stopReceiver() noexcept; + void startReceiver() noexcept(false); + void stopReceiver() noexcept; - void createPublishers() noexcept; - void destroyPublishers() noexcept; + void createPublishers() noexcept; + void destroyPublishers() noexcept; - void startPublishers() noexcept(false); - void stopPublishers() noexcept; + void startPublishers() noexcept(false); + void stopPublishers() noexcept; - static - void onEvent(GooseSubscriber subscriber, InputEventContext &context) noexcept; + static void onEvent(GooseSubscriber subscriber, + InputEventContext &context) noexcept; - void addSubscriber(InputEventContext &ctx) noexcept; - void pushSample(uint64_t timestamp) noexcept; + void addSubscriber(InputEventContext &ctx) noexcept; + void pushSample(uint64_t timestamp) noexcept; - static - void publish_values(GoosePublisher publisher, std::vector &values, bool changed, int burst = 1) noexcept; - static - void resend_thread(GooseNode::Output *output) noexcept; + static void publish_values(GoosePublisher publisher, + std::vector &values, bool changed, + int burst = 1) noexcept; + static void resend_thread(GooseNode::Output *output) noexcept; - void parseInput(json_t *json); - void parseSubscriber(json_t *json, SubscriberConfig &sc); - void parseSubscribers(json_t *json, std::map &ctx); - void parseInputSignals(json_t *json, std::vector &mappings); + void parseInput(json_t *json); + void parseSubscriber(json_t *json, SubscriberConfig &sc); + void parseSubscribers(json_t *json, + std::map &ctx); + void parseInputSignals(json_t *json, std::vector &mappings); - void parseOutput(json_t *json); - void parsePublisherData(json_t *json, std::vector &data); - void parsePublisher(json_t *json, PublisherConfig &pc); - void parsePublishers(json_t *json, std::vector &ctx); + void parseOutput(json_t *json); + void parsePublisherData(json_t *json, std::vector &data); + void parsePublisher(json_t *json, PublisherConfig &pc); + void parsePublishers(json_t *json, std::vector &ctx); - virtual - int _read(struct Sample *smps[], unsigned cnt) override; + virtual int _read(struct Sample *smps[], unsigned cnt) override; - virtual - int _write(struct Sample *smps[], unsigned cnt) override; + virtual int _write(struct Sample *smps[], unsigned cnt) override; public: - GooseNode(const uuid_t &id = {}, const std::string &name = ""); + GooseNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~GooseNode() override; + virtual ~GooseNode() override; - virtual - std::vector getPollFDs() override; + virtual std::vector getPollFDs() override; - virtual - int parse(json_t *json) override; + virtual int parse(json_t *json) override; - virtual - int prepare() override; + virtual int prepare() override; - virtual - int start() override; + virtual int start() override; - virtual - int stop() override; + virtual int stop() override; }; } // namespace iec61850 diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index f46612834..65d40851f 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -12,10 +12,10 @@ #include #include -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -24,47 +24,47 @@ namespace node { class NodeCompat; struct iec61850_sv { - char *interface; - int app_id; - struct ether_addr dst_address; + char *interface; + int app_id; + struct ether_addr dst_address; - struct { - bool enabled; + struct { + bool enabled; - SVSubscriber subscriber; - SVReceiver receiver; + SVSubscriber subscriber; + SVReceiver receiver; - struct CQueueSignalled queue; - struct Pool pool; + struct CQueueSignalled queue; + struct Pool pool; - struct List signals; // Mappings of type struct iec61850_type_descriptor - int total_size; - } in; + struct List signals; // Mappings of type struct iec61850_type_descriptor + int total_size; + } in; - struct { - bool enabled; + struct { + bool enabled; - SVPublisher publisher; - SVPublisher_ASDU asdu; + SVPublisher publisher; + SVPublisher_ASDU asdu; - char *svid; + char *svid; - int vlan_priority; - int vlan_id; - int smpmod; - int smprate; - int confrev; + int vlan_priority; + int vlan_id; + int smpmod; + int smprate; + int confrev; - struct List signals; // Mappings of type struct iec61850_type_descriptor - int total_size; - } out; + struct List signals; // Mappings of type struct iec61850_type_descriptor + int total_size; + } out; }; int iec61850_sv_type_stop(); int iec61850_sv_parse(NodeCompat *n, json_t *json); -char * iec61850_sv_print(NodeCompat *n); +char *iec61850_sv_print(NodeCompat *n); int iec61850_sv_start(NodeCompat *n); @@ -72,9 +72,9 @@ int iec61850_sv_stop(NodeCompat *n); int iec61850_sv_destroy(NodeCompat *n); -int iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int iec61850_sv_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int iec61850_sv_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int iec61850_sv_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index f733ffd25..8cd1e25f9 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -7,10 +7,10 @@ #pragma once -#include -#include -#include #include +#include +#include +#include namespace villas { namespace node { @@ -25,76 +25,76 @@ class NodeCompat; #define CHK_PER_ITER 2048 struct infiniband { - // IBV/RDMA CM structs - struct context_s { - struct rdma_cm_id *listen_id; - struct rdma_cm_id *id; - struct rdma_event_channel *ec; + // IBV/RDMA CM structs + struct context_s { + struct rdma_cm_id *listen_id; + struct rdma_cm_id *id; + struct rdma_event_channel *ec; - struct ibv_pd *pd; - struct ibv_cq *recv_cq; - struct ibv_cq *send_cq; - struct ibv_comp_channel *comp_channel; - } ctx; + struct ibv_pd *pd; + struct ibv_cq *recv_cq; + struct ibv_cq *send_cq; + struct ibv_comp_channel *comp_channel; + } ctx; - // Queue Pair init variables - struct ibv_qp_init_attr qp_init; + // Queue Pair init variables + struct ibv_qp_init_attr qp_init; - // Size of receive and send completion queue - int recv_cq_size; - int send_cq_size; + // Size of receive and send completion queue + int recv_cq_size; + int send_cq_size; - // Bool, set if threads should be aborted - int stopThreads; + // Bool, set if threads should be aborted + int stopThreads; - // When most messages are sent inline, once every cycles a signal must be sent. - unsigned signaling_counter; - unsigned periodic_signaling; + // When most messages are sent inline, once every cycles a signal must be sent. + unsigned signaling_counter; + unsigned periodic_signaling; - // Connection specific variables - struct connection_s { - struct addrinfo *src_addr; - struct addrinfo *dst_addr; + // Connection specific variables + struct connection_s { + struct addrinfo *src_addr; + struct addrinfo *dst_addr; - // RDMA_PS_TCP or RDMA_PS_UDP - enum rdma_port_space port_space; + // RDMA_PS_TCP or RDMA_PS_UDP + enum rdma_port_space port_space; - // Timeout for rdma_resolve_route - int timeout; + // Timeout for rdma_resolve_route + int timeout; - // Thread to monitor RDMA CM Event threads - pthread_t rdma_cm_event_thread; + // Thread to monitor RDMA CM Event threads + pthread_t rdma_cm_event_thread; - // Bool, should data be send inline if possible? - int send_inline; + // Bool, should data be send inline if possible? + int send_inline; - // Bool, should node have a fallback if it can't connect to a remote host? - int use_fallback; + // Bool, should node have a fallback if it can't connect to a remote host? + int use_fallback; - // Counter to keep track of available recv. WRs - unsigned available_recv_wrs; + // Counter to keep track of available recv. WRs + unsigned available_recv_wrs; - /* Fixed number to substract from min. number available + /* Fixed number to substract from min. number available * WRs in receive queue */ - unsigned buffer_subtraction; + unsigned buffer_subtraction; - // Unrealiable connectionless data - struct ud_s { - struct rdma_ud_param ud; - struct ibv_ah *ah; - void *grh_ptr; - struct ibv_mr *grh_mr; - } ud; + // Unrealiable connectionless data + struct ud_s { + struct rdma_ud_param ud; + struct ibv_ah *ah; + void *grh_ptr; + struct ibv_mr *grh_mr; + } ud; - } conn; + } conn; - // Misc settings - int is_source; + // Misc settings + int is_source; }; int ib_reverse(NodeCompat *n); -char * ib_print(NodeCompat *n); +char *ib_print(NodeCompat *n); int ib_parse(NodeCompat *n, json_t *json); @@ -106,9 +106,9 @@ int ib_destroy(NodeCompat *n); int ib_stop(NodeCompat *n); -int ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ib_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ib_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/influxdb.hpp b/include/villas/nodes/influxdb.hpp index 2352a12ed..184d32f09 100644 --- a/include/villas/nodes/influxdb.hpp +++ b/include/villas/nodes/influxdb.hpp @@ -17,16 +17,16 @@ class NodeCompat; struct Sample; struct influxdb { - char *host; - char *port; - char *key; + char *host; + char *port; + char *key; - struct List fields; + struct List fields; - int sd; + int sd; }; -char * influxdb_print(NodeCompat *n); +char *influxdb_print(NodeCompat *n); int influxdb_parse(NodeCompat *n, json_t *json); @@ -34,7 +34,7 @@ int influxdb_open(NodeCompat *n); int influxdb_close(NodeCompat *n); -int influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int influxdb_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/kafka.hpp b/include/villas/nodes/kafka.hpp index d4438d824..4ca6a765a 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -9,8 +9,8 @@ #include -#include #include +#include #include namespace villas { @@ -20,42 +20,42 @@ namespace node { class NodeCompat; struct kafka { - struct CQueueSignalled queue; - struct Pool pool; + struct CQueueSignalled queue; + struct Pool pool; - double timeout; // Timeout in seconds. - char *server; // Hostname/IP:Port address of the bootstrap server. - char *protocol; // Security protocol. - char *produce; // Producer topic. - char *consume; // Consumer topic. - char *client_id; // Client ID. + double timeout; // Timeout in seconds. + char *server; // Hostname/IP:Port address of the bootstrap server. + char *protocol; // Security protocol. + char *produce; // Producer topic. + char *consume; // Consumer topic. + char *client_id; // Client ID. - struct { - rd_kafka_t *client; - rd_kafka_topic_t *topic; - } producer; + struct { + rd_kafka_t *client; + rd_kafka_topic_t *topic; + } producer; - struct { - rd_kafka_t *client; - char *group_id; // Group id. - } consumer; + struct { + rd_kafka_t *client; + char *group_id; // Group id. + } consumer; - struct { - char *ca; // SSL CA file. - } ssl; + struct { + char *ca; // SSL CA file. + } ssl; - struct { - char *mechanisms; // SASL mechanisms. - char *username; // SSL CA path. - char *password; // SSL certificate. - } sasl; + struct { + char *mechanisms; // SASL mechanisms. + char *username; // SSL CA path. + char *password; // SSL certificate. + } sasl; - Format *formatter; + Format *formatter; }; int kafka_reverse(NodeCompat *n); -char * kafka_print(NodeCompat *n); +char *kafka_print(NodeCompat *n); int kafka_init(NodeCompat *n); @@ -75,9 +75,9 @@ int kafka_type_stop(); int kafka_poll_fds(NodeCompat *n, int fds[]); -int kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int kafka_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int kafka_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/loopback.hpp b/include/villas/nodes/loopback.hpp index 404ce1571..5632f96df 100644 --- a/include/villas/nodes/loopback.hpp +++ b/include/villas/nodes/loopback.hpp @@ -17,36 +17,28 @@ namespace node { class LoopbackNode : public Node { protected: - int queuelen; - struct CQueueSignalled queue; - enum QueueSignalledMode mode; + int queuelen; + struct CQueueSignalled queue; + enum QueueSignalledMode mode; - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - LoopbackNode(const uuid_t &id = {}, const std::string &name = ""); + LoopbackNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~LoopbackNode(); + virtual ~LoopbackNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); }; } // namespace node diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index 8317164a2..566ad0b21 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -16,62 +16,48 @@ namespace node { class InternalLoopbackNode : public Node { protected: - unsigned queuelen; - struct CQueueSignalled queue; + unsigned queuelen; + struct CQueueSignalled queue; - Node *source; + Node *source; - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - InternalLoopbackNode(Node *src, unsigned id = 0, unsigned ql = DEFAULT_QUEUE_LENGTH); + InternalLoopbackNode(Node *src, unsigned id = 0, + unsigned ql = DEFAULT_QUEUE_LENGTH); - virtual - ~InternalLoopbackNode(); + virtual ~InternalLoopbackNode(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - int stop(); + virtual int stop(); }; class InternalLoopbackNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &name = "") - { - return nullptr; - } + virtual Node *make(const uuid_t &id = {}, const std::string &name = "") { + return nullptr; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::INTERNAL | - (int) NodeFactory::Flags::PROVIDES_SIGNALS | - (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::INTERNAL | + (int)NodeFactory::Flags::PROVIDES_SIGNALS | + (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL; + } - virtual - std::string getName() const - { - return "loopback.internal"; - } + virtual std::string getName() const { return "loopback.internal"; } - virtual - std::string getDescription() const - { - return "internal loopback node"; - } + virtual std::string getDescription() const { + return "internal loopback node"; + } }; } // namespace node diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index 27436d2be..e0f9b61c7 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -7,22 +7,22 @@ #pragma once -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -32,37 +32,35 @@ using modbus_addr_t = uint16_t; using modbus_addrdiff_t = int32_t; enum class Parity : char { - None = 'N', - Even = 'E', - Odd = 'O', + None = 'N', + Even = 'E', + Odd = 'O', }; enum class Endianess : char { - Big, - Little, + Big, + Little, }; // The settings for an RTU modbus connection. struct Rtu { - std::string device; - Parity parity; - int baudrate; - int data_bits; - int stop_bits; - unsigned char unit; + std::string device; + Parity parity; + int baudrate; + int data_bits; + int stop_bits; + unsigned char unit; - static - Rtu parse(json_t *json); + static Rtu parse(json_t *json); }; // The settings for an TCP MODBUS connection. struct Tcp { - std::string remote; - uint16_t port; - std::optional unit; + std::string remote; + uint16_t port; + std::optional unit; - static - Tcp parse(json_t *json); + static Tcp parse(json_t *json); }; // Forward declarations @@ -72,7 +70,8 @@ class RegisterMappingSingle; using RegisterMappingBlock = std::vector; // Either a single mapping or a merged block of mappings. -using RegisterMapping = std::variant; +using RegisterMapping = + std::variant; // Swap the two bytes of a 16 bit integer. uint16_t byteswap(uint16_t i); @@ -105,13 +104,16 @@ modbus_addr_t mappedRegisters(RegisterMappingBlock const &block); modbus_addr_t mappedRegisters(RegisterMapping const &mapping); // The distance between two blocks. -modbus_addrdiff_t blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs); +modbus_addrdiff_t blockDistance(RegisterMapping const &lhs, + RegisterMapping const &rhs); // Whether there are overlapping bit mappings between lhs and rhs. -bool hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs); +bool hasOverlappingBitMapping(RegisterMapping const &lhs, + RegisterMapping const &rhs); // The compare the addresses of two mappings. -bool compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs); +bool compareBlockAddress(RegisterMapping const &lhs, + RegisterMapping const &rhs); // Parse an Endianess from a null terminated string. Endianess parseEndianess(char const *str); @@ -122,170 +124,176 @@ Parity parseParity(char const *str); // The mapping from a register to a signal. class RegisterMappingSingle { public: - inline static constexpr - size_t MAX_REGISTERS = sizeof(int64_t) / sizeof(int16_t); + inline static constexpr size_t MAX_REGISTERS = + sizeof(int64_t) / sizeof(int16_t); - struct IntegerToInteger { - Endianess word_endianess; - Endianess byte_endianess; - modbus_addr_t num_registers; + struct IntegerToInteger { + Endianess word_endianess; + Endianess byte_endianess; + modbus_addr_t num_registers; - int64_t read(uint16_t const *registers) const; - void write(int64_t i, uint16_t *registers) const; - }; + int64_t read(uint16_t const *registers) const; + void write(int64_t i, uint16_t *registers) const; + }; - struct IntegerToFloat { - IntegerToInteger integer_conversion; - double offset; - double scale; + struct IntegerToFloat { + IntegerToInteger integer_conversion; + double offset; + double scale; - double read(uint16_t const *registers) const; - void write(double d, uint16_t *registers) const; - }; + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; - struct FloatToFloat { - Endianess word_endianess; - Endianess byte_endianess; - double offset; - double scale; + struct FloatToFloat { + Endianess word_endianess; + Endianess byte_endianess; + double offset; + double scale; - double read(uint16_t const *registers) const; - void write(double d, uint16_t *registers) const; - }; + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; - struct BitToBool { - uint8_t bit; + struct BitToBool { + uint8_t bit; - bool read(uint16_t reg) const; - }; + bool read(uint16_t reg) const; + }; - // Conversion rule for registers. - // - // - IntegerToInteger means merging multiple registers. - // - FloatToFloat converts from IEEE float to float. - // - IntegerToFloat converts registers to integer, casts to float - // and then applies offset and scale to produce a float. - // - BitToBool takes a single bit from a registers and reports it as a boolean. - std::variant conversion; + // Conversion rule for registers. + // + // - IntegerToInteger means merging multiple registers. + // - FloatToFloat converts from IEEE float to float. + // - IntegerToFloat converts registers to integer, casts to float + // and then applies offset and scale to produce a float. + // - BitToBool takes a single bit from a registers and reports it as a boolean. + std::variant + conversion; - RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address); + RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address); - unsigned int signal_index; - modbus_addr_t address; + unsigned int signal_index; + modbus_addr_t address; - static - RegisterMappingSingle parse(unsigned int index, Signal::Ptr signal, json_t *json); + static RegisterMappingSingle parse(unsigned int index, Signal::Ptr signal, + json_t *json); - SignalData read(uint16_t const *registers, modbus_addr_t length) const; - void write(SignalData data, uint16_t *registers, modbus_addr_t length) const; + SignalData read(uint16_t const *registers, modbus_addr_t length) const; + void write(SignalData data, uint16_t *registers, modbus_addr_t length) const; - modbus_addr_t num_registers() const; + modbus_addr_t num_registers() const; }; class ModbusNode final : public Node { private: - // The maximum size of a RegisterMappingBlock created during mergeMappings. - // The size of a block here is defined as the difference between blockBegin and blockEnd. - modbus_addr_t max_block_size; + // The maximum size of a RegisterMappingBlock created during mergeMappings. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + modbus_addr_t max_block_size; - // The minimum block usage of a RegisterMappingBlock created during mergeMappings. - // The usage of a block is defined as the ration of registers used in mappings to the size of the block. - // The size of a block here is defined as the difference between blockBegin and blockEnd. - float min_block_usage; + // The minimum block usage of a RegisterMappingBlock created during mergeMappings. + // The usage of a block is defined as the ration of registers used in mappings to the size of the block. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + float min_block_usage; - // The type of connection settings used to initialize the modbus_context. - std::variant connection_settings; + // The type of connection settings used to initialize the modbus_context. + std::variant connection_settings; - // The rate used for periodically querying the modbus device registers. - double rate; + // The rate used for periodically querying the modbus device registers. + double rate; - // The timeout in seconds when waiting for a response from a modbus slave/server. - double response_timeout; + // The timeout in seconds when waiting for a response from a modbus slave/server. + double response_timeout; - // Mappings used to create the input signals from the read registers. - std::vector in_mappings; + // Mappings used to create the input signals from the read registers. + std::vector in_mappings; - // Number of in signals. - unsigned int num_in_signals; + // Number of in signals. + unsigned int num_in_signals; - // Mappings used to create the input signals from the read registers. - std::vector out_mappings; + // Mappings used to create the input signals from the read registers. + std::vector out_mappings; - // Number of out signals. - unsigned int num_out_signals; + // Number of out signals. + unsigned int num_out_signals; - // The interval in seconds for trying to reconnect on connection loss. - double reconnect_interval; + // The interval in seconds for trying to reconnect on connection loss. + double reconnect_interval; - std::vector read_buffer; - std::vector write_buffer; - modbus_t *modbus_context; - Task read_task; - std::atomic reconnecting; + std::vector read_buffer; + std::vector write_buffer; + modbus_t *modbus_context; + Task read_task; + std::atomic reconnecting; - bool isReconnecting(); - void reconnect(); + bool isReconnecting(); + void reconnect(); - static - void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs); + static void mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingBlock const &rhs); - static - void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs); + static void mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingSingle const &rhs); - bool tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs); + bool tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs); - void mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance); + void mergeMappings(std::vector &mappings, + modbus_addrdiff_t max_block_distance); - unsigned int parseMappings(std::vector &mappings, json_t *json); + unsigned int parseMappings(std::vector &mappings, + json_t *json); - int readMapping(RegisterMappingSingle const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMappingSingle const &mapping, + uint16_t const *registers, modbus_addr_t num_registers, + SignalData *signals, unsigned int num_signals); - int readMapping(RegisterMappingBlock const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMappingBlock const &mapping, + uint16_t const *registers, modbus_addr_t num_registers, + SignalData *signals, unsigned int num_signals); - int readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMapping const &mapping, uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals); - int readBlock(RegisterMapping const &mapping, SignalData *signals, size_t num_signals); + int readBlock(RegisterMapping const &mapping, SignalData *signals, + size_t num_signals); - virtual - int _read(struct Sample *smps[], unsigned int cnt); + virtual int _read(struct Sample *smps[], unsigned int cnt); - int writeMapping(RegisterMappingSingle const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeMapping(RegisterMappingBlock const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeBlock(RegisterMapping const &mapping, SignalData const *signals, size_t num_signals); + int writeMapping(RegisterMappingSingle const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeMapping(RegisterMappingBlock const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeMapping(RegisterMapping const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeBlock(RegisterMapping const &mapping, SignalData const *signals, + size_t num_signals); - virtual - int _write(struct Sample *smps[], unsigned int cnt); + virtual int _write(struct Sample *smps[], unsigned int cnt); public: - ModbusNode(const uuid_t &id = {}, const std::string &name = ""); + ModbusNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~ModbusNode(); + virtual ~ModbusNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int check(); + virtual int check(); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - std::vector getNetemFDs(); + virtual std::vector getNetemFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; } // namespace modbus diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 30f421a96..53c9ea750 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,38 +22,38 @@ namespace node { class NodeCompat; struct mqtt { - struct mosquitto *client; - struct CQueueSignalled queue; - struct Pool pool; + struct mosquitto *client; + struct CQueueSignalled queue; + struct Pool pool; - int keepalive; // Keep-alive interval in seconds. Zero for no keepalive. - int port; // Hostname / IP address of the broker. - int qos; // Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. - int retain; // Mark published messages as retained. - char *host; // Hostname / IP address of the broker. - char *username; // Username for authentication to the broker. - char *password; // Password for authentication to the broker. - char *publish; // Publish topic. - char *subscribe; // Subscribe topic. + int keepalive; // Keep-alive interval in seconds. Zero for no keepalive. + int port; // Hostname / IP address of the broker. + int qos; // Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. + int retain; // Mark published messages as retained. + char *host; // Hostname / IP address of the broker. + char *username; // Username for authentication to the broker. + char *password; // Password for authentication to the broker. + char *publish; // Publish topic. + char *subscribe; // Subscribe topic. - struct { - int enabled; // Enable SSL encrypted connection to broker. - int insecure; // Allow insecure SSL connections. - char *cafile; // SSL CA file. - char *capath; // SSL CA path. - char *certfile; // SSL certificate. - char *keyfile; // SSL private key. - int cert_reqs; // SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) - char *tls_version; // SSL tls verion - char *ciphers; // SSL chipher list. - } ssl; + struct { + int enabled; // Enable SSL encrypted connection to broker. + int insecure; // Allow insecure SSL connections. + char *cafile; // SSL CA file. + char *capath; // SSL CA path. + char *certfile; // SSL certificate. + char *keyfile; // SSL private key. + int cert_reqs; // SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) + char *tls_version; // SSL tls verion + char *ciphers; // SSL chipher list. + } ssl; - Format *formatter; + Format *formatter; }; int mqtt_reverse(NodeCompat *n); -char * mqtt_print(NodeCompat *n); +char *mqtt_print(NodeCompat *n); int mqtt_prepare(NodeCompat *n); @@ -75,9 +75,9 @@ int mqtt_type_stop(); int mqtt_poll_fds(NodeCompat *n, int fds[]); -int mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int mqtt_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int mqtt_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index e45c1ec8a..775149002 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -20,15 +20,15 @@ class NodeCompat; #define NANOMSG_MAX_PACKET_LEN 1500 struct nanomsg { - struct { - int socket; - struct List endpoints; - } in, out; + struct { + int socket; + struct List endpoints; + } in, out; - Format *formatter; + Format *formatter; }; -char * nanomsg_print(NodeCompat *n); +char *nanomsg_print(NodeCompat *n); int nanomsg_init(NodeCompat *n); @@ -48,9 +48,9 @@ int nanomsg_poll_fds(NodeCompat *n, int fds[]); int nanomsg_netem_fds(NodeCompat *n, int fds[]); -int nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int nanomsg_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int nanomsg_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ngsi.hpp b/include/villas/nodes/ngsi.hpp index ebcd6dbfd..8604343a7 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -26,26 +26,28 @@ namespace node { class NodeCompat; struct ngsi { - const char *endpoint; // The NGSI context broker endpoint URL. - const char *entity_id; // The context broker entity id related to this node - const char *entity_type; // The type of the entity - const char *access_token; // An optional authentication token which will be sent as HTTP header. + const char *endpoint; // The NGSI context broker endpoint URL. + const char *entity_id; // The context broker entity id related to this node + const char *entity_type; // The type of the entity + const char * + access_token; // An optional authentication token which will be sent as HTTP header. - bool create; // Weather we want to create the context element during startup. - bool remove; // Weather we want to delete the context element during startup. + bool create; // Weather we want to create the context element during startup. + bool remove; // Weather we want to delete the context element during startup. - double timeout; // HTTP timeout in seconds - double rate; // Rate used for polling. + double timeout; // HTTP timeout in seconds + double rate; // Rate used for polling. - struct Task task; // Timer for periodic events. - int ssl_verify; // Boolean flag whether SSL server certificates should be verified or not. + struct Task task; // Timer for periodic events. + int ssl_verify; // Boolean flag whether SSL server certificates should be verified or not. - struct curl_slist *headers; // List of HTTP request headers for libcurl + struct curl_slist *headers; // List of HTTP request headers for libcurl - struct { - CURL *curl; // libcurl: handle - struct List signals; // A mapping between indices of the VILLASnode samples and the attributes in ngsi::context - } in, out; + struct { + CURL *curl; // libcurl: handle + struct List + signals; // A mapping between indices of the VILLASnode samples and the attributes in ngsi::context + } in, out; }; int ngsi_type_start(SuperNode *sn); @@ -54,7 +56,7 @@ int ngsi_type_stop(); int ngsi_parse(NodeCompat *n, json_t *json); -char * ngsi_print(NodeCompat *n); +char *ngsi_print(NodeCompat *n); int ngsi_init(NodeCompat *n); @@ -66,9 +68,9 @@ int ngsi_stop(NodeCompat *n); int ngsi_reverse(NodeCompat *n); -int ngsi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ngsi_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ngsi_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int ngsi_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index 17117b4d4..b613bbdbf 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -18,19 +18,19 @@ namespace node { class NodeCompat; extern "C" { - #include +#include } struct opal { - int reply; - int mode; - int sequenceNo; + int reply; + int mode; + int sequenceNo; - unsigned sendID; - unsigned recvID; + unsigned sendID; + unsigned recvID; - Opal_SendAsyncParam sendParams; - Opal_RecvAsyncParam recvParams; + Opal_SendAsyncParam sendParams; + Opal_RecvAsyncParam recvParams; }; int opal_type_start(SuperNode *sn); @@ -41,15 +41,15 @@ int opal_type_stop(); int opal_parse(NodeCompat *n, json_t *json); -char * opal_print(NodeCompat *n); +char *opal_print(NodeCompat *n); int opal_start(NodeCompat *n); int opal_stop(NodeCompat *n); -int opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int opal_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int opal_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index 4a56002c2..ab9b43c4d 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -13,80 +13,71 @@ #include -#include -#include -#include #include -#include +#include +#include #include #include +#include +#include namespace villas { namespace node { -enum class RedisMode { - KEY, - HASH, - CHANNEL -}; +enum class RedisMode { KEY, HASH, CHANNEL }; class RedisConnection { public: - sw::redis::Redis context; + sw::redis::Redis context; protected: - enum State { - INITIALIZED, - RUNNING, - STOPPING - }; + enum State { INITIALIZED, RUNNING, STOPPING }; - std::thread thread; - std::atomic state; + std::thread thread; + std::atomic state; - void onMessage(const std::string &channel, const std::string &msg); + void onMessage(const std::string &channel, const std::string &msg); - void loop(); + void loop(); - std::unordered_multimap subscriberMap; + std::unordered_multimap subscriberMap; - sw::redis::Subscriber subscriber; + sw::redis::Subscriber subscriber; - villas::Logger logger; + villas::Logger logger; public: + RedisConnection(const sw::redis::ConnectionOptions &opts); - RedisConnection(const sw::redis::ConnectionOptions &opts); + static RedisConnection *get(const sw::redis::ConnectionOptions &opts); - static - RedisConnection * get(const sw::redis::ConnectionOptions &opts); + void start(); + void stop(); - void start(); - void stop(); - - void subscribe(NodeCompat *n, const std::string &channel); - void unsubscribe(NodeCompat *n, const std::string &channel); + void subscribe(NodeCompat *n, const std::string &channel); + void unsubscribe(NodeCompat *n, const std::string &channel); }; struct redis { - sw::redis::ConnectionOptions options; + sw::redis::ConnectionOptions options; - RedisConnection *conn; + RedisConnection *conn; - enum RedisMode mode; + enum RedisMode mode; - std::string key; + std::string key; - bool notify; // Use Redis Keyspace notifications to listen for updates. + bool notify; // Use Redis Keyspace notifications to listen for updates. - struct Task task; // Timer for periodic events. - double rate; // Rate for polling key updates if keyspace notifications are disabled. + struct Task task; // Timer for periodic events. + double + rate; // Rate for polling key updates if keyspace notifications are disabled. - Format *formatter; + Format *formatter; - struct Pool pool; - struct CQueueSignalled queue; + struct Pool pool; + struct CQueueSignalled queue; }; int redis_init(NodeCompat *n); @@ -95,7 +86,7 @@ int redis_destroy(NodeCompat *n); int redis_parse(NodeCompat *n, json_t *json); -char * redis_print(NodeCompat *n); +char *redis_print(NodeCompat *n); int redis_check(NodeCompat *n); @@ -109,9 +100,9 @@ int redis_pause(NodeCompat *n); int redis_resume(NodeCompat *n); -int redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int redis_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int redis_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int redis_reverse(NodeCompat *n); diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index e8fe617b9..701bde7ec 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -9,57 +9,42 @@ #include #include -#include #include +#include #include namespace std { -template -struct hash> -{ - std::size_t operator()(std::chrono::duration<_rep, ratio> const& s) const - { - return std::hash<_rep>{}(s.count()); - } +template +struct hash> { + std::size_t operator()(std::chrono::duration<_rep, ratio> const &s) const { + return std::hash<_rep>{}(s.count()); + } }; -template <> -struct hash -{ - std::size_t operator()(const sw::redis::tls::TlsOptions& t) const - { +template <> struct hash { + std::size_t operator()(const sw::redis::tls::TlsOptions &t) const { #ifdef REDISPP_WITH_TLS - return hash()(t.enabled) ^ - hash()(t.cacert) ^ - hash()(t.cacertdir) ^ - hash()(t.cert) ^ - hash()(t.key) ^ - hash()(t.sni); + return hash()(t.enabled) ^ hash()(t.cacert) ^ + hash()(t.cacertdir) ^ hash()(t.cert) ^ + hash()(t.key) ^ hash()(t.sni); #else - return 0; + return 0; #endif // REDISPP_WITH_TLS - } + } }; -template <> -struct hash -{ - std::size_t operator()(const sw::redis::ConnectionOptions& o) const - { - return hash()(static_cast(o.type)) ^ - hash()(o.host) ^ - hash()(o.port) ^ - hash()(o.path) ^ - hash()(o.user) ^ - hash()(o.password) ^ - hash()(o.db) ^ - hash()(o.keep_alive) ^ - hash()(o.connect_timeout) ^ - hash()(o.socket_timeout) ^ - hash()(o.tls); - } +template <> struct hash { + std::size_t operator()(const sw::redis::ConnectionOptions &o) const { + return hash()(static_cast(o.type)) ^ hash()(o.host) ^ + hash()(o.port) ^ hash()(o.path) ^ + hash()(o.user) ^ hash()(o.password) ^ + hash()(o.db) ^ hash()(o.keep_alive) ^ + hash()(o.connect_timeout) ^ + hash()(o.socket_timeout) ^ + hash()(o.tls); + } }; } // namespace std @@ -67,140 +52,123 @@ struct hash namespace sw { namespace redis { -bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) -{ +bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { #ifdef REDISPP_WITH_TLS - return o1.enabled == o2.enabled && - o1.cacert == o2.cacert && - o1.cacertdir == o2.cacertdir && - o1.cert == o2.cert && - o1.key == o2.key && - o1.sni == o2.sni; + return o1.enabled == o2.enabled && o1.cacert == o2.cacert && + o1.cacertdir == o2.cacertdir && o1.cert == o2.cert && + o1.key == o2.key && o1.sni == o2.sni; #else - return true; + return true; #endif // REDISPP_WITH_TLS } -bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) -{ - return o1.type == o2.type && - o1.host == o2.host && - o1.port == o2.port && - o1.path == o2.path && - o1.user == o2.user && - o1.password == o2.password && - o1.db == o2.db && - o1.keep_alive == o2.keep_alive && - o1.connect_timeout == o2.connect_timeout && - o1.socket_timeout == o2.socket_timeout && - o1.tls == o2.tls; +bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { + return o1.type == o2.type && o1.host == o2.host && o1.port == o2.port && + o1.path == o2.path && o1.user == o2.user && + o1.password == o2.password && o1.db == o2.db && + o1.keep_alive == o2.keep_alive && + o1.connect_timeout == o2.connect_timeout && + o1.socket_timeout == o2.socket_timeout && o1.tls == o2.tls; } #ifdef REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const tls::TlsOptions &t) -{ - os << "tls.enabled=" << (t.enabled ? "yes" : "no"); +template +OStream &operator<<(OStream &os, const tls::TlsOptions &t) { + os << "tls.enabled=" << (t.enabled ? "yes" : "no"); - if (t.enabled) { - if (!t.cacert.empty()) - os << ", tls.cacert=" << t.cacert; + if (t.enabled) { + if (!t.cacert.empty()) + os << ", tls.cacert=" << t.cacert; - if (!t.cacertdir.empty()) - os << ", tls.cacertdir=" << t.cacertdir; + if (!t.cacertdir.empty()) + os << ", tls.cacertdir=" << t.cacertdir; - if (!t.cert.empty()) - os << ", tls.cert=" << t.cert; + if (!t.cert.empty()) + os << ", tls.cert=" << t.cert; - if (!t.key.empty()) - os << ", tls.key=" << t.key; + if (!t.key.empty()) + os << ", tls.key=" << t.key; - if (!t.sni.empty()) - os << ", tls.sni=" << t.sni; - } + if (!t.sni.empty()) + os << ", tls.sni=" << t.sni; + } - return os; + return os; } #endif // REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const ConnectionType &t) -{ - switch (t) { - case ConnectionType::TCP: - os << "tcp"; - break; +template +OStream &operator<<(OStream &os, const ConnectionType &t) { + switch (t) { + case ConnectionType::TCP: + os << "tcp"; + break; - case ConnectionType::UNIX: - os << "unix"; - break; - } + case ConnectionType::UNIX: + os << "unix"; + break; + } - return os; + return os; } -template -OStream &operator<<(OStream &os, const ConnectionOptions &o) -{ - os << "type=" << o.type; +template +OStream &operator<<(OStream &os, const ConnectionOptions &o) { + os << "type=" << o.type; - switch (o.type) { - case ConnectionType::TCP: - os << ", host=" << o.host << ", port=" << o.port; - break; + switch (o.type) { + case ConnectionType::TCP: + os << ", host=" << o.host << ", port=" << o.port; + break; - case ConnectionType::UNIX: - os << ", path=" << o.path; - break; - } + case ConnectionType::UNIX: + os << ", path=" << o.path; + break; + } - os << ", db=" << o.db - << ", user=" << o.user - << ", keepalive=" << (o.keep_alive ? "yes" : "no"); + os << ", db=" << o.db << ", user=" << o.user + << ", keepalive=" << (o.keep_alive ? "yes" : "no"); #ifdef REDISPP_WITH_TLS - os << ", " << o.tls; + os << ", " << o.tls; #endif - return os; + return os; } } // namespace redis } // namespace sw -template -OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) -{ - switch (m) { - case villas::node::RedisMode::KEY: - os << "key"; - break; +template +OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) { + switch (m) { + case villas::node::RedisMode::KEY: + os << "key"; + break; - case villas::node::RedisMode::HASH: - os << "hash"; - break; + case villas::node::RedisMode::HASH: + os << "hash"; + break; - case villas::node::RedisMode::CHANNEL: - os << "channel"; - break; - } + case villas::node::RedisMode::CHANNEL: + os << "channel"; + break; + } - return os; + return os; } namespace villas { namespace node { #ifdef REDISPP_WITH_URI - sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) - { - auto u = sw::redis::Uri { uri }; - return u.connection_options(); - } +sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { + auto u = sw::redis::Uri{uri}; + return u.connection_options(); +} #else - sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) - { - return sw::redis::ConnectionOptions { uri }; - } +sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { + return sw::redis::ConnectionOptions{uri}; +} #endif -} // node -} // villas +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index 2ef6b736c..e5a44745a 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -12,17 +12,17 @@ #include +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include extern "C" { - #include - #include +#include +#include } namespace villas { @@ -36,53 +36,49 @@ class SuperNode; #define RTP_INITIAL_BUFFER_LEN 1500 #define RTP_PACKET_TYPE 21 -enum class RTPHookType { - DISABLED, - DECIMATE, - LIMIT_RATE -}; +enum class RTPHookType { DISABLED, DECIMATE, LIMIT_RATE }; struct rtp { - struct rtp_sock *rs; // RTP socket + struct rtp_sock *rs; // RTP socket - struct { - struct sa saddr_rtp; // Local/Remote address of the RTP socket - struct sa saddr_rtcp; // Local/Remote address of the RTCP socket - } in, out; + struct { + struct sa saddr_rtp; // Local/Remote address of the RTP socket + struct sa saddr_rtcp; // Local/Remote address of the RTCP socket + } in, out; - Format *formatter; + Format *formatter; - struct { - int enabled; + struct { + int enabled; - int num_rrs; - } rtcp; + int num_rrs; + } rtcp; - struct { - double a; - double b; + struct { + double a; + double b; - enum RTPHookType rate_hook_type; + enum RTPHookType rate_hook_type; - LimitHook::Ptr rate_hook; - dsp::PID rate_pid; + LimitHook::Ptr rate_hook; + dsp::PID rate_pid; - // PID parameters for rate controller - double Kp, Ki, Kd; - double rate_min; + // PID parameters for rate controller + double Kp, Ki, Kd; + double rate_min; - double rate; - double rate_source; // Sample rate of source + double rate; + double rate_source; // Sample rate of source - std::ofstream *log; - char *log_filename; - } aimd; // AIMD state + std::ofstream *log; + char *log_filename; + } aimd; // AIMD state - struct CQueueSignalled recv_queue; - struct mbuf *send_mb; + struct CQueueSignalled recv_queue; + struct mbuf *send_mb; }; -char * rtp_print(NodeCompat *n); +char *rtp_print(NodeCompat *n); int rtp_parse(NodeCompat *n, json_t *json); @@ -104,9 +100,9 @@ int rtp_netem_fds(NodeCompat *n, int fds[]); int rtp_poll_fds(NodeCompat *n, int fds[]); -int rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int rtp_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int rtp_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/shmem.hpp b/include/villas/nodes/shmem.hpp index 7fbf4d81e..a47f8d377 100644 --- a/include/villas/nodes/shmem.hpp +++ b/include/villas/nodes/shmem.hpp @@ -7,10 +7,10 @@ #pragma once +#include #include #include #include -#include #include namespace villas { @@ -20,14 +20,14 @@ namespace node { class NodeCompat; struct shmem { - const char* out_name; // Name of the shm object for the output queue. - const char* in_name; // Name of the shm object for the input queue. - struct ShmemConfig conf; // Interface configuration struct. - char **exec; // External program to execute on start. - struct ShmemInterface intf; // Shmem interface + const char *out_name; // Name of the shm object for the output queue. + const char *in_name; // Name of the shm object for the input queue. + struct ShmemConfig conf; // Interface configuration struct. + char **exec; // External program to execute on start. + struct ShmemInterface intf; // Shmem interface }; -char * shmem_print(NodeCompat *n); +char *shmem_print(NodeCompat *n); int shmem_parse(NodeCompat *n, json_t *json); @@ -39,9 +39,9 @@ int shmem_init(NodeCompat *n); int shmem_prepare(NodeCompat *n); -int shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int shmem_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int shmem_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/signal.hpp b/include/villas/nodes/signal.hpp index e0a09a0e0..2a3895d34 100644 --- a/include/villas/nodes/signal.hpp +++ b/include/villas/nodes/signal.hpp @@ -7,9 +7,9 @@ #pragma once -#include -#include #include +#include +#include namespace villas { namespace node { @@ -20,86 +20,80 @@ struct Sample; class SignalNodeSignal { public: - enum class Type { - RANDOM, - SINE, - SQUARE, - TRIANGLE, - RAMP, - COUNTER, - CONSTANT, - PULSE, - MIXED - }; + enum class Type { + RANDOM, + SINE, + SQUARE, + TRIANGLE, + RAMP, + COUNTER, + CONSTANT, + PULSE, + MIXED + }; - enum Type type; + enum Type type; - double frequency; // Frequency of the generated signals. - double amplitude; // Amplitude of the generated signals. - double stddev; // Standard deviation of random signals (normal distributed). - double offset; // A constant bias. - double pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) - double pulse_low; // Amplitude when pulse signal is off - double pulse_high; // Amplitude when pulse signal is on - double phase; // Phase (rad) offset with respect to program start - double last; // The values from the previous period which are required for random walk. + double frequency; // Frequency of the generated signals. + double amplitude; // Amplitude of the generated signals. + double stddev; // Standard deviation of random signals (normal distributed). + double offset; // A constant bias. + double + pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double pulse_low; // Amplitude when pulse signal is off + double pulse_high; // Amplitude when pulse signal is on + double phase; // Phase (rad) offset with respect to program start + double + last; // The values from the previous period which are required for random walk. public: - SignalNodeSignal(json_t *json); + SignalNodeSignal(json_t *json); - int parse(json_t *json); + int parse(json_t *json); - static - enum Type lookupType(const std::string &type); + static enum Type lookupType(const std::string &type); - static - std::string typeToString(enum Type type); + static std::string typeToString(enum Type type); - void start(); + void start(); - void read(unsigned c, double t, double rate, SignalData *d); + void read(unsigned c, double t, double rate, SignalData *d); - Signal::Ptr toSignal(Signal::Ptr tpl) const; + Signal::Ptr toSignal(Signal::Ptr tpl) const; }; class SignalNode : public Node { protected: - std::vector signals; + std::vector signals; - struct Task task; // Timer for periodic events. - int rt; // Real-time mode? + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? - double rate; // Sampling rate. - bool monitor_missed; // Boolean, if set, node counts missed steps and warns user. - int limit; // The number of values which should be generated by this node. <0 for infinite. + double rate; // Sampling rate. + bool + monitor_missed; // Boolean, if set, node counts missed steps and warns user. + int limit; // The number of values which should be generated by this node. <0 for infinite. - struct timespec started; // Point in time when this node was started. - unsigned missed_steps; // Total number of missed steps. + struct timespec started; // Point in time when this node was started. + unsigned missed_steps; // Total number of missed steps. - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - SignalNode(const uuid_t &id = {}, const std::string &name = ""); + SignalNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - int prepare(); + virtual int prepare(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; } // namespace node diff --git a/include/villas/nodes/signal_old.hpp b/include/villas/nodes/signal_old.hpp index 9617d4a1a..e63556ccc 100644 --- a/include/villas/nodes/signal_old.hpp +++ b/include/villas/nodes/signal_old.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -18,43 +18,46 @@ class NodeCompat; struct Sample; struct signal_node { - struct Task task; // Timer for periodic events. - int rt; // Real-time mode? + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? - enum class SignalType { - RANDOM, - SINE, - SQUARE, - TRIANGLE, - RAMP, - COUNTER, - CONSTANT, - MIXED, - PULSE - } *type; // Signal type + enum class SignalType { + RANDOM, + SINE, + SQUARE, + TRIANGLE, + RAMP, + COUNTER, + CONSTANT, + MIXED, + PULSE + } * + type; // Signal type - double rate; // Sampling rate. - double *frequency; // Frequency of the generated signals. - double *amplitude; // Amplitude of the generated signals. - double *stddev; // Standard deviation of random signals (normal distributed). - double *offset; // A constant bias. - double *pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) - double *pulse_low; // Amplitude when pulse signal is off - double *pulse_high; // Amplitude when pulse signal is on - double *phase; // Phase (rad) offset with respect to program start - int monitor_missed; // Boolean, if set, node counts missed steps and warns user. + double rate; // Sampling rate. + double *frequency; // Frequency of the generated signals. + double *amplitude; // Amplitude of the generated signals. + double *stddev; // Standard deviation of random signals (normal distributed). + double *offset; // A constant bias. + double * + pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double *pulse_low; // Amplitude when pulse signal is off + double *pulse_high; // Amplitude when pulse signal is on + double *phase; // Phase (rad) offset with respect to program start + int monitor_missed; // Boolean, if set, node counts missed steps and warns user. - double *last; // The values from the previous period which are required for random walk. + double * + last; // The values from the previous period which are required for random walk. - unsigned values; // The number of values which will be emitted by this node. - int limit; // The number of values which should be generated by this node. <0 for infinitve. + unsigned values; // The number of values which will be emitted by this node. + int limit; // The number of values which should be generated by this node. <0 for infinitve. - struct timespec started; // Point in time when this node was started. - unsigned counter; // The number of packets already emitted. - unsigned missed_steps; // Total number of missed steps. + struct timespec started; // Point in time when this node was started. + unsigned counter; // The number of packets already emitted. + unsigned missed_steps; // Total number of missed steps. }; -char * signal_node_print(NodeCompat *n); +char *signal_node_print(NodeCompat *n); int signal_node_parse(NodeCompat *n, json_t *json); @@ -68,7 +71,7 @@ int signal_node_destroy(NodeCompat *n); int signal_node_prepare(NodeCompat *n); -int signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int signal_node_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int signal_node_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index cd14d1f51..8882a607d 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include namespace villas { namespace node { @@ -18,29 +18,30 @@ namespace node { class NodeCompat; // The maximum length of a packet which contains stuct msg. -#define SOCKET_INITIAL_BUFFER_LEN (64*1024) +#define SOCKET_INITIAL_BUFFER_LEN (64 * 1024) struct Socket { - int sd; // The socket descriptor - int verify_source; // Verify the source address of incoming packets against socket::remote. + int sd; // The socket descriptor + int verify_source; // Verify the source address of incoming packets against socket::remote. - enum SocketLayer 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 - Format *formatter; + Format *formatter; - // Multicast options - struct multicast { - int enabled; // Is multicast enabled? - unsigned char loop; // Loopback multicast packets to local host? - unsigned char ttl; // The time to live for multicast packets. - struct ip_mreq mreq; // A multicast group to join. - } multicast; + // Multicast options + struct multicast { + int enabled; // Is multicast enabled? + unsigned char loop; // Loopback multicast packets to local host? + unsigned char ttl; // The time to live for multicast packets. + struct ip_mreq mreq; // A multicast group to join. + } multicast; - struct { - char *buf; // Buffer for receiving messages - size_t buflen; - union sockaddr_union saddr; // Remote address of the socket - } in, out; + struct { + char *buf; // Buffer for receiving messages + size_t buflen; + union sockaddr_union saddr; // Remote address of the socket + } in, out; }; int socket_type_start(SuperNode *sn); @@ -61,13 +62,13 @@ int socket_reverse(NodeCompat *n); int socket_fds(NodeCompat *n, int fds[]); -int socket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int socket_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int socket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int socket_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int socket_parse(NodeCompat *n, json_t *json); -char * socket_print(NodeCompat *n); +char *socket_print(NodeCompat *n); } // namespace node } // namespace villas diff --git a/include/villas/nodes/stats.hpp b/include/villas/nodes/stats.hpp index f25dac4b5..9b622a4e1 100644 --- a/include/villas/nodes/stats.hpp +++ b/include/villas/nodes/stats.hpp @@ -9,9 +9,9 @@ #include +#include #include #include -#include namespace villas { namespace node { @@ -20,19 +20,19 @@ namespace node { class NodeCompat; struct stats_node_signal { - Node *node; - char *node_str; + Node *node; + char *node_str; - enum villas::Stats::Metric metric; - enum villas::Stats::Type type; + enum villas::Stats::Metric metric; + enum villas::Stats::Type type; }; struct stats_node { - double rate; + double rate; - struct Task task; + struct Task task; - struct List signals; // List of type struct stats_node_signal + struct List signals; // List of type struct stats_node_signal }; int stats_node_type_start(SuperNode *sn); @@ -51,7 +51,7 @@ int stats_node_start(NodeCompat *n); int stats_node_stop(NodeCompat *n); -int stats_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int stats_node_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int stats_node_parse_signal(struct stats_node_signal *s, json_t *json); diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index 4bbecd157..e48533d42 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -7,11 +7,11 @@ #pragma once -#include #include +#include +#include #include #include -#include namespace villas { namespace node { @@ -22,123 +22,86 @@ class NodeCompat; class TEMPerDevice : public villas::usb::Device { protected: - constexpr static - unsigned char question_temperature[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 }; + constexpr static unsigned char question_temperature[] = { + 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00}; - float scale; - float offset; + float scale; + float offset; - int timeout; + int timeout; - villas::Logger logger; + villas::Logger logger; + + virtual void decode(unsigned char *answer, float *temp) = 0; - virtual - void decode(unsigned char *answer, float *temp) = 0; public: - static - TEMPerDevice * make(struct libusb_device *desc); + static TEMPerDevice *make(struct libusb_device *desc); - TEMPerDevice(struct libusb_device *dev); - virtual - ~TEMPerDevice() - { } + TEMPerDevice(struct libusb_device *dev); + virtual ~TEMPerDevice() {} - void open(bool reset = true); - void close(); + void open(bool reset = true); + void close(); - virtual - int getNumSensors() const - { - return 1; - } + virtual int getNumSensors() const { return 1; } - virtual - bool hasHumiditySensor() const - { - return false; - } + virtual bool hasHumiditySensor() const { return false; } - void read(struct Sample *smp); + void read(struct Sample *smp); }; class TEMPer1Device : public TEMPerDevice { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPerDevice::TEMPerDevice; + using TEMPerDevice::TEMPerDevice; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPer1"; - } + static std::string getName() { return "TEMPer1"; } }; class TEMPer2Device : public TEMPer1Device { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPer1Device::TEMPer1Device; + using TEMPer1Device::TEMPer1Device; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPer2"; - } + static std::string getName() { return "TEMPer2"; } - virtual - int getNumSensors() const - { - return 2; - } + virtual int getNumSensors() const { return 2; } }; class TEMPerHUMDevice : public TEMPerDevice { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPerDevice::TEMPerDevice; + using TEMPerDevice::TEMPerDevice; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPerHUM"; - } + static std::string getName() { return "TEMPerHUM"; } - virtual - bool hasHumiditySensor() const - { - return true; - } + virtual bool hasHumiditySensor() const { return true; } }; struct temper { - struct { - double scale; - double offset; - } calibration; + struct { + double scale; + double offset; + } calibration; - struct villas::usb::Filter filter; + struct villas::usb::Filter filter; - TEMPerDevice *device; + TEMPerDevice *device; }; int temper_type_start(SuperNode *sn); @@ -153,7 +116,7 @@ int temper_destroy(NodeCompat *n); int temper_parse(NodeCompat *n, json_t *json); -char * temper_print(NodeCompat *n); +char *temper_print(NodeCompat *n); int temper_check(); @@ -167,9 +130,9 @@ int temper_pause(NodeCompat *n); int temper_resume(NodeCompat *n); -int temper_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int temper_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int temper_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int temper_reverse(NodeCompat *n); diff --git a/include/villas/nodes/test_rtt.hpp b/include/villas/nodes/test_rtt.hpp index 1d04ef4a5..56c78058f 100644 --- a/include/villas/nodes/test_rtt.hpp +++ b/include/villas/nodes/test_rtt.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include namespace villas { @@ -21,33 +21,33 @@ struct Sample; struct test_rtt; struct test_rtt_case { - double rate; - unsigned values; - unsigned limit; // The number of samples we take per test. + double rate; + unsigned values; + unsigned limit; // The number of samples we take per test. - char *filename; - char *filename_formatted; + char *filename; + char *filename_formatted; - NodeCompat *node; + NodeCompat *node; }; struct test_rtt { - struct Task task; // The periodic task for test_rtt_read() - Format *formatter;// The format of the output file - FILE *stream; + struct Task task; // The periodic task for test_rtt_read() + Format *formatter; // The format of the output file + FILE *stream; - double cooldown; // Number of seconds to wait beween tests. + double cooldown; // Number of seconds to wait beween tests. - int current; // Index of current test in test_rtt::cases - int counter; + int current; // Index of current test in test_rtt::cases + int counter; - struct List cases; // List of test cases + struct List cases; // List of test cases - char *output; // The directory where we place the results. - char *prefix; // An optional prefix in the filename. + char *output; // The directory where we place the results. + char *prefix; // An optional prefix in the filename. }; -char * test_rtt_print(NodeCompat *n); +char *test_rtt_print(NodeCompat *n); int test_rtt_parse(NodeCompat *n, json_t *json); @@ -61,9 +61,9 @@ int test_rtt_start(NodeCompat *n); int test_rtt_stop(NodeCompat *n); -int test_rtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int test_rtt_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int test_rtt_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int test_rtt_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/uldaq.hpp b/include/villas/nodes/uldaq.hpp index 0a13c00fc..628ae7fc6 100644 --- a/include/villas/nodes/uldaq.hpp +++ b/include/villas/nodes/uldaq.hpp @@ -10,8 +10,8 @@ #include -#include #include +#include #include @@ -22,34 +22,34 @@ namespace villas { namespace node { struct uldaq { - const char *device_id; + const char *device_id; - DaqDeviceHandle device_handle; - DaqDeviceDescriptor *device_descriptor; - DaqDeviceInterface device_interface_type; + DaqDeviceHandle device_handle; + DaqDeviceDescriptor *device_descriptor; + DaqDeviceInterface device_interface_type; - uint64_t sequence; + uint64_t sequence; - struct { - double sample_rate; - double *buffer; - size_t buffer_len; - size_t buffer_pos; - size_t channel_count; + struct { + double sample_rate; + double *buffer; + size_t buffer_len; + size_t buffer_pos; + size_t channel_count; - ScanOption scan_options; - AInScanFlag flags; - AiQueueElement *queues; - ScanStatus status; // protected by mutex - TransferStatus transfer_status; // protected by mutex + ScanOption scan_options; + AInScanFlag flags; + AiQueueElement *queues; + ScanStatus status; // protected by mutex + TransferStatus transfer_status; // protected by mutex - pthread_mutex_t mutex; - pthread_cond_t cv; - } in; + pthread_mutex_t mutex; + pthread_cond_t cv; + } in; - struct { - // TODO - } out; + struct { + // TODO + } out; }; int uldaq_type_start(SuperNode *sn); @@ -60,7 +60,7 @@ int uldaq_destroy(NodeCompat *n); int uldaq_parse(NodeCompat *n, json_t *json); -char * uldaq_print(NodeCompat *n); +char *uldaq_print(NodeCompat *n); int uldaq_check(NodeCompat *n); @@ -68,7 +68,7 @@ int uldaq_start(NodeCompat *n); int uldaq_stop(NodeCompat *n); -int uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int uldaq_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp index c0f327c33..3238738ff 100644 --- a/include/villas/nodes/webrtc.hpp +++ b/include/villas/nodes/webrtc.hpp @@ -11,12 +11,12 @@ #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -27,91 +27,70 @@ struct Sample; class WebRTCNode : public Node { protected: - std::string server; - std::string session; - std::string peer; + std::string server; + std::string session; + std::string peer; - int wait_seconds; - Format *format; - struct CQueueSignalled queue; - struct Pool pool; + int wait_seconds; + Format *format; + struct CQueueSignalled queue; + struct Pool pool; - std::shared_ptr conn; - rtc::Configuration rtcConf; - rtc::DataChannelInit dci; + std::shared_ptr conn; + rtc::Configuration rtcConf; + rtc::DataChannelInit dci; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - json_t * _readStatus() const; + virtual json_t *_readStatus() const; public: - WebRTCNode(const uuid_t &id = {}, const std::string &name = ""); + WebRTCNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~WebRTCNode(); + virtual ~WebRTCNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; class WebRTCNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - auto *n = new WebRTCNode(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + auto *n = new WebRTCNode(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL | - (int) NodeFactory::Flags::REQUIRES_WEB; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL | + (int)NodeFactory::Flags::REQUIRES_WEB; + } - virtual - std::string getName() const - { - return "webrtc"; - } + virtual std::string getName() const { return "webrtc"; } - virtual - std::string getDescription() const - { - return "Web Real-time Communication"; - } + virtual std::string getDescription() const { + return "Web Real-time Communication"; + } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); }; } // namespace node diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index cb122bf30..26fb62d74 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -13,9 +13,9 @@ #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -24,69 +24,72 @@ namespace webrtc { class PeerConnection { public: - PeerConnection(const std::string &server, const std::string &session, const std::string &peer, std::shared_ptr signals, rtc::Configuration config, Web *w, rtc::DataChannelInit d); - ~PeerConnection(); + PeerConnection(const std::string &server, const std::string &session, + const std::string &peer, std::shared_ptr signals, + rtc::Configuration config, Web *w, rtc::DataChannelInit d); + ~PeerConnection(); - bool waitForDataChannel(std::chrono::seconds timeout); - void onMessage(std::function callback); - void sendMessage(rtc::binary msg); + bool waitForDataChannel(std::chrono::seconds timeout); + void onMessage(std::function callback); + void sendMessage(rtc::binary msg); - json_t * readStatus() const; + json_t *readStatus() const; - void connect(); - void disconnect(); + void connect(); + void disconnect(); protected: - Web *web; - std::vector extraServers; - rtc::DataChannelInit dataChannelInit; - rtc::Configuration defaultConfig; + Web *web; + std::vector extraServers; + rtc::DataChannelInit dataChannelInit; + rtc::Configuration defaultConfig; - std::shared_ptr conn; - std::shared_ptr chan; - std::shared_ptr client; - std::shared_ptr signals; + std::shared_ptr conn; + std::shared_ptr chan; + std::shared_ptr client; + std::shared_ptr signals; - Logger logger; + Logger logger; - std::mutex mutex; + std::mutex mutex; - std::condition_variable_any startupCondition; - bool stopStartup; + std::condition_variable_any startupCondition; + bool stopStartup; - bool warnNotConnected; - bool standby; - bool first; - int firstID; - int secondID; + bool warnNotConnected; + bool standby; + bool first; + int firstID; + int secondID; - std::function onMessageCallback; + std::function onMessageCallback; - void resetConnection(std::unique_lock &lock); - void resetConnectionAndStandby(std::unique_lock &lock); - void notifyStartup(); + void resetConnection(std::unique_lock &lock); + void resetConnectionAndStandby( + std::unique_lock &lock); + void notifyStartup(); - void setupPeerConnection(std::shared_ptr = nullptr); - void setupDataChannel(std::shared_ptr = nullptr); + void setupPeerConnection(std::shared_ptr = nullptr); + void setupDataChannel(std::shared_ptr = nullptr); - void onLocalDescription(rtc::Description sdp); - void onLocalCandidate(rtc::Candidate cand); + void onLocalDescription(rtc::Description sdp); + void onLocalCandidate(rtc::Candidate cand); - void onConnectionStateChange(rtc::PeerConnection::State state); - void onSignalingStateChange(rtc::PeerConnection::SignalingState state); - void onGatheringStateChange(rtc::PeerConnection::GatheringState state); + void onConnectionStateChange(rtc::PeerConnection::State state); + void onSignalingStateChange(rtc::PeerConnection::SignalingState state); + void onGatheringStateChange(rtc::PeerConnection::GatheringState state); - void onSignalingConnected(); - void onSignalingDisconnected(); - void onSignalingError(std::string err); - void onSignalingMessage(SignalingMessage msg); + void onSignalingConnected(); + void onSignalingDisconnected(); + void onSignalingError(std::string err); + void onSignalingMessage(SignalingMessage msg); - void onDataChannel(std::shared_ptr dc); - void onDataChannelOpen(); - void onDataChannelClosed(); - void onDataChannelError(std::string err); - void onDataChannelMessage(rtc::string msg); - void onDataChannelMessage(rtc::binary msg); + void onDataChannel(std::shared_ptr dc); + void onDataChannelOpen(); + void onDataChannelClosed(); + void onDataChannelError(std::string err); + void onDataChannelMessage(rtc::string msg); + void onDataChannelMessage(rtc::binary msg); }; } // namespace webrtc diff --git a/include/villas/nodes/webrtc/signaling_client.hpp b/include/villas/nodes/webrtc/signaling_client.hpp index 5d6a63e9d..edfa8853b 100644 --- a/include/villas/nodes/webrtc/signaling_client.hpp +++ b/include/villas/nodes/webrtc/signaling_client.hpp @@ -9,16 +9,16 @@ #pragma once -#include #include +#include #include -#include #include -#include #include #include +#include +#include namespace villas { namespace node { @@ -31,87 +31,82 @@ namespace webrtc { class SignalingClient { protected: - struct sul_offsetof_helper { - lws_sorted_usec_list_t sul; // Schedule connection retry - SignalingClient *self; - } sul_helper; + struct sul_offsetof_helper { + lws_sorted_usec_list_t sul; // Schedule connection retry + SignalingClient *self; + } sul_helper; - uint16_t retry_count; // Count of consecutive retries + uint16_t retry_count; // Count of consecutive retries - struct lws *wsi; - struct lws_client_connect_info info; + struct lws *wsi; + struct lws_client_connect_info info; - // The retry and backoff policy we want to use for our client connections - static constexpr - uint32_t backoff_ms[] = { 1<<4, 1<<6, 1<<8, 1<<10, 1<<12, 1<<14, 1<<16 }; - static constexpr - lws_retry_bo_t retry = { - .retry_ms_table = backoff_ms, - .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), - .conceal_count = LWS_ARRAY_SIZE(backoff_ms) + 1, + // The retry and backoff policy we want to use for our client connections + static constexpr uint32_t backoff_ms[] = {1 << 4, 1 << 6, 1 << 8, 1 << 10, + 1 << 12, 1 << 14, 1 << 16}; + static constexpr lws_retry_bo_t retry = { + .retry_ms_table = backoff_ms, + .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), + .conceal_count = LWS_ARRAY_SIZE(backoff_ms) + 1, - .secs_since_valid_ping = 3, // force PINGs after secs idle - .secs_since_valid_hangup = 10, // hangup after secs idle + .secs_since_valid_ping = 3, // force PINGs after secs idle + .secs_since_valid_hangup = 10, // hangup after secs idle - .jitter_percent = 20, - }; + .jitter_percent = 20, + }; - std::function cbMessage; - std::function cbConnected; - std::function cbDisconnected; - std::function cbError; + std::function cbMessage; + std::function cbConnected; + std::function cbDisconnected; + std::function cbError; - Queue outgoingMessages; + Queue outgoingMessages; - Web *web; + Web *web; - char *uri; - char *path; + char *uri; + char *path; - std::atomic running; + std::atomic running; - Buffer buffer; // A buffer for received fragments before JSON decoding. + Buffer buffer; // A buffer for received fragments before JSON decoding. - Logger logger; + Logger logger; - int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *in, size_t len); + int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *in, size_t len); - static - void connectStatic(struct lws_sorted_usec_list *sul); + static void connectStatic(struct lws_sorted_usec_list *sul); - int writable(); + int writable(); public: - SignalingClient(const std::string &server, const std::string &session, const std::string &peer, Web *w); - ~SignalingClient(); + SignalingClient(const std::string &server, const std::string &session, + const std::string &peer, Web *w); + ~SignalingClient(); - static - int protocolCallbackStatic(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallbackStatic(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len); - void connect(); - void disconnect(); + void connect(); + void disconnect(); - void sendMessage(SignalingMessage); + void sendMessage(SignalingMessage); - void onMessage(std::function callback) - { - cbMessage = callback; - } + void onMessage(std::function callback) { + cbMessage = callback; + } - void onConnected(std::function callback) - { - cbConnected = callback; - } + void onConnected(std::function callback) { cbConnected = callback; } - void onDisconnected(std::function callback) - { - cbDisconnected = callback; - } + void onDisconnected(std::function callback) { + cbDisconnected = callback; + } - void onError(std::function callback) - { - cbError = callback; - } + void onError(std::function callback) { + cbError = callback; + } }; } // namespace webrtc diff --git a/include/villas/nodes/webrtc/signaling_message.hpp b/include/villas/nodes/webrtc/signaling_message.hpp index 2a9039693..62ba4a63f 100644 --- a/include/villas/nodes/webrtc/signaling_message.hpp +++ b/include/villas/nodes/webrtc/signaling_message.hpp @@ -9,13 +9,13 @@ #pragma once -#include #include -#include +#include #include +#include -#include #include +#include #include @@ -24,37 +24,38 @@ namespace node { namespace webrtc { struct Peer { - int id; - std::string name; - std::string remote; - std::string userAgent; - std::chrono::time_point created; + int id; + std::string name; + std::string remote; + std::string userAgent; + std::chrono::time_point created; - Peer(json_t *j); - json_t * toJson() const; + Peer(json_t *j); + json_t *toJson() const; }; struct RelayMessage { - std::vector servers; + std::vector servers; - RelayMessage(json_t *j); + RelayMessage(json_t *j); }; struct ControlMessage { - int peerID; - std::vector peers; + int peerID; + std::vector peers; - ControlMessage(json_t *j); - json_t * toJson() const; + ControlMessage(json_t *j); + json_t *toJson() const; }; struct SignalingMessage { - std::variant message; + std::variant + message; - static - SignalingMessage fromJson(json_t *j); - json_t * toJson() const; - std::string toString() const; + static SignalingMessage fromJson(json_t *j); + json_t *toJson() const; + std::string toString() const; }; } // namespace webrtc diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index c8f72ef99..071fe1af0 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -9,14 +9,14 @@ #include -#include -#include -#include #include +#include #include #include #include #include +#include +#include // Forward declarations struct lws; @@ -24,84 +24,89 @@ struct lws; namespace villas { namespace node { -#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) +#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) // Internal data per websocket node struct websocket { - struct List destinations; // List of websocket servers connect to in client mode (struct websocket_destination). + struct List + destinations; // List of websocket servers connect to in client mode (struct websocket_destination). - bool wait; // Wait until all destinations are connected. + bool wait; // Wait until all destinations are connected. - struct Pool pool; - struct CQueueSignalled queue; // For samples which are received from WebSockets + struct Pool pool; + struct CQueueSignalled + queue; // For samples which are received from WebSockets }; struct websocket_destination { - char *uri; - struct lws_client_connect_info info; + char *uri; + struct lws_client_connect_info info; }; // Internal datastructures struct websocket_connection { - enum State { - DESTROYED, - INITIALIZED, - CONNECTING, - RECONNECTING, - ESTABLISHED, - CLOSING, - CLOSED, - ERROR - } state; // The current status of this connection. + enum State { + DESTROYED, + INITIALIZED, + CONNECTING, + RECONNECTING, + ESTABLISHED, + CLOSING, + CLOSED, + ERROR + } state; // The current status of this connection. - enum class Mode { - CLIENT, - SERVER, - } mode; + enum class Mode { + CLIENT, + SERVER, + } mode; - struct lws *wsi; - NodeCompat *node; - Format *formatter; - struct CQueue queue; // For samples which are sent to the Websocket + struct lws *wsi; + NodeCompat *node; + Format *formatter; + struct CQueue queue; // For samples which are sent to the Websocket - struct websocket_destination *destination; + struct websocket_destination *destination; - struct { - villas::Buffer *recv; // A buffer for reconstructing fragmented messages. - villas::Buffer *send; // A buffer for constructing messages before calling lws_write() - } buffers; + struct { + villas::Buffer *recv; // A buffer for reconstructing fragmented messages. + villas::Buffer + *send; // A buffer for constructing messages before calling lws_write() + } buffers; - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const struct websocket_connection &c) - { - if (c.wsi) { - char name[128]; + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, + const struct websocket_connection &c) { + if (c.wsi) { + char name[128]; - lws_get_peer_simple(c.wsi, name, sizeof(name)); + lws_get_peer_simple(c.wsi, name, sizeof(name)); - os << "remote=" << name; - } - else if (c.mode == websocket_connection::Mode::CLIENT && c.destination != nullptr) - os << "dest=" << c.destination->info.address << ":" << c.destination->info.port; + os << "remote=" << name; + } else if (c.mode == websocket_connection::Mode::CLIENT && + c.destination != nullptr) + os << "dest=" << c.destination->info.address << ":" + << c.destination->info.port; - if (c.node) - os << ", node=" << c.node->getName(); + if (c.node) + os << ", node=" << c.node->getName(); - os << ", mode=" << (c.mode == websocket_connection::Mode::CLIENT ? "client" : "server"); + os << ", mode=" + << (c.mode == websocket_connection::Mode::CLIENT ? "client" : "server"); - return os; - } + return os; + } - std::string toString() - { - std::stringstream ss; - ss << *this; - return ss.str(); - } + std::string toString() { + std::stringstream ss; + ss << *this; + return ss.str(); + } }; -int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); +int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); int websocket_type_start(SuperNode *sn); @@ -109,7 +114,7 @@ int websocket_type_stop(); int websocket_parse(NodeCompat *n, json_t *j); -char * websocket_print(NodeCompat *n); +char *websocket_print(NodeCompat *n); int websocket_start(NodeCompat *n); @@ -121,9 +126,9 @@ int websocket_destroy(NodeCompat *n); int websocket_poll_fds(NodeCompat *n, int fds[]); -int websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int websocket_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int websocket_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/zeromq.hpp b/include/villas/nodes/zeromq.hpp index 60d7d985a..1478ae727 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -10,12 +10,14 @@ #include #include -#include -#include #include +#include +#include -#if ZMQ_BUILD_DRAFT_API && (ZMQ_VERSION_MAJOR > 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2)) - #define ZMQ_BUILD_DISH 1 +#if ZMQ_BUILD_DRAFT_API && \ + (ZMQ_VERSION_MAJOR > 4 || \ + (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2)) +#define ZMQ_BUILD_DISH 1 #endif namespace villas { @@ -26,35 +28,35 @@ class NodeCompat; struct Sample; struct zeromq { - int ipv6; + int ipv6; - Format *formatter; + Format *formatter; - struct Curve { - int enabled; - struct { - char public_key[41]; - char secret_key[41]; - } server, client; - } curve; + struct Curve { + int enabled; + struct { + char public_key[41]; + char secret_key[41]; + } server, client; + } curve; - enum class Pattern { - PUBSUB, + enum class Pattern { + PUBSUB, #ifdef ZMQ_BUILD_DISH - RADIODISH + RADIODISH #endif - } pattern; + } pattern; - struct Dir { - void *socket; // ZeroMQ socket. - void *mon_socket; - struct List endpoints; - char *filter; - int bind, pending; - } in, out; + struct Dir { + void *socket; // ZeroMQ socket. + void *mon_socket; + struct List endpoints; + char *filter; + int bind, pending; + } in, out; }; -char * zeromq_print(NodeCompat *n); +char *zeromq_print(NodeCompat *n); int zeromq_parse(NodeCompat *n, json_t *json); @@ -78,9 +80,9 @@ int zeromq_poll_fds(NodeCompat *n, int fds[]); int zeromq_netem_fds(NodeCompat *n, int fds[]); -int zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int zeromq_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int zeromq_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 2aaa3c88d..90e06b499 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -9,23 +9,23 @@ #include -#include -#include #include +#include #include +#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include @@ -40,125 +40,123 @@ class Node; // The datastructure for a path. class Path { - friend PathSource; - friend SecondaryPathSource; - friend PathDestination; + friend PathSource; + friend SecondaryPathSource; + friend PathDestination; protected: - void * runSingle(); - void * runPoll(); + void *runSingle(); + void *runPoll(); - static - void * runWrapper(void *arg); + static void *runWrapper(void *arg); - void startPoll(); + void startPoll(); - static - int id; + static int id; public: - enum State state; // Path state. + enum State state; // Path state. - // The register mode determines under which condition the path is triggered. - enum class Mode { - 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. - } mode; // Determines when this path is triggered. + // The register mode determines under which condition the path is triggered. + enum class Mode { + 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. + } mode; // Determines when this path is triggered. - uuid_t uuid; + uuid_t uuid; - std::vector pfds; + std::vector pfds; - struct Pool pool; - struct Sample *last_sample; - int last_sequence; + struct Pool pool; + struct Sample *last_sample; + int last_sequence; - NodeList masked; - MappingList mappings; // List of all input mappings. - PathSourceList sources; // List of all incoming nodes. - PathDestinationList destinations; // List of all outgoing nodes. - HookList hooks; // List of processing hooks. - SignalList::Ptr signals; // List of signals which this path creates. + NodeList masked; + MappingList mappings; // List of all input mappings. + PathSourceList sources; // List of all incoming nodes. + PathDestinationList destinations; // List of all outgoing nodes. + HookList hooks; // List of processing hooks. + SignalList::Ptr signals; // List of signals which this path creates. - struct Task timeout; + struct Task timeout; - double rate; // A timeout for - int affinity; // Thread affinity. - bool enabled; // Is this path enabled? - int poll; // Weather or not to use poll(2). - bool reversed; // This path has a matching reverse path. - bool builtin; // This path should use built-in hooks by default. - int original_sequence_no; // Use original source sequence number when multiplexing - unsigned queuelen; // The queue length for each path_destination::queue + double rate; // A timeout for + int affinity; // Thread affinity. + bool enabled; // Is this path enabled? + int poll; // Weather or not to use poll(2). + bool reversed; // This path has a matching reverse path. + bool builtin; // This path should use built-in hooks by default. + int original_sequence_no; // Use original source sequence number when multiplexing + unsigned queuelen; // The queue length for each path_destination::queue - pthread_t tid; // The thread id for this path. - json_t *config; // A JSON object containing the configuration of the path. + pthread_t tid; // The thread id for this path. + json_t *config; // A JSON object containing the configuration of the path. - Logger logger; + Logger logger; - std::bitset mask; // A mask of PathSources which are enabled for poll(). - std::bitset received; // A mask of PathSources for which we already received samples. + std::bitset + mask; // A mask of PathSources which are enabled for poll(). + std::bitset + received; // A mask of PathSources for which we already received samples. - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Path &p) - { - if (p.sources.size() > 1) - os << "[ "; + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const Path &p) { + if (p.sources.size() > 1) + os << "[ "; - for (auto ps : p.sources) - os << ps->getNode()->getNameShort() << " "; + for (auto ps : p.sources) + os << ps->getNode()->getNameShort() << " "; - if (p.sources.size() > 1) - os << "] "; + if (p.sources.size() > 1) + os << "] "; - os << CLR_MAG("=>"); + os << CLR_MAG("=>"); - if (p.destinations.size() != 1) - os << " ["; + if (p.destinations.size() != 1) + os << " ["; - for (auto pd : p.destinations) - os << " " << pd->getNode()->getNameShort(); + for (auto pd : p.destinations) + os << " " << pd->getNode()->getNameShort(); - if (p.destinations.size() != 1) - os << " ]"; + if (p.destinations.size() != 1) + os << " ]"; - return os; - } + return os; + } - std::string toString() - { - std::stringstream ss; - ss << *this; - return ss.str(); - } + std::string toString() { + std::stringstream ss; + ss << *this; + return ss.str(); + } - Path(); - ~Path(); + Path(); + ~Path(); - void prepare(NodeList &nodes); + void prepare(NodeList &nodes); - // Check if path configuration is proper. - void check(); + // Check if path configuration is proper. + void check(); - // Check prepared path. - void checkPrepared(); + // Check prepared path. + void checkPrepared(); - /* Start a path. + /* Start a path. * * Start a new pthread for receiving/sending messages over this path. */ - void start(); + void start(); - // Stop a path. - void stop(); + // Stop a path. + void stop(); - // Get a list of signals which is emitted by the path. - SignalList::Ptr getOutputSignals(bool after_hooks = true); + // Get a list of signals which is emitted by the path. + SignalList::Ptr getOutputSignals(bool after_hooks = true); - unsigned getOutputSignalsMaxCount(); + unsigned getOutputSignalsMaxCount(); - /* Parse a single path and add it to the global configuration. + /* Parse a single path and add it to the global configuration. * * @param json A JSON object containing the configuration of the path. * @param p Pointer to the allocated memory for this path @@ -166,35 +164,23 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - void parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid); + void parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid); - void parseMask(json_t *json_mask, NodeList &nodes); + void parseMask(json_t *json_mask, NodeList &nodes); - bool isSimple() const; - bool isMuxed() const; + bool isSimple() const; + bool isMuxed() const; - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } - bool isReversed() const - { - return reversed; - } + bool isReversed() const { return reversed; } - State getState() const - { - return state; - } + State getState() const { return state; } - // Get the UUID of this path. - const uuid_t & getUuid() const - { - return uuid; - } + // Get the UUID of this path. + const uuid_t &getUuid() const { return uuid; } - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/path_destination.hpp b/include/villas/path_destination.hpp index 8ea9e908d..2a97a6a3a 100644 --- a/include/villas/path_destination.hpp +++ b/include/villas/path_destination.hpp @@ -21,35 +21,32 @@ struct Sample; class PathDestination; class PathDestination { - friend Path; + friend Path; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; protected: - Node *node; - Path *path; + Node *node; + Path *path; - struct CQueue queue; + struct CQueue queue; public: - PathDestination(Path *p, Node *n); + PathDestination(Path *p, Node *n); - ~PathDestination(); + ~PathDestination(); - int prepare(int queuelen); + int prepare(int queuelen); - void check(); + void check(); - static - void enqueueAll(class Path *p, const struct Sample * const smps[], unsigned cnt); + static void enqueueAll(class Path *p, const struct Sample *const smps[], + unsigned cnt); - void write(); + void write(); - Node * getNode() const - { - return node; - } + Node *getNode() const { return node; } }; using PathDestinationList = std::vector; diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 8ad9e3e39..d76a689a6 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,10 +22,10 @@ class Path; class PathList : public std::list { public: - // Lookup a path from the list based on its UUID - Path * lookup(const uuid_t &uuid) const; + // Lookup a path from the list based on its UUID + Path *lookup(const uuid_t &uuid) const; - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp index f5412a17b..bfe272038 100644 --- a/include/villas/path_source.hpp +++ b/include/villas/path_source.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,43 +22,34 @@ class Node; class Path; class PathSource { - friend Path; + friend Path; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; protected: - Node *node; - Path *path; + Node *node; + Path *path; - bool masked; + bool masked; - struct Pool pool; + struct Pool pool; - MappingList mappings; // List of mappings (struct MappingEntry). + MappingList mappings; // List of mappings (struct MappingEntry). public: - PathSource(Path *p, Node *n); - virtual - ~PathSource(); + PathSource(Path *p, Node *n); + virtual ~PathSource(); - void check(); + void check(); - int read(int i); + int read(int i); - virtual - void writeToSecondaries(struct Sample *smps[], unsigned cnt) - { } + virtual void writeToSecondaries(struct Sample *smps[], unsigned cnt) {} - Node * getNode() const - { - return node; - } + Node *getNode() const { return node; } - Path * getPath() const - { - return path; - } + Path *getPath() const { return path; } }; using PathSourceList = std::vector; @@ -66,12 +57,13 @@ using PathSourceList = std::vector; class SecondaryPathSource : public PathSource { protected: - PathSource::Ptr master; + PathSource::Ptr master; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - SecondaryPathSource(Path *p, Node *n, NodeList &nodes, PathSource::Ptr master); + SecondaryPathSource(Path *p, Node *n, NodeList &nodes, + PathSource::Ptr master); }; using SecondaryPathSourceList = std::vector; @@ -79,25 +71,18 @@ using SecondaryPathSourceList = std::vector; class MasterPathSource : public PathSource { protected: - SecondaryPathSourceList secondaries; // List of secondary path sources (PathSource). + SecondaryPathSourceList + secondaries; // List of secondary path sources (PathSource). public: - MasterPathSource(Path *p, Node *n); + MasterPathSource(Path *p, Node *n); - void addSecondary(SecondaryPathSource::Ptr ps) - { - secondaries.push_back(ps); - } + void addSecondary(SecondaryPathSource::Ptr ps) { secondaries.push_back(ps); } - SecondaryPathSourceList getSecondaries() - { - return secondaries; - } + SecondaryPathSourceList getSecondaries() { return secondaries; } - virtual - void writeToSecondaries(struct Sample *smps[], unsigned cnt); + virtual void writeToSecondaries(struct Sample *smps[], unsigned cnt); }; - } // namespace node } // namespace villas diff --git a/include/villas/pool.hpp b/include/villas/pool.hpp index 41fb88caf..bfcc4065e 100644 --- a/include/villas/pool.hpp +++ b/include/villas/pool.hpp @@ -12,27 +12,28 @@ #include #include -#include #include #include +#include namespace villas { namespace node { // 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 + off_t + buffer_off; // Offset from the struct address to the underlying memory area - size_t len; // Length of the underlying memory area - size_t blocksz; // Length of a block in bytes - size_t alignment; // Alignment of a block in bytes + size_t len; // Length of the underlying memory area + size_t blocksz; // Length of a block in bytes + size_t alignment; // Alignment of a block in bytes - struct CQueue queue; // The queue which is used to keep track of free blocks + struct CQueue queue; // The queue which is used to keep track of free blocks }; -#define pool_buffer(p) ((char *) (p) + (p)->buffer_off) +#define pool_buffer(p) ((char *)(p) + (p)->buffer_off) /* Initiazlize a pool * @@ -43,10 +44,12 @@ struct Pool { * @retval 0 The pool has been successfully initialized. * @retval <>0 There was an error during the pool initialization. */ -int pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); +int pool_init(struct Pool *p, size_t cnt, size_t blocksz, + struct memory::Type *mem = memory::default_type) + __attribute__((warn_unused_result)); // Destroy and release memory used by pool. -int pool_destroy(struct Pool *p) __attribute__ ((warn_unused_result)); +int pool_destroy(struct Pool *p) __attribute__((warn_unused_result)); /* Pop up to \p cnt values from the stack an place them in the array \p blocks. * @@ -60,7 +63,7 @@ ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt); ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt); // Get a free memory block from pool. -void * pool_get(struct Pool *p); +void *pool_get(struct Pool *p); // Release a memory block back to the pool. int pool_put(struct Pool *p, void *buf); diff --git a/include/villas/queue.h b/include/villas/queue.h index 4b35d5ac0..aabe06438 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -49,35 +49,37 @@ namespace node { typedef char cacheline_pad_t[CACHELINE_SIZE]; struct CQueue_cell { - std::atomic sequence; - off_t data_off; // Pointer relative to the queue struct + std::atomic sequence; + off_t data_off; // Pointer relative to the queue struct }; // A lock-free multiple-producer, multiple-consumer (MPMC) queue. struct CQueue { - std::atomic state; + std::atomic state; - cacheline_pad_t _pad0; // Shared area: all threads read + cacheline_pad_t _pad0; // Shared area: all threads read - size_t buffer_mask; - off_t buffer_off; // Relative pointer to struct CQueue_cell[] + size_t buffer_mask; + off_t buffer_off; // Relative pointer to struct CQueue_cell[] - cacheline_pad_t _pad1; // Producer area: only producers read & write + cacheline_pad_t _pad1; // Producer area: only producers read & write - std::atomic tail; // Queue tail pointer + std::atomic tail; // Queue tail pointer - cacheline_pad_t _pad2; // Consumer area: only consumers read & write + cacheline_pad_t _pad2; // Consumer area: only consumers read & write - std::atomic head; // Queue head pointer + std::atomic head; // Queue head pointer - cacheline_pad_t _pad3; // TODO: Why needed? + cacheline_pad_t _pad3; // TODO: Why needed? }; // Initialize MPMC queue -int queue_init(struct CQueue *q, size_t size, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); +int queue_init(struct CQueue *q, size_t size, + struct memory::Type *mem = memory::default_type) + __attribute__((warn_unused_result)); // Desroy MPMC queue and release memory -int queue_destroy(struct CQueue *q) __attribute__ ((warn_unused_result)); +int queue_destroy(struct CQueue *q) __attribute__((warn_unused_result)); /* Return estimation of current queue usage. * diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index f04835619..236bd62d4 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -12,38 +12,33 @@ namespace villas { -template -class Queue { +template class Queue { protected: - std::queue queue; - std::mutex mtx; + std::queue queue; + std::mutex mtx; public: - void push(T p) - { - std::unique_lock guard(mtx); + void push(T p) { + std::unique_lock guard(mtx); - queue.push(p); - } + queue.push(p); + } - T pop() - { - std::unique_lock guard(mtx); + T pop() { + std::unique_lock guard(mtx); - T res = queue.front(); - queue.pop(); + T res = queue.front(); + queue.pop(); - return res; - } + return res; + } - bool empty() - { - std::unique_lock guard(mtx); - - return queue.empty(); - } + bool empty() { + std::unique_lock guard(mtx); + return queue.empty(); + } }; } // namespace villas diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index a33cd65e2..4fe7b5aef 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -9,59 +9,67 @@ #include -#include #include +#include namespace villas { namespace node { enum class QueueSignalledMode { - AUTO, // We will choose the best method available on the platform - PTHREAD, - POLLING, + AUTO, // We will choose the best method available on the platform + PTHREAD, + POLLING, #ifdef HAS_EVENTFD - EVENTFD, + EVENTFD, #endif }; -enum class QueueSignalledFlags { - PROCESS_SHARED = (1 << 4) -}; +enum class QueueSignalledFlags { PROCESS_SHARED = (1 << 4) }; // Wrapper around queue that uses POSIX CV's for signalling writes. struct CQueueSignalled { - struct CQueue queue; // Actual underlying queue. + struct CQueue queue; // Actual underlying queue. - enum QueueSignalledMode mode; - enum QueueSignalledFlags flags; + enum QueueSignalledMode mode; + enum QueueSignalledFlags flags; - union { - struct { - pthread_cond_t ready; // Condition variable to signal writes to the queue. - pthread_mutex_t mutex; // Mutex for ready. - } pthread; + union { + struct { + pthread_cond_t ready; // Condition variable to signal writes to the queue. + pthread_mutex_t mutex; // Mutex for ready. + } pthread; #ifdef __linux__ - int eventfd; + int eventfd; #endif - }; + }; }; #define queue_signalled_available(q) queue_available(&((q)->queue)) -int queue_signalled_init(struct CQueueSignalled *qs, size_t size = DEFAULT_QUEUE_LENGTH, struct memory::Type *mem = memory::default_type, enum QueueSignalledMode mode = QueueSignalledMode::AUTO, int flags = 0) __attribute__ ((warn_unused_result)); +int queue_signalled_init( + struct CQueueSignalled *qs, size_t size = DEFAULT_QUEUE_LENGTH, + struct memory::Type *mem = memory::default_type, + enum QueueSignalledMode mode = QueueSignalledMode::AUTO, int flags = 0) + __attribute__((warn_unused_result)); -int queue_signalled_destroy(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); +int queue_signalled_destroy(struct CQueueSignalled *qs) + __attribute__((warn_unused_result)); -int queue_signalled_push(struct CQueueSignalled *qs, void *ptr) __attribute__ ((warn_unused_result)); +int queue_signalled_push(struct CQueueSignalled *qs, void *ptr) + __attribute__((warn_unused_result)); -int queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) __attribute__ ((warn_unused_result)); +int queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) + __attribute__((warn_unused_result)); -int queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) __attribute__ ((warn_unused_result)); +int queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], + size_t cnt) __attribute__((warn_unused_result)); -int queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) __attribute__ ((warn_unused_result)); +int queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], + size_t cnt) __attribute__((warn_unused_result)); -int queue_signalled_close(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); +int queue_signalled_close(struct CQueueSignalled *qs) + __attribute__((warn_unused_result)); // Returns a file descriptor which can be used with poll / select to wait for new data int queue_signalled_fd(struct CQueueSignalled *qs); diff --git a/include/villas/queue_signalled.hpp b/include/villas/queue_signalled.hpp index 6e474b533..631cda832 100644 --- a/include/villas/queue_signalled.hpp +++ b/include/villas/queue_signalled.hpp @@ -7,39 +7,36 @@ #pragma once -#include #include +#include #include namespace villas { -template -class QueueSignalled : public Queue { +template class QueueSignalled : public Queue { private: - std::condition_variable cv; + std::condition_variable cv; public: - void push(const T &data) - { - Queue::push(data); + void push(const T &data) { + Queue::push(data); - cv.notify_one(); - } + cv.notify_one(); + } - T pop() - { - std::unique_lock l(Queue::mtx); + T pop() { + std::unique_lock l(Queue::mtx); - while (Queue::queue.empty()) - cv.wait(l); + while (Queue::queue.empty()) + cv.wait(l); - T res = Queue::queue.front(); - Queue::queue.pop(); + T res = Queue::queue.front(); + Queue::queue.pop(); - return res; - } + return res; + } }; } // namespace villas diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index 600037e00..80f3f3878 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include #include #include @@ -19,16 +19,16 @@ #include // The length of a sample datastructure with \p values values in bytes. -#define SAMPLE_LENGTH(len) (sizeof(struct Sample) + SAMPLE_DATA_LENGTH(len)) +#define SAMPLE_LENGTH(len) (sizeof(struct Sample) + SAMPLE_DATA_LENGTH(len)) // The length of a sample data portion of a sample datastructure with \p values values in bytes. -#define SAMPLE_DATA_LENGTH(len) ((len) * sizeof(double)) +#define SAMPLE_DATA_LENGTH(len) ((len) * sizeof(double)) // The number of values in a sample datastructure. -#define SAMPLE_NUMBER_OF_VALUES(len) ((len) / sizeof(double)) +#define SAMPLE_NUMBER_OF_VALUES(len) ((len) / sizeof(double)) // The offset to the beginning of the data section. -#define SAMPLE_DATA_OFFSET(smp) ((char *) (smp) + offsetof(struct Sample, data)) +#define SAMPLE_DATA_OFFSET(smp) ((char *)(smp) + offsetof(struct Sample, data)) namespace villas { namespace node { @@ -38,37 +38,41 @@ struct Pool; // Parts of a sample that can be serialized / de-serialized by the IO formats 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_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_TS = HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. - HAS_ALL = (1 << 5) - 1, // Enable all output options. + HAS_TS = + HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. + HAS_ALL = (1 << 5) - 1, // Enable all output options. - 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 + 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 { - uint64_t sequence; // The sequence number of this sample. - unsigned length; // The number of values in sample::values which are valid. - unsigned capacity; // The number of values in sample::values for which memory is reserved. - int flags; // Flags are used to store binary properties of a sample. + uint64_t sequence; // The sequence number of this sample. + unsigned length; // The number of values in sample::values which are valid. + unsigned + capacity; // The number of values in sample::values for which memory is reserved. + int flags; // Flags are used to store binary properties of a sample. - SignalList::Ptr signals; // The list of signal descriptors. + SignalList::Ptr signals; // The list of signal descriptors. - std::atomic refcnt; // Reference counter. - ptrdiff_t pool_off; // This sample belongs to this memory pool (relative pointer). See sample_pool(). + std::atomic refcnt; // Reference counter. + ptrdiff_t + pool_off; // This sample belongs to this memory pool (relative pointer). See sample_pool(). - // All timestamps are seconds / nano seconds after 1.1.1970 UTC - struct { - struct timespec origin; // The point in time when this data was sampled. - struct timespec received; // The point in time when this data was received. - } ts; + // All timestamps are seconds / nano seconds after 1.1.1970 UTC + struct { + struct timespec origin; // The point in time when this data was sampled. + struct timespec received; // The point in time when this data was received. + } ts; - /* The sample signal values. + /* The sample signal values. * * This variable length array (VLA) extends over the end of struct Sample. * Make sure that pointers to struct Sample point to memory blocks of adequate size. @@ -78,21 +82,24 @@ struct Sample { * are stored in the struct Sample::signals list. Each entry in this list corresponedents * to an entry in the struct Sample::data array. */ - union SignalData data[]; + union SignalData data[]; }; #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 ? nullptr : (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); +struct Sample *sample_alloc(struct Pool *p); -struct Sample * sample_alloc_mem(int capacity); +struct Sample *sample_alloc_mem(int capacity); int sample_init(struct Sample *s); -struct Sample * sample_clone(struct Sample *smp); +struct Sample *sample_clone(struct Sample *smp); void sample_free(struct Sample *s); @@ -118,14 +125,17 @@ void sample_dump(villas::Logger logger, struct Sample *s); // Compare two samples int sample_cmp(struct Sample *a, struct Sample *b, double epsilon, int flags); -int sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt); -int sample_copy_many(struct Sample * const dsts[], const struct Sample * const srcs[], int cnt); -int sample_incref_many(struct Sample * const smps[], int cnt); -int sample_decref_many(struct Sample * const smps[], int cnt); +int sample_clone_many(struct Sample *dsts[], const struct Sample *const srcs[], + int cnt); +int sample_copy_many(struct Sample *const dsts[], + const struct Sample *const srcs[], int cnt); +int sample_incref_many(struct Sample *const smps[], int cnt); +int sample_decref_many(struct Sample *const smps[], int cnt); enum SignalType sample_format(const struct Sample *s, unsigned idx); -void sample_data_insert(struct Sample *smp, const union SignalData *src, size_t offset, size_t len); +void sample_data_insert(struct Sample *smp, const union SignalData *src, + size_t offset, size_t len); void sample_data_remove(struct Sample *smp, size_t offset, size_t len); } // namespace node diff --git a/include/villas/shmem.hpp b/include/villas/shmem.hpp index d8940c24c..17119deeb 100644 --- a/include/villas/shmem.hpp +++ b/include/villas/shmem.hpp @@ -12,8 +12,8 @@ #include #include -#define DEFAULT_SHMEM_QUEUELEN 512u -#define DEFAULT_SHMEM_SAMPLELEN 64u +#define DEFAULT_SHMEM_QUEUELEN 512u +#define DEFAULT_SHMEM_SAMPLELEN 64u namespace villas { namespace node { @@ -21,30 +21,30 @@ namespace node { /* Struct containing all parameters that need to be known when creating a new * shared memory object. */ struct ShmemConfig { - int polling; // Whether to use polling instead of POSIX CVs - int queuelen; // Size of the queues (in elements) - int samplelen; // Maximum number of data entries in a single sample + int polling; // Whether to use polling instead of POSIX CVs + int queuelen; // Size of the queues (in elements) + int samplelen; // Maximum number of data entries in a single sample }; // The structure that actually resides in the shared memory. struct ShmemShared { - int polling; // Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. - struct CQueueSignalled queue; // Queue for samples passed in both directions. - struct Pool pool; // Pool for the samples in the queues. + int polling; // Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. + struct CQueueSignalled queue; // Queue for samples passed in both directions. + struct Pool pool; // Pool for the samples in the queues. }; // Relevant information for one direction of the interface. struct shmem_dir { - void *base; // Base address of the region. - const char *name; // Name of the shmem object. - size_t len; // Total size of the region. - struct ShmemShared *shared; // Actually shared datastructure + void *base; // Base address of the region. + const char *name; // Name of the shmem object. + size_t len; // Total size of the region. + struct ShmemShared *shared; // Actually shared datastructure }; // Main structure representing the shared memory interface. struct ShmemInterface { - struct shmem_dir read, write; - std::atomic readers, writers, closed; + struct shmem_dir read, write; + std::atomic readers, writers, closed; }; /* Open the shared memory objects and retrieve / initialize the shared data structures. @@ -58,7 +58,8 @@ struct ShmemInterface { * @retval 0 The objects were opened and initialized successfully. * @retval <0 An error occured; errno is set accordingly. */ -int shmem_int_open(const char* wname, const char* rname, struct ShmemInterface* shm, struct ShmemConfig* conf); +int shmem_int_open(const char *wname, const char *rname, + struct ShmemInterface *shm, struct ShmemConfig *conf); /* Close and destroy the shared memory interface and related structures. * @@ -77,7 +78,8 @@ int shmem_int_close(struct ShmemInterface *shm); * @retval >=0 Number of samples that were read. Can be less than cnt (including 0) in case not enough samples were available. * @retval -1 The other process closed the interface; no samples can be read anymore. */ -int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt); +int shmem_int_read(struct ShmemInterface *shm, struct Sample *const smps[], + unsigned cnt); /* Write samples to the interface. * @@ -87,7 +89,8 @@ int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], uns * @retval >=0 Number of samples that were successfully written. Can be less than cnt (including 0) in case of a full queue. * @retval -1 The write failed for some reason; no more samples can be written. */ -int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt); +int shmem_int_write(struct ShmemInterface *shm, + const struct Sample *const smps[], unsigned cnt); /* Allocate samples to be written to the interface. * @@ -97,7 +100,8 @@ int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps * @param cnt Number of samples to allocate. * @return Number of samples that were successfully allocated (may be less then cnt). */ -int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned cnt); +int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], + unsigned cnt); /* Returns the total size of the shared memory region with the given size of * the input/output queues (in elements) and the given number of data elements diff --git a/include/villas/signal.hpp b/include/villas/signal.hpp index 58a9ef14a..71e90e629 100644 --- a/include/villas/signal.hpp +++ b/include/villas/signal.hpp @@ -11,8 +11,8 @@ #include -#include #include +#include // "I" defined by complex.h collides with a define in OpenSSL #undef I @@ -27,26 +27,27 @@ namespace node { class Signal { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - std::string name; // The name of the signal. - std::string unit; // The unit of the signal. + std::string name; // The name of the signal. + std::string unit; // The unit of the signal. - union SignalData init; // The initial value of the signal. - enum SignalType type; + union SignalData init; // The initial value of the signal. + enum SignalType type; - // Initialize a signal with default values. - Signal(const std::string &n = "", const std::string &u = "", enum SignalType t = SignalType::INVALID); + // Initialize a signal with default values. + Signal(const std::string &n = "", const std::string &u = "", + enum SignalType t = SignalType::INVALID); - // Parse signal description. - int parse(json_t *json); + // Parse signal description. + int parse(json_t *json); - std::string toString(const union SignalData *d = nullptr) const; + std::string toString(const union SignalData *d = nullptr) const; - // Produce JSON representation of signal. - json_t * toJson() const; + // Produce JSON representation of signal. + json_t *toJson() const; - bool isNext(const Signal &sig); + bool isNext(const Signal &sig); }; } // namespace node diff --git a/include/villas/signal_data.hpp b/include/villas/signal_data.hpp index 56ee7105f..e4351e84e 100644 --- a/include/villas/signal_data.hpp +++ b/include/villas/signal_data.hpp @@ -9,8 +9,8 @@ #include -#include #include +#include #include #include @@ -23,46 +23,40 @@ namespace node { * Data is in host endianess! */ union SignalData { - double f; // Floating point values. - int64_t i; // Integer values. - bool b; // Boolean values. - std::complex z; // Complex values. + double f; // Floating point values. + int64_t i; // Integer values. + bool b; // Boolean values. + std::complex z; // Complex values. - SignalData() : - i(0) - { } + SignalData() : i(0) {} - static - union SignalData nan() - { - union SignalData d; + static union SignalData nan() { + union SignalData d; - d.f = std::numeric_limits::quiet_NaN(); + d.f = std::numeric_limits::quiet_NaN(); - return d; - } + return d; + } - bool is_nan() - { - return f == std::numeric_limits::quiet_NaN(); - } + bool is_nan() { return f == std::numeric_limits::quiet_NaN(); } - // Convert signal data from one description/format to another. - SignalData cast(enum SignalType type, enum SignalType to) const; + // Convert signal data from one description/format to another. + SignalData cast(enum SignalType type, enum SignalType to) const; - // Set data from double - void set(enum SignalType type, double val); + // Set data from double + void set(enum SignalType type, double val); - // Print value of a signal to a character buffer. - int printString(enum SignalType type, char *buf, size_t len, int precision = 5) const; + // Print value of a signal to a character buffer. + int printString(enum SignalType type, char *buf, size_t len, + int precision = 5) const; - int parseString(enum SignalType type, const char *ptr, char **end); + int parseString(enum SignalType type, const char *ptr, char **end); - int parseJson(enum SignalType type, json_t *json); + int parseJson(enum SignalType type, json_t *json); - json_t * toJson(enum SignalType type) const; + json_t *toJson(enum SignalType type) const; - std::string toString(enum SignalType type, int precision = 5) const; + std::string toString(enum SignalType type, int precision = 5) const; }; } // namespace node diff --git a/include/villas/signal_list.hpp b/include/villas/signal_list.hpp index 8fe04c777..9a326abfd 100644 --- a/include/villas/signal_list.hpp +++ b/include/villas/signal_list.hpp @@ -12,9 +12,9 @@ #include +#include #include #include -#include namespace villas { namespace node { @@ -22,31 +22,30 @@ namespace node { class SignalList : public std::vector { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - SignalList() - { } + SignalList() {} - SignalList(unsigned len, enum SignalType fmt); - SignalList(const char *dt); - SignalList(json_t *json) - { - int ret = parse(json); - if (ret) - throw RuntimeError("Failed to parse signal list"); - } + SignalList(unsigned len, enum SignalType fmt); + SignalList(const char *dt); + SignalList(json_t *json) { + int ret = parse(json); + if (ret) + throw RuntimeError("Failed to parse signal list"); + } - int parse(json_t *json); + int parse(json_t *json); - Ptr clone(); + Ptr clone(); - void dump(villas::Logger logger, const union SignalData *data = nullptr, unsigned len = 0) const; + void dump(villas::Logger logger, const union SignalData *data = nullptr, + unsigned len = 0) const; - json_t * toJson() const; + json_t *toJson() const; - int getIndexByName(const std::string &name); - Signal::Ptr getByName(const std::string &name); - Signal::Ptr getByIndex(unsigned idx); + int getIndexByName(const std::string &name); + Signal::Ptr getByName(const std::string &name); + Signal::Ptr getByIndex(unsigned idx); }; } // namespace node diff --git a/include/villas/signal_type.hpp b/include/villas/signal_type.hpp index f890afd67..30af86e4a 100644 --- a/include/villas/signal_type.hpp +++ b/include/villas/signal_type.hpp @@ -13,11 +13,11 @@ namespace villas { namespace node { enum class SignalType { - INVALID = 0, // Signal type is invalid. - FLOAT = 1, // See SignalData::f - INTEGER = 2, // See SignalData::i - BOOLEAN = 3, // See SignalData::b - COMPLEX = 4 // See SignalData::z + INVALID = 0, // Signal type is invalid. + FLOAT = 1, // See SignalData::f + INTEGER = 2, // See SignalData::i + BOOLEAN = 3, // See SignalData::b + COMPLEX = 4 // See SignalData::z }; enum SignalType signalTypeFromString(const std::string &str); diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index 07e9de46d..d3947a171 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -7,40 +7,35 @@ #pragma once -#include -#include -#include #include +#include +#include +#include #include #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) - #define WITH_SOCKET_LAYER_ETH +#define WITH_SOCKET_LAYER_ETH - #include - #include +#include +#include #endif // LIBNL3_ROUTE_FOUND union sockaddr_union { - struct sockaddr sa; - struct sockaddr_storage ss; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - struct sockaddr_un sun; + struct sockaddr sa; + struct sockaddr_storage ss; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_un sun; #ifdef WITH_SOCKET_LAYER_ETH - struct sockaddr_ll sll; + struct sockaddr_ll sll; #endif }; namespace villas { namespace node { -enum class SocketLayer { - ETH, - IP, - UDP, - UNIX -}; +enum class SocketLayer { ETH, IP, UDP, UNIX }; /* Generate printable socket address depending on the address family * @@ -50,7 +45,7 @@ enum class SocketLayer { * @param sa A pointer to the socket address. * @return The buffer containing the textual representation of the address. The caller is responsible to free() this buffer! */ -char * socket_print_addr(struct sockaddr *saddr); +char *socket_print_addr(struct sockaddr *saddr); /* Parse a socket address depending on the address family * @@ -66,7 +61,8 @@ 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 SocketLayer 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); diff --git a/include/villas/stats.hpp b/include/villas/stats.hpp index 696aa29c1..b550b80d1 100644 --- a/include/villas/stats.hpp +++ b/include/villas/stats.hpp @@ -10,15 +10,15 @@ #include #include -#include #include #include +#include #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -27,104 +27,82 @@ namespace node { struct Sample; class Node; -} +} // namespace node class Stats { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - enum class Format { - HUMAN, - JSON, - MATLAB - }; + enum class Format { HUMAN, JSON, MATLAB }; - enum class Metric { - SMPS_SKIPPED, // Counter for skipped samples due to hooks. - SMPS_REORDERED, // Counter for reordered samples. + 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. - SIGNAL_COUNT, // Number of signals per sample. + // 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. + SIGNAL_COUNT, // Number of signals per sample. - // RTP metrics - RTP_LOSS_FRACTION, // Fraction lost since last RTP SR/RR. - RTP_PKTS_LOST, // Cumul. no. pkts lost. - RTP_JITTER // Interarrival jitter. - }; + // 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 - }; + enum class Type { LAST, HIGHEST, LOWEST, MEAN, VAR, STDDEV, TOTAL }; protected: - std::unordered_map histograms; + std::unordered_map histograms; - struct MetricDescription { - const char *name; - const char *unit; - const char *desc; - }; + struct MetricDescription { + const char *name; + const char *unit; + const char *desc; + }; - struct TypeDescription { - const char *name; - enum node::SignalType signal_type; - }; + struct TypeDescription { + const char *name; + enum node::SignalType signal_type; + }; - static - std::shared_ptr table; + static std::shared_ptr
table; - static - void setupTable(); + static void setupTable(); - Logger logger; + Logger logger; public: + Stats(int buckets, int warmup); - Stats(int buckets, int warmup); + static enum Format lookupFormat(const std::string &str); - static - enum Format lookupFormat(const std::string &str); + static enum Metric lookupMetric(const std::string &str); - static - enum Metric lookupMetric(const std::string &str); + static enum Type lookupType(const std::string &str); - static - enum Type lookupType(const std::string &str); + void update(enum Metric id, double val); - void update(enum Metric id, double val); + void reset(); - void reset(); + json_t *toJson() const; - json_t * toJson() const; + static void printHeader(enum Format fmt); - static - void printHeader(enum Format fmt); + void printPeriodic(FILE *f, enum Format fmt, node::Node *n) const; - void printPeriodic(FILE *f, enum Format fmt, node::Node *n) const; + void print(FILE *f, enum Format fmt, int verbose) const; - void print(FILE *f, enum Format fmt, int verbose) const; + union node::SignalData getValue(enum Metric sm, enum Type st) const; - union node::SignalData getValue(enum Metric sm, enum Type st) const; + const Hist &getHistogram(enum Metric sm) const; - const Hist & getHistogram(enum Metric sm) const; - - static - std::unordered_map metrics; - static - std::unordered_map types; - static - std::vector columns; + static std::unordered_map metrics; + static std::unordered_map types; + static std::vector columns; }; } // namespace villas diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index a843a8bc6..0bf2d4b60 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -11,22 +11,22 @@ #ifdef WITH_GRAPHVIZ extern "C" { - #include +#include } #endif #include #include -#include -#include +#include #include +#include +#include #include #include #include #include -#include -#include +#include namespace villas { namespace node { @@ -38,159 +38,117 @@ class Node; class SuperNode { protected: - enum State state; + enum State state; - int idleStop; + int idleStop; - Logger logger; + Logger logger; - NodeList nodes; - PathList paths; - std::list interfaces; + NodeList nodes; + PathList paths; + std::list interfaces; #ifdef WITH_API - Api api; + Api api; #endif #ifdef WITH_WEB - Web web; + Web web; #endif - int priority; // Process priority (lower is better) - int affinity; // Process affinity of the server and all created threads - int hugepages; // Number of hugepages to reserve. - double statsRate; // Rate at which we display the periodic stats. + int priority; // Process priority (lower is better) + int affinity; // Process affinity of the server and all created threads + int hugepages; // Number of hugepages to reserve. + double statsRate; // Rate at which we display the periodic stats. - struct Task task; // Task for periodic stats output + struct Task task; // Task for periodic stats output - uuid_t uuid; // A globally unique identifier of the instance + uuid_t uuid; // A globally unique identifier of the instance - struct timespec started; // The time at which the instance has been started. + struct timespec started; // The time at which the instance has been started. - std::string uri; // URI of configuration + std::string uri; // URI of configuration - Config config; // The configuration file. + Config config; // The configuration file. public: - // Inititalize configuration object before parsing the configuration. - SuperNode(); + // Inititalize configuration object before parsing the configuration. + SuperNode(); - int init(); + int init(); - // Wrapper for parse() which loads the config first. - void parse(const std::string &name); + // Wrapper for parse() which loads the config first. + void parse(const std::string &name); - /* Parse super-node configuration. + /* Parse super-node configuration. * * @param json A libjansson object which contains the configuration. */ - void parse(json_t *json); + void parse(json_t *json); - // Check validity of super node configuration. - void check(); + // Check validity of super node configuration. + void check(); - // Initialize after parsing the configuration file. - void prepare(); - void start(); - void stop(); - void run(); + // Initialize after parsing the configuration file. + void prepare(); + void start(); + void stop(); + void run(); - void preparePaths(); - void prepareNodes(); - void prepareNodeTypes(); + void preparePaths(); + void prepareNodes(); + void prepareNodeTypes(); - void startPaths(); - void startNodes(); - void startInterfaces(); + void startPaths(); + void startNodes(); + void startInterfaces(); - void stopPaths(); - void stopNodes(); - void stopNodeTypes(); - void stopInterfaces(); + void stopPaths(); + void stopNodes(); + void stopNodeTypes(); + void stopInterfaces(); #ifdef WITH_GRAPHVIZ - graph_t * getGraph(); + graph_t *getGraph(); #endif - // Run periodic hooks of this super node. - int periodic(); + // Run periodic hooks of this super node. + int periodic(); - void setState(enum State st) - { - state = st; - } + void setState(enum State st) { state = st; } - Node * getNode(const std::string &name) - { - return nodes.lookup(name); - } + Node *getNode(const std::string &name) { return nodes.lookup(name); } - NodeList & getNodes() - { - return nodes; - } + NodeList &getNodes() { return nodes; } - PathList & getPaths() - { - return paths; - } + PathList &getPaths() { return paths; } - std::list & getInterfaces() - { - return interfaces; - } + std::list &getInterfaces() { return interfaces; } - enum State getState() const - { - return state; - } + enum State getState() const { return state; } - const uuid_t & getUuid() const - { - return uuid; - } + const uuid_t &getUuid() const { return uuid; } - struct timespec getStartTime() const - { - return started; - } + struct timespec getStartTime() const { return started; } #ifdef WITH_API - Api * getApi() - { - return &api; - } + Api *getApi() { return &api; } #endif #ifdef WITH_WEB - Web * getWeb() - { - return &web; - } + Web *getWeb() { return &web; } #endif - json_t * getConfig() - { - return config.root; - } + json_t *getConfig() { return config.root; } - std::string getConfigUri() const - { - return uri; - } + std::string getConfigUri() const { return uri; } - int getAffinity() const - { - return affinity; - } + int getAffinity() const { return affinity; } - Logger getLogger() - { - return logger; - } + Logger getLogger() { return logger; } - // Destroy configuration object. - ~SuperNode(); + // Destroy configuration object. + ~SuperNode(); }; } // namespace node diff --git a/include/villas/usb.hpp b/include/villas/usb.hpp index 67be5f560..7c0086b71 100644 --- a/include/villas/usb.hpp +++ b/include/villas/usb.hpp @@ -15,96 +15,82 @@ namespace villas { namespace usb { struct Filter { - int bus; - int port; - int vendor_id; - int product_id; + int bus; + int port; + int vendor_id; + int product_id; }; class Error : public std::runtime_error { protected: - enum libusb_error err; - char *msg; + enum libusb_error err; + char *msg; public: - Error(enum libusb_error e, const std::string &what) : - std::runtime_error(what), - err(e) - { - int ret __attribute__((unused)); - ret = asprintf(&msg, "%s: %s", std::runtime_error::what(), libusb_strerror(err)); - } + Error(enum libusb_error e, const std::string &what) + : std::runtime_error(what), err(e) { + int ret __attribute__((unused)); + ret = asprintf(&msg, "%s: %s", std::runtime_error::what(), + libusb_strerror(err)); + } - template - Error(enum libusb_error e, const std::string &what, Args&&... args) : - usb::Error(e, fmt::format(what, std::forward(args)...)) - { } + template + Error(enum libusb_error e, const std::string &what, Args &&...args) + : usb::Error(e, fmt::format(what, std::forward(args)...)) {} - // Same as above but with int - Error(int e, const std::string &what) : - usb::Error((enum libusb_error) e, what) - { } + // Same as above but with int + Error(int e, const std::string &what) + : usb::Error((enum libusb_error)e, what) {} - template - Error(int e, const std::string &what, Args&&... args) : - usb::Error((enum libusb_error) e, what, std::forward(args)...) - { } + template + Error(int e, const std::string &what, Args &&...args) + : usb::Error((enum libusb_error)e, what, std::forward(args)...) {} - ~Error() - { - if (msg) - free(msg); - } + ~Error() { + if (msg) + free(msg); + } - virtual - const char * what() const noexcept - { - return msg; - } + virtual const char *what() const noexcept { return msg; } }; class Device { protected: - struct libusb_device *device; - struct libusb_device_handle *handle; - struct libusb_device_descriptor desc; + struct libusb_device *device; + struct libusb_device_handle *handle; + struct libusb_device_descriptor desc; - std::string getStringDescriptor(uint8_t desc_id) const; + std::string getStringDescriptor(uint8_t desc_id) const; public: - Device(struct libusb_device *dev) : - device(dev), - handle(nullptr) - { } + Device(struct libusb_device *dev) : device(dev), handle(nullptr) {} - const struct libusb_device_descriptor & getDescriptor() const - { return desc; } + const struct libusb_device_descriptor &getDescriptor() const { return desc; } - int getBus() const - { return libusb_get_bus_number(device); } + int getBus() const { return libusb_get_bus_number(device); } - int getPort() const - { return libusb_get_port_number(device); } + int getPort() const { return libusb_get_port_number(device); } - std::string getManufacturer() const - { return getStringDescriptor(desc.iManufacturer); } + std::string getManufacturer() const { + return getStringDescriptor(desc.iManufacturer); + } - std::string getProduct() const - { return getStringDescriptor(desc.iProduct); } + std::string getProduct() const { return getStringDescriptor(desc.iProduct); } - std::string getSerial() const - { return getStringDescriptor(desc.iSerialNumber); } + std::string getSerial() const { + return getStringDescriptor(desc.iSerialNumber); + } - bool match(const Filter *flt) const; + bool match(const Filter *flt) const; }; -struct libusb_context * init(); +struct libusb_context *init(); void deinit_context(struct libusb_context *ctx); -struct libusb_context * get_context(); +struct libusb_context *get_context(); void detach(struct libusb_device_handle *hdl, int iface); diff --git a/include/villas/web.hpp b/include/villas/web.hpp index acf73edbd..b31727cd2 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -10,11 +10,11 @@ #include #include -#include #include +#include -#include #include +#include #include namespace villas { @@ -26,74 +26,57 @@ class Api; class Web final { private: - enum State state; + enum State state; - Logger logger; + Logger logger; - lws_context *context; // The libwebsockets server context. - lws_vhost *vhost; // The libwebsockets vhost. + lws_context *context; // The libwebsockets server context. + lws_vhost *vhost; // The libwebsockets vhost. - Queue writables; // Queue of WSIs for which we will call lws_callback_on_writable() + Queue + writables; // Queue of WSIs for which we will call lws_callback_on_writable() - int port; // Port of the build in HTTP / WebSocket server. - std::string ssl_cert; // Path to the SSL certitifcate for HTTPS / WSS. - std::string ssl_private_key; // Path to the SSL private key for HTTPS / WSS. + int port; // Port of the build in HTTP / WebSocket server. + std::string ssl_cert; // Path to the SSL certitifcate for HTTPS / WSS. + std::string ssl_private_key; // Path to the SSL private key for HTTPS / WSS. - std::thread thread; - std::atomic running; // Atomic flag for signalizing thread termination. + std::thread thread; + std::atomic running; // Atomic flag for signalizing thread termination. - Api *api; + Api *api; - void worker(); + void worker(); public: - - /* Initialize the web interface. + /* Initialize the web interface. * * The web interface is based on the libwebsockets library. */ - Web(Api *a = nullptr); + Web(Api *a = nullptr); - ~Web(); + ~Web(); - void start(); - void stop(); + void start(); + void stop(); - static - void lwsLogger(int level, const char *msg); - static - int lwsLogLevel(Log::Level lvl); + static void lwsLogger(int level, const char *msg); + static int lwsLogLevel(Log::Level lvl); - // Parse HTTPd and WebSocket related options - int parse(json_t *json); + // Parse HTTPd and WebSocket related options + int parse(json_t *json); - Api * getApi() - { - return api; - } + Api *getApi() { return api; } - // for C-compatability - lws_context * getContext() - { - return context; - } + // for C-compatability + lws_context *getContext() { return context; } - lws_vhost * getVHost() - { - return vhost; - } + lws_vhost *getVHost() { return vhost; } - enum State getState() const - { - return state; - } + enum State getState() const { return state; } - void callbackOnWritable(struct lws *wsi); + void callbackOnWritable(struct lws *wsi); - bool isEnabled() - { - return port != CONTEXT_PORT_NO_LISTEN; - } + bool isEnabled() { return port != CONTEXT_PORT_NO_LISTEN; } }; } // namespace node diff --git a/lib/api.cpp b/lib/api.cpp index 01b0e7547..c53bd47bb 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -6,84 +6,75 @@ */ #include -#include -#include #include -#include +#include +#include #include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::node::api; -InvalidMethod::InvalidMethod(Request *req) : - BadRequest("The '{}' API endpoint does not support {} requests", - req->factory->getName(), - Session::methodToString(req->method) - ) -{ } +InvalidMethod::InvalidMethod(Request *req) + : BadRequest("The '{}' API endpoint does not support {} requests", + req->factory->getName(), + Session::methodToString(req->method)) {} -Api::Api(SuperNode *sn) : - logger(logging.get("api")), - state(State::INITIALIZED), - super_node(sn) -{ } +Api::Api(SuperNode *sn) + : logger(logging.get("api")), state(State::INITIALIZED), super_node(sn) {} -Api::~Api() -{ - if (state == State::STARTED) - stop(); +Api::~Api() { + if (state == State::STARTED) + stop(); } -void Api::start() -{ - assert(state != State::STARTED); +void Api::start() { + assert(state != State::STARTED); - logger->info("Starting sub-system"); + logger->info("Starting sub-system"); - running = true; - thread = std::thread(&Api::worker, this); + running = true; + thread = std::thread(&Api::worker, this); - state = State::STARTED; + state = State::STARTED; } -void Api::stop() -{ - assert(state == State::STARTED); +void Api::stop() { + assert(state == State::STARTED); - logger->info("Stopping sub-system"); + logger->info("Stopping sub-system"); - for (Session *s : sessions) - s->shutdown(); + for (Session *s : sessions) + s->shutdown(); - for (int i = 0; i < 2 && sessions.size() > 0; i++) { - logger->info("Waiting for {} sessions to terminate", sessions.size()); - usleep(1 * 1e6); - } + for (int i = 0; i < 2 && sessions.size() > 0; i++) { + logger->info("Waiting for {} sessions to terminate", sessions.size()); + usleep(1 * 1e6); + } - running = false; - pending.push(nullptr); // unblock thread - thread.join(); + running = false; + pending.push(nullptr); // unblock thread + thread.join(); - state = State::STOPPED; + state = State::STOPPED; } -void Api::worker() -{ - logger->info("Started worker"); +void Api::worker() { + logger->info("Started worker"); - // Process pending requests - while (running) { - Session *s = pending.pop(); - if (s) { - // Check that the session is still alive - auto it = std::find(sessions.begin(), sessions.end(), s); - if (it != sessions.end()) - s->execute(); - } - } + // Process pending requests + while (running) { + Session *s = pending.pop(); + if (s) { + // Check that the session is still alive + auto it = std::find(sessions.begin(), sessions.end(), s); + if (it != sessions.end()) + s->execute(); + } + } - logger->info("Stopped worker"); + logger->info("Stopped worker"); } diff --git a/lib/api/request.cpp b/lib/api/request.cpp index 2f9b20fda..e8e508ada 100644 --- a/lib/api/request.cpp +++ b/lib/api/request.cpp @@ -5,50 +5,47 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include using namespace villas; using namespace villas::node::api; -void Request::decode() -{ - body = buffer.decode(); - if (!body) - throw BadRequest("Failed to decode request payload"); +void Request::decode() { + body = buffer.decode(); + if (!body) + throw BadRequest("Failed to decode request payload"); } -std::string Request::toString() -{ - return fmt::format("endpoint={}, method={}", factory->getName(), Session::methodToString(method)); +std::string Request::toString() { + return fmt::format("endpoint={}, method={}", factory->getName(), + Session::methodToString(method)); } -Request * RequestFactory::create(Session *s, const std::string &uri, Session::Method meth, unsigned long ct) -{ - s->logger->info("Lookup request handler for: uri={}", uri); +Request *RequestFactory::create(Session *s, const std::string &uri, + Session::Method meth, unsigned long ct) { + s->logger->info("Lookup request handler for: uri={}", uri); - for (auto *rf : plugin::registry->lookup()) { - std::smatch mr; - if (not rf->match(uri, mr)) - continue; + for (auto *rf : plugin::registry->lookup()) { + std::smatch mr; + if (not rf->match(uri, mr)) + continue; - auto *p = rf->make(s); + auto *p = rf->make(s); - for (auto m : mr) - p->matches.push_back(m.str()); + for (auto m : mr) + p->matches.push_back(m.str()); - p->factory = rf; - p->method = meth; - p->contentLength = ct; + p->factory = rf; + p->method = meth; + p->contentLength = ct; - p->prepare(); + p->prepare(); - return p; - } + return p; + } - throw BadRequest("Unknown API request", "{ s: s, s: s }", - "uri", uri.c_str(), - "method", Session::methodToString(meth).c_str() - ); + throw BadRequest("Unknown API request", "{ s: s, s: s }", "uri", uri.c_str(), + "method", Session::methodToString(meth).c_str()); } diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index 68c30346b..a26048e35 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -16,27 +16,26 @@ namespace api { class CapabilitiesRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Capabilities endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Capabilities endpoint does not accept any body data"); - auto *json_capabilities = getCapabilities(); + auto *json_capabilities = getCapabilities(); - return new JsonResponse(session, HTTP_STATUS_OK, json_capabilities); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_capabilities); + } }; // Register API request static char n[] = "capabilities"; static char r[] = "/capabilities"; -static char d[] = "get capabiltities and details about this VILLASnode instance"; +static char d[] = + "get capabiltities and details about this VILLASnode instance"; static RequestPlugin p; } // namespace api diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index ae8a76f29..79fed58e9 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -17,25 +17,21 @@ namespace api { class ConfigRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - json_t *json = session->getSuperNode()->getConfig(); + virtual Response *execute() { + json_t *json = session->getSuperNode()->getConfig(); - if (method != Session::Method::GET) - throw InvalidMethod(this); + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Config endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Config endpoint does not accept any body data"); - auto *json_config = json - ? json_incref(json) - : json_object(); + auto *json_config = json ? json_incref(json) : json_object(); - return new JsonResponse(session, HTTP_STATUS_OK, json_config); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_config); + } }; // Register API request diff --git a/lib/api/requests/graph.cpp b/lib/api/requests/graph.cpp index cddb698c3..a8bf96ce9 100644 --- a/lib/api/requests/graph.cpp +++ b/lib/api/requests/graph.cpp @@ -6,12 +6,12 @@ */ extern "C" { - #include +#include } -#include #include #include +#include namespace villas { namespace node { @@ -20,92 +20,90 @@ namespace api { class GraphRequest : public Request { protected: - GVC_t *gvc; + GVC_t *gvc; - std::string layout; - std::string format; + std::string layout; + std::string format; public: - GraphRequest(Session *s) : - Request(s), - gvc(gvContext()), - layout(getQueryArg("layout")) - { - if (layout.empty()) - layout = "neato"; - } + GraphRequest(Session *s) + : Request(s), gvc(gvContext()), layout(getQueryArg("layout")) { + if (layout.empty()) + layout = "neato"; + } - ~GraphRequest() - { - gvFreeContext(gvc); - } + ~GraphRequest() { gvFreeContext(gvc); } - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Status endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Status endpoint does not accept any body data"); - auto *sn = session->getSuperNode(); - auto *graph = sn->getGraph(); + auto *sn = session->getSuperNode(); + auto *graph = sn->getGraph(); - char *data; - unsigned len; + char *data; + unsigned len; - std::list supportedLayouts = { "circo", "dot", "fdp", "neato", "nop", "nop1", "nop2", "osage", "patchwork", "sfdp", "twopi" }; - std::list supportedFormats = { "ps", "eps", "txt", "svg", "svgz", "gif", "png", "jpg", "jpeg", "bmp", "dot", "fig", "json", "pdf" }; + std::list supportedLayouts = { + "circo", "dot", "fdp", "neato", "nop", "nop1", + "nop2", "osage", "patchwork", "sfdp", "twopi"}; + std::list supportedFormats = { + "ps", "eps", "txt", "svg", "svgz", "gif", "png", + "jpg", "jpeg", "bmp", "dot", "fig", "json", "pdf"}; - format = matches[1]; + format = matches[1]; - auto lit = std::find(supportedLayouts.begin(), supportedLayouts.end(), layout); - if (lit == supportedLayouts.end()) - throw BadRequest("Unsupported layout: {}", layout); + auto lit = + std::find(supportedLayouts.begin(), supportedLayouts.end(), layout); + if (lit == supportedLayouts.end()) + throw BadRequest("Unsupported layout: {}", layout); - auto fit = std::find(supportedFormats.begin(), supportedFormats.end(), format); - if (fit == supportedFormats.end()) - throw BadRequest("Unsupported format: {}", format); + auto fit = + std::find(supportedFormats.begin(), supportedFormats.end(), format); + if (fit == supportedFormats.end()) + throw BadRequest("Unsupported format: {}", format); - std::string ct = "text/plain"; - if (format == "svg") - ct = "image/svg+xml"; - else if (format == "eps" || format == "ps") - ct = "application/postscript"; - else if (format == "txt") - ct = "text/plain"; - else if (format == "gif") - ct = "image/gif"; - else if (format == "png") - ct = "image/png"; - else if (format == "jpg" || format == "jpeg") - ct = "image/jpeg"; - else if (format == "bmp") - ct = "image/bmp"; - else if (format == "dot") - ct = "text/vnd.graphviz"; - else if (format == "json") - ct = "application/json"; - else if (format == "pdf") - ct = "application/pdf"; + std::string ct = "text/plain"; + if (format == "svg") + ct = "image/svg+xml"; + else if (format == "eps" || format == "ps") + ct = "application/postscript"; + else if (format == "txt") + ct = "text/plain"; + else if (format == "gif") + ct = "image/gif"; + else if (format == "png") + ct = "image/png"; + else if (format == "jpg" || format == "jpeg") + ct = "image/jpeg"; + else if (format == "bmp") + ct = "image/bmp"; + else if (format == "dot") + ct = "text/vnd.graphviz"; + else if (format == "json") + ct = "application/json"; + else if (format == "pdf") + ct = "application/pdf"; - gvLayout(gvc, graph, layout.c_str()); - gvRenderData(gvc, graph, format.c_str(), &data, &len); + gvLayout(gvc, graph, layout.c_str()); + gvRenderData(gvc, graph, format.c_str(), &data, &len); - auto buf = Buffer(data, len); - auto *resp = new Response(session, HTTP_STATUS_OK, ct, buf); + auto buf = Buffer(data, len); + auto *resp = new Response(session, HTTP_STATUS_OK, ct, buf); - if (format == "svgz") - resp->setHeader("Content-Encoding", "gzip"); + if (format == "svgz") + resp->setHeader("Content-Encoding", "gzip"); #if 0 gvFreeRenderData(data); #endif - gvFreeLayout(gvc, graph); + gvFreeLayout(gvc, graph); - return resp; - } + return resp; + } }; // Register API request diff --git a/lib/api/requests/node.cpp b/lib/api/requests/node.cpp index fd4452359..b66f869ce 100644 --- a/lib/api/requests/node.cpp +++ b/lib/api/requests/node.cpp @@ -9,26 +9,21 @@ using namespace villas::node::api; -void NodeRequest::prepare() -{ - int ret; +void NodeRequest::prepare() { + int ret; - auto &nodes = session->getSuperNode()->getNodes(); + auto &nodes = session->getSuperNode()->getNodes(); - uuid_t uuid; - ret = uuid_parse(matches[1].c_str(), uuid); - if (ret) { - node = nodes.lookup(matches[1]); - if (!node) - throw BadRequest("Unknown node", "{ s: s }", - "node", matches[1].c_str() - ); - } - else { - node = nodes.lookup(uuid); - if (!node) - throw BadRequest("No node found with with matching UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); - } + uuid_t uuid; + ret = uuid_parse(matches[1].c_str(), uuid); + if (ret) { + node = nodes.lookup(matches[1]); + if (!node) + throw BadRequest("Unknown node", "{ s: s }", "node", matches[1].c_str()); + } else { + node = nodes.lookup(uuid); + if (!node) + throw BadRequest("No node found with with matching UUID", "{ s: s }", + "uuid", matches[1].c_str()); + } } diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index d3d811601..f7c1718d0 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -7,42 +7,36 @@ #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -template -class NodeActionRequest : public NodeRequest { +template class NodeActionRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Node endpoints do not accept any body data"); + if (body != nullptr) + throw BadRequest("Node endpoints do not accept any body data"); - int ret = (node->*func)(); - if (ret) - throw BadRequest("Failed to execute action", "{ s: d }", - "ret", ret - ); - - return new Response(session, HTTP_STATUS_OK); - } + int ret = (node->*func)(); + if (ret) + throw BadRequest("Failed to execute action", "{ s: d }", "ret", ret); + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 200c61189..124a8bd31 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include +#include +#include +#include #include #include -#include namespace villas { namespace node { @@ -21,32 +21,29 @@ namespace api { class FileRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET && method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET && method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("File endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("File endpoint does not accept any body data"); - NodeFactory *nf = plugin::registry->lookup("file"); + NodeFactory *nf = plugin::registry->lookup("file"); - if (node->getFactory() != nf) - throw BadRequest("This node is not a file node", "{ s: s }", - "type", node->getFactory()->getName() - ); + if (node->getFactory() != nf) + throw BadRequest("This node is not a file node", "{ s: s }", "type", + node->getFactory()->getName()); - auto *nc = dynamic_cast(node); - auto *f = nc->getData(); + auto *nc = dynamic_cast(node); + auto *f = nc->getData(); - if (matches[2] == "rewind") - rewind(f->stream_in); + if (matches[2] == "rewind") + rewind(f->stream_in); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API request diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index bd5ca0c27..f13bdc432 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,28 +22,26 @@ namespace api { class NodeInfoRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Nodes endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Nodes endpoint does not accept any body data"); - auto *json_node = node->toJson(); + auto *json_node = node->toJson(); - auto sigs = node->getOutputSignals(); - if (sigs) { - auto *json_out = json_object_get(json_node, "out"); - if (json_out) - json_object_set_new(json_out, "signals", sigs->toJson()); - } + auto sigs = node->getOutputSignals(); + if (sigs) { + auto *json_out = json_object_get(json_node, "out"); + if (json_out) + json_object_set_new(json_out, "signals", sigs->toJson()); + } - return new JsonResponse(session, HTTP_STATUS_OK, json_node); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_node); + } }; // Register API request diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index 271764d67..8c12906f8 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -7,14 +7,14 @@ #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { @@ -23,22 +23,22 @@ namespace api { class StatsRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Stats endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Stats endpoint does not accept any body data"); - if (node->getStats() == nullptr) - throw BadRequest("The statistics collection for this node is not enabled"); + if (node->getStats() == nullptr) + throw BadRequest( + "The statistics collection for this node is not enabled"); - return new JsonResponse(session, HTTP_STATUS_OK, node->getStats()->toJson()); - } + return new JsonResponse(session, HTTP_STATUS_OK, + node->getStats()->toJson()); + } }; // Register API requests diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index 778c15e44..27ee85ce1 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -7,40 +7,39 @@ #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -class StatsRequest : public NodeRequest { +class StatsRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Stats endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Stats endpoint does not accept any body data"); - if (node->getStats() == nullptr) - throw BadRequest("The statistics collection for this node is not enabled"); + if (node->getStats() == nullptr) + throw BadRequest( + "The statistics collection for this node is not enabled"); - node->getStats()->reset(); + node->getStats()->reset(); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index b73230639..4cf4ebb6f 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,21 +22,19 @@ namespace api { class NodesRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Nodes endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Nodes endpoint does not accept any body data"); - json_t *json_nodes = session->getSuperNode()->getNodes().toJson(); + json_t *json_nodes = session->getSuperNode()->getNodes().toJson(); - return new JsonResponse(session, HTTP_STATUS_OK, json_nodes); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_nodes); + } }; // Register API request diff --git a/lib/api/requests/path.cpp b/lib/api/requests/path.cpp index f5dc2cd74..aae5cddb4 100644 --- a/lib/api/requests/path.cpp +++ b/lib/api/requests/path.cpp @@ -10,21 +10,17 @@ using namespace villas::node::api; -void PathRequest::prepare() -{ - int ret; - uuid_t uuid; +void PathRequest::prepare() { + int ret; + uuid_t uuid; - ret = uuid_parse(matches[1].c_str(), uuid); - if (ret) - throw BadRequest("Invalid UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); + ret = uuid_parse(matches[1].c_str(), uuid); + if (ret) + throw BadRequest("Invalid UUID", "{ s: s }", "uuid", matches[1].c_str()); - auto paths = session->getSuperNode()->getPaths(); - path = paths.lookup(uuid); - if (!path) - throw BadRequest("No path found with with matching UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); + auto paths = session->getSuperNode()->getPaths(); + path = paths.lookup(uuid); + if (!path) + throw BadRequest("No path found with with matching UUID", "{ s: s }", + "uuid", matches[1].c_str()); } diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 020ab91b1..b48ff9d66 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -7,38 +7,34 @@ #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -template -class PathActionRequest : public PathRequest { +template class PathActionRequest : public PathRequest { public: - using PathRequest::PathRequest; + using PathRequest::PathRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Path endpoints do not accept any body data"); + if (body != nullptr) + throw BadRequest("Path endpoints do not accept any body data"); - (path->*func)(); - - return new Response(session, HTTP_STATUS_OK); - } + (path->*func)(); + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index 9b834d180..57478d710 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,19 +22,17 @@ namespace api { class PathInfoRequest : public PathRequest { public: - using PathRequest::PathRequest; + using PathRequest::PathRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Endpoint does not accept any body data"); - return new JsonResponse(session, HTTP_STATUS_OK, path->toJson()); - } + return new JsonResponse(session, HTTP_STATUS_OK, path->toJson()); + } }; // Register API request diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index 8043d8dad..da37b4bbb 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,21 +22,19 @@ namespace api { class PathsRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Paths endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Paths endpoint does not accept any body data"); - json_t *json_paths = session->getSuperNode()->getPaths().toJson(); + json_t *json_paths = session->getSuperNode()->getPaths().toJson(); - return new JsonResponse(session, HTTP_STATUS_OK, json_paths); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_paths); + } }; // Register API request diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 9f481c26b..f470bbda4 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -5,13 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include namespace villas { namespace node { @@ -20,103 +20,92 @@ namespace api { class RestartRequest : public Request { protected: - static - std::string configUri; + static std::string configUri; - static - void handler() - { - int ret; - const char *cfg = !configUri.empty() - ? configUri.c_str() - : nullptr; + static void handler() { + int ret; + const char *cfg = !configUri.empty() ? configUri.c_str() : nullptr; - const char *argv[] = { "villas-node", cfg, nullptr }; + const char *argv[] = {"villas-node", cfg, nullptr}; - Logger logger = logging.get("api:restart"); + Logger logger = logging.get("api:restart"); - if (cfg) - logger->info("Restarting instance: config={}", cfg); - else - logger->info("Restarting instance"); + if (cfg) + logger->info("Restarting instance: config={}", cfg); + else + logger->info("Restarting instance"); - ret = execvp("/proc/self/exe", (char **) argv); - if (ret) - throw SystemError("Failed to restart"); - } + ret = execvp("/proc/self/exe", (char **)argv); + if (ret) + throw SystemError("Failed to restart"); + } public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - int ret; - json_error_t err; + virtual Response *execute() { + int ret; + json_error_t err; - if (method != Session::Method::POST) - throw InvalidMethod(this); + if (method != Session::Method::POST) + throw InvalidMethod(this); - json_t *json_config = nullptr; + json_t *json_config = nullptr; - if (body) { - ret = json_unpack_ex(body, &err, 0, "{ s?: o }", - "config", &json_config - ); - if (ret < 0) - throw BadRequest("Failed to parse request body"); - } + if (body) { + ret = json_unpack_ex(body, &err, 0, "{ s?: o }", "config", &json_config); + if (ret < 0) + throw BadRequest("Failed to parse request body"); + } - if (json_config) { - if (json_is_string(json_config)) - configUri = json_string_value(json_config); - else if (json_is_object(json_config)) { - char configUriBuf[] = "villas-node.json.XXXXXX"; - int configFd = mkstemp(configUriBuf); + if (json_config) { + if (json_is_string(json_config)) + configUri = json_string_value(json_config); + else if (json_is_object(json_config)) { + char configUriBuf[] = "villas-node.json.XXXXXX"; + int configFd = mkstemp(configUriBuf); - FILE *configFile = fdopen(configFd, "w+"); + FILE *configFile = fdopen(configFd, "w+"); - ret = json_dumpf(json_config, configFile, JSON_INDENT(4)); - if (ret < 0) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to create temporary config file"); + ret = json_dumpf(json_config, configFile, JSON_INDENT(4)); + if (ret < 0) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to create temporary config file"); - fclose(configFile); - configUri = configUriBuf; - } - else if (json_config != nullptr) - throw BadRequest("Parameter 'config' must be either a URL (string) or a configuration (object)"); - } - else // If no config is provided via request, we will use the previous one - configUri = session->getSuperNode()->getConfigUri(); + fclose(configFile); + configUri = configUriBuf; + } else if (json_config != nullptr) + throw BadRequest("Parameter 'config' must be either a URL (string) or " + "a configuration (object)"); + } else // If no config is provided via request, we will use the previous one + configUri = session->getSuperNode()->getConfigUri(); - logger->info("Restarting to {}", configUri); + logger->info("Restarting to {}", configUri); - // Increment API restart counter - char *scnt = getenv("VILLAS_API_RESTART_COUNT"); - int cnt = scnt ? atoi(scnt) : 0; - char buf[32]; - snprintf(buf, sizeof(buf), "%d", cnt + 1); + // Increment API restart counter + char *scnt = getenv("VILLAS_API_RESTART_COUNT"); + int cnt = scnt ? atoi(scnt) : 0; + char buf[32]; + snprintf(buf, sizeof(buf), "%d", cnt + 1); - // We pass some env variables to the new process - setenv("VILLAS_API_RESTART_COUNT", buf, 1); + // We pass some env variables to the new process + setenv("VILLAS_API_RESTART_COUNT", buf, 1); - auto *json_response = json_pack("{ s: i, s: o }", - "restarts", cnt, - "config", configUri.empty() - ? json_null() - : json_string(configUri.c_str()) - ); + auto *json_response = json_pack( + "{ s: i, s: o }", "restarts", cnt, "config", + configUri.empty() ? json_null() : json_string(configUri.c_str())); - // Register exit handler - ret = atexit(handler); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to restart VILLASnode instance"); + // Register exit handler + ret = atexit(handler); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to restart VILLASnode instance"); - // Properly terminate current instance - utils::killme(SIGTERM); + // Properly terminate current instance + utils::killme(SIGTERM); - return new JsonResponse(session, HTTP_STATUS_OK, json_response); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_response); + } }; std::string RestartRequest::configUri; diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index c7869f4e4..ebfad3e29 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -7,9 +7,9 @@ #include -#include #include #include +#include namespace villas { namespace node { @@ -18,21 +18,19 @@ namespace api { class ShutdownRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Shutdown endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Shutdown endpoint does not accept any body data"); - utils::killme(SIGTERM); + utils::killme(SIGTERM); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API request diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index a1895eef4..1ccaff634 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -21,92 +21,79 @@ namespace api { class StatusRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - int ret; + virtual Response *execute() { + int ret; - if (method != Session::Method::GET) - throw InvalidMethod(this); + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Status endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Status endpoint does not accept any body data"); - auto *sn = session->getSuperNode(); + auto *sn = session->getSuperNode(); - struct utsname uts; - struct sysinfo sinfo; - char hname[128]; + struct utsname uts; + struct sysinfo sinfo; + char hname[128]; - auto now = time_now(); - auto started = sn->getStartTime(); + auto now = time_now(); + auto started = sn->getStartTime(); - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system hostname"); + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get system hostname"); - ret = uname(&uts); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get kernel information"); + ret = uname(&uts); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get kernel information"); - ret = sysinfo(&sinfo); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system information"); + ret = sysinfo(&sinfo); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get system information"); - float f_load = 1.f / (1 << SI_LOAD_SHIFT); + float f_load = 1.f / (1 << SI_LOAD_SHIFT); - tzset(); + tzset(); - json_error_t err; - json_t *json_status = json_pack_ex(&err, 0, "{ s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: f, s: f, s: { s: s, s: I, s: b }, s: { s: s, s: s, s: s, s: s, s: s, s: s}, s: { s: i, s: i, s: I, s: I, s: [ f, f, f ], s: { s: I, s, I, s: I, s: I }, s: { s: I, s: I }, s: { s: I, s: I } } }", - "state", stateToString(sn->getState()).c_str(), - "version", PROJECT_VERSION_STR, - "release", PROJECT_RELEASE, - "build_id", PROJECT_BUILD_ID, - "build_date", PROJECT_BUILD_DATE, - "hostname", hname, - "uuid", uuid::toString(sn->getUuid()).c_str(), - "time_now", time_to_double(&now), - "time_started", time_to_double(&started), - "timezone", - "name", tzname[daylight], - "offset", (json_int_t) timezone, - "dst", daylight, - "kernel", - "sysname", uts.sysname, - "nodename", uts.nodename, - "release", uts.release, - "version", uts.version, - "machine", uts.machine, - "domainname", uts.domainname, - "system", - "cores_configured", get_nprocs_conf(), - "cores", get_nprocs(), - "processes", (json_int_t) sinfo.procs, - "uptime", (json_int_t) sinfo.uptime, - "load", - f_load * sinfo.loads[0], - f_load * sinfo.loads[1], - f_load * sinfo.loads[2], - "ram", - "total", (json_int_t) (sinfo.totalram * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freeram * sinfo.mem_unit), - "shared", (json_int_t) (sinfo.sharedram * sinfo.mem_unit), - "buffer", (json_int_t) (sinfo.bufferram * sinfo.mem_unit), - "swap", - "total", (json_int_t) (sinfo.totalswap * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freeswap * sinfo.mem_unit), - "highmem", - "total", (json_int_t) (sinfo.totalhigh * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freehigh * sinfo.mem_unit) - ); - if (!json_status) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to prepare response: {}", err.text); + json_error_t err; + json_t *json_status = json_pack_ex( + &err, 0, + "{ s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: f, s: f, s: { s: s, s: " + "I, s: b }, s: { s: s, s: s, s: s, s: s, s: s, s: s}, s: { s: i, s: i, " + "s: I, s: I, s: [ f, f, f ], s: { s: I, s, I, s: I, s: I }, s: { s: I, " + "s: I }, s: { s: I, s: I } } }", + "state", stateToString(sn->getState()).c_str(), "version", + PROJECT_VERSION_STR, "release", PROJECT_RELEASE, "build_id", + PROJECT_BUILD_ID, "build_date", PROJECT_BUILD_DATE, "hostname", hname, + "uuid", uuid::toString(sn->getUuid()).c_str(), "time_now", + time_to_double(&now), "time_started", time_to_double(&started), + "timezone", "name", tzname[daylight], "offset", (json_int_t)timezone, + "dst", daylight, "kernel", "sysname", uts.sysname, "nodename", + uts.nodename, "release", uts.release, "version", uts.version, "machine", + uts.machine, "domainname", uts.domainname, "system", "cores_configured", + get_nprocs_conf(), "cores", get_nprocs(), "processes", + (json_int_t)sinfo.procs, "uptime", (json_int_t)sinfo.uptime, "load", + f_load * sinfo.loads[0], f_load * sinfo.loads[1], + f_load * sinfo.loads[2], "ram", "total", + (json_int_t)(sinfo.totalram * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freeram * sinfo.mem_unit), "shared", + (json_int_t)(sinfo.sharedram * sinfo.mem_unit), "buffer", + (json_int_t)(sinfo.bufferram * sinfo.mem_unit), "swap", "total", + (json_int_t)(sinfo.totalswap * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freeswap * sinfo.mem_unit), "highmem", "total", + (json_int_t)(sinfo.totalhigh * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freehigh * sinfo.mem_unit)); + if (!json_status) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to prepare response: {}", err.text); - return new JsonResponse(session, HTTP_STATUS_OK, json_status); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_status); + } }; // Register API request diff --git a/lib/api/requests/universal.cpp b/lib/api/requests/universal.cpp index 9ae25c389..d3083cef5 100644 --- a/lib/api/requests/universal.cpp +++ b/lib/api/requests/universal.cpp @@ -11,11 +11,11 @@ using namespace villas::node; using namespace villas::node::api; using namespace villas::node::api::universal; -void UniversalRequest::prepare() -{ - NodeRequest::prepare(); +void UniversalRequest::prepare() { + NodeRequest::prepare(); - api_node = dynamic_cast(node); - if (!api_node) - throw BadRequest("Node {} is not an univeral API node!", node->getNameShort()); + api_node = dynamic_cast(node); + if (!api_node) + throw BadRequest("Node {} is not an univeral API node!", + node->getNameShort()); } diff --git a/lib/api/requests/universal/channel.cpp b/lib/api/requests/universal/channel.cpp index 94e0851fa..b27216124 100644 --- a/lib/api/requests/universal/channel.cpp +++ b/lib/api/requests/universal/channel.cpp @@ -16,145 +16,137 @@ namespace universal { class ChannelRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - Response * executeGet(const std::string &signalName, PayloadType payload) - { - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + Response *executeGet(const std::string &signalName, PayloadType payload) { + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - pthread_mutex_lock(&api_node->write.mutex); + pthread_mutex_lock(&api_node->write.mutex); - auto *smp = api_node->write.sample; - if (!smp) { - pthread_mutex_unlock(&api_node->write.mutex); - throw Error(HTTP_STATUS_NOT_FOUND, "No data available"); - } + auto *smp = api_node->write.sample; + if (!smp) { + pthread_mutex_unlock(&api_node->write.mutex); + throw Error(HTTP_STATUS_NOT_FOUND, "No data available"); + } - auto idx = smp->signals->getIndexByName(signalName); - if (idx < 0) { - pthread_mutex_unlock(&api_node->write.mutex); - throw Error(HTTP_STATUS_NOT_FOUND, "Unknown signal id: {}", signalName); - } + auto idx = smp->signals->getIndexByName(signalName); + if (idx < 0) { + pthread_mutex_unlock(&api_node->write.mutex); + throw Error(HTTP_STATUS_NOT_FOUND, "Unknown signal id: {}", signalName); + } - auto sig = smp->signals->getByIndex(idx); - auto ch = api_node->write.channels.at(idx); + auto sig = smp->signals->getByIndex(idx); + auto ch = api_node->write.channels.at(idx); - if (payload != ch->payload) - throw BadRequest("Mismatching payload type"); + if (payload != ch->payload) + throw BadRequest("Mismatching payload type"); - auto *json_signal = json_pack("{ s: f, s: o, s: s, s: s, s: s }", - "timestamp", time_to_double(&smp->ts.origin), - "value", smp->data[idx].toJson(sig->type), - "validity", "unknown", - "source", "unknown", - "timesource", "unknown" - ); + auto *json_signal = + json_pack("{ s: f, s: o, s: s, s: s, s: s }", "timestamp", + time_to_double(&smp->ts.origin), "value", + smp->data[idx].toJson(sig->type), "validity", "unknown", + "source", "unknown", "timesource", "unknown"); - if (smp->length <= (unsigned) idx) - smp->length = idx + 1; + if (smp->length <= (unsigned)idx) + smp->length = idx + 1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA; - pthread_mutex_unlock(&api_node->write.mutex); + pthread_mutex_unlock(&api_node->write.mutex); - return new JsonResponse(session, HTTP_STATUS_OK, json_signal); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_signal); + } - Response * executePut(const std::string &signalName, PayloadType payload) - { - int ret; + Response *executePut(const std::string &signalName, PayloadType payload) { + int ret; - pthread_mutex_lock(&api_node->read.mutex); + pthread_mutex_lock(&api_node->read.mutex); - auto *smp = api_node->read.sample; - if (!smp) { - pthread_mutex_unlock(&api_node->read.mutex); - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not initialized yet"); - } + auto *smp = api_node->read.sample; + if (!smp) { + pthread_mutex_unlock(&api_node->read.mutex); + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not initialized yet"); + } - auto idx = smp->signals->getIndexByName(signalName); - if (idx < 0) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Unknown signal id: {}", signalName); - } + auto idx = smp->signals->getIndexByName(signalName); + if (idx < 0) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Unknown signal id: {}", signalName); + } - auto sig = smp->signals->getByIndex(idx); - auto ch = api_node->read.channels.at(idx); + auto sig = smp->signals->getByIndex(idx); + auto ch = api_node->read.channels.at(idx); - if (payload != ch->payload) - throw BadRequest("Mismatching payload type"); + if (payload != ch->payload) + throw BadRequest("Mismatching payload type"); - double timestamp = 0; - json_t *json_value; - const char *validity = nullptr; - const char *source = nullptr; - const char *timesource = nullptr; + double timestamp = 0; + json_t *json_value; + const char *validity = nullptr; + const char *source = nullptr; + const char *timesource = nullptr; - json_error_t err; - ret = json_unpack_ex(body, &err, 0, "{ s: F, s: o, s?: s, s?: s, s?: s }", - "timestamp", ×tamp, - "value", &json_value, - "validity", &validity, - "timesource", ×ource, - "source", &source - ); - if (ret) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Malformed body: {}", err.text); - } + json_error_t err; + ret = json_unpack_ex(body, &err, 0, "{ s: F, s: o, s?: s, s?: s, s?: s }", + "timestamp", ×tamp, "value", &json_value, + "validity", &validity, "timesource", ×ource, + "source", &source); + if (ret) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Malformed body: {}", err.text); + } - if (validity) - logger->warn("Attribute 'validity' is not supported by VILLASnode"); + if (validity) + logger->warn("Attribute 'validity' is not supported by VILLASnode"); - if (source) - logger->warn("Attribute 'source' is not supported by VILLASnode"); + if (source) + logger->warn("Attribute 'source' is not supported by VILLASnode"); - if (timesource) - logger->warn("Attribute 'timesource' is not supported by VILLASnode"); + if (timesource) + logger->warn("Attribute 'timesource' is not supported by VILLASnode"); - ret = smp->data[idx].parseJson(sig->type, json_value); - if (ret) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Malformed value"); - } + ret = smp->data[idx].parseJson(sig->type, json_value); + if (ret) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Malformed value"); + } - smp->ts.origin = time_from_double(timestamp); + smp->ts.origin = time_from_double(timestamp); - pthread_cond_signal(&api_node->read.cv); - pthread_mutex_unlock(&api_node->read.mutex); + pthread_cond_signal(&api_node->read.cv); + pthread_mutex_unlock(&api_node->read.mutex); - return new JsonResponse(session, HTTP_STATUS_OK, json_object()); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_object()); + } - virtual - Response * execute() - { - auto const &signalName = matches[2]; - auto const &subResource = matches[3]; + virtual Response *execute() { + auto const &signalName = matches[2]; + auto const &subResource = matches[3]; - PayloadType payload; - if (subResource == "event") - payload = PayloadType::EVENTS; - else if (subResource == "sample") - payload = PayloadType::EVENTS; - else - throw BadRequest("Unsupported sub-resource: {}", subResource); + PayloadType payload; + if (subResource == "event") + payload = PayloadType::EVENTS; + else if (subResource == "sample") + payload = PayloadType::EVENTS; + else + throw BadRequest("Unsupported sub-resource: {}", subResource); - switch (method) { - case Session::Method::GET: - return executeGet(signalName, payload); - case Session::Method::PUT: - return executePut(signalName, payload); - default: - throw InvalidMethod(this); - } - } + switch (method) { + case Session::Method::GET: + return executeGet(signalName, payload); + case Session::Method::PUT: + return executePut(signalName, payload); + default: + throw InvalidMethod(this); + } + } }; // Register API requests static char n[] = "universal/channel/sample"; -static char r[] = "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|event)"; +static char r[] = + "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|event)"; static char d[] = "retrieve or send samples via universal data-exchange API"; static RequestPlugin p; diff --git a/lib/api/requests/universal/channels.cpp b/lib/api/requests/universal/channels.cpp index ae7a720a1..139724822 100644 --- a/lib/api/requests/universal/channels.cpp +++ b/lib/api/requests/universal/channels.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include namespace villas { namespace node { @@ -16,37 +16,39 @@ namespace universal { class SignalsRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *json_sigs = json_array(); + auto *json_sigs = json_array(); - for (size_t i = 0; i < MIN(api_node->getOutputSignals()->size(), api_node->write.channels.size()); i++) { - auto sig = api_node->getOutputSignals()->at(i); - auto ch = api_node->write.channels.at(i); - auto *json_sig = ch->toJson(sig); + for (size_t i = 0; i < MIN(api_node->getOutputSignals()->size(), + api_node->write.channels.size()); + i++) { + auto sig = api_node->getOutputSignals()->at(i); + auto ch = api_node->write.channels.at(i); + auto *json_sig = ch->toJson(sig); - json_array_append(json_sigs, json_sig); - } + json_array_append(json_sigs, json_sig); + } - for (size_t i = 0; i < MIN(api_node->getInputSignals()->size(), api_node->read.channels.size()); i++) { - auto sig = api_node->getInputSignals()->at(i); - auto ch = api_node->read.channels.at(i); - auto *json_sig = ch->toJson(sig); + for (size_t i = 0; i < MIN(api_node->getInputSignals()->size(), + api_node->read.channels.size()); + i++) { + auto sig = api_node->getInputSignals()->at(i); + auto ch = api_node->read.channels.at(i); + auto *json_sig = ch->toJson(sig); - json_array_append(json_sigs, json_sig); - } + json_array_append(json_sigs, json_sig); + } - return new JsonResponse(session, HTTP_STATUS_OK, json_sigs); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_sigs); + } }; // Register API requests diff --git a/lib/api/requests/universal/info.cpp b/lib/api/requests/universal/info.cpp index 6ec3b58bd..9101f131a 100644 --- a/lib/api/requests/universal/info.cpp +++ b/lib/api/requests/universal/info.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include namespace villas { namespace node { @@ -17,29 +17,24 @@ namespace universal { class InfoRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *info = json_pack("{ s: s, s: s, s: { s: s, s: s, s: s } }", - "id", node->getNameShort().c_str(), - "uuid", uuid::toString(node->getUuid()).c_str(), + auto *info = json_pack("{ s: s, s: s, s: { s: s, s: s, s: s } }", "id", + node->getNameShort().c_str(), "uuid", + uuid::toString(node->getUuid()).c_str(), - "transport", - "type", "villas", - "version", PROJECT_VERSION, - "build", PROJECT_BUILD_ID - ); + "transport", "type", "villas", "version", + PROJECT_VERSION, "build", PROJECT_BUILD_ID); - return new JsonResponse(session, HTTP_STATUS_OK, info); - } + return new JsonResponse(session, HTTP_STATUS_OK, info); + } }; // Register API requests diff --git a/lib/api/requests/universal/status.cpp b/lib/api/requests/universal/status.cpp index dc4d43130..d77aae217 100644 --- a/lib/api/requests/universal/status.cpp +++ b/lib/api/requests/universal/status.cpp @@ -16,24 +16,22 @@ namespace universal { class StatusRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *json_response = json_pack("{ s: s }", - // TODO: Add connectivity check or heuristic here. - "connected", "unknown" - ); + auto *json_response = + json_pack("{ s: s }", + // TODO: Add connectivity check or heuristic here. + "connected", "unknown"); - return new JsonResponse(session, HTTP_STATUS_OK, json_response); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_response); + } }; // Register API requests diff --git a/lib/api/response.cpp b/lib/api/response.cpp index 8048a0890..62914191e 100644 --- a/lib/api/response.cpp +++ b/lib/api/response.cpp @@ -5,79 +5,68 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include using namespace villas::node::api; -Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) : - session(s), - logger(logging.get("api:response")), - buffer(b), - code(c), - contentType(ct), - headers{ - { "Server:", HTTP_USER_AGENT }, - { "Access-Control-Allow-Origin:", "*" }, - { "Access-Control-Allow-Methods:", "GET, POST, OPTIONS" }, - { "Access-Control-Allow-Headers:", "Content-Type" }, - { "Access-Control-Max-Age:", "86400" } - } -{ } +Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) + : session(s), logger(logging.get("api:response")), buffer(b), code(c), + contentType(ct), + headers{{"Server:", HTTP_USER_AGENT}, + {"Access-Control-Allow-Origin:", "*"}, + {"Access-Control-Allow-Methods:", "GET, POST, OPTIONS"}, + {"Access-Control-Allow-Headers:", "Content-Type"}, + {"Access-Control-Max-Age:", "86400"}} {} -int Response::writeBody(struct lws *wsi) -{ - int ret; +int Response::writeBody(struct lws *wsi) { + int ret; - ret = lws_write(wsi, (unsigned char *) buffer.data(), buffer.size(), LWS_WRITE_HTTP_FINAL); - if (ret < 0) - return -1; + ret = lws_write(wsi, (unsigned char *)buffer.data(), buffer.size(), + LWS_WRITE_HTTP_FINAL); + if (ret < 0) + return -1; - return 1; + return 1; } -int Response::writeHeaders(struct lws *wsi) -{ - int ret; - uint8_t headerBuffer[2048], *p = headerBuffer, *end = &headerBuffer[sizeof(headerBuffer) - 1]; +int Response::writeHeaders(struct lws *wsi) { + int ret; + uint8_t headerBuffer[2048], *p = headerBuffer, + *end = &headerBuffer[sizeof(headerBuffer) - 1]; - // We need to encode the buffer here for getting the real content length of the response - encodeBody(); + // We need to encode the buffer here for getting the real content length of the response + encodeBody(); - ret = lws_add_http_common_headers(wsi, code, contentType.c_str(), - buffer.size(), - &p, end); - if (ret) - return 1; + ret = lws_add_http_common_headers(wsi, code, contentType.c_str(), + buffer.size(), &p, end); + if (ret) + return 1; - for (auto &hdr : headers) { - ret = lws_add_http_header_by_name (wsi, - reinterpret_cast(hdr.first.c_str()), - reinterpret_cast(hdr.second.c_str()), - hdr.second.size(), &p, end); - if (ret) - return -1; - } + for (auto &hdr : headers) { + ret = lws_add_http_header_by_name( + wsi, reinterpret_cast(hdr.first.c_str()), + reinterpret_cast(hdr.second.c_str()), + hdr.second.size(), &p, end); + if (ret) + return -1; + } - ret = lws_finalize_write_http_header(wsi, headerBuffer, &p, end); - if (ret) - return 1; + ret = lws_finalize_write_http_header(wsi, headerBuffer, &p, end); + if (ret) + return 1; - // Do we have a body to send? - if (buffer.size() > 0) - lws_callback_on_writable(wsi); + // Do we have a body to send? + if (buffer.size() > 0) + lws_callback_on_writable(wsi); - return 0; + return 0; } -JsonResponse::~JsonResponse() -{ - if (response) - json_decref(response); +JsonResponse::~JsonResponse() { + if (response) + json_decref(response); } -void JsonResponse::encodeBody() -{ - buffer.encode(response, JSON_INDENT(4)); -} +void JsonResponse::encodeBody() { buffer.encode(response, JSON_INDENT(4)); } diff --git a/lib/api/session.cpp b/lib/api/session.cpp index a734f015d..123599237 100644 --- a/lib/api/session.cpp +++ b/lib/api/session.cpp @@ -9,281 +9,271 @@ #include -#include #include +#include -#include #include #include +#include using namespace villas; using namespace villas::node; using namespace villas::node::api; -Session::Session(lws *w) : - version(Version::VERSION_2), - wsi(w), - logger(logging.get("api:session")) -{ - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); +Session::Session(lws *w) + : version(Version::VERSION_2), wsi(w), logger(logging.get("api:session")) { + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - web = static_cast(user_ctx); - api = web->getApi(); + web = static_cast(user_ctx); + api = web->getApi(); - if (!api) - throw RuntimeError("API is disabled"); + if (!api) + throw RuntimeError("API is disabled"); - api->sessions.push_back(this); + api->sessions.push_back(this); - logger->debug("Initiated API session: {}", getName()); + logger->debug("Initiated API session: {}", getName()); - state = Session::State::ESTABLISHED; + state = Session::State::ESTABLISHED; } -Session::~Session() -{ - api->sessions.remove(this); +Session::~Session() { + api->sessions.remove(this); - logger->debug("Destroyed API session: {}", getName()); + logger->debug("Destroyed API session: {}", getName()); } -void Session::execute() -{ - logger->debug("Running API request: {}", request->toString()); +void Session::execute() { + logger->debug("Running API request: {}", request->toString()); - try { - response = std::unique_ptr(request->execute()); + try { + response = std::unique_ptr(request->execute()); - logger->debug("Completed API request: {}", request->toString()); - } catch (const Error &e) { - response = std::make_unique(this, e); + logger->debug("Completed API request: {}", request->toString()); + } catch (const Error &e) { + response = std::make_unique(this, e); - logger->warn("API request failed: {}, code={}: {}", request->toString(), e.code, e.what()); - } catch (const RuntimeError &e) { - response = std::make_unique(this, e); + logger->warn("API request failed: {}, code={}: {}", request->toString(), + e.code, e.what()); + } catch (const RuntimeError &e) { + response = std::make_unique(this, e); - logger->warn("API request failed: {}: {}", request->toString(), e.what()); - } + logger->warn("API request failed: {}: {}", request->toString(), e.what()); + } - logger->debug("Ran pending API requests. Triggering on_writeable callback: wsi={}", (void *) wsi); + logger->debug( + "Ran pending API requests. Triggering on_writeable callback: wsi={}", + (void *)wsi); - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } -std::string Session::getName() const -{ - std::stringstream ss; +std::string Session::getName() const { + std::stringstream ss; - ss << "version=" << version; + ss << "version=" << version; - if (wsi) { - char name[128]; - char ip[128]; + if (wsi) { + char name[128]; + char ip[128]; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, sizeof(ip)); + lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, + sizeof(ip)); - ss << ", remote.name=" << name << ", remote.ip=" << ip; - } + ss << ", remote.name=" << name << ", remote.ip=" << ip; + } - return ss.str(); + return ss.str(); } -void Session::shutdown() -{ - state = State::SHUTDOWN; +void Session::shutdown() { + state = State::SHUTDOWN; - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } -void Session::open(void *in, size_t len) -{ - int ret; - char buf[32]; +void Session::open(void *in, size_t len) { + int ret; + char buf[32]; - auto uri = reinterpret_cast(in); + auto uri = reinterpret_cast(in); - try { - unsigned int len; - auto method = getRequestMethod(); - if (method == Method::UNKNOWN) - throw RuntimeError("Invalid request method"); + try { + unsigned int len; + auto method = getRequestMethod(); + if (method == Method::UNKNOWN) + throw RuntimeError("Invalid request method"); - ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH); - if (ret < 0) - throw RuntimeError("Failed to get content length"); + ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH); + if (ret < 0) + throw RuntimeError("Failed to get content length"); - try { - len = std::stoull(buf); - } catch (const std::invalid_argument &) { - len = 0; - } + try { + len = std::stoull(buf); + } catch (const std::invalid_argument &) { + len = 0; + } - request = std::unique_ptr(RequestFactory::create(this, uri, method, len)); + request = std::unique_ptr( + RequestFactory::create(this, uri, method, len)); - /* This is an OPTIONS request. + /* This is an OPTIONS request. * * We immediatly send headers and close the connection * without waiting for a POST body */ - if (method == Method::OPTIONS) - lws_callback_on_writable(wsi); - /* This request has no body. + if (method == Method::OPTIONS) + lws_callback_on_writable(wsi); + /* This request has no body. * We can reply immediatly */ - else if (len == 0) - api->pending.push(this); - else { - // This request has a HTTP body. We wait for more data to arrive - } - } catch (const Error &e) { - response = std::make_unique(this, e); - lws_callback_on_writable(wsi); - } catch (const RuntimeError &e) { - response = std::make_unique(this, e); - lws_callback_on_writable(wsi); - } + else if (len == 0) + api->pending.push(this); + else { + // This request has a HTTP body. We wait for more data to arrive + } + } catch (const Error &e) { + response = std::make_unique(this, e); + lws_callback_on_writable(wsi); + } catch (const RuntimeError &e) { + response = std::make_unique(this, e); + lws_callback_on_writable(wsi); + } } -void Session::body(void *in, size_t len) -{ - request->buffer.append((const char *) in, len); +void Session::body(void *in, size_t len) { + request->buffer.append((const char *)in, len); } -void Session::bodyComplete() -{ - try { - request->decode(); +void Session::bodyComplete() { + try { + request->decode(); - api->pending.push(this); - } catch (const Error &e) { - response = std::make_unique(this, e); + api->pending.push(this); + } catch (const Error &e) { + response = std::make_unique(this, e); - logger->warn("Failed to decode API request: {}", e.what()); - } + logger->warn("Failed to decode API request: {}", e.what()); + } } -int Session::writeable() -{ - if (!response) - return 0; +int Session::writeable() { + if (!response) + return 0; - if (!headersSent) { - response->writeHeaders(wsi); + if (!headersSent) { + response->writeHeaders(wsi); - // Now wait, until we can send the body - headersSent = true; + // Now wait, until we can send the body + headersSent = true; - return 0; - } - else { - if (response) - return response->writeBody(wsi); - else - return 0; - } + return 0; + } else { + if (response) + return response->writeBody(wsi); + else + return 0; + } } -int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret; - Session *s = reinterpret_cast(user); +int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret; + Session *s = reinterpret_cast(user); - switch (reason) { - case LWS_CALLBACK_HTTP_BIND_PROTOCOL: - try { - new (s) Session(wsi); - } catch (const RuntimeError &e) { - return -1; - } + switch (reason) { + case LWS_CALLBACK_HTTP_BIND_PROTOCOL: + try { + new (s) Session(wsi); + } catch (const RuntimeError &e) { + return -1; + } - break; + break; - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (s == nullptr) - return -1; + case LWS_CALLBACK_HTTP_DROP_PROTOCOL: + if (s == nullptr) + return -1; - s->~Session(); + s->~Session(); - break; + break; - case LWS_CALLBACK_HTTP: - s->open(in, len); + case LWS_CALLBACK_HTTP: + s->open(in, len); - break; + break; - case LWS_CALLBACK_HTTP_BODY: - s->body(in, len); + case LWS_CALLBACK_HTTP_BODY: + s->body(in, len); - break; + break; - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - s->bodyComplete(); + case LWS_CALLBACK_HTTP_BODY_COMPLETION: + s->bodyComplete(); - break; + break; - case LWS_CALLBACK_HTTP_WRITEABLE: - ret = s->writeable(); + case LWS_CALLBACK_HTTP_WRITEABLE: + ret = s->writeable(); - /* + /* * HTTP/1.0 no keepalive: close network connection * HTTP/1.1 or HTTP1.0 + KA: wait / process next transaction * HTTP/2: stream ended, parent connection remains up */ - if (ret) { - if (lws_http_transaction_completed(wsi)) - return -1; - } - else - lws_callback_on_writable(wsi); + if (ret) { + if (lws_http_transaction_completed(wsi)) + return -1; + } else + lws_callback_on_writable(wsi); - break; + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -Session::Method Session::getRequestMethod() const -{ - if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) - return Method::GET; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) - return Method::POST; +Session::Method Session::getRequestMethod() const { + if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) + return Method::GET; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) + return Method::POST; #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) - return Method::PUT; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) - return Method::PATCH; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) - return Method::OPTIONS; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) + return Method::PUT; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) + return Method::PATCH; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) + return Method::OPTIONS; #endif - else - return Method::UNKNOWN; + else + return Method::UNKNOWN; } -std::string Session::methodToString(Method method) -{ - switch (method) { - case Method::POST: - return "POST"; +std::string Session::methodToString(Method method) { + switch (method) { + case Method::POST: + return "POST"; - case Method::GET: - return "GET"; + case Method::GET: + return "GET"; - case Method::DELETE: - return "DELETE"; + case Method::DELETE: + return "DELETE"; - case Method::PUT: - return "PUT"; + case Method::PUT: + return "PUT"; - case Method::PATCH: - return "GPATCHET"; + case Method::PATCH: + return "GPATCHET"; - case Method::OPTIONS: - return "OPTIONS"; + case Method::OPTIONS: + return "OPTIONS"; - default: - return "UNKNOWN"; - } + default: + return "UNKNOWN"; + } } diff --git a/lib/api/universal.cpp b/lib/api/universal.cpp index 1788f09b2..bae23be14 100644 --- a/lib/api/universal.cpp +++ b/lib/api/universal.cpp @@ -5,140 +5,137 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include #include +#include using namespace villas::node::api::universal; -void ChannelList::parse(json_t *json, bool readable, bool writable) -{ - if (!json_is_array(json)) - throw ConfigError(json, "node-config-node-api-signals", "Signal list of API node must be an array"); +void ChannelList::parse(json_t *json, bool readable, bool writable) { + if (!json_is_array(json)) + throw ConfigError(json, "node-config-node-api-signals", + "Signal list of API node must be an array"); - clear(); + clear(); - size_t i; - json_t *json_channel; - json_array_foreach(json, i, json_channel) { - auto channel = std::make_shared(); + size_t i; + json_t *json_channel; + json_array_foreach(json, i, json_channel) { + auto channel = std::make_shared(); - channel->parse(json_channel); - channel->readable = readable; - channel->writable = writable; + channel->parse(json_channel); + channel->readable = readable; + channel->writable = writable; - push_back(channel); - } + push_back(channel); + } } -void Channel::parse(json_t *json) -{ - const char *desc = nullptr; - const char *pl = nullptr; - json_t *json_range = nullptr; +void Channel::parse(json_t *json) { + const char *desc = nullptr; + const char *pl = nullptr; + json_t *json_range = nullptr; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F }", - "description", &desc, - "payload", &pl, - "range", &json_range, - "rate", &rate - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api-signals"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F }", + "description", &desc, "payload", &pl, "range", + &json_range, "rate", &rate); + if (ret) + throw ConfigError(json, err, "node-config-node-api-signals"); - if (desc) - description = desc; + if (desc) + description = desc; - if (pl) { - if (!strcmp(pl, "samples")) - payload = PayloadType::SAMPLES; - else if (!strcmp(pl, "events")) - payload = PayloadType::EVENTS; - else - throw ConfigError(json, "node-config-node-api-signals-payload", "Invalid payload type: {}", pl); - } + if (pl) { + if (!strcmp(pl, "samples")) + payload = PayloadType::SAMPLES; + else if (!strcmp(pl, "events")) + payload = PayloadType::EVENTS; + else + throw ConfigError(json, "node-config-node-api-signals-payload", + "Invalid payload type: {}", pl); + } - range_min = std::numeric_limits::quiet_NaN(); - range_max = std::numeric_limits::quiet_NaN(); - if (json_range) { - if (json_is_array(json_range)) { - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", - "min", &range_min, - "max", &range_max - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api-signals-range", "Failed to parse channel range"); - } else if (json_is_object(json_range)) { - size_t i; - json_t *json_option; + range_min = std::numeric_limits::quiet_NaN(); + range_max = std::numeric_limits::quiet_NaN(); + if (json_range) { + if (json_is_array(json_range)) { + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", "min", &range_min, + "max", &range_max); + if (ret) + throw ConfigError(json, err, "node-config-node-api-signals-range", + "Failed to parse channel range"); + } else if (json_is_object(json_range)) { + size_t i; + json_t *json_option; - range_options.clear(); + range_options.clear(); - json_array_foreach(json_range, i, json_option) { - if (!json_is_string(json_option)) - throw ConfigError(json, err, "node-config-node-api-signals-range", "Channel range options must be strings"); + json_array_foreach(json_range, i, json_option) { + if (!json_is_string(json_option)) + throw ConfigError(json, err, "node-config-node-api-signals-range", + "Channel range options must be strings"); - auto *option = json_string_value(json_option); - range_options.push_back(option); - } - } else - throw ConfigError(json, "node-config-node-api-signals-range", "Channel range must be an array or object"); - } + auto *option = json_string_value(json_option); + range_options.push_back(option); + } + } else + throw ConfigError(json, "node-config-node-api-signals-range", + "Channel range must be an array or object"); + } } -json_t * Channel::toJson(Signal::Ptr sig) const -{ - json_error_t err; - json_t *json_ch = json_pack_ex(&err, 0, "{ s: s, s: s, s: b, s: b }", - "id", sig->name.c_str(), - "datatype", signalTypeToString(sig->type).c_str(), - "readable", (int) readable, - "writable", (int) writable - ); +json_t *Channel::toJson(Signal::Ptr sig) const { + json_error_t err; + json_t *json_ch = json_pack_ex( + &err, 0, "{ s: s, s: s, s: b, s: b }", "id", sig->name.c_str(), + "datatype", signalTypeToString(sig->type).c_str(), "readable", + (int)readable, "writable", (int)writable); - if (!description.empty()) - json_object_set(json_ch, "description", json_string(description.c_str())); + if (!description.empty()) + json_object_set(json_ch, "description", json_string(description.c_str())); - if (!sig->unit.empty()) - json_object_set(json_ch, "unit", json_string(sig->unit.c_str())); + if (!sig->unit.empty()) + json_object_set(json_ch, "unit", json_string(sig->unit.c_str())); - if (rate > 0) - json_object_set(json_ch, "rate", json_real(rate)); + if (rate > 0) + json_object_set(json_ch, "rate", json_real(rate)); - switch (payload) { - case PayloadType::EVENTS: - json_object_set(json_ch, "payload", json_string("events")); - break; + switch (payload) { + case PayloadType::EVENTS: + json_object_set(json_ch, "payload", json_string("events")); + break; - case PayloadType::SAMPLES: - json_object_set(json_ch, "payload", json_string("samples")); - break; + case PayloadType::SAMPLES: + json_object_set(json_ch, "payload", json_string("samples")); + break; - default: {} - } + default: { + } + } - switch (sig->type) { - case SignalType::FLOAT: { - if (std::isnan(range_min) && std::isnan(range_max)) - break; + switch (sig->type) { + case SignalType::FLOAT: { + if (std::isnan(range_min) && std::isnan(range_max)) + break; - json_t *json_range = json_object(); + json_t *json_range = json_object(); - if (!std::isnan(range_min)) - json_object_set(json_range, "min", json_real(range_min)); + if (!std::isnan(range_min)) + json_object_set(json_range, "min", json_real(range_min)); - if (!std::isnan(range_max)) - json_object_set(json_range, "max", json_real(range_max)); + if (!std::isnan(range_max)) + json_object_set(json_range, "max", json_real(range_max)); - json_object_set(json_ch, "range", json_range); - break; - } + json_object_set(json_ch, "range", json_range); + break; + } - default: {} - } + default: { + } + } - return json_ch; + return json_ch; } diff --git a/lib/capabilities.cpp b/lib/capabilities.cpp index 2c8f9cbb8..2296c2438 100644 --- a/lib/capabilities.cpp +++ b/lib/capabilities.cpp @@ -7,52 +7,48 @@ #include -#include -#include -#include #include +#include +#include +#include using namespace villas; using namespace villas::node; -json_t * villas::node::getCapabilities() -{ - json_t *json_hooks = json_array(); - json_t *json_apis = json_array(); - json_t *json_nodes = json_array(); - json_t *json_formats = json_array(); - json_t *json_name; +json_t *villas::node::getCapabilities() { + json_t *json_hooks = json_array(); + json_t *json_apis = json_array(); + json_t *json_nodes = json_array(); + json_t *json_formats = json_array(); + json_t *json_name; - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_apis, json_name); - } + json_array_append_new(json_apis, json_name); + } - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_hooks, json_name); - } + json_array_append_new(json_hooks, json_name); + } - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_formats, json_name); - } + json_array_append_new(json_formats, json_name); + } - for (auto f : plugin::registry->lookup()) { - if (f->isInternal()) - continue; + for (auto f : plugin::registry->lookup()) { + if (f->isInternal()) + continue; - json_name = json_string(f->getName().c_str()); + json_name = json_string(f->getName().c_str()); - json_array_append_new(json_nodes, json_name); - } + json_array_append_new(json_nodes, json_name); + } - return json_pack("{ s: o, s: o, s: o, s: o }", - "hooks", json_hooks, - "nodes", json_nodes, - "apis", json_apis, - "formats", json_formats); + return json_pack("{ s: o, s: o, s: o, s: o }", "hooks", json_hooks, "nodes", + json_nodes, "apis", json_apis, "formats", json_formats); } diff --git a/lib/config.cpp b/lib/config.cpp index 221cfdebd..66acc5205 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -5,370 +5,355 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include -#include #include -#include #include +#include +#include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include #ifdef WITH_CONFIG - #include +#include #endif using namespace villas; using namespace villas::node; -Config::Config() : - logger(logging.get("config")), - root(nullptr) -{ } +Config::Config() : logger(logging.get("config")), root(nullptr) {} -Config::Config(const std::string &u) : - Config() -{ - root = load(u); +Config::Config(const std::string &u) : Config() { root = load(u); } + +Config::~Config() { json_decref(root); } + +json_t *Config::load(std::FILE *f, bool resolveInc, bool resolveEnvVars) { + json_t *root = decode(f); + + if (resolveInc) { + json_t *root_old = root; + root = expandIncludes(root); + json_decref(root_old); + } + + if (resolveEnvVars) { + json_t *root_old = root; + root = expandEnvVars(root); + json_decref(root_old); + } + + return root; } -Config::~Config() -{ - json_decref(root); +json_t *Config::load(const std::string &u, bool resolveInc, + bool resolveEnvVars) { + FILE *f; + + if (u == "-") + f = loadFromStdio(); + else + f = loadFromLocalFile(u); + + json_t *root = load(f, resolveInc, resolveEnvVars); + + fclose(f); + + return root; } -json_t * Config::load(std::FILE *f, bool resolveInc, bool resolveEnvVars) -{ - json_t *root = decode(f); +FILE *Config::loadFromStdio() { + logger->info("Reading configuration from standard input"); - if (resolveInc) { - json_t *root_old = root; - root = expandIncludes(root); - json_decref(root_old); - } - - if (resolveEnvVars) { - json_t *root_old = root; - root = expandEnvVars(root); - json_decref(root_old); - } - - return root; + return stdin; } -json_t * Config::load(const std::string &u, bool resolveInc, bool resolveEnvVars) -{ - FILE *f; +FILE *Config::loadFromLocalFile(const std::string &u) { + logger->info("Reading configuration from local file: {}", u); - if (u == "-") - f = loadFromStdio(); - else - f = loadFromLocalFile(u); + FILE *f = fopen(u.c_str(), "r"); + if (!f) + throw RuntimeError("Failed to open configuration from: {}", u); - json_t *root = load(f, resolveInc, resolveEnvVars); - - fclose(f); - - return root; + return f; } -FILE * Config::loadFromStdio() -{ - logger->info("Reading configuration from standard input"); +json_t *Config::decode(FILE *f) { + json_error_t err; - return stdin; -} + // Update list of include directories + auto incDirs = getIncludeDirectories(f); + includeDirectories.insert(includeDirectories.end(), incDirs.begin(), + incDirs.end()); -FILE * Config::loadFromLocalFile(const std::string &u) -{ - logger->info("Reading configuration from local file: {}", u); - - FILE *f = fopen(u.c_str(), "r"); - if (!f) - throw RuntimeError("Failed to open configuration from: {}", u); - - return f; -} - -json_t * Config::decode(FILE *f) -{ - json_error_t err; - - // Update list of include directories - auto incDirs = getIncludeDirectories(f); - includeDirectories.insert(includeDirectories.end(), incDirs.begin(), incDirs.end()); - - json_t *root = json_loadf(f, 0, &err); - if (root == nullptr) { + json_t *root = json_loadf(f, 0, &err); + if (root == nullptr) { #ifdef WITH_CONFIG - // We try again to parse the config in the legacy format - root = libconfigDecode(f); + // We try again to parse the config in the legacy format + root = libconfigDecode(f); #else - throw JanssonParseError(err); + throw JanssonParseError(err); #endif // WITH_CONFIG - } + } - return root; + return root; } -std::list Config::getIncludeDirectories(FILE *f) const -{ - int ret, fd; - char buf[PATH_MAX]; - char *dir; +std::list Config::getIncludeDirectories(FILE *f) const { + int ret, fd; + char buf[PATH_MAX]; + char *dir; - std::list dirs; + std::list dirs; - // Adding directory of base configuration file - fd = fileno(f); - if (fd < 0) - throw SystemError("Failed to get file descriptor"); + // Adding directory of base configuration file + fd = fileno(f); + if (fd < 0) + throw SystemError("Failed to get file descriptor"); - auto path = fmt::format("/proc/self/fd/{}", fd); + auto path = fmt::format("/proc/self/fd/{}", fd); - ret = readlink(path.c_str(), buf, sizeof(buf)); - if (ret > 0) { - buf[ret] = 0; - if (isLocalFile(buf)) { - dir = dirname(buf); - dirs.push_back(dir); - } - } + ret = readlink(path.c_str(), buf, sizeof(buf)); + if (ret > 0) { + buf[ret] = 0; + if (isLocalFile(buf)) { + dir = dirname(buf); + dirs.push_back(dir); + } + } - // Adding current working directory - dir = getcwd(buf, sizeof(buf)); - if (dir != nullptr) - dirs.push_back(dir); + // Adding current working directory + dir = getcwd(buf, sizeof(buf)); + if (dir != nullptr) + dirs.push_back(dir); - return dirs; + return dirs; } -std::list Config::resolveIncludes(const std::string &n) -{ - glob_t gb; - int ret, flags = 0; +std::list Config::resolveIncludes(const std::string &n) { + glob_t gb; + int ret, flags = 0; - memset(&gb, 0, sizeof(gb)); + memset(&gb, 0, sizeof(gb)); - auto name = n; - resolveEnvVars(name); + auto name = n; + resolveEnvVars(name); - if (name.size() >= 1 && name[0] == '/') { // absolute path - ret = glob(name.c_str(), flags, nullptr, &gb); - if (ret && ret != GLOB_NOMATCH) - gb.gl_pathc = 0; - } - else { // relative path - for (auto &dir : includeDirectories) { - auto pattern = fmt::format("{}/{}", dir, name.c_str()); + if (name.size() >= 1 && name[0] == '/') { // absolute path + ret = glob(name.c_str(), flags, nullptr, &gb); + if (ret && ret != GLOB_NOMATCH) + gb.gl_pathc = 0; + } else { // relative path + for (auto &dir : includeDirectories) { + auto pattern = fmt::format("{}/{}", dir, name.c_str()); - ret = glob(pattern.c_str(), flags, nullptr, &gb); - if (ret && ret != GLOB_NOMATCH) { - gb.gl_pathc = 0; + ret = glob(pattern.c_str(), flags, nullptr, &gb); + if (ret && ret != GLOB_NOMATCH) { + gb.gl_pathc = 0; - goto out; - } + goto out; + } - flags |= GLOB_APPEND; - } - } + flags |= GLOB_APPEND; + } + } -out: std::list files; - for (unsigned i = 0; i < gb.gl_pathc; i++) - files.push_back(gb.gl_pathv[i]); +out: + std::list files; + for (unsigned i = 0; i < gb.gl_pathc; i++) + files.push_back(gb.gl_pathv[i]); - globfree(&gb); + globfree(&gb); - return files; + return files; } -void Config::resolveEnvVars(std::string &text) -{ - static - const std::regex env_re{R"--(\$\{([^}]+)\})--"}; +void Config::resolveEnvVars(std::string &text) { + static const std::regex env_re{R"--(\$\{([^}]+)\})--"}; - std::smatch match; - while (std::regex_search(text, match, env_re)) { - auto const from = match[0]; - auto const var_name = match[1].str().c_str(); - char *var_value = std::getenv(var_name); - if (!var_value) - throw RuntimeError("Unresolved environment variable: {}", var_name); + std::smatch match; + while (std::regex_search(text, match, env_re)) { + auto const from = match[0]; + auto const var_name = match[1].str().c_str(); + char *var_value = std::getenv(var_name); + if (!var_value) + throw RuntimeError("Unresolved environment variable: {}", var_name); - text.replace(from.first - text.begin(), from.second - from.first, var_value); + text.replace(from.first - text.begin(), from.second - from.first, + var_value); - logger->debug("Replace env var {} in \"{}\" with value \"{}\"", - var_name, text, var_value); - } + logger->debug("Replace env var {} in \"{}\" with value \"{}\"", var_name, + text, var_value); + } } #ifdef WITH_CONFIG -#if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) -const char ** Config::includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error) -{ - void *ctx = config_get_hook(cfg); +#if (LIBCONFIG_VER_MAJOR > 1) || \ + ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) +const char **Config::includeFuncStub(config_t *cfg, const char *include_dir, + const char *path, const char **error) { + void *ctx = config_get_hook(cfg); - return reinterpret_cast(ctx)->includeFunc(cfg, include_dir, path, error); + return reinterpret_cast(ctx)->includeFunc(cfg, include_dir, path, + error); } -const char ** Config::includeFunc(config_t *cfg, const char *include_dir, const char *path, const char **error) -{ - auto paths = resolveIncludes(path); +const char **Config::includeFunc(config_t *cfg, const char *include_dir, + const char *path, const char **error) { + auto paths = resolveIncludes(path); - unsigned i = 0; - auto files = (const char **) malloc(sizeof(char **) * (paths.size() + 1)); + unsigned i = 0; + auto files = (const char **)malloc(sizeof(char **) * (paths.size() + 1)); - for (auto &path : paths) - files[i++] = strdup(path.c_str()); + for (auto &path : paths) + files[i++] = strdup(path.c_str()); - files[i] = NULL; + files[i] = NULL; - return files; + return files; } #endif -json_t * Config::libconfigDecode(FILE *f) -{ - int ret; +json_t *Config::libconfigDecode(FILE *f) { + int ret; - config_t cfg; - config_setting_t *cfg_root; - config_init(&cfg); - config_set_auto_convert(&cfg, 1); + config_t cfg; + config_setting_t *cfg_root; + config_init(&cfg); + config_set_auto_convert(&cfg, 1); - // Setup libconfig include path -#if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) - config_set_hook(&cfg, this); + // Setup libconfig include path +#if (LIBCONFIG_VER_MAJOR > 1) || \ + ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) + config_set_hook(&cfg, this); - config_set_include_func(&cfg, includeFuncStub); + config_set_include_func(&cfg, includeFuncStub); #else - if (includeDirectories.size() > 0) { - logger->info("Setting include dir to: {}", includeDirectories.front()); + if (includeDirectories.size() > 0) { + logger->info("Setting include dir to: {}", includeDirectories.front()); - config_set_include_dir(&cfg, includeDirectories.front().c_str()); + config_set_include_dir(&cfg, includeDirectories.front().c_str()); - if (includeDirectories.size() > 1) { - logger->warn("Ignoring all but the first include directories for libconfig"); - logger->warn(" libconfig does not support more than a single include dir!"); - } - } + if (includeDirectories.size() > 1) { + logger->warn( + "Ignoring all but the first include directories for libconfig"); + logger->warn( + " libconfig does not support more than a single include dir!"); + } + } #endif - // Rewind before re-reading - rewind(f); + // Rewind before re-reading + rewind(f); - ret = config_read(&cfg, f); - if (ret != CONFIG_TRUE) - throw LibconfigParseError(&cfg); + ret = config_read(&cfg, f); + if (ret != CONFIG_TRUE) + throw LibconfigParseError(&cfg); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json_t *root = config_to_json(cfg_root); - if (!root) - throw RuntimeError("Failed to convert JSON to configuration file"); + json_t *root = config_to_json(cfg_root); + if (!root) + throw RuntimeError("Failed to convert JSON to configuration file"); - config_destroy(&cfg); + config_destroy(&cfg); - return root; + return root; } #endif // WITH_CONFIG -json_t * Config::walkStrings(json_t *root, str_walk_fcn_t cb) -{ - const char *key; - size_t index; - json_t *val, *new_val, *new_root; +json_t *Config::walkStrings(json_t *root, str_walk_fcn_t cb) { + const char *key; + size_t index; + json_t *val, *new_val, *new_root; - switch (json_typeof(root)) { - case JSON_STRING: - return cb(root); + switch (json_typeof(root)) { + case JSON_STRING: + return cb(root); - case JSON_OBJECT: - new_root = json_object(); + case JSON_OBJECT: + new_root = json_object(); - json_object_foreach(root, key, val) { - new_val = walkStrings(val, cb); + json_object_foreach(root, key, val) { + new_val = walkStrings(val, cb); - json_object_set_new(new_root, key, new_val); - } + json_object_set_new(new_root, key, new_val); + } - return new_root; + return new_root; - case JSON_ARRAY: - new_root = json_array(); + case JSON_ARRAY: + new_root = json_array(); - json_array_foreach(root, index, val) { - new_val = walkStrings(val, cb); + json_array_foreach(root, index, val) { + new_val = walkStrings(val, cb); - json_array_append_new(new_root, new_val); - } + json_array_append_new(new_root, new_val); + } - return new_root; + return new_root; - default: - return json_incref(root); - }; + default: + return json_incref(root); + }; } -json_t * Config::expandEnvVars(json_t *in) -{ - return walkStrings(in, [this](json_t *str) -> json_t * { - std::string text = json_string_value(str); +json_t *Config::expandEnvVars(json_t *in) { + return walkStrings(in, [this](json_t *str) -> json_t * { + std::string text = json_string_value(str); - resolveEnvVars(text); + resolveEnvVars(text); - return json_string(text.c_str()); - }); + return json_string(text.c_str()); + }); } -json_t * Config::expandIncludes(json_t *in) -{ - return walkStrings(in, [this](json_t *str) -> json_t * { - int ret; - std::string text = json_string_value(str); - static - const std::string kw = "@include "; +json_t *Config::expandIncludes(json_t *in) { + return walkStrings(in, [this](json_t *str) -> json_t * { + int ret; + std::string text = json_string_value(str); + static const std::string kw = "@include "; - if (text.find(kw) != 0) - return json_incref(str); - else { - std::string pattern = text.substr(kw.size()); + if (text.find(kw) != 0) + return json_incref(str); + else { + std::string pattern = text.substr(kw.size()); - resolveEnvVars(pattern); + resolveEnvVars(pattern); - json_t *incl = nullptr; + json_t *incl = nullptr; - for (auto &path : resolveIncludes(pattern)) { - json_t *other = load(path); - if (!other) - throw ConfigError(str, "Failed to include config file from {}", path); + for (auto &path : resolveIncludes(pattern)) { + json_t *other = load(path); + if (!other) + throw ConfigError(str, "Failed to include config file from {}", path); - if (!incl) - incl = other; - else if (json_is_object(incl) && json_is_object(other)) { - ret = json_object_update_recursive(incl, other); - if (ret) - throw ConfigError(str, "Can not mix object and array-typed include files"); - } - else if (json_is_array(incl) && json_is_array(other)) { - ret = json_array_extend(incl, other); - if (ret) - throw ConfigError(str, "Can not mix object and array-typed include files"); - } + if (!incl) + incl = other; + else if (json_is_object(incl) && json_is_object(other)) { + ret = json_object_update_recursive(incl, other); + if (ret) + throw ConfigError( + str, "Can not mix object and array-typed include files"); + } else if (json_is_array(incl) && json_is_array(other)) { + ret = json_array_extend(incl, other); + if (ret) + throw ConfigError( + str, "Can not mix object and array-typed include files"); + } - logger->debug("Included config from: {}", path); - } + logger->debug("Included config from: {}", path); + } - return incl; - } - }); + return incl; + } + }); } diff --git a/lib/config_helper.cpp b/lib/config_helper.cpp index 5e0747518..7e4da1b31 100644 --- a/lib/config_helper.cpp +++ b/lib/config_helper.cpp @@ -5,347 +5,337 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include #include +#include #include #ifdef WITH_CONFIG -static -int json_to_config_type(int type) -{ - switch (type) { - case JSON_OBJECT: - return CONFIG_TYPE_GROUP; +static int json_to_config_type(int type) { + switch (type) { + case JSON_OBJECT: + return CONFIG_TYPE_GROUP; - case JSON_ARRAY: - return CONFIG_TYPE_LIST; + case JSON_ARRAY: + return CONFIG_TYPE_LIST; - case JSON_STRING: - return CONFIG_TYPE_STRING; + case JSON_STRING: + return CONFIG_TYPE_STRING; - case JSON_INTEGER: - return CONFIG_TYPE_INT64; + case JSON_INTEGER: + return CONFIG_TYPE_INT64; - case JSON_REAL: - return CONFIG_TYPE_FLOAT; + case JSON_REAL: + return CONFIG_TYPE_FLOAT; - case JSON_TRUE: - case JSON_FALSE: - case JSON_NULL: - return CONFIG_TYPE_BOOL; - } + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + return CONFIG_TYPE_BOOL; + } - return -1; + return -1; } -json_t * villas::node::config_to_json(config_setting_t *cfg) -{ - switch (config_setting_type(cfg)) { - case CONFIG_TYPE_INT: - return json_integer(config_setting_get_int(cfg)); +json_t *villas::node::config_to_json(config_setting_t *cfg) { + switch (config_setting_type(cfg)) { + case CONFIG_TYPE_INT: + return json_integer(config_setting_get_int(cfg)); - case CONFIG_TYPE_INT64: - return json_integer(config_setting_get_int64(cfg)); + case CONFIG_TYPE_INT64: + return json_integer(config_setting_get_int64(cfg)); - case CONFIG_TYPE_FLOAT: - return json_real(config_setting_get_float(cfg)); + case CONFIG_TYPE_FLOAT: + return json_real(config_setting_get_float(cfg)); - case CONFIG_TYPE_STRING: - return json_string(config_setting_get_string(cfg)); + case CONFIG_TYPE_STRING: + return json_string(config_setting_get_string(cfg)); - case CONFIG_TYPE_BOOL: - return json_boolean(config_setting_get_bool(cfg)); + case CONFIG_TYPE_BOOL: + return json_boolean(config_setting_get_bool(cfg)); - case CONFIG_TYPE_ARRAY: - case CONFIG_TYPE_LIST: { - json_t *json = json_array(); + case CONFIG_TYPE_ARRAY: + case CONFIG_TYPE_LIST: { + json_t *json = json_array(); - for (int i = 0; i < config_setting_length(cfg); i++) { - auto *elm = config_setting_get_elem(cfg, i); - json_array_append_new(json, config_to_json(elm)); - } + for (int i = 0; i < config_setting_length(cfg); i++) { + auto *elm = config_setting_get_elem(cfg, i); + json_array_append_new(json, config_to_json(elm)); + } - return json; - } + return json; + } - case CONFIG_TYPE_GROUP: { - json_t *json = json_object(); + case CONFIG_TYPE_GROUP: { + json_t *json = json_object(); - for (int i = 0; i < config_setting_length(cfg); i++) { - auto *elm = config_setting_get_elem(cfg, i); - json_object_set_new(json, - config_setting_name(elm), - config_to_json(elm) - ); - } + for (int i = 0; i < config_setting_length(cfg); i++) { + auto *elm = config_setting_get_elem(cfg, i); + json_object_set_new(json, config_setting_name(elm), config_to_json(elm)); + } - return json; - } + return json; + } - default: - return json_object(); - } + default: + return json_object(); + } } -int villas::node::json_to_config(json_t *json, config_setting_t *parent) -{ - config_setting_t *cfg; - int ret, type; +int villas::node::json_to_config(json_t *json, config_setting_t *parent) { + config_setting_t *cfg; + int ret, type; - if (config_setting_is_root(parent)) { - if (!json_is_object(json)) - return -1; // The root must be an object! - } + if (config_setting_is_root(parent)) { + if (!json_is_object(json)) + return -1; // The root must be an object! + } - switch (json_typeof(json)) { - case JSON_OBJECT: { - const char *key; - json_t *json_value; + switch (json_typeof(json)) { + case JSON_OBJECT: { + const char *key; + json_t *json_value; - json_object_foreach(json, key, json_value) { - type = json_to_config_type(json_typeof(json_value)); + json_object_foreach(json, key, json_value) { + type = json_to_config_type(json_typeof(json_value)); - cfg = config_setting_add(parent, key, type); - ret = json_to_config(json_value, cfg); - if (ret) - return ret; - } - break; - } + cfg = config_setting_add(parent, key, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } - case JSON_ARRAY: { - size_t i; - json_t *json_value; + case JSON_ARRAY: { + size_t i; + json_t *json_value; - json_array_foreach(json, i, json_value) { - type = json_to_config_type(json_typeof(json_value)); + json_array_foreach(json, i, json_value) { + type = json_to_config_type(json_typeof(json_value)); - cfg = config_setting_add(parent, nullptr, type); - ret = json_to_config(json_value, cfg); - if (ret) - return ret; - } - break; - } + cfg = config_setting_add(parent, nullptr, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } - case JSON_STRING: - config_setting_set_string(parent, json_string_value(json)); - break; + case JSON_STRING: + config_setting_set_string(parent, json_string_value(json)); + break; - case JSON_INTEGER: - config_setting_set_int64(parent, json_integer_value(json)); - break; + case JSON_INTEGER: + config_setting_set_int64(parent, json_integer_value(json)); + break; - case JSON_REAL: - config_setting_set_float(parent, json_real_value(json)); - break; + case JSON_REAL: + config_setting_set_float(parent, json_real_value(json)); + break; - case JSON_TRUE: - case JSON_FALSE: - case JSON_NULL: - config_setting_set_bool(parent, json_is_true(json)); - break; - } + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + config_setting_set_bool(parent, json_is_true(json)); + break; + } - return 0; + return 0; } #endif // WITH_CONFIG -void villas::node::json_object_extend_key_value_token(json_t *obj, const char *key, const char *value) -{ - char *str = strdup(value); - const char *delim = ","; +void villas::node::json_object_extend_key_value_token(json_t *obj, + const char *key, + const char *value) { + char *str = strdup(value); + const char *delim = ","; - char *lasts; - char *token = strtok_r(str, delim, &lasts); + char *lasts; + char *token = strtok_r(str, delim, &lasts); - while (token) { - json_object_extend_key_value(obj, key, token); + while (token) { + json_object_extend_key_value(obj, key, token); - token = strtok_r(nullptr, delim, &lasts); - } + token = strtok_r(nullptr, delim, &lasts); + } - free(str); + free(str); } -void villas::node::json_object_extend_key_value(json_t *obj, const char *key, const char *value) -{ - char *end, *cpy, *key1, *key2, *lasts; +void villas::node::json_object_extend_key_value(json_t *obj, const char *key, + const char *value) { + char *end, *cpy, *key1, *key2, *lasts; - double real; - long integer; + double real; + long integer; - json_t *arr, *add, *existing, *subobj; + json_t *arr, *add, *existing, *subobj; - // Is the key pointing to an object? - subobj = obj; - cpy = strdup(key); + // Is the key pointing to an object? + subobj = obj; + cpy = strdup(key); - key1 = strtok_r(cpy, ".", &lasts); - key2 = strtok_r(nullptr, ".", &lasts); + key1 = strtok_r(cpy, ".", &lasts); + key2 = strtok_r(nullptr, ".", &lasts); - while (key1 && key2) { - existing = json_object_get(subobj, key1); - if (existing) - subobj = existing; - else { - add = json_object(); - json_object_set(subobj, key1, add); + while (key1 && key2) { + existing = json_object_get(subobj, key1); + if (existing) + subobj = existing; + else { + add = json_object(); + json_object_set(subobj, key1, add); - subobj = add; - } + subobj = add; + } - key1 = key2; - key2 = strtok_r(nullptr, ".", &lasts); - } + key1 = key2; + key2 = strtok_r(nullptr, ".", &lasts); + } - // Try to parse as integer - integer = strtol(value, &end, 0); - if (*end == 0) { - add = json_integer(integer); - goto success; - } + // Try to parse as integer + integer = strtol(value, &end, 0); + if (*end == 0) { + add = json_integer(integer); + goto success; + } - // Try to parse as floating point - real = strtod(value, &end); - if (*end == 0) { - add = json_real(real); - goto success; - } + // Try to parse as floating point + real = strtod(value, &end); + if (*end == 0) { + add = json_real(real); + goto success; + } - // Try to parse special types - if (!strcmp(value, "true")) { - add = json_true(); - goto success; - } + // Try to parse special types + if (!strcmp(value, "true")) { + add = json_true(); + goto success; + } - if (!strcmp(value, "false")) { - add = json_false(); - goto success; - } + if (!strcmp(value, "false")) { + add = json_false(); + goto success; + } - if (!strcmp(value, "null")) { - add = json_null(); - goto success; - } + if (!strcmp(value, "null")) { + add = json_null(); + goto success; + } - // Fallback to string - add = json_string(value); + // Fallback to string + add = json_string(value); success: - /* Does the key already exist? + /* Does the key already exist? * If yes, transform to array. */ - existing = json_object_get(subobj, key1); - if (existing) { - if (json_is_array(existing)) - arr = existing; - else { - arr = json_array(); - json_object_set(subobj, key1, arr); - json_array_append(arr, existing); - } + existing = json_object_get(subobj, key1); + if (existing) { + if (json_is_array(existing)) + arr = existing; + else { + arr = json_array(); + json_object_set(subobj, key1, arr); + json_array_append(arr, existing); + } - json_array_append(arr, add); - } - else - json_object_set(subobj, key1, add); + json_array_append(arr, add); + } else + json_object_set(subobj, key1, add); } -json_t * villas::node::json_load_cli(int argc, const char *argv[]) -{ - const char *opt; - const char *key = nullptr; - const char *value = nullptr; - const char *sep; - char *cpy, *lasts; +json_t *villas::node::json_load_cli(int argc, const char *argv[]) { + const char *opt; + const char *key = nullptr; + const char *value = nullptr; + const char *sep; + char *cpy, *lasts; - json_t *json = json_object(); + json_t *json = json_object(); - for (int i = 1; i < argc; i++) { - opt = argv[i]; + for (int i = 1; i < argc; i++) { + opt = argv[i]; - // Long Option - if (opt[0] == '-' && opt[1] == '-') { - // Option without value? Abort - if (key != nullptr) - return nullptr; + // Long Option + if (opt[0] == '-' && opt[1] == '-') { + // Option without value? Abort + if (key != nullptr) + return nullptr; - key = opt + 2; + key = opt + 2; - // Does this option has the form "--option=value"? - sep = strchr(key, '='); - if (sep) { - cpy = strdup(key); + // Does this option has the form "--option=value"? + sep = strchr(key, '='); + if (sep) { + cpy = strdup(key); - key = strtok_r(cpy, "=", &lasts); - value = strtok_r(nullptr, "", &lasts); + key = strtok_r(cpy, "=", &lasts); + value = strtok_r(nullptr, "", &lasts); - json_object_extend_key_value_token(json, key, value); + json_object_extend_key_value_token(json, key, value); - free(cpy); - key = nullptr; - } - } - // Value - else { - // Value without key. Abort - if (key == nullptr) - return nullptr; + free(cpy); + key = nullptr; + } + } + // Value + else { + // Value without key. Abort + if (key == nullptr) + return nullptr; - value = opt; + value = opt; - json_object_extend_key_value_token(json, key, value); - key = nullptr; - } - } + json_object_extend_key_value_token(json, key, value); + key = nullptr; + } + } - return json; + return json; } -int villas::node::json_object_extend(json_t *obj, json_t *merge) -{ - const char *key; - int ret; - json_t *merge_value, *obj_value; +int villas::node::json_object_extend(json_t *obj, json_t *merge) { + const char *key; + int ret; + json_t *merge_value, *obj_value; - if (!json_is_object(obj) || !json_is_object(merge)) - return -1; + if (!json_is_object(obj) || !json_is_object(merge)) + return -1; - json_object_foreach(merge, key, merge_value) { - obj_value = json_object_get(obj, key); - if (obj_value && json_is_object(obj_value)) - ret = json_object_extend(obj_value, merge_value); - else - ret = json_object_set(obj, key, merge_value); + json_object_foreach(merge, key, merge_value) { + obj_value = json_object_get(obj, key); + if (obj_value && json_is_object(obj_value)) + ret = json_object_extend(obj_value, merge_value); + else + ret = json_object_set(obj, key, merge_value); - if (ret) - return ret; - } + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::json_object_extend_str(json_t *obj, const char *str) -{ - char *key, *value, *cpy, *lasts; +int villas::node::json_object_extend_str(json_t *obj, const char *str) { + char *key, *value, *cpy, *lasts; - cpy = strdup(str); + cpy = strdup(str); - key = strtok_r(cpy, "=", &lasts); - value = strtok_r(nullptr, "", &lasts); + key = strtok_r(cpy, "=", &lasts); + value = strtok_r(nullptr, "", &lasts); - if (!key || !value) - return -1; + if (!key || !value) + return -1; - json_object_extend_key_value_token(obj, key, value); + json_object_extend_key_value_token(obj, key, value); - free(cpy); + free(cpy); - return 0; + return 0; } diff --git a/lib/dumper.cpp b/lib/dumper.cpp index f4e4f186a..7b0862605 100644 --- a/lib/dumper.cpp +++ b/lib/dumper.cpp @@ -10,119 +10,106 @@ #include #include -#include #include +#include #include using namespace villas; using namespace villas::node; -Dumper::Dumper() : - active(false), - socketFd(0), - socketPath(""), - supressRepeatedWarning(true), - warningCounter(0), - logger(logging.get("dumper")) -{} +Dumper::Dumper() + : active(false), socketFd(0), socketPath(""), supressRepeatedWarning(true), + warningCounter(0), logger(logging.get("dumper")) {} -Dumper::~Dumper() { - closeSocket(); +Dumper::~Dumper() { closeSocket(); } + +bool Dumper::isActive() { return active; } + +int Dumper::setActive() { + active = true; + return 1; } -bool Dumper::isActive() -{ - return active; +int Dumper::openSocket() { + socketFd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (socketFd < 0) { + logger->info("Error creating socket {}", socketPath); + return -1; + } + + sockaddr_un socketaddrUn; + socketaddrUn.sun_family = AF_UNIX; + strcpy(socketaddrUn.sun_path, socketPath.c_str()); + + int ret = + connect(socketFd, (struct sockaddr *)&socketaddrUn, sizeof(socketaddrUn)); + if (!ret) + return ret; + + return 0; } -int Dumper::setActive() -{ - active = true; - return 1; +int Dumper::closeSocket() { + int ret = close(socketFd); + if (!ret) + return ret; + + return 0; } -int Dumper::openSocket() -{ - socketFd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (socketFd < 0) { - logger->info("Error creating socket {}", socketPath); - return -1; - } - - sockaddr_un socketaddrUn; - socketaddrUn.sun_family = AF_UNIX; - strcpy(socketaddrUn.sun_path, socketPath.c_str()); - - int ret = connect(socketFd, (struct sockaddr *) &socketaddrUn, sizeof(socketaddrUn)); - if (!ret) - return ret; - - return 0; +int Dumper::setPath(const std::string &socketPathIn) { + socketPath = socketPathIn; + return 1; } -int Dumper::closeSocket() -{ - int ret = close(socketFd); - if (!ret) - return ret; +void Dumper::writeDataBinary(unsigned len, double *yData, double *xData) { - return 0; + if (warningCounter > 10) + return; + + if (yData == nullptr) + return; + + unsigned dataLen = len * sizeof(double); + ssize_t bytesWritten = write(socketFd, &dataLen, sizeof(dataLen)); + if ((size_t)bytesWritten != sizeof(len)) { + logger->warn("Could not send all content (Len) to socket {}", socketPath); + warningCounter++; + } + + static const char buf[] = "d000"; + bytesWritten = write(socketFd, buf, sizeof(buf)); + if (bytesWritten != sizeof(buf)) { + logger->warn("Could not send all content (Type) to socket {}", socketPath); + warningCounter++; + } + + bytesWritten = write(socketFd, yData, dataLen); + if (bytesWritten != (ssize_t)dataLen && + (!supressRepeatedWarning || warningCounter < 1)) { + logger->warn("Could not send all content (Data) to socket {}", socketPath); + warningCounter++; + } } -int Dumper::setPath(const std::string &socketPathIn) -{ - socketPath = socketPathIn; - return 1; -} - -void Dumper::writeDataBinary(unsigned len, double *yData, double *xData) -{ - - if (warningCounter > 10) - return; - - if (yData == nullptr) - return; - - unsigned dataLen = len * sizeof(double); - ssize_t bytesWritten = write(socketFd, &dataLen, sizeof(dataLen)); - if ((size_t) bytesWritten != sizeof(len)) { - logger->warn("Could not send all content (Len) to socket {}", socketPath); - warningCounter++; - } - - static const char buf[] = "d000"; - bytesWritten = write(socketFd, buf, sizeof(buf)); - if (bytesWritten != sizeof(buf)) { - logger->warn("Could not send all content (Type) to socket {}", socketPath); - warningCounter++; - } - - bytesWritten = write(socketFd, yData, dataLen ); - if (bytesWritten != (ssize_t) dataLen && (!supressRepeatedWarning || warningCounter <1 )) { - logger->warn("Could not send all content (Data) to socket {}", socketPath); - warningCounter++; - } -} - -void Dumper::writeDataCSV(unsigned len, double *yData, double *xData) -{ - for (unsigned i = 0; i < len; i++) { - std::stringstream ss; - - ss << yData[i]; - - if (xData != nullptr) - ss << ";" << xData[i]; - - ss << std::endl; - - auto str = ss.str(); - auto bytesWritten = write(socketFd, str.c_str(), str.length()); - if ((size_t) bytesWritten != str.length() && (!supressRepeatedWarning || warningCounter < 1)) { - logger->warn("Could not send all content to socket {}", socketPath); - warningCounter++; - } - } +void Dumper::writeDataCSV(unsigned len, double *yData, double *xData) { + for (unsigned i = 0; i < len; i++) { + std::stringstream ss; + + ss << yData[i]; + + if (xData != nullptr) + ss << ";" << xData[i]; + + ss << std::endl; + + auto str = ss.str(); + auto bytesWritten = write(socketFd, str.c_str(), str.length()); + if ((size_t)bytesWritten != str.length() && + (!supressRepeatedWarning || warningCounter < 1)) { + logger->warn("Could not send all content to socket {}", socketPath); + warningCounter++; + } + } } diff --git a/lib/format.cpp b/lib/format.cpp index 02e7ae293..0c5b5c5fc 100644 --- a/lib/format.cpp +++ b/lib/format.cpp @@ -5,159 +5,144 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -Format * FormatFactory::make(json_t *json) -{ - std::string type; - Format *f; +Format *FormatFactory::make(json_t *json) { + std::string type; + Format *f; - if (json_is_string(json)) { - type = json_string_value(json); + if (json_is_string(json)) { + type = json_string_value(json); - return FormatFactory::make(type); - } - else if (json_is_object(json)) { - json_t *json_type = json_object_get(json, "type"); + return FormatFactory::make(type); + } else if (json_is_object(json)) { + json_t *json_type = json_object_get(json, "type"); - type = json_string_value(json_type); + type = json_string_value(json_type); - f = FormatFactory::make(type); - if (!f) - return nullptr; + f = FormatFactory::make(type); + if (!f) + return nullptr; - f->parse(json); + f->parse(json); - return f; - } - else - throw ConfigError(json, "node-config-format", "Invalid format config"); + return f; + } else + throw ConfigError(json, "node-config-format", "Invalid format config"); } -Format * FormatFactory::make(const std::string &format) -{ - FormatFactory *ff = plugin::registry->lookup(format); - if (!ff) - throw RuntimeError("Unknown format: {}", format); +Format *FormatFactory::make(const std::string &format) { + FormatFactory *ff = plugin::registry->lookup(format); + if (!ff) + throw RuntimeError("Unknown format: {}", format); - return ff->make(); + return ff->make(); } -Format::Format(int fl) : - flags(fl), - real_precision(17), - signals(nullptr) -{ - in.buflen = - out.buflen = DEFAULT_FORMAT_BUFFER_LENGTH; +Format::Format(int fl) : flags(fl), real_precision(17), signals(nullptr) { + in.buflen = out.buflen = DEFAULT_FORMAT_BUFFER_LENGTH; - in.buffer = new char[in.buflen]; - out.buffer = new char[out.buflen]; + in.buffer = new char[in.buflen]; + out.buffer = new char[out.buflen]; - if (!in.buffer || !out.buffer) - throw MemoryAllocationError(); + if (!in.buffer || !out.buffer) + throw MemoryAllocationError(); } -Format::~Format() -{ - int ret __attribute__((unused)); +Format::~Format() { + int ret __attribute__((unused)); - delete[] in.buffer; - delete[] out.buffer; + delete[] in.buffer; + delete[] out.buffer; } -void Format::start(SignalList::Ptr sigs, int fl) -{ - flags &= fl; +void Format::start(SignalList::Ptr sigs, int fl) { + flags &= fl; - signals = sigs; + signals = sigs; - start(); + start(); } -void Format::start(const std::string &dtypes, int fl) -{ - flags |= fl; +void Format::start(const std::string &dtypes, int fl) { + flags |= fl; - signals = std::make_shared(dtypes.c_str()); - if (!signals) - throw MemoryAllocationError(); + signals = std::make_shared(dtypes.c_str()); + if (!signals) + throw MemoryAllocationError(); - start(); + start(); } -int Format::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - size_t wbytes; +int Format::print(FILE *f, const struct Sample *const smps[], unsigned cnt) { + int ret; + size_t wbytes; - ret = sprint(out.buffer, out.buflen, &wbytes, smps, cnt); + ret = sprint(out.buffer, out.buflen, &wbytes, smps, cnt); - fwrite(out.buffer, wbytes, 1, f); + fwrite(out.buffer, wbytes, 1, f); - return ret; + return ret; } -int Format::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - size_t bytes, rbytes; +int Format::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + size_t bytes, rbytes; - bytes = fread(in.buffer, 1, in.buflen, f); + bytes = fread(in.buffer, 1, in.buflen, f); - return sscan(in.buffer, bytes, &rbytes, smps, cnt); + return sscan(in.buffer, bytes, &rbytes, smps, cnt); } -void Format::parse(json_t *json) -{ - int ret; - json_error_t err; +void Format::parse(json_t *json) { + int ret; + json_error_t err; - int ts_origin = -1; - int ts_received = -1; - int sequence = -1; - int data = -1; - int offset = -1; + int ts_origin = -1; + int ts_received = -1; + int sequence = -1; + int data = -1; + int offset = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: b, s?: b, s?: b, s?: b, s?: i }", - "ts_origin", &ts_origin, - "ts_received", &ts_received, - "sequence", &sequence, - "data", &data, - "offset", &offset, - "real_precision", &real_precision - ); - if (ret) - throw ConfigError(json, err, "node-config-format", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: b, s?: b, s?: b, s?: b, s?: b, s?: i }", + "ts_origin", &ts_origin, "ts_received", &ts_received, + "sequence", &sequence, "data", &data, "offset", &offset, + "real_precision", &real_precision); + if (ret) + throw ConfigError(json, err, "node-config-format", + "Failed to parse format configuration"); - if (real_precision < 0 || real_precision > 31) - throw ConfigError(json, err, "node-config-format-precision", "The valid range for the real_precision setting is between 0 and 31 (inclusive)"); + if (real_precision < 0 || real_precision > 31) + throw ConfigError(json, err, "node-config-format-precision", + "The valid range for the real_precision setting is " + "between 0 and 31 (inclusive)"); - if (ts_origin == 0) - flags &= ~ (int) SampleFlags::HAS_TS_ORIGIN; + if (ts_origin == 0) + flags &= ~(int)SampleFlags::HAS_TS_ORIGIN; - if (ts_received == 0) - flags &= ~ (int) SampleFlags::HAS_TS_RECEIVED; + if (ts_received == 0) + flags &= ~(int)SampleFlags::HAS_TS_RECEIVED; - if (sequence == 0) - flags &= ~ (int) SampleFlags::HAS_SEQUENCE; + if (sequence == 0) + flags &= ~(int)SampleFlags::HAS_SEQUENCE; - if (data == 0) - flags &= ~ (int) SampleFlags::HAS_DATA; + if (data == 0) + flags &= ~(int)SampleFlags::HAS_DATA; - if (offset == 0) - flags &= ~ (int) SampleFlags::HAS_OFFSET; + if (offset == 0) + flags &= ~(int)SampleFlags::HAS_OFFSET; } diff --git a/lib/formats/column.cpp b/lib/formats/column.cpp index 12cbcdf67..0aeab52f2 100644 --- a/lib/formats/column.cpp +++ b/lib/formats/column.cpp @@ -9,183 +9,196 @@ #include #include +#include #include #include #include #include -#include using namespace villas; using namespace villas::node; -size_t ColumnLineFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) -{ - size_t off = 0; +size_t ColumnLineFormat::sprintLine(char *buf, size_t len, + const struct Sample *smp) { + size_t off = 0; - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) - off += snprintf(buf + off, len - off, "%lld%c%09lld", (long long) smp->ts.origin.tv_sec, separator, - (long long) smp->ts.origin.tv_nsec); - else - off += snprintf(buf + off, len - off, "nan%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) + off += snprintf(buf + off, len - off, "%lld%c%09lld", + (long long)smp->ts.origin.tv_sec, separator, + (long long)smp->ts.origin.tv_nsec); + else + off += snprintf(buf + off, len - off, "nan%cnan", separator); - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) - off += snprintf(buf + off, len - off, "%c%.09f", separator, time_delta(&smp->ts.origin, &smp->ts.received)); - else - off += snprintf(buf + off, len - off, "%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) + off += snprintf(buf + off, len - off, "%c%.09f", separator, + time_delta(&smp->ts.origin, &smp->ts.received)); + else + off += snprintf(buf + off, len - off, "%cnan", separator); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - off += snprintf(buf + off, len - off, "%c%" PRIu64, separator, smp->sequence); - else - off += snprintf(buf + off, len - off, "%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + off += + snprintf(buf + off, len - off, "%c%" PRIu64, separator, smp->sequence); + else + off += snprintf(buf + off, len - off, "%cnan", separator); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - break; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + break; - off += snprintf(buf + off, len - off, "%c", separator); - off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); - } + off += snprintf(buf + off, len - off, "%c", separator); + off += smp->data[i].printString(sig->type, buf + off, len - off, + real_precision); + } - off += snprintf(buf + off, len - off, "%c", delimiter); + off += snprintf(buf + off, len - off, "%c", delimiter); - return off; + return off; } -size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) -{ - int ret; - unsigned i = 0; - const char *ptr = buf; - char *end; +size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, + struct Sample *smp) { + int ret; + unsigned i = 0; + const char *ptr = buf; + char *end; - struct timespec offset; + struct timespec offset; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - smp->ts.origin.tv_sec = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->ts.origin.tv_sec = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - ptr = end + 1; + ptr = end + 1; - smp->ts.origin.tv_nsec = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->ts.origin.tv_nsec = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - ptr = end + 1; + ptr = end + 1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - offset = time_from_double(strtof(ptr, &end)); - if (end == ptr || *end == delimiter) - goto out; + offset = time_from_double(strtof(ptr, &end)); + if (end == ptr || *end == delimiter) + goto out; - smp->ts.received = time_add(&smp->ts.origin, &offset); + smp->ts.received = time_add(&smp->ts.origin, &offset); - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; - ptr = end + 1; + ptr = end + 1; - smp->sequence = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->sequence = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; - for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { - if (*end == delimiter) - goto out; + for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { + if (*end == delimiter) + goto out; - auto sig = smp->signals->getByIndex(i); - if (!sig) - goto out; + auto sig = smp->signals->getByIndex(i); + if (!sig) + goto out; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; - } + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; + } -out: if (*end == delimiter) - end++; +out: + if (*end == delimiter) + end++; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return end - buf; + return end - buf; } -void ColumnLineFormat::header(FILE *f, const SignalList::Ptr sigs) -{ - // Abort if we are not supposed to, or have already printed the header - if (!print_header || header_printed) - return; +void ColumnLineFormat::header(FILE *f, const SignalList::Ptr sigs) { + // Abort if we are not supposed to, or have already printed the header + if (!print_header || header_printed) + return; - if (comment) - fprintf(f, "%c", comment); + if (comment) + fprintf(f, "%c", comment); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) - fprintf(f, "secs%cnsecs%c", separator, separator); + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) + fprintf(f, "secs%cnsecs%c", separator, separator); - if (flags & (int) SampleFlags::HAS_OFFSET) - fprintf(f, "offset%c", separator); + if (flags & (int)SampleFlags::HAS_OFFSET) + fprintf(f, "offset%c", separator); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - fprintf(f, "sequence%c", separator); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + fprintf(f, "sequence%c", separator); - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < sigs->size(); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + break; - if (!sig->name.empty()) - fprintf(f, "%s", sig->name.c_str()); - else - fprintf(f, "signal%u", i); + if (!sig->name.empty()) + fprintf(f, "%s", sig->name.c_str()); + else + fprintf(f, "signal%u", i); - if (!sig->unit.empty()) - fprintf(f, "[%s]", sig->unit.c_str()); + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); - if (i + 1 < sigs->size()) - fprintf(f, "%c", separator); - } - } + if (i + 1 < sigs->size()) + fprintf(f, "%c", separator); + } + } - fprintf(f, "%c", delimiter); + fprintf(f, "%c", delimiter); - LineFormat::header(f, sigs); + LineFormat::header(f, sigs); } -void ColumnLineFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - const char *sep = nullptr; +void ColumnLineFormat::parse(json_t *json) { + int ret; + json_error_t err; + const char *sep = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s }", - "separator", &sep - ); - if (ret) - throw ConfigError(json, err, "node-config-format-column", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s }", "separator", &sep); + if (ret) + throw ConfigError(json, err, "node-config-format-column", + "Failed to parse format configuration"); - if (sep) { - if (strlen(sep) != 1) - throw ConfigError(json, "node-config-format-column-separator", "Column separator must be a single character!"); + if (sep) { + if (strlen(sep) != 1) + throw ConfigError(json, "node-config-format-column-separator", + "Column separator must be a single character!"); - separator = sep[0]; - } + separator = sep[0]; + } - LineFormat::parse(json); + LineFormat::parse(json); } // Register formats static char n1[] = "csv"; static char d1[] = "Comma-separated values"; -static ColumnLineFormatPlugin p1; +static ColumnLineFormatPlugin + p1; static char n2[] = "tsv"; static char d2[] = "Tabulator-separated values"; -static ColumnLineFormatPlugin p2; +static ColumnLineFormatPlugin + p2; diff --git a/lib/formats/iotagent_ul.cpp b/lib/formats/iotagent_ul.cpp index 069fa9d40..8ba278a1b 100644 --- a/lib/formats/iotagent_ul.cpp +++ b/lib/formats/iotagent_ul.cpp @@ -9,45 +9,52 @@ #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - size_t printed = 0; - const struct Sample *smp = smps[0]; +int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], + unsigned cnt) { + size_t printed = 0; + const struct Sample *smp = smps[0]; - for (unsigned i = 0; (i < smp->length) && (printed < len); i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; (i < smp->length) && (printed < len); i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - if (!sig->name.empty()) - printed += snprintf(buf + printed, len - printed, "%s|%f|", sig->name.c_str(), smp->data[i].f); - else { - printed += snprintf(buf + printed, len - printed, "signal_%u|%f|", i, smp->data[i].f); - } - } + if (!sig->name.empty()) + printed += snprintf(buf + printed, len - printed, "%s|%f|", + sig->name.c_str(), smp->data[i].f); + else { + printed += snprintf(buf + printed, len - printed, "signal_%u|%f|", i, + smp->data[i].f); + } + } - if (wbytes) - *wbytes = printed - 1; // -1 to cut off last '|' + if (wbytes) + *wbytes = printed - 1; // -1 to cut off last '|' - return 0; + return 0; } -int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - return -1; +int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + return -1; } // Register format static char n[] = "iotagent_ul"; static char d[] = "FIWARE IotAgent UltraLight format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json.cpp b/lib/formats/json.cpp index 854255f8c..d67d0475b 100644 --- a/lib/formats/json.cpp +++ b/lib/formats/json.cpp @@ -5,369 +5,371 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include +#include +#include +#include using namespace villas; using namespace villas::node; -enum SignalType JsonFormat::detect(const json_t *val) -{ - int type = json_typeof(val); +enum SignalType JsonFormat::detect(const json_t *val) { + int type = json_typeof(val); - switch (type) { - case JSON_REAL: - return SignalType::FLOAT; + switch (type) { + case JSON_REAL: + return SignalType::FLOAT; - case JSON_INTEGER: - return SignalType::INTEGER; + case JSON_INTEGER: + return SignalType::INTEGER; - case JSON_TRUE: - case JSON_FALSE: - return SignalType::BOOLEAN; + case JSON_TRUE: + case JSON_FALSE: + return SignalType::BOOLEAN; - case JSON_OBJECT: - return SignalType::COMPLEX; // must be a complex number + case JSON_OBJECT: + return SignalType::COMPLEX; // must be a complex number - default: - return SignalType::INVALID; - } + default: + return SignalType::INVALID; + } } -json_t * JsonFormat::packTimestamps(const struct Sample *smp) -{ - json_t *json_ts = json_object(); +json_t *JsonFormat::packTimestamps(const struct Sample *smp) { + json_t *json_ts = json_object(); #ifdef __arm__ // TODO: check - const char *fmt = "[ i, i ]"; + const char *fmt = "[ i, i ]"; #else - const char *fmt = "[ I, I ]"; + const char *fmt = "[ I, I ]"; #endif - if (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 (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 (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)); - } + if (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)); + } - return json_ts; + return json_ts; } -int JsonFormat::unpackTimestamps(json_t *json_ts, struct Sample *smp) -{ - int ret; - json_error_t err; - json_t *json_ts_origin = nullptr; - json_t *json_ts_received = nullptr; +int JsonFormat::unpackTimestamps(json_t *json_ts, struct Sample *smp) { + int ret; + json_error_t err; + 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, - "received", &json_ts_received - ); + json_unpack_ex(json_ts, &err, 0, "{ s?: o, s?: o }", "origin", + &json_ts_origin, "received", &json_ts_received); - if (json_ts_origin) { - ret = json_unpack_ex(json_ts_origin, &err, 0, "[ I, I ]", &smp->ts.origin.tv_sec, &smp->ts.origin.tv_nsec); - if (ret) - return ret; + if (json_ts_origin) { + ret = json_unpack_ex(json_ts_origin, &err, 0, "[ I, I ]", + &smp->ts.origin.tv_sec, &smp->ts.origin.tv_nsec); + if (ret) + return ret; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - if (json_ts_received) { - ret = json_unpack_ex(json_ts_received, &err, 0, "[ I, I ]", &smp->ts.received.tv_sec, &smp->ts.received.tv_nsec); - if (ret) - return ret; + if (json_ts_received) { + ret = json_unpack_ex(json_ts_received, &err, 0, "[ I, I ]", + &smp->ts.received.tv_sec, &smp->ts.received.tv_nsec); + if (ret) + return ret; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - return 0; + return 0; } -int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_root; - json_error_t err; +int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_t *json_root; + json_error_t err; - json_root = json_pack_ex(&err, 0, "{ s: o }", "ts", packTimestamps(smp)); + json_root = json_pack_ex(&err, 0, "{ s: o }", "ts", packTimestamps(smp)); - if (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - json_t *json_sequence = json_integer(smp->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + json_t *json_sequence = json_integer(smp->sequence); - json_object_set_new(json_root, "sequence", json_sequence); - } - } + json_object_set_new(json_root, "sequence", json_sequence); + } + } - if (flags & (int) SampleFlags::HAS_DATA) { - json_t *json_data = json_array(); + if (flags & (int)SampleFlags::HAS_DATA) { + json_t *json_data = json_array(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - json_t *json_value = smp->data[i].toJson(sig->type); + json_t *json_value = smp->data[i].toJson(sig->type); - json_array_append_new(json_data, json_value); - } + json_array_append_new(json_data, json_value); + } - json_object_set_new(json_root, "data", json_data); - } + json_object_set_new(json_root, "data", json_data); + } - *json_smp = json_root; + *json_smp = json_root; - return 0; + return 0; } -int JsonFormat::packSamples(json_t **json_smps, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json_root = json_array(); +int JsonFormat::packSamples(json_t **json_smps, + const struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json_root = json_array(); - for (unsigned i = 0; i < cnt; i++) { - json_t *json_smp; + for (unsigned i = 0; i < cnt; i++) { + json_t *json_smp; - ret = packSample(&json_smp, smps[i]); - if (ret) - break; + ret = packSample(&json_smp, smps[i]); + if (ret) + break; - json_array_append_new(json_root, json_smp); - } + json_array_append_new(json_root, json_smp); + } - *json_smps = json_root; + *json_smps = json_root; - return cnt; + return cnt; } -int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret; - json_error_t err; - json_t *json_data, *json_value, *json_ts = nullptr; - size_t i; - int64_t sequence = -1; +int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret; + json_error_t err; + json_t *json_data, *json_value, *json_ts = nullptr; + size_t i; + int64_t sequence = -1; - smp->signals = signals; + smp->signals = signals; - ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: I, s: o }", - "ts", &json_ts, - "sequence", &sequence, - "data", &json_data); - if (ret) - return ret; + ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: I, s: o }", "ts", + &json_ts, "sequence", &sequence, "data", &json_data); + if (ret) + return ret; - smp->flags = 0; - smp->length = 0; + smp->flags = 0; + smp->length = 0; - if (json_ts) { - ret = unpackTimestamps(json_ts, smp); - if (ret) - return ret; - } + if (json_ts) { + ret = unpackTimestamps(json_ts, smp); + if (ret) + return ret; + } - if (!json_is_array(json_data)) - return -1; + if (!json_is_array(json_data)) + return -1; - if (sequence >= 0) { - smp->sequence = sequence; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (sequence >= 0) { + smp->sequence = sequence; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - json_array_foreach(json_data, i, json_value) { - if (i >= smp->capacity) - break; + json_array_foreach(json_data, i, json_value) { + if (i >= smp->capacity) + break; - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - enum SignalType fmt = detect(json_value); - if (sig->type != fmt) - throw RuntimeError("Received invalid data type in JSON payload: Received {}, expected {} for signal {} (index {}).", - signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); + enum SignalType fmt = detect(json_value); + if (sig->type != fmt) + throw RuntimeError("Received invalid data type in JSON payload: Received " + "{}, expected {} for signal {} (index {}).", + signalTypeToString(fmt), signalTypeToString(sig->type), + sig->name, i); - ret = smp->data[i].parseJson(sig->type, json_value); - if (ret) - return -3; + ret = smp->data[i].parseJson(sig->type, json_value); + if (ret) + return -3; - smp->length++; - } + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } -int JsonFormat::unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json_smp; - size_t i; +int JsonFormat::unpackSamples(json_t *json_smps, struct Sample *const smps[], + unsigned cnt) { + int ret; + json_t *json_smp; + size_t i; - if (!json_is_array(json_smps)) - return -1; + if (!json_is_array(json_smps)) + return -1; - json_array_foreach(json_smps, i, json_smp) { - if (i >= cnt) - break; + json_array_foreach(json_smps, i, json_smp) { + if (i >= cnt) + break; - ret = unpackSample(json_smp, smps[i]); - if (ret < 0) - break; - } + ret = unpackSample(json_smp, smps[i]); + if (ret < 0) + break; + } - return i; + return i; } -int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json; - size_t wr; +int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json; + size_t wr; - ret = packSamples(&json, smps, cnt); - if (ret < 0) - return ret; + ret = packSamples(&json, smps, cnt); + if (ret < 0) + return ret; - wr = json_dumpb(json, buf, len, dump_flags); + wr = json_dumpb(json, buf, len, dump_flags); - json_decref(json); + json_decref(json); - if (wbytes) - *wbytes = wr; + if (wbytes) + *wbytes = wr; - return ret; + return ret; } -int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json; - json_error_t err; +int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json; + json_error_t err; - json = json_loadb(buf, len, 0, &err); - if (!json) - return -1; + json = json_loadb(buf, len, 0, &err); + if (!json) + return -1; - ret = unpackSamples(json, smps, cnt); + ret = unpackSamples(json, smps, cnt); - json_decref(json); + json_decref(json); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - if (rbytes) - *rbytes = err.position; + if (rbytes) + *rbytes = err.position; - return ret; + return ret; } -int JsonFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - json_t *json; +int JsonFormat::print(FILE *f, const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; + json_t *json; - for (i = 0; i < cnt; i++) { - ret = packSample(&json, smps[i]); - if (ret) - return ret; + for (i = 0; i < cnt; i++) { + ret = packSample(&json, smps[i]); + if (ret) + return ret; - ret = json_dumpf(json, f, dump_flags); - fputc('\n', f); + ret = json_dumpf(json, f, dump_flags); + fputc('\n', f); - json_decref(json); + json_decref(json); - if (ret) - return ret; - } + if (ret) + return ret; + } - return i; + return i; } -int JsonFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - json_t *json; - json_error_t err; +int JsonFormat::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + int ret; + unsigned i; + json_t *json; + json_error_t err; - for (i = 0; i < cnt; i++) { - if (feof(f)) - return -1; + for (i = 0; i < cnt; i++) { + if (feof(f)) + return -1; -skip: json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err); - if (!json) - break; + skip: + json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err); + if (!json) + break; - ret = unpackSample(json, smps[i]); - if (ret) - goto skip; + ret = unpackSample(json, smps[i]); + if (ret) + goto skip; - json_decref(json); - } + json_decref(json); + } - return i; + return i; } -void JsonFormat::parse(json_t *json) -{ - int ret; - json_error_t err; +void JsonFormat::parse(json_t *json) { + int ret; + json_error_t err; - int indent = 0; - int compact = 0; - int ensure_ascii = 0; - int escape_slash = 0; - int sort_keys = 0; + int indent = 0; + int compact = 0; + int ensure_ascii = 0; + int escape_slash = 0; + int sort_keys = 0; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b, s?: b, s?: b, s?: b }", - "indent", &indent, - "compact", &compact, - "ensure_ascii", &ensure_ascii, - "escape_slash", &escape_slash, - "sort_keys", &sort_keys + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b, s?: b, s?: b, s?: b }", + "indent", &indent, "compact", &compact, "ensure_ascii", + &ensure_ascii, "escape_slash", &escape_slash, + "sort_keys", &sort_keys - ); - if (ret) - throw ConfigError(json, err, "node-config-format-json", "Failed to parse format configuration"); + ); + if (ret) + throw ConfigError(json, err, "node-config-format-json", + "Failed to parse format configuration"); - if (indent > JSON_MAX_INDENT) - throw ConfigError(json, "node-config-format-json-indent", "The maximum indentation level is {}", JSON_MAX_INDENT); + if (indent > JSON_MAX_INDENT) + throw ConfigError(json, "node-config-format-json-indent", + "The maximum indentation level is {}", JSON_MAX_INDENT); - dump_flags = 0; + dump_flags = 0; - if (indent) - dump_flags |= JSON_INDENT(indent); + if (indent) + dump_flags |= JSON_INDENT(indent); - if (compact) - dump_flags |= JSON_COMPACT; + if (compact) + dump_flags |= JSON_COMPACT; - if (ensure_ascii) - dump_flags |= JSON_ENSURE_ASCII; + if (ensure_ascii) + dump_flags |= JSON_ENSURE_ASCII; - if (escape_slash) - dump_flags |= JSON_ESCAPE_SLASH; + if (escape_slash) + dump_flags |= JSON_ESCAPE_SLASH; - if (sort_keys) - dump_flags |= JSON_SORT_KEYS; + if (sort_keys) + dump_flags |= JSON_SORT_KEYS; - Format::parse(json); + Format::parse(json); - if (real_precision) - dump_flags |= JSON_REAL_PRECISION(real_precision); + if (real_precision) + dump_flags |= JSON_REAL_PRECISION(real_precision); } // Register format static char n[] = "json"; static char d[] = "Javascript Object Notation"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_edgeflex.cpp b/lib/formats/json_edgeflex.cpp index eaee6236b..861a2314c 100644 --- a/lib/formats/json_edgeflex.cpp +++ b/lib/formats/json_edgeflex.cpp @@ -7,92 +7,95 @@ #include -#include #include +#include using namespace villas::node; -int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_data, *json_value; - json_t *json_created = nullptr; +int JsonEdgeflexFormat::packSample(json_t **json_smp, + const struct Sample *smp) { + json_t *json_data, *json_value; + json_t *json_created = nullptr; - if (smp->length < 1) - return -1; + if (smp->length < 1) + return -1; - json_data = json_object(); + json_data = json_object(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - json_value = smp->data[i].toJson(sig->type); - json_object_set(json_data, sig->name.c_str(), json_value); - } + json_value = smp->data[i].toJson(sig->type); + json_object_set(json_data, sig->name.c_str(), json_value); + } - json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); - json_object_set(json_data, "created", json_created); + json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); + json_object_set(json_data, "created", json_created); - *json_smp = json_data; + *json_smp = json_data; - return 0; + return 0; } -int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret; - const char *key; - json_t *json_value, *json_created = nullptr; - json_int_t created = -1; +int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret; + const char *key; + json_t *json_value, *json_created = nullptr; + json_int_t created = -1; - if (smp->capacity < 1) - return -1; + if (smp->capacity < 1) + return -1; - if (json_typeof(json_smp) != JSON_OBJECT) - return -1; + if (json_typeof(json_smp) != JSON_OBJECT) + return -1; - json_object_foreach(json_smp, key, json_value) { - if (!strcmp(key, "created")) - json_created = json_incref(json_value); - else { - auto idx = signals->getIndexByName(key); - if (idx < 0) { - ret = sscanf(key, "signal_%d", &idx); - if (ret != 1) - continue; + json_object_foreach(json_smp, key, json_value) { + if (!strcmp(key, "created")) + json_created = json_incref(json_value); + else { + auto idx = signals->getIndexByName(key); + if (idx < 0) { + ret = sscanf(key, "signal_%d", &idx); + if (ret != 1) + continue; - if (idx < 0) - return -1; - } + if (idx < 0) + return -1; + } - auto sig = signals->getByIndex(idx); + auto sig = signals->getByIndex(idx); - if (idx < (int) smp->capacity) { - ret = smp->data[idx].parseJson(sig->type, json_value); - if (ret) - return ret; - } + if (idx < (int)smp->capacity) { + ret = smp->data[idx].parseJson(sig->type, json_value); + if (ret) + return ret; + } - if (idx >= (int) smp->length) - smp->length = idx + 1; - } - } + if (idx >= (int)smp->length) + smp->length = idx + 1; + } + } - if (!json_created || !json_is_number(json_created)) - return -1; + if (!json_created || !json_is_number(json_created)) + return -1; - created = json_number_value(json_created); - smp->ts.origin = time_from_double(created / 1e3); + created = json_number_value(json_created); + smp->ts.origin = time_from_double(created / 1e3); - smp->flags = (int) SampleFlags::HAS_TS_ORIGIN; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->flags = (int)SampleFlags::HAS_TS_ORIGIN; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } // Register format static char n[] = "json.edgeflex"; static char d[] = "EdgeFlex JSON format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_kafka.cpp b/lib/formats/json_kafka.cpp index 4bae33c7b..32f1c6e25 100644 --- a/lib/formats/json_kafka.cpp +++ b/lib/formats/json_kafka.cpp @@ -5,178 +5,165 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; -const char * JsonKafkaFormat::villasToKafkaType(enum SignalType vt) -{ - switch (vt) { - case SignalType::FLOAT: - return "double"; +const char *JsonKafkaFormat::villasToKafkaType(enum SignalType vt) { + switch (vt) { + case SignalType::FLOAT: + return "double"; - case SignalType::INTEGER: - return "int64"; + case SignalType::INTEGER: + return "int64"; - case SignalType::BOOLEAN: - return "boolean"; + case SignalType::BOOLEAN: + return "boolean"; - default: - case SignalType::COMPLEX: - case SignalType::INVALID: - return "unknown"; - } + default: + case SignalType::COMPLEX: + case SignalType::INVALID: + return "unknown"; + } } -int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_payload, *json_fields, *json_field, *json_value; +int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_t *json_payload, *json_fields, *json_field, *json_value; - json_fields = json_array(); - json_payload = json_object(); + json_fields = json_array(); + json_payload = json_object(); - // Include sample timestamp - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - json_field = json_pack("{ s: s, s: b, s: s }", - "type", "int64", - "optional", false, - "field", "timestamp" - ); + // Include sample timestamp + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", "optional", + false, "field", "timestamp"); - uint64_t ts_origin_ms = smp->ts.origin.tv_sec * 1e3 + smp->ts.origin.tv_nsec / 1e6; - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, "timestamp", json_integer(ts_origin_ms)); - } + uint64_t ts_origin_ms = + smp->ts.origin.tv_sec * 1e3 + smp->ts.origin.tv_nsec / 1e6; + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, "timestamp", json_integer(ts_origin_ms)); + } - // Include sample sequence no - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - json_field = json_pack("{ s: s, s: b, s: s }", - "type", "int64", - "optional", false, - "field", "sequence" - ); + // Include sample sequence no + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", "optional", + false, "field", "sequence"); - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, "sequence", json_integer(smp->sequence)); - } + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, "sequence", json_integer(smp->sequence)); + } - // Include sample data - for (size_t i = 0; i < MIN(smp->length, smp->signals->size()); i++) { - const auto sig = smp->signals->getByIndex(i); - const auto *data = &smp->data[i]; + // Include sample data + for (size_t i = 0; i < MIN(smp->length, smp->signals->size()); i++) { + const auto sig = smp->signals->getByIndex(i); + const auto *data = &smp->data[i]; - json_field = json_pack("{ s: s, s: b, s: s }", - "type", villasToKafkaType(sig->type), - "optional", false, - "field", sig->name - ); + json_field = + json_pack("{ s: s, s: b, s: s }", "type", villasToKafkaType(sig->type), + "optional", false, "field", sig->name); - json_value = data->toJson(sig->type); + json_value = data->toJson(sig->type); - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, sig->name.c_str(), json_value); - } + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, sig->name.c_str(), json_value); + } - json_object_set_new(json_schema, "fields", json_fields); + json_object_set_new(json_schema, "fields", json_fields); - json_incref(json_schema); - *json_smp = json_pack("{ s: o, s: o }", - "schema", json_schema, - "payload", json_payload - ); - if (*json_smp == nullptr) - return -1; + json_incref(json_schema); + *json_smp = json_pack("{ s: o, s: o }", "schema", json_schema, "payload", + json_payload); + if (*json_smp == nullptr) + return -1; - return 0; + return 0; } -int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - json_t *json_payload, *json_value; +int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + json_t *json_payload, *json_value; - json_payload = json_object_get(json_smp, "payload"); - if (!json_payload) - return -1; + json_payload = json_object_get(json_smp, "payload"); + if (!json_payload) + return -1; - smp->length = 0; - smp->flags = 0; - smp->signals = signals; + smp->length = 0; + smp->flags = 0; + smp->signals = signals; - // Unpack timestamp - json_value = json_object_get(json_payload, "timestamp"); - if (json_value) { - uint64_t ts_origin_ms = json_integer_value(json_value); - smp->ts.origin = time_from_double(ts_origin_ms / 1e3); + // Unpack timestamp + json_value = json_object_get(json_payload, "timestamp"); + if (json_value) { + uint64_t ts_origin_ms = json_integer_value(json_value); + smp->ts.origin = time_from_double(ts_origin_ms / 1e3); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - // Unpack sequence no - json_value = json_object_get(json_payload, "sequence"); - if (json_value) { - smp->sequence = json_integer_value(json_value); + // Unpack sequence no + json_value = json_object_get(json_payload, "sequence"); + if (json_value) { + smp->sequence = json_integer_value(json_value); - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - // Unpack signal data - for (size_t i = 0; i < signals->size(); i++) { - auto sig = signals->getByIndex(i); + // Unpack signal data + for (size_t i = 0; i < signals->size(); i++) { + auto sig = signals->getByIndex(i); - json_value = json_object_get(json_payload, sig->name.c_str()); - if (!json_value) - continue; + json_value = json_object_get(json_payload, sig->name.c_str()); + if (!json_value) + continue; - smp->data[i].parseJson(sig->type, json_value); - smp->length++; - } + smp->data[i].parseJson(sig->type, json_value); + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } -void JsonKafkaFormat::parse(json_t *json) -{ - int ret; +void JsonKafkaFormat::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_schema_tmp = nullptr; + json_error_t err; + json_t *json_schema_tmp = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: o }", - "schema", &json_schema_tmp - ); - if (ret) - throw ConfigError(json, err, "node-config-format-json-kafka", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o }", "schema", &json_schema_tmp); + if (ret) + throw ConfigError(json, err, "node-config-format-json-kafka", + "Failed to parse format configuration"); - if (json_schema_tmp) { - if (!json_is_object(json_schema_tmp)) - throw ConfigError(json, "node-config-format-json-kafka-schema", "Kafka schema must be configured as a dictionary"); + if (json_schema_tmp) { + if (!json_is_object(json_schema_tmp)) + throw ConfigError(json, "node-config-format-json-kafka-schema", + "Kafka schema must be configured as a dictionary"); - if (json_schema) - json_decref(json_schema); + if (json_schema) + json_decref(json_schema); - json_schema = json_schema_tmp; - } + json_schema = json_schema_tmp; + } - JsonFormat::parse(json); + JsonFormat::parse(json); } -JsonKafkaFormat::JsonKafkaFormat(int fl) : - JsonFormat(fl) -{ - json_schema = json_pack("{ s: s, s: s }", - "type", "struct", - "name", "villas-node.Value" - ); +JsonKafkaFormat::JsonKafkaFormat(int fl) : JsonFormat(fl) { + json_schema = json_pack("{ s: s, s: s }", "type", "struct", "name", + "villas-node.Value"); } // Register format static char n[] = "json.kafka"; static char d[] = "JSON Kafka schema/payload messages"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_reserve.cpp b/lib/formats/json_reserve.cpp index 29913a1b8..14128a261 100644 --- a/lib/formats/json_reserve.cpp +++ b/lib/formats/json_reserve.cpp @@ -7,73 +7,68 @@ #include -#include #include +#include using namespace villas::node; #define JSON_RESERVE_INTEGER_TARGET 1 -int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_error_t err; - json_t *json_root; - json_t *json_data; - json_t *json_name; - json_t *json_unit; - json_t *json_value; - json_t *json_created = nullptr; - json_t *json_sequence = nullptr; +int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_error_t err; + json_t *json_root; + json_t *json_data; + json_t *json_name; + json_t *json_unit; + json_t *json_value; + json_t *json_created = nullptr; + json_t *json_sequence = nullptr; - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) - json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) + json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - json_sequence = json_integer(smp->sequence); + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + json_sequence = json_integer(smp->sequence); - json_data = json_array(); + json_data = json_array(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - if (!sig->name.empty()) - json_name = json_string(sig->name.c_str()); - else { - char name[32]; - snprintf(name, 32, "signal%u", i); + if (!sig->name.empty()) + json_name = json_string(sig->name.c_str()); + else { + char name[32]; + snprintf(name, 32, "signal%u", i); - json_name = json_string(name); - } + json_name = json_string(name); + } - if (!sig->unit.empty()) - json_unit = json_string(sig->unit.c_str()); - else - json_unit = nullptr; + if (!sig->unit.empty()) + json_unit = json_string(sig->unit.c_str()); + else + json_unit = nullptr; - json_value = json_pack_ex(&err, 0, "{ s: o, s: f }", - "name", json_name, - "value", smp->data[i].f - ); - if (!json_value) - continue; + json_value = json_pack_ex(&err, 0, "{ s: o, s: f }", "name", json_name, + "value", smp->data[i].f); + if (!json_value) + continue; - if (json_unit) - json_object_set_new(json_value, "unit", json_unit); - if (json_created) - json_object_set_new(json_value, "created", json_created); - if (json_sequence) - json_object_set_new(json_value, "sequence", json_sequence); + if (json_unit) + json_object_set_new(json_value, "unit", json_unit); + if (json_created) + json_object_set_new(json_value, "created", json_created); + if (json_sequence) + json_object_set_new(json_value, "sequence", json_sequence); - json_array_append_new(json_data, json_value); - } + json_array_append_new(json_data, json_value); + } - json_root = json_pack_ex(&err, 0, "{ s: o }", - "measurements", json_data - ); - if (json_root == nullptr) - return -1; + json_root = json_pack_ex(&err, 0, "{ s: o }", "measurements", json_data); + if (json_root == nullptr) + return -1; #if 0 #ifdef JSON_RESERVE_INTEGER_TARGET if (io->out.node) { @@ -94,28 +89,24 @@ int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) #endif #endif - *json_smp = json_root; + *json_smp = json_root; - return 0; + return 0; } -int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret, idx; - double created = -1; - json_error_t err; - json_t *json_value, *json_data = nullptr; - json_t *json_origin = nullptr, *json_target = nullptr; - size_t i; +int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret, idx; + double created = -1; + json_error_t err; + 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 }", - "origin", &json_origin, - "target", &json_target, - "measurements", &json_data, - "setpoints", &json_data - ); - if (ret) - return -1; + ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: o, s?: o, s?: o }", + "origin", &json_origin, "target", &json_target, + "measurements", &json_data, "setpoints", &json_data); + if (ret) + return -1; #if 0 #ifdef JSON_RESERVE_INTEGER_TARGET @@ -146,57 +137,58 @@ int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) } #endif #endif - if (!json_data || !json_is_array(json_data)) - return -1; + if (!json_data || !json_is_array(json_data)) + return -1; - smp->flags = 0; - smp->length = 0; + smp->flags = 0; + smp->length = 0; - json_array_foreach(json_data, i, json_value) { - const char *name, *unit = nullptr; - double value; + json_array_foreach(json_data, i, json_value) { + const char *name, *unit = nullptr; + double value; - ret = json_unpack_ex(json_value, &err, 0, "{ s: s, s?: s, s: F, s?: F }", - "name", &name, - "unit", &unit, - "value", &value, - "created", &created - ); - if (ret) - return -1; + ret = json_unpack_ex(json_value, &err, 0, "{ s: s, s?: s, s: F, s?: F }", + "name", &name, "unit", &unit, "value", &value, + "created", &created); + if (ret) + return -1; - auto sig = signals->getByName(name); - if (sig) - idx = signals->getIndexByName(name); - else { - ret = sscanf(name, "signal_%d", &idx); - if (ret != 1) - continue; - } + auto sig = signals->getByName(name); + if (sig) + idx = signals->getIndexByName(name); + else { + ret = sscanf(name, "signal_%d", &idx); + if (ret != 1) + continue; + } - if (idx < 0) - return -1; + if (idx < 0) + return -1; - if (idx < (int) smp->capacity) { - smp->data[idx].f = value; + if (idx < (int)smp->capacity) { + smp->data[idx].f = value; - if (idx >= (int) smp->length) - smp->length = idx + 1; - } - } + if (idx >= (int)smp->length) + smp->length = idx + 1; + } + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (created > 0) { - smp->ts.origin = time_from_double(created * 1e-3); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + if (created > 0) { + smp->ts.origin = time_from_double(created * 1e-3); + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - return smp->length > 0 ? 1 : 0; + return smp->length > 0 ? 1 : 0; } // Register format static char n[] = "json.reserve"; static char d[] = "RESERVE JSON format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/line.cpp b/lib/formats/line.cpp index e5ed5ad59..07fb20115 100644 --- a/lib/formats/line.cpp +++ b/lib/formats/line.cpp @@ -5,161 +5,161 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::node; -int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; +int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; - for (i = 0; i < cnt && off < len; i++) - off += sprintLine(buf + off, len - off, smps[i]); + for (i = 0; i < cnt && off < len; i++) + off += sprintLine(buf + off, len - off, smps[i]); - if (wbytes) - *wbytes = off; + if (wbytes) + *wbytes = off; - return i; + return i; } -int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; +int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; - if (skip_first_line) { - if (!first_line_skipped) { - while (off < len) { - if (buf[off++] == delimiter) - break; - } + if (skip_first_line) { + if (!first_line_skipped) { + while (off < len) { + if (buf[off++] == delimiter) + break; + } - first_line_skipped = true; - } - } + first_line_skipped = true; + } + } - for (i = 0; i < cnt && off < len; i++) { - // Skip comment lines - if (buf[off] == comment) { - while (off < len) { - if (buf[++off] == delimiter) - break; - } + for (i = 0; i < cnt && off < len; i++) { + // Skip comment lines + if (buf[off] == comment) { + while (off < len) { + if (buf[++off] == delimiter) + break; + } - if (off == len) - break; - } + if (off == len) + break; + } - off += sscanLine(buf + off, len - off, smps[i]); - } + off += sscanLine(buf + off, len - off, smps[i]); + } - if (rbytes) - *rbytes = off; + if (rbytes) + *rbytes = off; - return i; + return i; } -int LineFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; +int LineFormat::print(FILE *f, const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; - if (cnt > 0 && smps[0]->signals) - header(f, smps[0]->signals); + if (cnt > 0 && smps[0]->signals) + header(f, smps[0]->signals); - for (i = 0; i < cnt; i++) { - size_t wbytes; + for (i = 0; i < cnt; i++) { + size_t wbytes; - ret = sprint(out.buffer, out.buflen, &wbytes, &smps[i], 1); - if (ret < 0) - return ret; + ret = sprint(out.buffer, out.buflen, &wbytes, &smps[i], 1); + if (ret < 0) + return ret; - fwrite(out.buffer, wbytes, 1, f); - } + fwrite(out.buffer, wbytes, 1, f); + } - return i; + return i; } -int LineFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - ssize_t bytes; +int LineFormat::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + int ret; + unsigned i; + ssize_t bytes; - if (skip_first_line) { - if (!first_line_skipped) { - bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); - if (bytes < 0) - return -1; // An error or eof occured + if (skip_first_line) { + if (!first_line_skipped) { + bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); + if (bytes < 0) + return -1; // An error or eof occured - first_line_skipped = true; - } - } + first_line_skipped = true; + } + } - for (i = 0; i < cnt && !feof(f); i++) { - size_t rbytes; - char *ptr; + for (i = 0; i < cnt && !feof(f); i++) { + size_t rbytes; + char *ptr; -skip: bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); - if (feof(f)) - break; - else if (bytes < 0) - return -1; // An error or eof occured + skip: + bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); + if (feof(f)) + break; + else if (bytes < 0) + return -1; // An error or eof occured - // Skip whitespaces, empty and comment lines - for (ptr = in.buffer; isspace(*ptr); ptr++); + // Skip whitespaces, empty and comment lines + for (ptr = in.buffer; isspace(*ptr); ptr++) + ; - if (ptr[0] == '\0' || ptr[0] == comment) - goto skip; + if (ptr[0] == '\0' || ptr[0] == comment) + goto skip; - ret = sscan(in.buffer, bytes, &rbytes, &smps[i], 1); - if (ret < 0) - return ret; - } + ret = sscan(in.buffer, bytes, &rbytes, &smps[i], 1); + if (ret < 0) + return ret; + } - return i; + return i; } -void LineFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - const char *delim = nullptr; - const char *com = nullptr; - int header = -1; - int skip = -1; +void LineFormat::parse(json_t *json) { + int ret; + json_error_t err; + const char *delim = nullptr; + const char *com = nullptr; + int header = -1; + int skip = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: b, s?: s }", - "delimiter", &delim, - "header", &header, - "skip_first_line", &skip, - "comment_prefix", &com - ); - if (ret) - throw ConfigError(json, err, "node-config-format-line", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: b, s?: s }", + "delimiter", &delim, "header", &header, + "skip_first_line", &skip, "comment_prefix", &com); + if (ret) + throw ConfigError(json, err, "node-config-format-line", + "Failed to parse format configuration"); - if (delim) { - if (strlen(delim) != 1) - throw ConfigError(json, "node-config-format-line-delimiter", "Line delimiter must be a single character!"); + if (delim) { + if (strlen(delim) != 1) + throw ConfigError(json, "node-config-format-line-delimiter", + "Line delimiter must be a single character!"); - delimiter = delim[0]; - } + delimiter = delim[0]; + } - if (com) { - if (strlen(com) != 1) - throw ConfigError(json, "node-config-format-line-comment_prefix", "Comment prefix must be a single character!"); + if (com) { + if (strlen(com) != 1) + throw ConfigError(json, "node-config-format-line-comment_prefix", + "Comment prefix must be a single character!"); - comment = com[0]; - } + comment = com[0]; + } - if (header >= 0) - print_header = header; + if (header >= 0) + print_header = header; - if (skip >= 0) - skip_first_line = skip; + if (skip >= 0) + skip_first_line = skip; - Format::parse(json); + Format::parse(json); } diff --git a/lib/formats/msg.cpp b/lib/formats/msg.cpp index 85b672b82..31818b8f2 100644 --- a/lib/formats/msg.cpp +++ b/lib/formats/msg.cpp @@ -9,127 +9,126 @@ #include #include +#include #include #include #include -#include using namespace villas; using namespace villas::node; -void villas::node::msg_ntoh(struct Message *m) -{ - msg_hdr_ntoh(m); +void villas::node::msg_ntoh(struct Message *m) { + msg_hdr_ntoh(m); - for (int i = 0; i < m->length; i++) - m->data[i].i = ntohl(m->data[i].i); + for (int i = 0; i < m->length; i++) + m->data[i].i = ntohl(m->data[i].i); } -void villas::node::msg_hton(struct Message *m) -{ - for (int i = 0; i < m->length; i++) - m->data[i].i = htonl(m->data[i].i); +void villas::node::msg_hton(struct Message *m) { + for (int i = 0; i < m->length; i++) + m->data[i].i = htonl(m->data[i].i); - msg_hdr_hton(m); + msg_hdr_hton(m); } -void villas::node::msg_hdr_hton(struct Message *m) -{ - m->length = htons(m->length); - m->sequence = htonl(m->sequence); - m->ts.sec = htonl(m->ts.sec); - m->ts.nsec = htonl(m->ts.nsec); +void villas::node::msg_hdr_hton(struct Message *m) { + m->length = htons(m->length); + m->sequence = htonl(m->sequence); + m->ts.sec = htonl(m->ts.sec); + m->ts.nsec = htonl(m->ts.nsec); } -void villas::node::msg_hdr_ntoh(struct Message *m) -{ - m->length = ntohs(m->length); - m->sequence = ntohl(m->sequence); - m->ts.sec = ntohl(m->ts.sec); - m->ts.nsec = ntohl(m->ts.nsec); +void villas::node::msg_hdr_ntoh(struct Message *m) { + m->length = ntohs(m->length); + m->sequence = ntohl(m->sequence); + m->ts.sec = ntohl(m->ts.sec); + m->ts.nsec = ntohl(m->ts.nsec); } -int villas::node::msg_verify(const struct Message *m) -{ - if (m->version != MSG_VERSION) - return -1; - else if (m->type != MSG_TYPE_DATA) - return -2; - else if (m->reserved1 != 0) - return -3; - else - return 0; +int villas::node::msg_verify(const struct Message *m) { + if (m->version != MSG_VERSION) + return -1; + else if (m->type != MSG_TYPE_DATA) + return -2; + else if (m->reserved1 != 0) + return -3; + else + return 0; } -int villas::node::msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalList::Ptr sigs, uint8_t *source_index) -{ - int ret; - unsigned i; +int villas::node::msg_to_sample(const struct Message *msg, struct Sample *smp, + const SignalList::Ptr sigs, + uint8_t *source_index) { + int ret; + unsigned i; - ret = msg_verify(msg); - if (ret) - return ret; + ret = msg_verify(msg); + if (ret) + return ret; - unsigned len = MIN(msg->length, smp->capacity); - for (i = 0; i < MIN(len, sigs->size()); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - return -1; + unsigned len = MIN(msg->length, smp->capacity); + for (i = 0; i < MIN(len, sigs->size()); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::FLOAT: - smp->data[i].f = msg->data[i].f; - break; + switch (sig->type) { + case SignalType::FLOAT: + smp->data[i].f = msg->data[i].f; + break; - case SignalType::INTEGER: - smp->data[i].i = msg->data[i].i; - break; + case SignalType::INTEGER: + smp->data[i].i = msg->data[i].i; + break; - default: - return -1; - } - } + default: + return -1; + } + } - smp->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->length = i; - smp->sequence = msg->sequence; - MSG_TS(msg, smp->ts.origin); + smp->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->length = i; + smp->sequence = msg->sequence; + MSG_TS(msg, smp->ts.origin); - if (source_index) - *source_index = msg->source_index; + if (source_index) + *source_index = msg->source_index; - return 0; + return 0; } -int villas::node::msg_from_sample(struct Message *msg_in, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index) -{ - msg_in->type = MSG_TYPE_DATA; - msg_in->version = MSG_VERSION; - msg_in->reserved1 = 0; - msg_in->source_index = source_index; - msg_in->length = (uint16_t) smp->length; - msg_in->sequence = (uint32_t) smp->sequence; - msg_in->ts.sec = smp->ts.origin.tv_sec; - msg_in->ts.nsec = smp->ts.origin.tv_nsec; +int villas::node::msg_from_sample(struct Message *msg_in, + const struct Sample *smp, + const SignalList::Ptr sigs, + uint8_t source_index) { + msg_in->type = MSG_TYPE_DATA; + msg_in->version = MSG_VERSION; + msg_in->reserved1 = 0; + msg_in->source_index = source_index; + msg_in->length = (uint16_t)smp->length; + msg_in->sequence = (uint32_t)smp->sequence; + msg_in->ts.sec = smp->ts.origin.tv_sec; + msg_in->ts.nsec = smp->ts.origin.tv_nsec; - for (unsigned i = 0; i < smp->length; i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::FLOAT: - msg_in->data[i].f = smp->data[i].f; - break; + switch (sig->type) { + case SignalType::FLOAT: + msg_in->data[i].f = smp->data[i].f; + break; - case SignalType::INTEGER: - msg_in->data[i].i = smp->data[i].i; - break; + case SignalType::INTEGER: + msg_in->data[i].i = smp->data[i].i; + break; - default: - return -1; - } - } + default: + return -1; + } + } - return 0; + return 0; } diff --git a/lib/formats/opal_asyncip.cpp b/lib/formats/opal_asyncip.cpp index e19bc1c96..eb438329e 100644 --- a/lib/formats/opal_asyncip.cpp +++ b/lib/formats/opal_asyncip.cpp @@ -7,111 +7,110 @@ #include -#include #include +#include #include #include using namespace villas; using namespace villas::node; -int OpalAsyncIPFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - auto *ptr = buf; - ssize_t slen = len; +int OpalAsyncIPFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + auto *ptr = buf; + ssize_t slen = len; - for (i = 0; i < cnt && ptr - buf < slen; i++) { - auto *pl = (struct Payload *) ptr; - auto *smp = smps[i]; + for (i = 0; i < cnt && ptr - buf < slen; i++) { + auto *pl = (struct Payload *)ptr; + auto *smp = smps[i]; - auto wlen = smp->length * sizeof(double) + sizeof(struct Payload); - if (wlen > len) - return -1; + auto wlen = smp->length * sizeof(double) + sizeof(struct Payload); + if (wlen > len) + return -1; - pl->dev_id = htole16(dev_id); - pl->msg_id = htole32(smp->sequence); - pl->msg_len = htole16(smp->length * sizeof(double)); + pl->dev_id = htole16(dev_id); + pl->msg_id = htole32(smp->sequence); + pl->msg_len = htole16(smp->length * sizeof(double)); - if (smp->length > MAXSIZE) - logger->warn("Can not sent more then {} signals via opal.asyncip format. We only send the first {}..", MAXSIZE, MAXSIZE); + if (smp->length > MAXSIZE) + logger->warn("Can not sent more then {} signals via opal.asyncip format. " + "We only send the first {}..", + MAXSIZE, MAXSIZE); - for (unsigned j = 0; j < MIN(MAXSIZE, smp->length); j++) { - auto sig = smp->signals->getByIndex(j); - auto d = smp->data[j]; + for (unsigned j = 0; j < MIN(MAXSIZE, smp->length); j++) { + auto sig = smp->signals->getByIndex(j); + auto d = smp->data[j]; - d = d.cast(sig->type, SignalType::FLOAT); - d.i = htole64(d.i); + d = d.cast(sig->type, SignalType::FLOAT); + d.i = htole64(d.i); - pl->data[j] = d.f; - } + pl->data[j] = d.f; + } - ptr += wlen; - } + ptr += wlen; + } - if (wbytes) - *wbytes = ptr - buf; + if (wbytes) + *wbytes = ptr - buf; - return i; + return i; } -int OpalAsyncIPFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - auto *ptr = buf; +int OpalAsyncIPFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i; + auto *ptr = buf; - if (len % 8 != 0) - return -1; // Packet size is invalid: Must be multiple of 8 bytes + if (len % 8 != 0) + return -1; // Packet size is invalid: Must be multiple of 8 bytes - for (i = 0; i < cnt && ptr - buf + sizeof(struct Payload) < len; i++) { - auto *pl = (struct Payload *) ptr; - auto *smp = smps[i]; + for (i = 0; i < cnt && ptr - buf + sizeof(struct Payload) < len; i++) { + auto *pl = (struct Payload *)ptr; + auto *smp = smps[i]; - auto rlen = le16toh(pl->msg_len); - if (len < ptr - buf + rlen + sizeof(struct Payload)) - return -2; + auto rlen = le16toh(pl->msg_len); + if (len < ptr - buf + rlen + sizeof(struct Payload)) + return -2; - smp->sequence = le32toh(pl->msg_id); - smp->length = rlen / sizeof(double); - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->signals = signals; + smp->sequence = le32toh(pl->msg_id); + smp->length = rlen / sizeof(double); + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->signals = signals; - for (unsigned j = 0; j < MIN(smp->length, smp->capacity); j++) { - auto sig = signals->getByIndex(j); + for (unsigned j = 0; j < MIN(smp->length, smp->capacity); j++) { + auto sig = signals->getByIndex(j); - SignalData d; - d.f = pl->data[j]; - d.i = le64toh(d.i); + SignalData d; + d.f = pl->data[j]; + d.i = le64toh(d.i); - smp->data[j] = d.cast(SignalType::FLOAT, sig->type); - } + smp->data[j] = d.cast(SignalType::FLOAT, sig->type); + } - ptr += rlen + sizeof(struct Payload); - } + ptr += rlen + sizeof(struct Payload); + } - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return i; + return i; } -void OpalAsyncIPFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - int did = -1; +void OpalAsyncIPFormat::parse(json_t *json) { + int ret; + json_error_t err; + int did = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "dev_id", &did - ); - if (ret) - throw ConfigError(json, err, "node-config-format-opal-asyncip", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i }", "dev_id", &did); + if (ret) + throw ConfigError(json, err, "node-config-format-opal-asyncip", + "Failed to parse format configuration"); - if (did >= 0) - dev_id = did; + if (did >= 0) + dev_id = did; - Format::parse(json); + Format::parse(json); } -static -OpalAsyncIPFormatPlugin p; +static OpalAsyncIPFormatPlugin p; diff --git a/lib/formats/protobuf.cpp b/lib/formats/protobuf.cpp index 41828733c..70b9796a7 100644 --- a/lib/formats/protobuf.cpp +++ b/lib/formats/protobuf.cpp @@ -5,222 +5,229 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include #include using namespace villas::node; -enum SignalType ProtobufFormat::detect(const Villas__Node__Value *val) -{ - switch (val->value_case) { - case VILLAS__NODE__VALUE__VALUE_F: - return SignalType::FLOAT; +enum SignalType ProtobufFormat::detect(const Villas__Node__Value *val) { + switch (val->value_case) { + case VILLAS__NODE__VALUE__VALUE_F: + return SignalType::FLOAT; - case VILLAS__NODE__VALUE__VALUE_I: - return SignalType::INTEGER; + case VILLAS__NODE__VALUE__VALUE_I: + return SignalType::INTEGER; - case VILLAS__NODE__VALUE__VALUE_B: - return SignalType::BOOLEAN; + case VILLAS__NODE__VALUE__VALUE_B: + return SignalType::BOOLEAN; - case VILLAS__NODE__VALUE__VALUE_Z: - return SignalType::COMPLEX; + case VILLAS__NODE__VALUE__VALUE_Z: + return SignalType::COMPLEX; - case VILLAS__NODE__VALUE__VALUE__NOT_SET: - default: - return SignalType::INVALID; - } + case VILLAS__NODE__VALUE__VALUE__NOT_SET: + default: + return SignalType::INVALID; + } } -int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned psz; +int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned psz; - auto *pb_msg = new Villas__Node__Message; - if (!pb_msg) - throw MemoryAllocationError(); + auto *pb_msg = new Villas__Node__Message; + if (!pb_msg) + throw MemoryAllocationError(); - villas__node__message__init(pb_msg); + villas__node__message__init(pb_msg); - pb_msg->n_samples = cnt; - pb_msg->samples = new Villas__Node__Sample*[pb_msg->n_samples]; - if (!pb_msg->samples) - throw MemoryAllocationError(); + pb_msg->n_samples = cnt; + pb_msg->samples = new Villas__Node__Sample *[pb_msg->n_samples]; + if (!pb_msg->samples) + throw MemoryAllocationError(); - for (unsigned i = 0; i < pb_msg->n_samples; i++) { - Villas__Node__Sample *pb_smp = pb_msg->samples[i] = new Villas__Node__Sample; - if (!pb_msg->samples[i]) - throw MemoryAllocationError(); + for (unsigned i = 0; i < pb_msg->n_samples; i++) { + Villas__Node__Sample *pb_smp = pb_msg->samples[i] = + new Villas__Node__Sample; + if (!pb_msg->samples[i]) + throw MemoryAllocationError(); - villas__node__sample__init(pb_smp); + villas__node__sample__init(pb_smp); - const struct Sample *smp = smps[i]; + const struct Sample *smp = smps[i]; - pb_smp->type = VILLAS__NODE__SAMPLE__TYPE__DATA; + pb_smp->type = VILLAS__NODE__SAMPLE__TYPE__DATA; - if (flags & smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - pb_smp->has_sequence = 1; - pb_smp->sequence = smp->sequence; - } + if (flags & smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + pb_smp->has_sequence = 1; + pb_smp->sequence = smp->sequence; + } - if (flags & smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - pb_smp->timestamp = new Villas__Node__Timestamp; - if (!pb_smp->timestamp) - throw MemoryAllocationError(); + if (flags & smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + pb_smp->timestamp = new Villas__Node__Timestamp; + if (!pb_smp->timestamp) + throw MemoryAllocationError(); - villas__node__timestamp__init(pb_smp->timestamp); + villas__node__timestamp__init(pb_smp->timestamp); - pb_smp->timestamp->sec = smp->ts.origin.tv_sec; - pb_smp->timestamp->nsec = smp->ts.origin.tv_nsec; - } + pb_smp->timestamp->sec = smp->ts.origin.tv_sec; + pb_smp->timestamp->nsec = smp->ts.origin.tv_nsec; + } - pb_smp->n_values = smp->length; - pb_smp->values = new Villas__Node__Value*[pb_smp->n_values]; - if (!pb_smp->values) - throw MemoryAllocationError(); + pb_smp->n_values = smp->length; + pb_smp->values = new Villas__Node__Value *[pb_smp->n_values]; + if (!pb_smp->values) + throw MemoryAllocationError(); - for (unsigned j = 0; j < pb_smp->n_values; j++) { - Villas__Node__Value *pb_val = pb_smp->values[j] = new Villas__Node__Value; - if (!pb_val) - throw MemoryAllocationError(); + for (unsigned j = 0; j < pb_smp->n_values; j++) { + Villas__Node__Value *pb_val = pb_smp->values[j] = new Villas__Node__Value; + if (!pb_val) + throw MemoryAllocationError(); - villas__node__value__init(pb_val); + villas__node__value__init(pb_val); - enum SignalType fmt = sample_format(smp, j); - switch (fmt) { - case SignalType::FLOAT: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_F; - pb_val->f = smp->data[j].f; - break; + enum SignalType fmt = sample_format(smp, j); + switch (fmt) { + case SignalType::FLOAT: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_F; + pb_val->f = smp->data[j].f; + break; - case SignalType::INTEGER: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_I; - pb_val->i = smp->data[j].i; - break; + case SignalType::INTEGER: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_I; + pb_val->i = smp->data[j].i; + break; - case SignalType::BOOLEAN: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_B; - pb_val->b = smp->data[j].b; - break; + case SignalType::BOOLEAN: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_B; + pb_val->b = smp->data[j].b; + break; - case SignalType::COMPLEX: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_Z; - pb_val->z = new Villas__Node__Complex; - if (!pb_val->z) - throw MemoryAllocationError(); + case SignalType::COMPLEX: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_Z; + pb_val->z = new Villas__Node__Complex; + if (!pb_val->z) + throw MemoryAllocationError(); - villas__node__complex__init(pb_val->z); + villas__node__complex__init(pb_val->z); - pb_val->z->real = std::real(smp->data[j].z); - pb_val->z->imag = std::imag(smp->data[j].z); - break; + pb_val->z->real = std::real(smp->data[j].z); + pb_val->z->imag = std::imag(smp->data[j].z); + break; - case SignalType::INVALID: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE__NOT_SET; - break; - } - } - } + case SignalType::INVALID: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE__NOT_SET; + break; + } + } + } - psz = villas__node__message__get_packed_size(pb_msg); + psz = villas__node__message__get_packed_size(pb_msg); - if (psz > len) - goto out; + if (psz > len) + goto out; - villas__node__message__pack(pb_msg, (uint8_t *) buf); - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__pack(pb_msg, (uint8_t *)buf); + villas__node__message__free_unpacked(pb_msg, nullptr); - *wbytes = psz; + *wbytes = psz; - return cnt; + return cnt; out: - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__free_unpacked(pb_msg, nullptr); - return -1; + return -1; } -int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i, j; - Villas__Node__Message *pb_msg; +int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i, j; + Villas__Node__Message *pb_msg; - pb_msg = villas__node__message__unpack(nullptr, len, (uint8_t *) buf); - if (!pb_msg) - return -1; + pb_msg = villas__node__message__unpack(nullptr, len, (uint8_t *)buf); + if (!pb_msg) + return -1; - for (i = 0; i < MIN(pb_msg->n_samples, cnt); i++) { - struct Sample *smp = smps[i]; - Villas__Node__Sample *pb_smp = pb_msg->samples[i]; + for (i = 0; i < MIN(pb_msg->n_samples, cnt); i++) { + struct Sample *smp = smps[i]; + Villas__Node__Sample *pb_smp = pb_msg->samples[i]; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - if (pb_smp->type != VILLAS__NODE__SAMPLE__TYPE__DATA) - throw RuntimeError("Parsed non supported message type. Skipping"); + if (pb_smp->type != VILLAS__NODE__SAMPLE__TYPE__DATA) + throw RuntimeError("Parsed non supported message type. Skipping"); - if (pb_smp->has_sequence) { - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - smp->sequence = pb_smp->sequence; - } + if (pb_smp->has_sequence) { + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + smp->sequence = pb_smp->sequence; + } - if (pb_smp->timestamp) { - 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; - } + if (pb_smp->timestamp) { + 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; + } - for (j = 0; j < MIN(pb_smp->n_values, smp->capacity); j++) { - Villas__Node__Value *pb_val = pb_smp->values[j]; + for (j = 0; j < MIN(pb_smp->n_values, smp->capacity); j++) { + Villas__Node__Value *pb_val = pb_smp->values[j]; - enum SignalType fmt = detect(pb_val); + enum SignalType fmt = detect(pb_val); - auto sig = smp->signals->getByIndex(j); - if (!sig) - return -1; + auto sig = smp->signals->getByIndex(j); + if (!sig) + return -1; - if (sig->type != fmt) - throw RuntimeError("Received invalid data type in Protobuf payload: Received {}, expected {} for signal {} (index {}).", - signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); + if (sig->type != fmt) + throw RuntimeError("Received invalid data type in Protobuf payload: " + "Received {}, expected {} for signal {} (index {}).", + signalTypeToString(fmt), + signalTypeToString(sig->type), sig->name, i); - switch (sig->type) { - case SignalType::FLOAT: - smp->data[j].f = pb_val->f; - break; + switch (sig->type) { + case SignalType::FLOAT: + smp->data[j].f = pb_val->f; + break; - case SignalType::INTEGER: - smp->data[j].i = pb_val->i; - break; + case SignalType::INTEGER: + smp->data[j].i = pb_val->i; + break; - case SignalType::BOOLEAN: - smp->data[j].b = pb_val->b; - break; + case SignalType::BOOLEAN: + smp->data[j].b = pb_val->b; + break; - case SignalType::COMPLEX: - smp->data[j].z = std::complex(pb_val->z->real, pb_val->z->imag); - break; + case SignalType::COMPLEX: + smp->data[j].z = std::complex(pb_val->z->real, pb_val->z->imag); + break; - default: { } - } - } + default: { + } + } + } - if (pb_smp->n_values > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (pb_smp->n_values > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - smp->length = j; - } + smp->length = j; + } - if (rbytes) - *rbytes = villas__node__message__get_packed_size(pb_msg); + if (rbytes) + *rbytes = villas__node__message__get_packed_size(pb_msg); - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__free_unpacked(pb_msg, nullptr); - return i; + return i; } // Register format static char n[] = "protobuf"; static char d[] = "Google Protobuf"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index e429c01d3..cc65fa7ce 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include #include +#include +#include +#include typedef float flt32_t; typedef double flt64_t; @@ -19,425 +19,520 @@ using namespace villas; using namespace villas::node; // Convert double to host byte order -#define SWAP_FLOAT_XTOH(o, b, n) ({ \ - union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ - x.i = (o) ? be ## b ## toh(x.i) : le ## b ## toh(x.i); \ - x.f; \ -}) +#define SWAP_FLOAT_XTOH(o, b, n) \ + ({ \ + union { \ + flt##b##_t f; \ + uint##b##_t i; \ + } x = {.f = n}; \ + x.i = (o) ? be##b##toh(x.i) : le##b##toh(x.i); \ + x.f; \ + }) // Convert double to big/little endian byte order -#define SWAP_FLOAT_HTOX(o, b, n) ({ \ - union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ - x.i = (o) ? htobe ## b (x.i) : htole ## b (x.i); \ - x.f; \ -}) +#define SWAP_FLOAT_HTOX(o, b, n) \ + ({ \ + union { \ + flt##b##_t f; \ + uint##b##_t i; \ + } x = {.f = n}; \ + x.i = (o) ? htobe##b(x.i) : htole##b(x.i); \ + x.f; \ + }) // Convert integer of varying width to host byte order -#define SWAP_INT_XTOH(o, b, n) (o ? be ## b ## toh(n) : le ## b ## toh(n)) +#define SWAP_INT_XTOH(o, b, n) (o ? be##b##toh(n) : le##b##toh(n)) // Convert integer of varying width to big/little endian byte order -#define SWAP_INT_HTOX(o, b, n) (o ? htobe ## b (n) : htole ## b (n)) +#define SWAP_INT_HTOX(o, b, n) (o ? htobe##b(n) : htole##b(n)) -int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int o = 0; - size_t nlen; +int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + int o = 0; + size_t nlen; - void *vbuf = (char *) buf; // Avoid warning about invalid pointer cast + void *vbuf = (char *)buf; // Avoid warning about invalid pointer cast - int8_t *i8 = (int8_t *) vbuf; - int16_t *i16 = (int16_t *) vbuf; - int32_t *i32 = (int32_t *) vbuf; - int64_t *i64 = (int64_t *) vbuf; - float *f32 = (float *) vbuf; - double *f64 = (double *) vbuf; + int8_t *i8 = (int8_t *)vbuf; + int16_t *i16 = (int16_t *)vbuf; + int32_t *i32 = (int32_t *)vbuf; + int64_t *i64 = (int64_t *)vbuf; + float *f32 = (float *)vbuf; + double *f64 = (double *)vbuf; #ifdef HAS_128BIT - __int128 *i128 = (__int128 *) vbuf; - __float128 *f128 = (__float128 *) vbuf; + __int128 *i128 = (__int128 *)vbuf; + __float128 *f128 = (__float128 *)vbuf; #endif - for (unsigned i = 0; i < cnt; i++) { - const struct Sample *smp = smps[i]; + for (unsigned i = 0; i < cnt; i++) { + const struct Sample *smp = smps[i]; - /* First three values are sequence, seconds and nano-seconds timestamps + /* First three values are sequence, seconds and nano-seconds timestamps * * These fields are always encoded as integers! */ - if (fake) { - // Check length - nlen = (o + 3) * (bits / 8); - if (nlen >= len) - goto out; + if (fake) { + // Check length + nlen = (o + 3) * (bits / 8); + if (nlen >= len) + goto out; - switch (bits) { - case 8: - i8[o++] = smp->sequence; - i8[o++] = smp->ts.origin.tv_sec; - i8[o++] = smp->ts.origin.tv_nsec; - break; + switch (bits) { + case 8: + i8[o++] = smp->sequence; + i8[o++] = smp->ts.origin.tv_sec; + i8[o++] = smp->ts.origin.tv_nsec; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->sequence); - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->ts.origin.tv_sec); - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->ts.origin.tv_nsec); - break; + case 16: + i16[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->sequence); + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, + smp->ts.origin.tv_sec); + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, + smp->ts.origin.tv_nsec); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->sequence); - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->ts.origin.tv_sec); - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->ts.origin.tv_nsec); - break; + case 32: + i32[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->sequence); + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, + smp->ts.origin.tv_sec); + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, + smp->ts.origin.tv_nsec); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->sequence); - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->ts.origin.tv_sec); - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->ts.origin.tv_nsec); - break; + case 64: + i64[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->sequence); + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, + smp->ts.origin.tv_sec); + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, + smp->ts.origin.tv_nsec); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->sequence); - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->ts.origin.tv_sec); - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->ts.origin.tv_nsec); - break; + case 128: + i128[o++] = + SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->sequence); + i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, + smp->ts.origin.tv_sec); + i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, + smp->ts.origin.tv_nsec); + break; #endif - } - } + } + } - for (unsigned j = 0; j < smp->length; j++) { - enum SignalType fmt = sample_format(smp, j); - const union SignalData *data = &smp->data[j]; + for (unsigned j = 0; j < smp->length; j++) { + enum SignalType fmt = sample_format(smp, j); + const union SignalData *data = &smp->data[j]; - // Check length - nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); - if (nlen >= len) - goto out; + // Check length + nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); + if (nlen >= len) + goto out; - switch (fmt) { - case SignalType::FLOAT: - switch (bits) { - case 8: - i8 [o++] = -1; - break; // Not supported + switch (fmt) { + case SignalType::FLOAT: + switch (bits) { + case 8: + i8[o++] = -1; + break; // Not supported - case 16: - i16[o++] = -1; - break; // Not supported + case 16: + i16[o++] = -1; + break; // Not supported - case 32: - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) data->f); - break; + case 32: + f32[o++] = + SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float)data->f); + break; - case 64: - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, data->f); - break; + case 64: + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, data->f); + break; #ifdef HAS_128BIT - case 128: f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, data->f); break; + case 128: + f128[o++] = + SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, data->f); + break; #endif - } - break; + } + break; - case SignalType::INTEGER: - switch (bits) { - case 8: - i8 [o++] = data->i; - break; + case SignalType::INTEGER: + switch (bits) { + case 8: + i8[o++] = data->i; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->i); - break; + case 16: + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->i); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->i); - break; + case 32: + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->i); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->i); - break; + case 64: + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->i); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->i); - break; + case 128: + i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->i); + break; #endif - } - break; + } + break; - case SignalType::BOOLEAN: - switch (bits) { - case 8: - i8 [o++] = data->b ? 1 : 0; - break; + case SignalType::BOOLEAN: + switch (bits) { + case 8: + i8[o++] = data->b ? 1 : 0; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->b ? 1 : 0); - break; + case 16: + i16[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->b ? 1 : 0); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->b ? 1 : 0); - break; + case 32: + i32[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->b ? 1 : 0); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->b ? 1 : 0); - break; + case 64: + i64[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->b ? 1 : 0); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->b ? 1 : 0); - break; + case 128: + i128[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->b ? 1 : 0); + break; #endif - } - break; + } + break; - case SignalType::COMPLEX: - switch (bits) { - case 8: - i8 [o++] = -1; // Not supported - i8 [o++] = -1; - break; + case SignalType::COMPLEX: + switch (bits) { + case 8: + i8[o++] = -1; // Not supported + i8[o++] = -1; + break; - case 16: - i16[o++] = -1; // Not supported - i16[o++] = -1; - break; + case 16: + i16[o++] = -1; // Not supported + i16[o++] = -1; + break; - case 32: - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) std::real(data->z)); - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) std::imag(data->z)); - break; + case 32: + f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, + (float)std::real(data->z)); + f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, + (float)std::imag(data->z)); + break; - case 64: - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, std::real(data->z)); - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, std::imag(data->z)); - break; + case 64: + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, + std::real(data->z)); + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, + std::imag(data->z)); + break; #ifdef HAS_128BIT - case 128: - f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, std::real(data->z)); - f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, std::imag(data->z)); - break; + case 128: + f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, + std::real(data->z)); + f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, + std::imag(data->z)); + break; #endif - } - break; + } + break; - case SignalType::INVALID: - return -1; - } - } - } + case SignalType::INVALID: + return -1; + } + } + } -out: if (wbytes) - *wbytes = o * (bits / 8); +out: + if (wbytes) + *wbytes = o * (bits / 8); - return cnt; + return cnt; } -int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - void *vbuf = (void *) buf; // Avoid warning about invalid pointer cast +int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + void *vbuf = (void *)buf; // Avoid warning about invalid pointer cast - int8_t *i8 = (int8_t *) vbuf; - int16_t *i16 = (int16_t *) vbuf; - int32_t *i32 = (int32_t *) vbuf; - int64_t *i64 = (int64_t *) vbuf; - float *f32 = (float *) vbuf; - double *f64 = (double *) vbuf; + int8_t *i8 = (int8_t *)vbuf; + int16_t *i16 = (int16_t *)vbuf; + int32_t *i32 = (int32_t *)vbuf; + int64_t *i64 = (int64_t *)vbuf; + float *f32 = (float *)vbuf; + double *f64 = (double *)vbuf; #ifdef HAS_128BIT - __int128 *i128 = (__int128 *) vbuf; - __float128 *f128 = (__float128 *) vbuf; + __int128 *i128 = (__int128 *)vbuf; + __float128 *f128 = (__float128 *)vbuf; #endif - /* The raw format can not encode multiple samples in one buffer + /* The raw format can not encode multiple samples in one buffer * as there is no support for framing. */ - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - int o = 0; - int nlen = len / (bits / 8); + int o = 0; + int nlen = len / (bits / 8); - if (cnt > 1) - return -1; + if (cnt > 1) + return -1; - if (len % (bits / 8)) - return -1; // Invalid RAW Payload length + if (len % (bits / 8)) + return -1; // Invalid RAW Payload length - if (fake) { - if (nlen < o + 3) - return -1; // Received a packet with no fake header. Skipping... + if (fake) { + if (nlen < o + 3) + return -1; // Received a packet with no fake header. Skipping... - switch (bits) { - case 8: - smp->sequence = i8[o++]; - smp->ts.origin.tv_sec = i8[o++]; - smp->ts.origin.tv_nsec = i8[o++]; - break; + switch (bits) { + case 8: + smp->sequence = i8[o++]; + smp->ts.origin.tv_sec = i8[o++]; + smp->ts.origin.tv_nsec = i8[o++]; + break; - case 16: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - break; + case 16: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; - case 32: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - break; + case 32: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; - case 64: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - break; + case 64: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - break; + case 128: + smp->sequence = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + break; #endif - } + } - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - } - else { - smp->flags = 0; - smp->sequence = 0; - smp->ts.origin.tv_sec = 0; - smp->ts.origin.tv_nsec = 0; - } + smp->flags = + (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + } else { + smp->flags = 0; + smp->sequence = 0; + smp->ts.origin.tv_sec = 0; + smp->ts.origin.tv_nsec = 0; + } - smp->signals = signals; + smp->signals = signals; - unsigned i; - for (i = 0; i < smp->capacity && o < nlen; i++) { - enum SignalType fmt = sample_format(smp, i); - union SignalData *data = &smp->data[i]; + unsigned i; + for (i = 0; i < smp->capacity && o < nlen; i++) { + enum SignalType fmt = sample_format(smp, i); + union SignalData *data = &smp->data[i]; - switch (fmt) { - case SignalType::FLOAT: - switch (bits) { - case 8: data->f = -1; o++; break; // Not supported - case 16: data->f = -1; o++; break; // Not supported + switch (fmt) { + case SignalType::FLOAT: + switch (bits) { + case 8: + data->f = -1; + o++; + break; // Not supported + case 16: + data->f = -1; + o++; + break; // Not supported - case 32: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]); break; - case 64: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]); break; + case 32: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]); + break; + case 64: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]); + break; #ifdef HAS_128BIT - case 128: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]); break; + case 128: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]); + break; #endif - } - break; + } + break; - case SignalType::INTEGER: - switch (bits) { - case 8: data->i = (int8_t) i8[o++]; break; - case 16: data->i = (int16_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); break; - case 32: data->i = (int32_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); break; - case 64: data->i = (int64_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); break; + case SignalType::INTEGER: + switch (bits) { + case 8: + data->i = (int8_t)i8[o++]; + break; + case 16: + data->i = + (int16_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; + case 32: + data->i = + (int32_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; + case 64: + data->i = + (int64_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: data->i = (__int128) SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); break; + case 128: + data->i = (__int128)SWAP_INT_XTOH(endianess == Endianess::BIG, 128, + i128[o++]); + break; #endif - } - break; + } + break; - case SignalType::BOOLEAN: - switch (bits) { - case 8: data->b = (bool) i8[o++]; break; - case 16: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); break; - case 32: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); break; - case 64: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); break; + case SignalType::BOOLEAN: + switch (bits) { + case 8: + data->b = (bool)i8[o++]; + break; + case 16: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; + case 32: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; + case 64: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); break; + case 128: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + break; #endif - } - break; + } + break; - case SignalType::COMPLEX: - switch (bits) { - case 8: data->z = std::complex(-1, -1); o += 2; break; // Not supported - case 16: data->z = std::complex(-1, -1); o += 2; break; // Not supported + case SignalType::COMPLEX: + switch (bits) { + case 8: + data->z = std::complex(-1, -1); + o += 2; + break; // Not supported + case 16: + data->z = std::complex(-1, -1); + o += 2; + break; // Not supported - case 32: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++])); + case 32: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++])); - break; + break; - case 64: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++])); - break; + case 64: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++])); + break; #if HAS_128BIT - case 128: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++])); - break; + case 128: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++])); + break; #endif - } - break; + } + break; - case SignalType::INVALID: - return -1; // Unsupported format in RAW payload - } - } + case SignalType::INVALID: + return -1; // Unsupported format in RAW payload + } + } - smp->length = i; + smp->length = i; - if (smp->length > smp->capacity) - smp->length = smp->capacity; // Received more values than supported + if (smp->length > smp->capacity) + smp->length = smp->capacity; // Received more values than supported - if (rbytes) - *rbytes = o * (bits / 8); + if (rbytes) + *rbytes = o * (bits / 8); - return 1; + return 1; } -void RawFormat::parse(json_t *json) -{ - int ret; - json_error_t err; +void RawFormat::parse(json_t *json) { + int ret; + json_error_t err; - int fake_tmp = 0; - const char *end = nullptr; + int fake_tmp = 0; + const char *end = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i }", - "endianess", &end, - "fake", &fake_tmp, - "bits", &bits - ); - if (ret) - throw ConfigError(json, err, "node-config-format-raw", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i }", "endianess", + &end, "fake", &fake_tmp, "bits", &bits); + if (ret) + throw ConfigError(json, err, "node-config-format-raw", + "Failed to parse format configuration"); - if (bits % 8 != 0 || bits > 128 || bits <= 0) - throw ConfigError(json, "node-config-format-raw-bits", "Failed to parse format configuration"); + if (bits % 8 != 0 || bits > 128 || bits <= 0) + throw ConfigError(json, "node-config-format-raw-bits", + "Failed to parse format configuration"); - if (end) { - if (bits <= 8) - throw ConfigError(json, "node-config-format-raw-endianess", "An endianess settings must only provided for bits > 8"); + if (end) { + if (bits <= 8) + throw ConfigError( + json, "node-config-format-raw-endianess", + "An endianess settings must only provided for bits > 8"); - if (!strcmp(end, "little")) - endianess = Endianess::LITTLE; - else if (!strcmp(end, "big")) - endianess = Endianess::BIG; - else - throw ConfigError(json, "node-config-format-raw-endianess", "Endianess must be either 'big' or 'little'"); - } + if (!strcmp(end, "little")) + endianess = Endianess::LITTLE; + else if (!strcmp(end, "big")) + endianess = Endianess::BIG; + else + throw ConfigError(json, "node-config-format-raw-endianess", + "Endianess must be either 'big' or 'little'"); + } - fake = fake_tmp; - if (fake) - flags |= (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - else - flags &= ~((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN); + fake = fake_tmp; + if (fake) + flags |= (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + else + flags &= + ~((int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN); - BinaryFormat::parse(json); + BinaryFormat::parse(json); } // Register formats static char n1[] = "raw"; static char d1[] = "Raw binary data"; -static FormatPlugin p1; +static FormatPlugin p1; static char n2[] = "gtnet"; static char d2[] = "RTDS GTNET"; -static FormatPlugin p2; +static FormatPlugin p2; diff --git a/lib/formats/value.cpp b/lib/formats/value.cpp index 33f3b416e..e4970006d 100644 --- a/lib/formats/value.cpp +++ b/lib/formats/value.cpp @@ -11,70 +11,71 @@ using namespace villas::node; -int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; - const struct Sample *smp = smps[0]; +int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; + const struct Sample *smp = smps[0]; - assert(cnt == 1); - assert(smp->length <= 1); + assert(cnt == 1); + assert(smp->length <= 1); - buf[0] = '\0'; + buf[0] = '\0'; - for (i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - off += smp->data[i].printString(sig->type, buf, len, real_precision); - off += snprintf(buf + off, len - off, "\n"); - } + off += smp->data[i].printString(sig->type, buf, len, real_precision); + off += snprintf(buf + off, len - off, "\n"); + } - if (wbytes) - *wbytes = off; + if (wbytes) + *wbytes = off; - return i; + return i; } -int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i = 0, ret; - struct Sample *smp = smps[0]; +int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i = 0, ret; + struct Sample *smp = smps[0]; - const char *ptr = buf; - char *end; + const char *ptr = buf; + char *end; - assert(cnt == 1); + assert(cnt == 1); - printf("Reading: %s", buf); + printf("Reading: %s", buf); - if (smp->capacity >= 1) { - auto sig = signals->getByIndex(i); - if (!sig) - return -1; + if (smp->capacity >= 1) { + auto sig = signals->getByIndex(i); + if (!sig) + return -1; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; - i++; - ptr = end; - } + i++; + ptr = end; + } -out: smp->flags = 0; - smp->signals = signals; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; +out: + smp->flags = 0; + smp->signals = signals; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return i; + return i; } // Register format static char n[] = "value"; static char d[] = "A bare text value without any headers"; -static FormatPlugin p; +static FormatPlugin p; diff --git a/lib/formats/villas_binary.cpp b/lib/formats/villas_binary.cpp index 87e233704..46211bafb 100644 --- a/lib/formats/villas_binary.cpp +++ b/lib/formats/villas_binary.cpp @@ -5,131 +5,125 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include #include #include -#include +#include #include #include using namespace villas; using namespace villas::node; -int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i = 0; - char *ptr = buf; +int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i = 0; + char *ptr = buf; - for (i = 0; i < cnt; i++) { - struct Message *msg = (struct Message *) ptr; - const struct Sample *smp = smps[i]; + for (i = 0; i < cnt; i++) { + struct Message *msg = (struct Message *)ptr; + const struct Sample *smp = smps[i]; - if (ptr + MSG_LEN(smp->length) > buf + len) - break; + if (ptr + MSG_LEN(smp->length) > buf + len) + break; - ret = msg_from_sample(msg, smp, smp->signals, source_index); - if (ret) - return ret; + ret = msg_from_sample(msg, smp, smp->signals, source_index); + if (ret) + return ret; - if (web) { - // TODO: convert to little endian - } - else - msg_hton(msg); + if (web) { + // TODO: convert to little endian + } else + msg_hton(msg); - ptr += MSG_LEN(smp->length); - } + ptr += MSG_LEN(smp->length); + } - if (wbytes) - *wbytes = ptr - buf; + if (wbytes) + *wbytes = ptr - buf; - return i; + return i; } -int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - int ret, values; - unsigned i, j; - const char *ptr = buf; - uint8_t sid; // source_index +int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + int ret, values; + unsigned i, j; + const char *ptr = buf; + uint8_t sid; // source_index - if (len % 4 != 0) - return -1; // Packet size is invalid: Must be multiple of 4 bytes + if (len % 4 != 0) + return -1; // Packet size is invalid: Must be multiple of 4 bytes - for (i = 0, j = 0; i < cnt; i++) { - struct Message *msg = (struct Message *) ptr; - struct Sample *smp = smps[j]; + for (i = 0, j = 0; i < cnt; i++) { + struct Message *msg = (struct Message *)ptr; + struct Sample *smp = smps[j]; - smp->signals = signals; + smp->signals = signals; - // Complete buffer has been parsed - if (ptr == buf + len) - break; + // Complete buffer has been parsed + if (ptr == buf + len) + break; - // Check if header is still in buffer bounaries - if (ptr + sizeof(struct Message) > buf + len) - return -2; // Invalid msg received + // Check if header is still in buffer bounaries + if (ptr + sizeof(struct Message) > buf + len) + return -2; // Invalid msg received - values = web ? msg->length : ntohs(msg->length); + values = web ? msg->length : ntohs(msg->length); - // Check if remainder of message is in buffer boundaries - if (ptr + MSG_LEN(values) > buf + len) - return -3; // Invalid msg receive + // Check if remainder of message is in buffer boundaries + if (ptr + MSG_LEN(values) > buf + len) + return -3; // Invalid msg receive - if (web) { - // TODO: convert from little endian - } - else - msg_ntoh(msg); + if (web) { + // TODO: convert from little endian + } else + msg_ntoh(msg); - ret = msg_to_sample(msg, smp, signals, &sid); - if (ret) - return ret; // Invalid msg received + ret = msg_to_sample(msg, smp, signals, &sid); + if (ret) + return ret; // Invalid msg received - if (validate_source_index && sid != source_index) { - // source index mismatch: we skip this sample - } - else - j++; + if (validate_source_index && sid != source_index) { + // source index mismatch: we skip this sample + } else + j++; - ptr += MSG_LEN(smp->length); - } + ptr += MSG_LEN(smp->length); + } - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return j; + return j; } -void VillasBinaryFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - int sid = -1; - int vsi = -1; +void VillasBinaryFormat::parse(json_t *json) { + int ret; + json_error_t err; + int sid = -1; + int vsi = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", - "source_index", &sid, - "validate_source_index", &vsi - ); - if (ret) - throw ConfigError(json, err, "node-config-format-villas-binary", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", "source_index", &sid, + "validate_source_index", &vsi); + if (ret) + throw ConfigError(json, err, "node-config-format-villas-binary", + "Failed to parse format configuration"); - if (vsi >= 0) - validate_source_index = vsi != 0; + if (vsi >= 0) + validate_source_index = vsi != 0; - if (sid >= 0) - source_index = sid; + if (sid >= 0) + source_index = sid; - Format::parse(json); + Format::parse(json); } // Register formats -static -VillasBinaryFormatPlugin p1; -static -VillasBinaryFormatPlugin p2; +static VillasBinaryFormatPlugin p1; +static VillasBinaryFormatPlugin p2; diff --git a/lib/formats/villas_human.cpp b/lib/formats/villas_human.cpp index a6cb49dab..a06a2d04e 100644 --- a/lib/formats/villas_human.cpp +++ b/lib/formats/villas_human.cpp @@ -8,183 +8,190 @@ #include #include -#include -#include +#include #include #include -#include +#include +#include using namespace villas::node; -size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) -{ - size_t off = 0; +size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, + const struct Sample *smp) { + size_t off = 0; - if (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); - } - else - off += snprintf(buf + off, len - off, "0.0"); - } + if (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); + } else + off += snprintf(buf + off, len - off, "0.0"); + } - if (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 (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 (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence); - } + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + break; - off += snprintf(buf + off, len - off, "\t"); - off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); - } - } + off += snprintf(buf + off, len - off, "\t"); + off += smp->data[i].printString(sig->type, buf + off, len - off, + real_precision); + } + } - off += snprintf(buf + off, len - off, "%c", delimiter); + off += snprintf(buf + off, len - off, "%c", delimiter); - return off; + return off; } -size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) -{ - int ret; - char *end; - const char *ptr = buf; +size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, + struct Sample *smp) { + int ret; + char *end; + const char *ptr = buf; - double offset = 0; + double offset = 0; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... + /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))? * * Please note that only the seconds and at least one value are mandatory */ - // Mandatory: seconds - smp->ts.origin.tv_sec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr == end || *end == delimiter) - return -1; + // Mandatory: seconds + smp->ts.origin.tv_sec = (uint32_t)strtoul(ptr, &end, 10); + if (ptr == end || *end == delimiter) + return -1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - // Optional: nano seconds - if (*end == '.') { - ptr = end + 1; + // Optional: nano seconds + if (*end == '.') { + ptr = end + 1; - smp->ts.origin.tv_nsec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr == end) - return -3; - } - else - smp->ts.origin.tv_nsec = 0; + smp->ts.origin.tv_nsec = (uint32_t)strtoul(ptr, &end, 10); + if (ptr == end) + return -3; + } else + smp->ts.origin.tv_nsec = 0; - // Optional: offset / delay - if (*end == '+' || *end == '-') { - ptr = end; + // Optional: offset / delay + if (*end == '+' || *end == '-') { + ptr = end; - offset = strtof(ptr, &end); // offset is ignored for now - if (ptr != end) - smp->flags |= (int) SampleFlags::HAS_OFFSET; - else - return -4; - } + offset = strtof(ptr, &end); // offset is ignored for now + if (ptr != end) + smp->flags |= (int)SampleFlags::HAS_OFFSET; + else + return -4; + } - // Optional: sequence - if (*end == '(') { - ptr = end + 1; + // Optional: sequence + if (*end == '(') { + ptr = end + 1; - smp->sequence = strtoul(ptr, &end, 10); - if (ptr != end) - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - else - return -5; + smp->sequence = strtoul(ptr, &end, 10); + if (ptr != end) + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + else + return -5; - if (*end == ')') - end++; - } + if (*end == ')') + end++; + } - unsigned i; - for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { - if (*end == delimiter) - goto out; + unsigned i; + for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { + if (*end == delimiter) + goto out; - auto sig = signals->getByIndex(i); - if (!sig) - goto out; + auto sig = signals->getByIndex(i); + if (!sig) + goto out; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; - } + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; + } -out: if (*end == delimiter) - end++; +out: + if (*end == delimiter) + end++; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (smp->flags & (int) SampleFlags::HAS_OFFSET) { - struct timespec off = time_from_double(offset); - smp->ts.received = time_add(&smp->ts.origin, &off); + 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 |= (int) SampleFlags::HAS_TS_RECEIVED; - } + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - return end - buf; + return end - buf; } -void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) -{ - // Abort if we are not supposed to, or have already printed the header - if (!print_header || header_printed) - return; +void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) { + // Abort if we are not supposed to, or have already printed the header + if (!print_header || header_printed) + return; - fprintf(f, "# "); + fprintf(f, "# "); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) - fprintf(f, "seconds.nanoseconds"); + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) + fprintf(f, "seconds.nanoseconds"); - if (flags & (int) SampleFlags::HAS_OFFSET) - fprintf(f, "+offset"); + if (flags & (int)SampleFlags::HAS_OFFSET) + fprintf(f, "+offset"); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - fprintf(f, "(sequence)"); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + fprintf(f, "(sequence)"); - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < sigs->size(); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + break; - if (!sig->name.empty()) - fprintf(f, "\t%s", sig->name.c_str()); - else - fprintf(f, "\tsignal%u", i); + if (!sig->name.empty()) + fprintf(f, "\t%s", sig->name.c_str()); + else + fprintf(f, "\tsignal%u", i); - if (!sig->unit.empty()) - fprintf(f, "[%s]", sig->unit.c_str()); - } - } + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); + } + } - fprintf(f, "%c", delimiter); + fprintf(f, "%c", delimiter); - LineFormat::header(f, sigs); + LineFormat::header(f, sigs); } // Register format static char n[] = "villas.human"; static char d[] = "VILLAS human readable format"; -static LineFormatPlugin p; +static LineFormatPlugin + p; diff --git a/lib/hook.cpp b/lib/hook.cpp index ed61459a1..363b74b37 100644 --- a/lib/hook.cpp +++ b/lib/hook.cpp @@ -5,172 +5,154 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include -#include #include +#include +#include #include #include +#include #include -#include -const char *hook_reasons[] = { - "ok", "error", "skip-sample", "stop-processing" -}; +const char *hook_reasons[] = {"ok", "error", "skip-sample", "stop-processing"}; using namespace villas; using namespace villas::node; -Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) : - logger(logging.get("hook")), - factory(nullptr), - state(fl & (int) Hook::Flags::BUILTIN - ? State::CHECKED - : State::INITIALIZED), // We dont need to parse builtin hooks - flags(fl), - priority(prio), - enabled(en), - path(p), - node(n), - config(nullptr) -{ } +Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) + : logger(logging.get("hook")), factory(nullptr), + state(fl & (int)Hook::Flags::BUILTIN + ? State::CHECKED + : State::INITIALIZED), // We dont need to parse builtin hooks + flags(fl), priority(prio), enabled(en), path(p), node(n), + config(nullptr) {} -void Hook::prepare(SignalList::Ptr sigs) -{ - assert(state == State::CHECKED); +void Hook::prepare(SignalList::Ptr sigs) { + assert(state == State::CHECKED); - signals = sigs->clone(); + signals = sigs->clone(); - prepare(); + prepare(); - state = State::PREPARED; + state = State::PREPARED; } -void Hook::parse(json_t *json) -{ - int ret; - json_error_t err; +void Hook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - int prio = -1; - int en = -1; + int prio = -1; + int en = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", - "priority", &prio, - "enabled", &en - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", "priority", &prio, + "enabled", &en); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (prio >= 0) - priority = prio; + if (prio >= 0) + priority = prio; - if (en >= 0) - enabled = en; + if (en >= 0) + enabled = en; - config = json; + config = json; - state = State::PARSED; + state = State::PARSED; } -void SingleSignalHook::parse(json_t *json) -{ - int ret; +void SingleSignalHook::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_signal; + json_error_t err; + json_t *json_signal; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: o }", - "signal", &json_signal - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s: o }", "signal", &json_signal); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signal'"); + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signal'"); - signalName = json_string_value(json_signal); + signalName = json_string_value(json_signal); } -void SingleSignalHook::prepare() -{ - Hook::prepare(); +void SingleSignalHook::prepare() { + Hook::prepare(); - // Setup mask - int index = signals->getIndexByName(signalName.c_str()); - if (index < 0) - throw RuntimeError("Failed to find signal {}", signalName); + // Setup mask + int index = signals->getIndexByName(signalName.c_str()); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); - signalIndex = (unsigned) index; + signalIndex = (unsigned)index; } // Multi Signal Hook -void MultiSignalHook::parse(json_t *json) -{ - int ret; - size_t i; +void MultiSignalHook::parse(json_t *json) { + int ret; + size_t i; - json_error_t err; - json_t *json_signals = nullptr; - json_t *json_signal = nullptr; + json_error_t err; + json_t *json_signals = nullptr; + json_t *json_signal = nullptr; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o }", - "signals", &json_signals, - "signal", &json_signal - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o }", "signals", + &json_signals, "signal", &json_signal); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (json_signals) { - if (!json_is_array(json_signals)) - throw ConfigError(json_signals, "node-config-hook-signals", "Setting 'signals' must be a list of signal names"); + if (json_signals) { + if (!json_is_array(json_signals)) + throw ConfigError(json_signals, "node-config-hook-signals", + "Setting 'signals' must be a list of signal names"); - json_array_foreach(json_signals, i, json_signal) { - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signals'"); + json_array_foreach(json_signals, i, json_signal) { + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signals'"); - const char *name = json_string_value(json_signal); + const char *name = json_string_value(json_signal); - signalNames.push_back(name); - } - } - else if (json_signal) { - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signals'"); + signalNames.push_back(name); + } + } else if (json_signal) { + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signals'"); - const char *name = json_string_value(json_signal); + const char *name = json_string_value(json_signal); - signalNames.push_back(name); - } - else - throw ConfigError(json, "node-config-hook-signals", "Missing 'signals' setting"); + signalNames.push_back(name); + } else + throw ConfigError(json, "node-config-hook-signals", + "Missing 'signals' setting"); } -void MultiSignalHook::prepare() -{ - Hook::prepare(); +void MultiSignalHook::prepare() { + Hook::prepare(); - for (const auto &signalName : signalNames) { - int index = signals->getIndexByName(signalName.c_str()); - if (index < 0) - throw RuntimeError("Failed to find signal {}", signalName); + for (const auto &signalName : signalNames) { + int index = signals->getIndexByName(signalName.c_str()); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); - signalIndices.push_back(index); - } + signalIndices.push_back(index); + } } -void MultiSignalHook::check() -{ - Hook::check(); +void MultiSignalHook::check() { + Hook::check(); - if (signalNames.size() == 0) - throw RuntimeError("At least a single signal must be provided"); + if (signalNames.size() == 0) + throw RuntimeError("At least a single signal must be provided"); } diff --git a/lib/hook_list.cpp b/lib/hook_list.cpp index 5e3452aac..2eadc93c9 100644 --- a/lib/hook_list.cpp +++ b/lib/hook_list.cpp @@ -5,193 +5,190 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include -#include +#include #include +#include using namespace villas; using namespace villas::node; -void HookList::parse(json_t *json, int mask, Path *o, Node *n) -{ - if (!json_is_array(json)) - throw ConfigError(json, "node-config-hook", "Hooks must be configured as a list of hook objects"); +void HookList::parse(json_t *json, int mask, Path *o, Node *n) { + if (!json_is_array(json)) + throw ConfigError(json, "node-config-hook", + "Hooks must be configured as a list of hook objects"); - size_t i; - json_t *json_hook; - json_array_foreach(json, i, json_hook) { - int ret; - const char *type; - Hook::Ptr h; - json_error_t err; - json_t *json_config; + size_t i; + json_t *json_hook; + json_array_foreach(json, i, json_hook) { + int ret; + const char *type; + Hook::Ptr h; + json_error_t err; + json_t *json_config; - switch (json_typeof(json_hook)) { - case JSON_STRING: - type = json_string_value(json_hook); - json_config = json_object(); - break; + switch (json_typeof(json_hook)) { + case JSON_STRING: + type = json_string_value(json_hook); + json_config = json_object(); + break; - case JSON_OBJECT: - ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type); - if (ret) - throw ConfigError(json_hook, err, "node-config-hook", "Failed to parse hook"); - json_config = json_hook; - break; + case JSON_OBJECT: + ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type); + if (ret) + throw ConfigError(json_hook, err, "node-config-hook", + "Failed to parse hook"); + json_config = json_hook; + break; - default: - throw ConfigError(json_hook, "node-config-hook", "Hook must be configured by simple string or object"); - } + default: + throw ConfigError(json_hook, "node-config-hook", + "Hook must be configured by simple string or object"); + } - auto hf = plugin::registry->lookup(type); - if (!hf) - throw ConfigError(json_hook, "node-config-hook", "Unknown hook type '{}'", type); + auto hf = plugin::registry->lookup(type); + if (!hf) + throw ConfigError(json_hook, "node-config-hook", "Unknown hook type '{}'", + type); - if (!(hf->getFlags() & mask)) - throw ConfigError(json_hook, "node-config-hook", "Hook '{}' not allowed here", type); + if (!(hf->getFlags() & mask)) + throw ConfigError(json_hook, "node-config-hook", + "Hook '{}' not allowed here", type); - h = hf->make(o, n); - h->parse(json_config); + h = hf->make(o, n); + h->parse(json_config); - push_back(h); - } + push_back(h); + } } -void HookList::check() -{ - for (auto h : *this) - h->check(); +void HookList::check() { + for (auto h : *this) + h->check(); } -void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) -{ - if (!m) - goto skip_add; +void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) { + if (!m) + goto skip_add; - // Add internal hooks if they are not already in the list - for (auto f : plugin::registry->lookup()) { - if ((f->getFlags() & m) == m) { - auto h = f->make(p, n); - push_back(h); - } - } + // Add internal hooks if they are not already in the list + for (auto f : plugin::registry->lookup()) { + if ((f->getFlags() & m) == m) { + auto h = f->make(p, n); + push_back(h); + } + } skip_add: - // Remove filters which are not enabled - remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); + // Remove filters which are not enabled + remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); - // We sort the hooks according to their priority - sort([](const value_type &a, const value_type b) { return a->getPriority() < b->getPriority(); }); + // We sort the hooks according to their priority + sort([](const value_type &a, const value_type b) { + return a->getPriority() < b->getPriority(); + }); - unsigned i = 0; - auto sigs = signals; - for (auto h : *this) { - h->prepare(sigs); + unsigned i = 0; + auto sigs = signals; + for (auto h : *this) { + h->prepare(sigs); - sigs = h->getSignals(); + sigs = h->getSignals(); - auto logger = h->getLogger(); - logger->debug("Signal list after hook #{}:", i++); - if (logger->level() <= spdlog::level::debug) - sigs->dump(logger); - } + auto logger = h->getLogger(); + logger->debug("Signal list after hook #{}:", i++); + if (logger->level() <= spdlog::level::debug) + sigs->dump(logger); + } } -int HookList::process(struct Sample * smps[], unsigned cnt) -{ - unsigned current, processed = 0; +int HookList::process(struct Sample *smps[], unsigned cnt) { + unsigned current, processed = 0; - if (size() == 0) - return cnt; + if (size() == 0) + return cnt; - for (current = 0; current < cnt; current++) { - struct Sample *smp = smps[current]; + for (current = 0; current < cnt; current++) { + struct Sample *smp = smps[current]; - for (auto h : *this) { - auto ret = h->process(smp); - smp->signals = h->getSignals(); - switch (ret) { - case Hook::Reason::ERROR: - return -1; + for (auto h : *this) { + auto ret = h->process(smp); + smp->signals = h->getSignals(); + switch (ret) { + case Hook::Reason::ERROR: + return -1; - case Hook::Reason::OK: - continue; + case Hook::Reason::OK: + continue; - case Hook::Reason::SKIP_SAMPLE: - goto skip; + case Hook::Reason::SKIP_SAMPLE: + goto skip; - case Hook::Reason::STOP_PROCESSING: - goto stop; - } - } + case Hook::Reason::STOP_PROCESSING: + goto stop; + } + } -stop: SWAP(smps[processed], smps[current]); - processed++; -skip: {} - } + stop: + SWAP(smps[processed], smps[current]); + processed++; + skip : {} + } - return processed; + return processed; } -void HookList::periodic() -{ - for (auto h : *this) - h->periodic(); +void HookList::periodic() { + for (auto h : *this) + h->periodic(); } -void HookList::start() -{ - for (auto h : *this) - h->start(); +void HookList::start() { + for (auto h : *this) + h->start(); } -void HookList::stop() -{ - for (auto h : *this) - h->stop(); +void HookList::stop() { + for (auto h : *this) + h->stop(); } -SignalList::Ptr HookList::getSignals() const -{ - auto h = back(); - if (!h) - return nullptr; +SignalList::Ptr HookList::getSignals() const { + auto h = back(); + if (!h) + return nullptr; - return h->getSignals(); + return h->getSignals(); } -unsigned HookList::getSignalsMaxCount() const -{ - unsigned max_cnt = 0; +unsigned HookList::getSignalsMaxCount() const { + unsigned max_cnt = 0; - for (auto h : *this) { - unsigned sigs_cnt = h->getSignals()->size(); + for (auto h : *this) { + unsigned sigs_cnt = h->getSignals()->size(); - if (sigs_cnt > max_cnt) - max_cnt = sigs_cnt; - } + if (sigs_cnt > max_cnt) + max_cnt = sigs_cnt; + } - return max_cnt; + return max_cnt; } -json_t * HookList::toJson() const -{ - json_t *json_hooks = json_array(); +json_t *HookList::toJson() const { + json_t *json_hooks = json_array(); - for (auto h : *this) - json_array_append(json_hooks, h->getConfig()); + for (auto h : *this) + json_array_append(json_hooks, h->getConfig()); - return json_hooks; + return json_hooks; } -void HookList::dump(Logger logger, std::string subject) const -{ - logger->debug("Hooks of {}:", subject); +void HookList::dump(Logger logger, std::string subject) const { + logger->debug("Hooks of {}:", subject); - unsigned i = 0; - for (auto h : *this) - logger->debug(" {}: {}", i++, h->getFactory()->getName()); + unsigned i = 0; + for (auto h : *this) + logger->debug(" {}: {}", i++, h->getFactory()->getName()); } diff --git a/lib/hooks/average.cpp b/lib/hooks/average.cpp index e6b77d264..895cdf9ff 100644 --- a/lib/hooks/average.cpp +++ b/lib/hooks/average.cpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -19,92 +19,85 @@ namespace node { class AverageHook : public MultiSignalHook { protected: - unsigned offset; + unsigned offset; public: - AverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - offset(0) - { } + AverageHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), offset(0) {} - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - MultiSignalHook::prepare(); + MultiSignalHook::prepare(); - // Add averaged signal - auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); - if (!avg_sig) - throw RuntimeError("Failed to create new signal"); + // Add averaged signal + auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); + if (!avg_sig) + throw RuntimeError("Failed to create new signal"); - signals->insert(signals->begin() + offset, avg_sig); + signals->insert(signals->begin() + offset, avg_sig); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-average"); + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-average"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - double avg, sum = 0; - int n = 0; + virtual Hook::Reason process(struct Sample *smp) { + double avg, sum = 0; + int n = 0; - assert(state == State::STARTED); + assert(state == State::STARTED); - for (unsigned index : signalIndices) { - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - sum += smp->data[index].i; - break; + for (unsigned index : signalIndices) { + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + sum += smp->data[index].i; + break; - case SignalType::FLOAT: - sum += smp->data[index].f; - break; + case SignalType::FLOAT: + sum += smp->data[index].f; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - case SignalType::BOOLEAN: - return Hook::Reason::ERROR; // not supported - } + case SignalType::INVALID: + case SignalType::COMPLEX: + case SignalType::BOOLEAN: + return Hook::Reason::ERROR; // not supported + } - n++; - } + n++; + } - avg = sum / n; + avg = sum / n; - if (offset >= smp->length) - return Reason::ERROR; + if (offset >= smp->length) + return Reason::ERROR; - sample_data_insert(smp, (union SignalData *) &avg, offset, 1); + sample_data_insert(smp, (union SignalData *)&avg, offset, 1); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "average"; static char d[] = "Calculate average over some signals"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/cast.cpp b/lib/hooks/cast.cpp index 8fb373830..03c6a7ad3 100644 --- a/lib/hooks/cast.cpp +++ b/lib/hooks/cast.cpp @@ -16,97 +16,87 @@ namespace node { class CastHook : public MultiSignalHook { protected: - enum SignalType new_type; - std::string new_name; - std::string new_unit; + enum SignalType new_type; + std::string new_name; + std::string new_unit; public: - CastHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - new_type(SignalType::INVALID) - { } + CastHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), new_type(SignalType::INVALID) {} - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - MultiSignalHook::prepare(); + MultiSignalHook::prepare(); - for (auto index : signalIndices) { - auto orig_sig = signals->getByIndex(index); + for (auto index : signalIndices) { + auto orig_sig = signals->getByIndex(index); - auto type = new_type == SignalType::INVALID ? orig_sig->type : new_type; - auto name = new_name.empty() ? orig_sig->name : new_name; - auto unit = new_unit.empty() ? orig_sig->unit : new_unit; + auto type = new_type == SignalType::INVALID ? orig_sig->type : new_type; + auto name = new_name.empty() ? orig_sig->name : new_name; + auto unit = new_unit.empty() ? orig_sig->unit : new_unit; - (*signals)[index] = std::make_shared(name, unit, type); - } + (*signals)[index] = std::make_shared(name, unit, type); + } - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - const char *name = nullptr; - const char *unit = nullptr; - const char *type = nullptr; + const char *name = nullptr; + const char *unit = nullptr; + const char *type = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s }", - "new_type", &type, - "new_name", &name, - "new_unit", &unit - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-cast"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s }", "new_type", + &type, "new_name", &name, "new_unit", &unit); + if (ret) + throw ConfigError(json, err, "node-config-hook-cast"); - if (type) { - new_type = signalTypeFromString(type); - 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 = SignalType::INVALID; + if (type) { + new_type = signalTypeFromString(type); + 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 = SignalType::INVALID; - if (name) - new_name = name; + if (name) + new_name = name; - if (unit) - new_unit = unit; + if (unit) + new_unit = unit; - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - for (auto index : signalIndices) { - auto orig_sig = smp->signals->getByIndex(index); - auto new_sig = signals->getByIndex(index); + for (auto index : signalIndices) { + auto orig_sig = smp->signals->getByIndex(index); + auto new_sig = signals->getByIndex(index); - smp->data[index] = smp->data[index].cast(orig_sig->type, new_sig->type); - } + smp->data[index] = smp->data[index].cast(orig_sig->type, new_sig->type); + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "cast"; static char d[] = "Cast signals types"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/decimate.cpp b/lib/hooks/decimate.cpp index a8124aa16..d30b7ac52 100644 --- a/lib/hooks/decimate.cpp +++ b/lib/hooks/decimate.cpp @@ -11,51 +11,49 @@ namespace villas { namespace node { -void DecimateHook::start() -{ - assert(state == State::PREPARED); +void DecimateHook::start() { + assert(state == State::PREPARED); - counter = 0; + counter = 0; - state = State::STARTED; + state = State::STARTED; } -void DecimateHook::parse(json_t *json) -{ - int ret; - json_error_t err; +void DecimateHook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: b }", - "ratio", &ratio, - "renumber", &renumber - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-decimate"); + ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: b }", "ratio", &ratio, + "renumber", &renumber); + if (ret) + throw ConfigError(json, err, "node-config-hook-decimate"); - state = State::PARSED; + state = State::PARSED; } -Hook::Reason DecimateHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason DecimateHook::process(struct Sample *smp) { + assert(state == State::STARTED); - if (renumber) - smp->sequence /= ratio; + if (renumber) + smp->sequence /= ratio; - if (ratio && counter++ % ratio != 0) - return Hook::Reason::SKIP_SAMPLE; + if (ratio && counter++ % ratio != 0) + return Hook::Reason::SKIP_SAMPLE; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "decimate"; static char d[] = "Downsamping by integer factor"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/dp.cpp b/lib/hooks/dp.cpp index c6a1c69fd..fd2b47687 100644 --- a/lib/hooks/dp.cpp +++ b/lib/hooks/dp.cpp @@ -10,9 +10,9 @@ #include +#include #include #include -#include #include using namespace std::complex_literals; @@ -24,36 +24,35 @@ namespace node { class DPHook : public Hook { protected: - char *signal_name; - unsigned signal_index; + char *signal_name; + unsigned signal_index; - int offset; - int inverse; + int offset; + int inverse; - double f0; - double timestep; - double time; - double steps; + double f0; + double timestep; + double time; + double steps; - std::complex *coeffs; - int *fharmonics; - int fharmonics_len; + std::complex *coeffs; + int *fharmonics; + int fharmonics_len; - dsp::Window window; + dsp::Window window; - void step(double *in, std::complex *out) - { - int N = window.size(); - __attribute__((unused)) std::complex om_k, corr; - double newest = *in; - __attribute__((unused)) double oldest = window.update(newest); + void step(double *in, std::complex *out) { + int N = window.size(); + __attribute__((unused)) std::complex om_k, corr; + double newest = *in; + __attribute__((unused)) double oldest = window.update(newest); - for (int k = 0; k < fharmonics_len; k++) { - om_k = 2.0i * M_PI * (double) fharmonics[k] / (double) N; + for (int k = 0; k < fharmonics_len; k++) { + om_k = 2.0i * M_PI * (double)fharmonics[k] / (double)N; - // Correction for stationary phasor - corr = std::exp(-om_k * (steps - (N + 1))); - //corr = 1; + // Correction for stationary phasor + corr = std::exp(-om_k * (steps - (N + 1))); + //corr = 1; #if 0 // Recursive update @@ -65,242 +64,225 @@ protected: if (fharmonics[k] == 0) out[k] /= 2.0; #else - // Full DFT - std::complex X_k = 0; + // Full DFT + std::complex X_k = 0; - for (int n = 0; n < N; n++) { - double x_n = window[n]; + for (int n = 0; n < N; n++) { + double x_n = window[n]; - X_k += x_n * std::exp(om_k * (double) n); - } + X_k += x_n * std::exp(om_k * (double)n); + } - out[k] = X_k / (corr * (double) N); + out[k] = X_k / (corr * (double)N); #endif - } - } + } + } - void istep(std::complex *in, double *out) - { - std::complex value = 0; + void istep(std::complex *in, double *out) { + std::complex value = 0; - // Reconstruct the original signal - for (int k = 0; k < fharmonics_len; k++) { - double freq = fharmonics[k]; - // cppcheck-suppress objectIndex - std::complex coeff = in[k]; - std::complex om = 2.0i * M_PI * freq * time; + // Reconstruct the original signal + for (int k = 0; k < fharmonics_len; k++) { + double freq = fharmonics[k]; + // cppcheck-suppress objectIndex + std::complex coeff = in[k]; + std::complex om = 2.0i * M_PI * freq * time; - value += coeff * std::exp(om); - } + value += coeff * std::exp(om); + } - *out = std::real(value); - } + *out = std::real(value); + } public: + DPHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), signal_name(nullptr), signal_index(0), + offset(0), inverse(0), f0(50.0), timestep(50e-6), time(), steps(0), + coeffs(), fharmonics(), fharmonics_len(0) {} - DPHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - signal_name(nullptr), - signal_index(0), - offset(0), - inverse(0), - f0(50.0), - timestep(50e-6), - time(), - steps(0), - coeffs(), - fharmonics(), - fharmonics_len(0) - { } + virtual ~DPHook() { + // Release memory + if (fharmonics) + delete fharmonics; - virtual - ~DPHook() - { - // Release memory - if (fharmonics) - delete fharmonics; + if (coeffs) + delete coeffs; - if (coeffs) - delete coeffs; + if (signal_name) + free(signal_name); + } - if (signal_name) - free(signal_name); - } + virtual void start() { + assert(state == State::PREPARED); - virtual - void start() - { - assert(state == State::PREPARED); + time = 0; + steps = 0; - time = 0; - steps = 0; + for (int i = 0; i < fharmonics_len; i++) + coeffs[i] = 0; - for (int i = 0; i < fharmonics_len; i++) - coeffs[i] = 0; + window = dsp::Window((1.0 / f0) / timestep, 0.0); - window = dsp::Window((1.0 / f0) / timestep, 0.0); + state = State::STARTED; + } - state = State::STARTED; - } + virtual void parse(json_t *json) { + int ret; + json_error_t err; + json_t *json_harmonics, *json_harmonic, *json_signal; + size_t i; - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; - json_t *json_harmonics, *json_harmonic, *json_signal; - size_t i; + Hook::parse(json); - Hook::parse(json); + double rate = -1, dt = -1; - double rate = -1, dt = -1; + ret = json_unpack_ex(json, &err, 0, + "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }", "signal", + &json_signal, "f0", &f0, "dt", &dt, "rate", &rate, + "harmonics", &json_harmonics, "inverse", &inverse); + if (ret) + throw ConfigError(json, err, "node-config-hook-dp"); - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }", - "signal", &json_signal, - "f0", &f0, - "dt", &dt, - "rate", &rate, - "harmonics", &json_harmonics, - "inverse", &inverse - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-dp"); + if (rate > 0) + timestep = 1. / rate; + else if (dt > 0) + timestep = dt; + else + throw ConfigError( + json, "node-config-hook-dp", + "Either on of the settings 'dt' or 'rate' must be given"); - if (rate > 0) - timestep = 1. / rate; - else if (dt > 0) - timestep = dt; - else - throw ConfigError(json, "node-config-hook-dp", "Either on of the settings 'dt' or 'rate' must be given"); + if (!json_is_array(json_harmonics)) + throw ConfigError(json_harmonics, "node-config-hook-dp-harmonics", + "Setting 'harmonics' must be a list of integers"); - if (!json_is_array(json_harmonics)) - throw ConfigError(json_harmonics, "node-config-hook-dp-harmonics", "Setting 'harmonics' must be a list of integers"); + switch (json_typeof(json_signal)) { + case JSON_STRING: + signal_name = strdup(json_string_value(json_signal)); + break; - switch (json_typeof(json_signal)) { - case JSON_STRING: - signal_name = strdup(json_string_value(json_signal)); - break; + case JSON_INTEGER: + signal_name = nullptr; + signal_index = json_integer_value(json_signal); + break; - case JSON_INTEGER: - signal_name = nullptr; - signal_index = json_integer_value(json_signal); - break; + default: + throw ConfigError(json_signal, "node-config-hook-dp-signal", + "Invalid value for setting 'signal'"); + } - default: - throw ConfigError(json_signal, "node-config-hook-dp-signal", "Invalid value for setting 'signal'"); - } + fharmonics_len = json_array_size(json_harmonics); + fharmonics = new int[fharmonics_len]; + coeffs = new std::complex[fharmonics_len]; + if (!fharmonics || !coeffs) + throw MemoryAllocationError(); - fharmonics_len = json_array_size(json_harmonics); - fharmonics = new int[fharmonics_len]; - coeffs = new std::complex[fharmonics_len]; - if (!fharmonics || !coeffs) - throw MemoryAllocationError(); + json_array_foreach(json_harmonics, i, json_harmonic) { + if (!json_is_integer(json_harmonic)) + throw ConfigError(json_harmonic, "node-config-hook-dp-harmonics", + "Setting 'harmonics' must be a list of integers"); - json_array_foreach(json_harmonics, i, json_harmonic) { - if (!json_is_integer(json_harmonic)) - throw ConfigError(json_harmonic, "node-config-hook-dp-harmonics", "Setting 'harmonics' must be a list of integers"); + fharmonics[i] = json_integer_value(json_harmonic); + } - fharmonics[i] = json_integer_value(json_harmonic); - } + state = State::PARSED; + } - state = State::PARSED; - } + virtual void prepare() { + assert(state == State::CHECKED); - virtual - void prepare() - { - assert(state == State::CHECKED); + char *new_sig_name; - char *new_sig_name; + assert(state != State::STARTED); - assert(state != State::STARTED); + if (signal_name) { + signal_index = signals->getIndexByName(signal_name); + if (signal_index < 0) + throw RuntimeError("Failed to find signal: {}", signal_name); + } - if (signal_name) { - signal_index = signals->getIndexByName(signal_name); - if (signal_index < 0) - throw RuntimeError("Failed to find signal: {}", signal_name); - } + if (inverse) { + // Remove complex-valued coefficient signals + for (int i = 0; i < fharmonics_len; i++) { + auto orig_sig = signals->getByIndex(signal_index + i); + if (!orig_sig) + throw RuntimeError("Failed to find signal"); - if (inverse) { - // Remove complex-valued coefficient signals - for (int i = 0; i < fharmonics_len; i++) { - auto orig_sig = signals->getByIndex(signal_index + i); - if (!orig_sig) - throw RuntimeError("Failed to find signal"); + if (orig_sig->type != SignalType::COMPLEX) + throw RuntimeError("Signal is not complex"); - if (orig_sig->type != SignalType::COMPLEX) - throw RuntimeError("Signal is not complex"); + signals->erase(signals->begin() + signal_index + i); + } - signals->erase(signals->begin() + signal_index + i); - } + // Add new real-valued reconstructed signals + auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); + if (!new_sig) + throw RuntimeError("Failed to create signal"); - // Add new real-valued reconstructed signals - auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); - if (!new_sig) - throw RuntimeError("Failed to create signal"); + signals->insert(signals->begin() + offset, new_sig); + } else { + auto orig_sig = signals->getByIndex(signal_index); + if (!orig_sig) + throw RuntimeError("Failed to find signal"); - signals->insert(signals->begin() + offset, new_sig); - } - else { - auto orig_sig = signals->getByIndex(signal_index); - if (!orig_sig) - throw RuntimeError("Failed to find signal"); + if (orig_sig->type != SignalType::FLOAT) + throw RuntimeError("Signal is not float"); - if (orig_sig->type != SignalType::FLOAT) - throw RuntimeError("Signal is not float"); + signals->erase(signals->begin() + signal_index); - signals->erase(signals->begin() + signal_index); + for (int i = 0; i < fharmonics_len; i++) { + new_sig_name = strf("%s_harm%d", orig_sig->name, i); - for (int i = 0; i < fharmonics_len; i++) { - new_sig_name = strf("%s_harm%d", orig_sig->name, i); + auto new_sig = std::make_shared(new_sig_name, orig_sig->unit, + SignalType::COMPLEX); + if (!new_sig) + throw RuntimeError("Failed to create new signal"); - auto new_sig = std::make_shared(new_sig_name, orig_sig->unit, SignalType::COMPLEX); - if (!new_sig) - throw RuntimeError("Failed to create new signal"); + signals->insert(signals->begin() + offset, new_sig); + } + } - signals->insert(signals->begin() + offset, new_sig); - } - } + state = State::PREPARED; + } - state = State::PREPARED; - } + virtual Hook::Reason process(struct Sample *smp) { + if (signal_index >= smp->length) + return Hook::Reason::ERROR; - virtual - Hook::Reason process(struct Sample *smp) - { - if (signal_index >= smp->length) - return Hook::Reason::ERROR; + if (inverse) { + double signal; + std::complex *coeffs = + reinterpret_cast *>(&smp->data[signal_index].z); - if (inverse) { - double signal; - std::complex *coeffs = reinterpret_cast *>(&smp->data[signal_index].z); + istep(coeffs, &signal); - istep(coeffs, &signal); + sample_data_remove(smp, signal_index, fharmonics_len); + sample_data_insert(smp, (union SignalData *)&signal, offset, 1); + } else { + double signal = smp->data[signal_index].f; + std::complex coeffs[fharmonics_len]; - sample_data_remove(smp, signal_index, fharmonics_len); - sample_data_insert(smp, (union SignalData *) &signal, offset, 1); - } - else { - double signal = smp->data[signal_index].f; - std::complex coeffs[fharmonics_len]; + step(&signal, coeffs); - step(&signal, coeffs); + sample_data_remove(smp, signal_index, 1); + sample_data_insert(smp, (union SignalData *)coeffs, offset, + fharmonics_len); + } - sample_data_remove(smp, signal_index, 1); - sample_data_insert(smp, (union SignalData *) coeffs, offset, fharmonics_len); - } + time += timestep; + steps++; - time += timestep; - steps++; - - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "dp"; static char d[] = "Transform to/from dynamic phasor domain"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/drop.cpp b/lib/hooks/drop.cpp index 516e9e3f6..e4a20ad7e 100644 --- a/lib/hooks/drop.cpp +++ b/lib/hooks/drop.cpp @@ -16,73 +16,68 @@ namespace node { class DropHook : public Hook { protected: - struct Sample *prev; + struct Sample *prev; public: - using Hook::Hook; + using Hook::Hook; - virtual - void start() - { - assert(state == State::PREPARED || state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - prev = nullptr; + prev = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (prev) - sample_decref(prev); + if (prev) + sample_decref(prev); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - int dist; + virtual Hook::Reason process(struct 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); + if (prev) { + dist = smp->sequence - (int64_t)prev->sequence; + if (dist <= 0) { + logger->debug("Dropping reordered sample: sequence={}, distance={}", + smp->sequence, dist); - return Hook::Reason::SKIP_SAMPLE; - } - } + return Hook::Reason::SKIP_SAMPLE; + } + } - sample_incref(smp); - if (prev) - sample_decref(prev); + sample_incref(smp); + if (prev) + sample_decref(prev); - prev = smp; + prev = smp; - return Reason::OK; - } + return Reason::OK; + } - virtual - void restart() - { - assert(state == State::STARTED); + virtual void restart() { + assert(state == State::STARTED); - if (prev) { - sample_decref(prev); - prev = nullptr; - } - } + if (prev) { + sample_decref(prev); + prev = nullptr; + } + } }; // Register hook static char n[] = "drop"; static char d[] = "Drop messages with reordered sequence numbers"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/dump.cpp b/lib/hooks/dump.cpp index 5dceb1fd1..952291dbf 100644 --- a/lib/hooks/dump.cpp +++ b/lib/hooks/dump.cpp @@ -14,23 +14,25 @@ namespace node { class DumpHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - sample_dump(logger, smp); + sample_dump(logger, smp); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "dump"; static char d[] = "Dump data to stdout"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/ebm.cpp b/lib/hooks/ebm.cpp index 231236efc..2b48c2146 100644 --- a/lib/hooks/ebm.cpp +++ b/lib/hooks/ebm.cpp @@ -17,101 +17,92 @@ namespace node { class EBMHook : public Hook { protected: - std::vector> phases; + std::vector> phases; - double energy; + double energy; - struct Sample *last; + struct Sample *last; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - size_t i; - json_error_t err; - json_t *json_phases, *json_phase; + size_t i; + json_error_t err; + json_t *json_phases, *json_phase; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: o }", - "phases", &json_phases - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-ebm"); + ret = json_unpack_ex(json, &err, 0, "{ s: o }", "phases", &json_phases); + if (ret) + throw ConfigError(json, err, "node-config-hook-ebm"); - if (!json_is_array(json_phases)) - throw ConfigError(json_phases, "node-config-hook-ebm-phases"); + if (!json_is_array(json_phases)) + throw ConfigError(json_phases, "node-config-hook-ebm-phases"); - json_array_foreach(json_phases, i, json_phase) { - int voltage, current; + json_array_foreach(json_phases, i, json_phase) { + int voltage, current; - ret = json_unpack_ex(json_phase, &err, 0, "[ i, i ]", - &voltage, ¤t - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-ebm-phases"); + ret = json_unpack_ex(json_phase, &err, 0, "[ i, i ]", &voltage, ¤t); + if (ret) + throw ConfigError(json, err, "node-config-hook-ebm-phases"); - phases.emplace_back(voltage, current); - } + phases.emplace_back(voltage, current); + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - energy = 0; - last = nullptr; + energy = 0; + last = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void periodic() - { - assert(state == State::STARTED); + virtual void periodic() { + assert(state == State::STARTED); - logger->info("Energy: {}", energy); - } + logger->info("Energy: {}", energy); + } - virtual - Hook::Reason process(struct Sample *smp) - { - double P, P_last, dt; + virtual Hook::Reason process(struct Sample *smp) { + double P, P_last, dt; - assert(state == State::STARTED); + assert(state == State::STARTED); - if (last) { - for (auto phase : phases) { - // Trapazoidal rule - dt = time_delta(&last->ts.origin, &smp->ts.origin); + if (last) { + for (auto phase : phases) { + // Trapazoidal rule + dt = time_delta(&last->ts.origin, &smp->ts.origin); - P = smp->data[phase.first].f * smp->data[phase.second].f; - P_last = last->data[phase.first].f * last->data[phase.second].f; + P = smp->data[phase.first].f * smp->data[phase.second].f; + P_last = last->data[phase.first].f * last->data[phase.second].f; - energy += dt * (P_last + P) / 2.0; - } + energy += dt * (P_last + P) / 2.0; + } - sample_decref(last); - } + sample_decref(last); + } - sample_incref(smp); - last = smp; + sample_incref(smp); + last = smp; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ebm"; static char d[] = "Energy-based Metric"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/fix.cpp b/lib/hooks/fix.cpp index ea653a773..02e74afb5 100644 --- a/lib/hooks/fix.cpp +++ b/lib/hooks/fix.cpp @@ -18,38 +18,38 @@ namespace node { class FixHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - timespec now = time_now(); + timespec now = time_now(); - if (!(smp->flags & (int) SampleFlags::HAS_SEQUENCE) && node) { - smp->sequence = node->sequence++; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (!(smp->flags & (int)SampleFlags::HAS_SEQUENCE) && node) { + smp->sequence = node->sequence++; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)) { - smp->ts.received = now; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + if (!(smp->flags & (int)SampleFlags::HAS_TS_RECEIVED)) { + smp->ts.received = now; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - if (!(smp->flags & (int) SampleFlags::HAS_TS_ORIGIN)) { - smp->ts.origin = smp->ts.received; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + if (!(smp->flags & (int)SampleFlags::HAS_TS_ORIGIN)) { + smp->ts.origin = smp->ts.received; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "fix"; static char d[] = "Fix received data by adding missing fields"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/gate.cpp b/lib/hooks/gate.cpp index 347d2dc30..7347ab331 100644 --- a/lib/hooks/gate.cpp +++ b/lib/hooks/gate.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include #include #include @@ -20,143 +20,131 @@ namespace node { class GateHook : public SingleSignalHook { protected: - enum class Mode { - ABOVE, - BELOW, - RISING_EDGE, - FALLING_EDGE - } mode; + enum class Mode { ABOVE, BELOW, RISING_EDGE, FALLING_EDGE } mode; - double threshold; - double duration; - int samples; - double previousValue; + double threshold; + double duration; + int samples; + double previousValue; - bool active; - uint64_t startSequence; - timespec startTime; + bool active; + uint64_t startSequence; + timespec startTime; public: - GateHook(Path *p, Node *n, int fl, int prio, bool en = true) : - SingleSignalHook(p, n, fl, prio, en), - mode(Mode::RISING_EDGE), - threshold(0.5), - duration(-1), - samples(-1), - previousValue(std::numeric_limits::quiet_NaN()), - active(false), - startSequence(0) - { } + GateHook(Path *p, Node *n, int fl, int prio, bool en = true) + : SingleSignalHook(p, n, fl, prio, en), mode(Mode::RISING_EDGE), + threshold(0.5), duration(-1), samples(-1), + previousValue(std::numeric_limits::quiet_NaN()), active(false), + startSequence(0) {} - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - json_error_t err; + json_error_t err; - const char *mode_str; + const char *mode_str; - assert(state != State::STARTED); + assert(state != State::STARTED); - SingleSignalHook::parse(json); + SingleSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s?: i, s?: s }", - "threshold", &threshold, - "duration", &duration, - "samples", &samples, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-gate"); + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s?: i, s?: s }", + "threshold", &threshold, "duration", &duration, + "samples", &samples, "mode", &mode_str); + if (ret) + throw ConfigError(json, 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; - } + 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; + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - SingleSignalHook::prepare(); + SingleSignalHook::prepare(); - // Check if signal type is float - auto sig = signals->getByIndex(signalIndex); - if (sig->type != SignalType::FLOAT) - throw RuntimeError("Gate signal must be of type float"); + // Check if signal type is float + auto sig = signals->getByIndex(signalIndex); + if (sig->type != SignalType::FLOAT) + throw RuntimeError("Gate signal must be of type float"); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - Hook::Reason reason; - double value = smp->data[signalIndex].f; + 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) { + 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; + 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::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::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; + case Mode::FALLING_EDGE: + reason = (!std::isnan(previousValue) && value < previousValue) + ? Reason::OK + : Reason::SKIP_SAMPLE; + break; - default: - reason = Reason::ERROR; - } + default: + reason = Reason::ERROR; + } - if (reason == Reason::OK) { - startTime = smp->ts.origin; - startSequence = smp->sequence; - active = true; - } - } + if (reason == Reason::OK) { + startTime = smp->ts.origin; + startSequence = smp->sequence; + active = true; + } + } - previousValue = value; + previousValue = value; - return reason; - } + return reason; + } }; // Register hook static char n[] = "gate"; -static char d[] = "Skip samples only if an enable signal is under a specified threshold"; -static HookPlugin p; +static char d[] = + "Skip samples only if an enable signal is under a specified threshold"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/jitter_calc.cpp b/lib/hooks/jitter_calc.cpp index 63c6ec1ee..628a6be40 100644 --- a/lib/hooks/jitter_calc.cpp +++ b/lib/hooks/jitter_calc.cpp @@ -5,13 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include -#include #include +#include #include #define GPS_NTP_DELAY_WIN_SIZE 16 @@ -22,80 +22,82 @@ namespace node { class JitterCalcHook : public Hook { protected: - std::vector jitter_val; - std::vector delay_series; - std::vector moving_avg; - std::vector moving_var; + std::vector jitter_val; + std::vector delay_series; + std::vector moving_avg; + std::vector moving_var; - int64_t delay_mov_sum; - int64_t delay_mov_sum_sqrd; - int curr_count; + int64_t delay_mov_sum; + int64_t delay_mov_sum_sqrd; + int curr_count; public: + JitterCalcHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), jitter_val(GPS_NTP_DELAY_WIN_SIZE), + delay_series(GPS_NTP_DELAY_WIN_SIZE), + moving_avg(GPS_NTP_DELAY_WIN_SIZE), moving_var(GPS_NTP_DELAY_WIN_SIZE), + delay_mov_sum(0), delay_mov_sum_sqrd(0), curr_count(0) {} - JitterCalcHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - jitter_val(GPS_NTP_DELAY_WIN_SIZE), - delay_series(GPS_NTP_DELAY_WIN_SIZE), - moving_avg(GPS_NTP_DELAY_WIN_SIZE), - moving_var(GPS_NTP_DELAY_WIN_SIZE), - delay_mov_sum(0), - delay_mov_sum_sqrd(0), - curr_count(0) - { } - - /* Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. + /* Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. * * Drawbacks: No protection for out of order packets. Default positive delay assumed, * so GPS timestamp should be earlier than NTP timestamp. If difference b/w NTP and GPS ts * is high (i.e. several mins depending on GPS_NTP_DELAY_WIN_SIZE), * the variance value will overrun the 64bit value. */ - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - timespec now = time_now(); - int64_t delay_sec, delay_nsec, curr_delay_us; + timespec now = time_now(); + int64_t delay_sec, delay_nsec, curr_delay_us; - delay_sec = now.tv_sec - smp->ts.origin.tv_sec; - delay_nsec = now.tv_nsec - smp->ts.origin.tv_nsec; + delay_sec = now.tv_sec - smp->ts.origin.tv_sec; + delay_nsec = now.tv_nsec - smp->ts.origin.tv_nsec; - /* Calc on microsec instead of nenosec delay as variance formula overflows otherwise.*/ - curr_delay_us = delay_sec * 1000000 + delay_nsec / 1000; + /* Calc on microsec instead of nenosec delay as variance formula overflows otherwise.*/ + curr_delay_us = delay_sec * 1000000 + delay_nsec / 1000; - delay_mov_sum = delay_mov_sum + curr_delay_us - delay_series[curr_count]; - moving_avg[curr_count] = delay_mov_sum / GPS_NTP_DELAY_WIN_SIZE; // Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values + delay_mov_sum = delay_mov_sum + curr_delay_us - delay_series[curr_count]; + moving_avg[curr_count] = + delay_mov_sum / + GPS_NTP_DELAY_WIN_SIZE; // Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values - delay_mov_sum_sqrd = delay_mov_sum_sqrd + (curr_delay_us * curr_delay_us) - (delay_series[curr_count] * delay_series[curr_count]); - moving_var[curr_count] = (delay_mov_sum_sqrd - (delay_mov_sum * delay_mov_sum) / GPS_NTP_DELAY_WIN_SIZE) / (GPS_NTP_DELAY_WIN_SIZE - 1); + delay_mov_sum_sqrd = delay_mov_sum_sqrd + (curr_delay_us * curr_delay_us) - + (delay_series[curr_count] * delay_series[curr_count]); + moving_var[curr_count] = + (delay_mov_sum_sqrd - + (delay_mov_sum * delay_mov_sum) / GPS_NTP_DELAY_WIN_SIZE) / + (GPS_NTP_DELAY_WIN_SIZE - 1); - delay_series[curr_count] = curr_delay_us; // Update the last delay value + delay_series[curr_count] = curr_delay_us; // Update the last delay value - /* Jitter calc formula as used in Wireshark according to RFC3550 (RTP) + /* Jitter calc formula as used in Wireshark according to RFC3550 (RTP) D(i,j) = (Rj-Ri)-(Sj-Si) = (Rj-Sj)-(Ri-Si) J(i) = J(i-1)+(|D(i-1,i)|-J(i-1))/16 */ - jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE] = jitter_val[curr_count] + (labs(curr_delay_us) - jitter_val[curr_count]) / 16; + jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE] = + jitter_val[curr_count] + + (labs(curr_delay_us) - jitter_val[curr_count]) / 16; - logger->info("{}: jitter={} usec, moving average={} usec, moving variance={} usec", __FUNCTION__, - jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE], - moving_avg[curr_count], - moving_var[curr_count]); + logger->info( + "{}: jitter={} usec, moving average={} usec, moving variance={} usec", + __FUNCTION__, jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE], + moving_avg[curr_count], moving_var[curr_count]); - curr_count++; - if (curr_count >= GPS_NTP_DELAY_WIN_SIZE) - curr_count = 0; + curr_count++; + if (curr_count >= GPS_NTP_DELAY_WIN_SIZE) + curr_count = 0; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "jitter_calc"; static char d[] = "Calc jitter, mean and variance of GPS vs NTP TS"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/limit_rate.cpp b/lib/hooks/limit_rate.cpp index 4dd0a8527..80cf00b22 100644 --- a/lib/hooks/limit_rate.cpp +++ b/lib/hooks/limit_rate.cpp @@ -7,79 +7,79 @@ #include -#include -#include #include +#include +#include namespace villas { namespace node { -void LimitRateHook::parse(json_t *json) -{ - int ret; - json_error_t err; +void LimitRateHook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - double rate; - const char *m = nullptr; + double rate; + const char *m = nullptr; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: F, s?: s }", - "rate", &rate, - "mode", &m - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-limit_rate"); + ret = json_unpack_ex(json, &err, 0, "{ s: F, s?: s }", "rate", &rate, "mode", + &m); + if (ret) + throw ConfigError(json, err, "node-config-hook-limit_rate"); - if (m) { - if (!strcmp(m, "origin")) - mode = LIMIT_RATE_ORIGIN; - else if (!strcmp(m, "received")) - mode = LIMIT_RATE_RECEIVED; - else if (!strcmp(m, "local")) - mode = LIMIT_RATE_LOCAL; - else - throw ConfigError(json, "node-config-hook-limit_rate-mode", "Invalid value '{}' for setting 'mode'", mode); - } + if (m) { + if (!strcmp(m, "origin")) + mode = LIMIT_RATE_ORIGIN; + else if (!strcmp(m, "received")) + mode = LIMIT_RATE_RECEIVED; + else if (!strcmp(m, "local")) + mode = LIMIT_RATE_LOCAL; + else + throw ConfigError(json, "node-config-hook-limit_rate-mode", + "Invalid value '{}' for setting 'mode'", mode); + } - deadtime = 1.0 / rate; + deadtime = 1.0 / rate; - state = State::PARSED; + state = State::PARSED; } -Hook::Reason LimitRateHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason LimitRateHook::process(struct Sample *smp) { + assert(state == State::STARTED); - timespec next; - switch (mode) { - case LIMIT_RATE_LOCAL: - next = time_now(); - break; + timespec next; + switch (mode) { + case LIMIT_RATE_LOCAL: + next = time_now(); + break; - case LIMIT_RATE_ORIGIN: - next = smp->ts.origin; - break; + case LIMIT_RATE_ORIGIN: + next = smp->ts.origin; + break; - case LIMIT_RATE_RECEIVED: - next = smp->ts.received; - break; - } + case LIMIT_RATE_RECEIVED: + next = smp->ts.received; + break; + } - if (time_delta(&last, &next) < deadtime) - return Hook::Reason::SKIP_SAMPLE; + if (time_delta(&last, &next) < deadtime) + return Hook::Reason::SKIP_SAMPLE; - last = next; + last = next; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "limit_rate"; static char d[] = "Limit sending rate"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/limit_value.cpp b/lib/hooks/limit_value.cpp index 9a4b0311d..0220115ef 100644 --- a/lib/hooks/limit_value.cpp +++ b/lib/hooks/limit_value.cpp @@ -11,8 +11,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -20,76 +20,69 @@ namespace node { class LimitValueHook : public MultiSignalHook { protected: - unsigned offset; + unsigned offset; - float min, max; + float min, max; public: - LimitValueHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - offset(0), - min(0), - max(0) - { } + LimitValueHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), offset(0), min(0), max(0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f }", - "min", &min, - "max", &max - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-average"); + ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f }", "min", &min, "max", + &max); + if (ret) + throw ConfigError(json, err, "node-config-hook-average"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - for (auto index : signalIndices) { - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - if (smp->data[index].i > max) - smp->data[index].i = max; + for (auto index : signalIndices) { + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + if (smp->data[index].i > max) + smp->data[index].i = max; - if (smp->data[index].i < min) - smp->data[index].i = min; - break; + if (smp->data[index].i < min) + smp->data[index].i = min; + break; - case SignalType::FLOAT: - if (smp->data[index].f > max) - smp->data[index].f = max; + case SignalType::FLOAT: + if (smp->data[index].f > max) + smp->data[index].f = max; - if (smp->data[index].f < min) - smp->data[index].f = min; - break; + if (smp->data[index].f < min) + smp->data[index].f = min; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - case SignalType::BOOLEAN: - return Hook::Reason::ERROR; // not supported - } - } + case SignalType::INVALID: + case SignalType::COMPLEX: + case SignalType::BOOLEAN: + return Hook::Reason::ERROR; // not supported + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "limit_value"; static char d[] = "Limit signal values"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index 4219eb061..6bf5875ae 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include extern "C" { - #include - #include - #include +#include +#include +#include }; #include @@ -30,749 +30,689 @@ using namespace villas::node; class LuaError : public RuntimeError { protected: - lua_State *L; - int err; + lua_State *L; + int err; public: - LuaError(lua_State *l, int e) : - RuntimeError(""), - L(l), - err(e) - { } + LuaError(lua_State *l, int e) : RuntimeError(""), L(l), err(e) {} - virtual - const char * what() const noexcept - { - const char *msg; - switch (err) { - case LUA_ERRSYNTAX: - msg = "Syntax error"; - break; + virtual const char *what() const noexcept { + const char *msg; + switch (err) { + case LUA_ERRSYNTAX: + msg = "Syntax error"; + break; - case LUA_ERRMEM: - msg = "Memory allocation error"; - break; + case LUA_ERRMEM: + msg = "Memory allocation error"; + break; - case LUA_ERRFILE: - msg = "Failed to open Lua script"; - break; + case LUA_ERRFILE: + msg = "Failed to open Lua script"; + break; - case LUA_ERRRUN: - msg = "Runtime error"; - break; + case LUA_ERRRUN: + msg = "Runtime error"; + break; - case LUA_ERRERR: - msg = "Failed to call error handler"; - break; + case LUA_ERRERR: + msg = "Failed to call error handler"; + break; - default: - msg = "Unknown error"; - break; - } + default: + msg = "Unknown error"; + break; + } - char *buf; + char *buf; - if (asprintf(&buf, "Lua: %s: %s", msg, lua_tostring(L, -1)) < 0) - return "Lua: could not format error message"; + if (asprintf(&buf, "Lua: %s: %s", msg, lua_tostring(L, -1)) < 0) + return "Lua: could not format error message"; - return buf; - } + return buf; + } }; -static -void lua_pushtimespec(lua_State *L, struct timespec *ts) -{ - lua_createtable(L, 2, 0); +static void lua_pushtimespec(lua_State *L, struct timespec *ts) { + lua_createtable(L, 2, 0); - lua_pushnumber(L, ts->tv_sec); - lua_rawseti(L, -2, 0); + lua_pushnumber(L, ts->tv_sec); + lua_rawseti(L, -2, 0); - lua_pushnumber(L, ts->tv_nsec); - lua_rawseti(L, -2, 1); + lua_pushnumber(L, ts->tv_nsec); + lua_rawseti(L, -2, 1); } -static -void lua_totimespec(lua_State *L, struct timespec *ts) -{ - lua_rawgeti(L, -1, 0); - ts->tv_sec = lua_tonumber(L, -1); +static void lua_totimespec(lua_State *L, struct timespec *ts) { + lua_rawgeti(L, -1, 0); + ts->tv_sec = lua_tonumber(L, -1); - lua_rawgeti(L, -2, 1); - ts->tv_nsec = lua_tonumber(L, -1); + lua_rawgeti(L, -2, 1); + ts->tv_nsec = lua_tonumber(L, -1); - lua_pop(L, 2); + lua_pop(L, 2); } -static -bool lua_pushsignaldata(lua_State *L, const union SignalData *data, const Signal::Ptr sig) -{ - switch (sig->type) { - case SignalType::FLOAT: - lua_pushnumber(L, data->f); - break; +static bool lua_pushsignaldata(lua_State *L, const union SignalData *data, + const Signal::Ptr sig) { + switch (sig->type) { + case SignalType::FLOAT: + lua_pushnumber(L, data->f); + break; - case SignalType::INTEGER: - lua_pushinteger(L, data->i); - break; + case SignalType::INTEGER: + lua_pushinteger(L, data->i); + break; - case SignalType::BOOLEAN: - lua_pushboolean(L, data->b); - break; + case SignalType::BOOLEAN: + lua_pushboolean(L, data->b); + break; - case SignalType::COMPLEX: - case SignalType::INVALID: - default: - return false; // we skip unknown types. Lua will see a nil value in the table - } + case SignalType::COMPLEX: + case SignalType::INVALID: + default: + return false; // we skip unknown types. Lua will see a nil value in the table + } - return true; + return true; } -static -void lua_tosignaldata(lua_State *L, union SignalData *data, enum SignalType targetType, int idx = -1) -{ - int luaType; - enum SignalType type; +static void lua_tosignaldata(lua_State *L, union SignalData *data, + enum SignalType targetType, int idx = -1) { + int luaType; + enum SignalType type; - luaType = lua_type(L, idx); - switch (luaType) { - case LUA_TBOOLEAN: - data->b = lua_toboolean(L, idx); - type = SignalType::BOOLEAN; - break; + luaType = lua_type(L, idx); + switch (luaType) { + case LUA_TBOOLEAN: + data->b = lua_toboolean(L, idx); + type = SignalType::BOOLEAN; + break; - case LUA_TNUMBER: - data->f = lua_tonumber(L, idx); - type = SignalType::FLOAT; - break; + case LUA_TNUMBER: + data->f = lua_tonumber(L, idx); + type = SignalType::FLOAT; + break; - default: - return; - } + default: + return; + } - *data = data->cast(type, targetType); + *data = data->cast(type, targetType); } -static -void lua_tosample(lua_State *L, struct Sample *smp, SignalList::Ptr signals, bool use_names = true, int idx = -1) -{ - int ret; +static void lua_tosample(lua_State *L, struct Sample *smp, + SignalList::Ptr signals, bool use_names = true, + int idx = -1) { + int ret; - smp->length = 0; - smp->flags = 0; + smp->length = 0; + smp->flags = 0; - lua_getfield(L, idx, "sequence"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - smp->sequence = lua_tonumber(L, -1); - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } - lua_pop(L, 1); + lua_getfield(L, idx, "sequence"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + smp->sequence = lua_tonumber(L, -1); + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } + lua_pop(L, 1); - lua_getfield(L, idx, "ts_origin"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - lua_totimespec(L, &smp->ts.origin); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } - lua_pop(L, 1); + lua_getfield(L, idx, "ts_origin"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + lua_totimespec(L, &smp->ts.origin); + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } + lua_pop(L, 1); - lua_getfield(L, idx, "ts_received"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - lua_totimespec(L, &smp->ts.received); - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } - lua_pop(L, 1); + lua_getfield(L, idx, "ts_received"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + lua_totimespec(L, &smp->ts.received); + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } + lua_pop(L, 1); - lua_getfield(L, idx, "data"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - int i = 0; - for (auto sig : *signals) { - if (use_names) - lua_getfield(L, -1, sig->name.c_str()); - else - lua_rawgeti(L, -1, i); + lua_getfield(L, idx, "data"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + int i = 0; + for (auto sig : *signals) { + if (use_names) + lua_getfield(L, -1, sig->name.c_str()); + else + lua_rawgeti(L, -1, i); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) - lua_tosignaldata(L, &smp->data[i], sig->type, -1); - else - smp->data[i] = sig->init; + ret = lua_type(L, -1); + if (ret != LUA_TNIL) + lua_tosignaldata(L, &smp->data[i], sig->type, -1); + else + smp->data[i] = sig->init; - lua_pop(L, 1); - i++; - smp->length++; - } + lua_pop(L, 1); + i++; + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; - } - lua_pop(L, 1); + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; + } + lua_pop(L, 1); } -static -void lua_pushsample(lua_State *L, struct Sample *smp, bool use_names = true) -{ - lua_createtable(L, 0, 5); +static void lua_pushsample(lua_State *L, struct Sample *smp, + bool use_names = true) { + lua_createtable(L, 0, 5); - lua_pushnumber(L, smp->flags); - lua_setfield(L, -2, "flags"); + lua_pushnumber(L, smp->flags); + lua_setfield(L, -2, "flags"); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - lua_pushnumber(L, smp->sequence); - lua_setfield(L, -2, "sequence"); - } + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + lua_pushnumber(L, smp->sequence); + lua_setfield(L, -2, "sequence"); + } - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - lua_pushtimespec(L, &smp->ts.origin); - lua_setfield(L, -2, "ts_origin"); - } + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + lua_pushtimespec(L, &smp->ts.origin); + lua_setfield(L, -2, "ts_origin"); + } - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) { - lua_pushtimespec(L, &smp->ts.received); - lua_setfield(L, -2, "ts_received"); - } + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) { + lua_pushtimespec(L, &smp->ts.received); + lua_setfield(L, -2, "ts_received"); + } - if (smp->flags & (int) SampleFlags::HAS_DATA) { - lua_createtable(L, smp->length, 0); + if (smp->flags & (int)SampleFlags::HAS_DATA) { + lua_createtable(L, smp->length, 0); - for (unsigned i = 0; i < smp->length; i++) { - const auto sig = smp->signals->getByIndex(i); - const auto *data = &smp->data[i]; + for (unsigned i = 0; i < smp->length; i++) { + const auto sig = smp->signals->getByIndex(i); + const auto *data = &smp->data[i]; - auto pushed = lua_pushsignaldata(L, data, sig); - if (!pushed) - continue; + auto pushed = lua_pushsignaldata(L, data, sig); + if (!pushed) + continue; - if (use_names) - lua_setfield(L, -2, sig->name.c_str()); - else - lua_rawseti(L, -2, i); - } + if (use_names) + lua_setfield(L, -2, sig->name.c_str()); + else + lua_rawseti(L, -2, i); + } - lua_setfield(L, -2, "data"); - } + lua_setfield(L, -2, "data"); + } } -static -void lua_pushjson(lua_State *L, json_t *json) -{ - size_t i; - const char *key; - json_t *json_value; +static void lua_pushjson(lua_State *L, json_t *json) { + size_t i; + const char *key; + json_t *json_value; - switch (json_typeof(json)) { - case JSON_OBJECT: - lua_newtable(L); - json_object_foreach(json, key, json_value) { - lua_pushjson(L, json_value); - lua_setfield(L, -2, key); - } - break; + switch (json_typeof(json)) { + case JSON_OBJECT: + lua_newtable(L); + json_object_foreach(json, key, json_value) { + lua_pushjson(L, json_value); + lua_setfield(L, -2, key); + } + break; - case JSON_ARRAY: - lua_newtable(L); - json_array_foreach(json, i, json_value) { - lua_pushjson(L, json_value); - lua_rawseti(L, -2, i); - } - break; + case JSON_ARRAY: + lua_newtable(L); + json_array_foreach(json, i, json_value) { + lua_pushjson(L, json_value); + lua_rawseti(L, -2, i); + } + break; - case JSON_STRING: - lua_pushstring(L, json_string_value(json)); - break; + case JSON_STRING: + lua_pushstring(L, json_string_value(json)); + break; - case JSON_REAL: - case JSON_INTEGER: - lua_pushnumber(L, json_integer_value(json)); - break; + case JSON_REAL: + case JSON_INTEGER: + lua_pushnumber(L, json_integer_value(json)); + break; - case JSON_TRUE: - case JSON_FALSE: - lua_pushboolean(L, json_boolean_value(json)); - break; + case JSON_TRUE: + case JSON_FALSE: + lua_pushboolean(L, json_boolean_value(json)); + break; - case JSON_NULL: - lua_pushnil(L); - break; - } + case JSON_NULL: + lua_pushnil(L); + break; + } } -static -json_t * lua_tojson(lua_State *L, int index = -1) -{ - double n; - const char *s; - bool b; +static json_t *lua_tojson(lua_State *L, int index = -1) { + double n; + const char *s; + bool b; - switch (lua_type(L, index)) { - case LUA_TFUNCTION: - case LUA_TUSERDATA: - case LUA_TTHREAD: - case LUA_TLIGHTUSERDATA: - case LUA_TNIL: - return json_null(); + switch (lua_type(L, index)) { + case LUA_TFUNCTION: + case LUA_TUSERDATA: + case LUA_TTHREAD: + case LUA_TLIGHTUSERDATA: + case LUA_TNIL: + return json_null(); - case LUA_TNUMBER: - n = lua_tonumber(L, index); - return n == (int) n - ? json_integer(n) - : json_real(n); + case LUA_TNUMBER: + n = lua_tonumber(L, index); + return n == (int)n ? json_integer(n) : json_real(n); - case LUA_TBOOLEAN: - b = lua_toboolean(L, index); - return json_boolean(b); + case LUA_TBOOLEAN: + b = lua_toboolean(L, index); + return json_boolean(b); - case LUA_TSTRING: - s = lua_tostring(L, index); - return json_string(s); + case LUA_TSTRING: + s = lua_tostring(L, index); + return json_string(s); - case LUA_TTABLE: { - int keys_total = 0, keys_int = 0, key_highest = -1; + case LUA_TTABLE: { + int keys_total = 0, keys_int = 0, key_highest = -1; - lua_pushnil(L); - while (lua_next(L, index) != 0) { - keys_total++; - if (lua_type(L, -2) == LUA_TNUMBER) { - int key = lua_tonumber(L, -1); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + keys_total++; + if (lua_type(L, -2) == LUA_TNUMBER) { + int key = lua_tonumber(L, -1); - if (key == (int) key) { - keys_int++; - if (key > key_highest) - key_highest = key; - } - } - lua_pop(L, 1); - } + if (key == (int)key) { + keys_int++; + if (key > key_highest) + key_highest = key; + } + } + lua_pop(L, 1); + } - bool is_array = keys_total == keys_int && key_highest / keys_int > 0.5; + bool is_array = keys_total == keys_int && key_highest / keys_int > 0.5; - json_t *json = is_array - ? json_array() - : json_object(); + json_t *json = is_array ? json_array() : json_object(); - lua_pushnil(L); - while (lua_next(L, index) != 0) { - json_t *val = lua_tojson(L, -1); - if (is_array) { - int key = lua_tonumber(L, -2); - json_array_set(json, key, val); - } - else { - const char *key = lua_tostring(L, -2); - if (key) // Skip table entries whose keys are neither string or number! - json_object_set(json, key, val); - } - lua_pop(L, 1); - } + lua_pushnil(L); + while (lua_next(L, index) != 0) { + json_t *val = lua_tojson(L, -1); + if (is_array) { + int key = lua_tonumber(L, -2); + json_array_set(json, key, val); + } else { + const char *key = lua_tostring(L, -2); + if (key) // Skip table entries whose keys are neither string or number! + json_object_set(json, key, val); + } + lua_pop(L, 1); + } - return json; - } - } + return json; + } + } - return nullptr; + return nullptr; } namespace villas { namespace node { -LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) : - cookie(0), - L(l) -{ - int ret; +LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) + : cookie(0), L(l) { + int ret; - json_error_t err; - const char *expr; + json_error_t err; + const char *expr; - // Parse expression - ret = json_unpack_ex(json_sig, &err, 0, "{ s: s }", - "expression", &expr - ); - if (ret) - throw ConfigError(json_sig, err, "node-config-hook-lua-signals"); + // Parse expression + ret = json_unpack_ex(json_sig, &err, 0, "{ s: s }", "expression", &expr); + if (ret) + throw ConfigError(json_sig, err, "node-config-hook-lua-signals"); - cfg = json_sig; + cfg = json_sig; - expression = expr; + expression = expr; } -void LuaSignalExpression::prepare() -{ - parseExpression(expression); +void LuaSignalExpression::prepare() { parseExpression(expression); } + +void LuaSignalExpression::parseExpression(const std::string &expr) { + // Release previous expression + if (cookie) + luaL_unref(L, LUA_REGISTRYINDEX, cookie); + + auto fexpr = fmt::format("return {}", expr); + + int err = luaL_loadstring(L, fexpr.c_str()); + if (err) + throw ConfigError(cfg, "node-config-hook-lua-signals", + "Failed to load Lua expression: {}", lua_tostring(L, -1)); + + cookie = luaL_ref(L, LUA_REGISTRYINDEX); } -void LuaSignalExpression::parseExpression(const std::string &expr) -{ - // Release previous expression - if (cookie) - luaL_unref(L, LUA_REGISTRYINDEX, cookie); +void LuaSignalExpression::evaluate(union SignalData *data, + enum SignalType type) { + int err; - auto fexpr = fmt::format("return {}", expr); + lua_rawgeti(L, LUA_REGISTRYINDEX, cookie); - int err = luaL_loadstring(L, fexpr.c_str()); - if (err) - throw ConfigError(cfg, "node-config-hook-lua-signals", "Failed to load Lua expression: {}", lua_tostring(L, -1)); + err = lua_pcall(L, 0, 1, 0); + if (err) { + throw RuntimeError("Lua: Evaluation failed: {}", lua_tostring(L, -1)); + lua_pop(L, 1); + } - cookie = luaL_ref(L, LUA_REGISTRYINDEX); + lua_tosignaldata(L, data, type, -1); + + lua_pop(L, 1); } -void LuaSignalExpression::evaluate(union SignalData *data, enum SignalType type) -{ - int err; +LuaHook::LuaHook(Path *p, Node *n, int fl, int prio, bool en) + : Hook(p, n, fl, prio, en), + signalsExpressions(std::make_shared()), L(luaL_newstate()), + useNames(true), hasExpressions(false), needsLocking(false), + functions({0}) {} - lua_rawgeti(L, LUA_REGISTRYINDEX, cookie); +LuaHook::~LuaHook() { lua_close(L); } - err = lua_pcall(L, 0, 1, 0); - if (err) { - throw RuntimeError("Lua: Evaluation failed: {}", lua_tostring(L, -1)); - lua_pop(L, 1); - } +void LuaHook::parseExpressions(json_t *json_sigs) { + int ret; + size_t i; + json_t *json_sig; - lua_tosignaldata(L, data, type, -1); + signalsExpressions->clear(); + ret = signalsExpressions->parse(json_sigs); + if (ret) + throw ConfigError(json_sigs, "node-config-hook-lua-signals", + "Setting 'signals' must be a list of dicts"); - lua_pop(L, 1); + // cppcheck-suppress unknownMacro + json_array_foreach(json_sigs, i, json_sig) + expressions.emplace_back(L, json_sig); + + hasExpressions = true; } -LuaHook::LuaHook(Path *p, Node *n, int fl, int prio, bool en) : - Hook(p, n, fl, prio, en), - signalsExpressions(std::make_shared()), - L(luaL_newstate()), - useNames(true), - hasExpressions(false), - needsLocking(false), - functions({0}) -{ } +void LuaHook::parse(json_t *json) { + int ret; + const char *script_str = nullptr; + int names = 1; + json_error_t err; + json_t *json_signals = nullptr; -LuaHook::~LuaHook() -{ - lua_close(L); + assert(state != State::STARTED); + + Hook::parse(json); + + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: b }", "script", + &script_str, "signals", &json_signals, "use_names", + &names); + if (ret) + throw ConfigError(json, err, "node-config-hook-lua"); + + useNames = names; + + if (script_str) + script = script_str; + + if (json_signals) + parseExpressions(json_signals); + + state = State::PARSED; } -void LuaHook::parseExpressions(json_t *json_sigs) -{ - int ret; - size_t i; - json_t *json_sig; +void LuaHook::lookupFunctions() { + int ret; - signalsExpressions->clear(); - ret = signalsExpressions->parse(json_sigs); - if (ret) - throw ConfigError(json_sigs, "node-config-hook-lua-signals", "Setting 'signals' must be a list of dicts"); + std::map funcs = { + {"start", &functions.start}, {"stop", &functions.stop}, + {"restart", &functions.restart}, {"prepare", &functions.prepare}, + {"periodic", &functions.periodic}, {"process", &functions.process}}; - // cppcheck-suppress unknownMacro - json_array_foreach(json_sigs, i, json_sig) - expressions.emplace_back(L, json_sig); + for (auto it : funcs) { + lua_getglobal(L, it.first); - hasExpressions = true; + ret = lua_type(L, -1); + if (ret == LUA_TFUNCTION) { + logger->debug("Found Lua function: {}()", it.first); + *(it.second) = lua_gettop(L); + } else { + *(it.second) = 0; + lua_pop(L, 1); + } + } } -void LuaHook::parse(json_t *json) -{ - int ret; - const char *script_str = nullptr; - int names = 1; - json_error_t err; - json_t *json_signals = nullptr; +void LuaHook::loadScript() { + int ret; - assert(state != State::STARTED); + if (script.empty()) + return; // No script given - Hook::parse(json); + ret = luaL_loadfile(L, script.c_str()); + if (ret) + throw LuaError(L, ret); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: b }", - "script", &script_str, - "signals", &json_signals, - "use_names", &names - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-lua"); - - useNames = names; - - if (script_str) - script = script_str; - - if (json_signals) - parseExpressions(json_signals); - - state = State::PARSED; + ret = lua_pcall(L, 0, LUA_MULTRET, 0); + if (ret) + throw LuaError(L, ret); } -void LuaHook::lookupFunctions() -{ - int ret; - - std::map funcs = { - { "start", &functions.start }, - { "stop", &functions.stop }, - { "restart", &functions.restart }, - { "prepare", &functions.prepare }, - { "periodic", &functions.periodic }, - { "process", &functions.process } - }; - - for (auto it : funcs) { - lua_getglobal(L, it.first); - - ret = lua_type(L, -1); - if (ret == LUA_TFUNCTION) { - logger->debug("Found Lua function: {}()", it.first); - *(it.second) = lua_gettop(L); - } - else { - *(it.second) = 0; - lua_pop(L, 1); - } - } +int LuaHook::luaRegisterApiHandler(lua_State *L) { + // register_api_handler(path_regex) + return 0; } -void LuaHook::loadScript() -{ - int ret; - - if (script.empty()) - return; // No script given - - ret = luaL_loadfile(L, script.c_str()); - if (ret) - throw LuaError(L, ret); - - ret = lua_pcall(L, 0, LUA_MULTRET, 0); - if (ret) - throw LuaError(L, ret); +int LuaHook::luaInfo(lua_State *L) { + logger->info(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaRegisterApiHandler(lua_State *L) -{ - // register_api_handler(path_regex) - return 0; +int LuaHook::luaWarn(lua_State *L) { + logger->warn(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaInfo(lua_State *L) -{ - logger->info(luaL_checkstring(L, 1)); - return 0; +int LuaHook::luaError(lua_State *L) { + logger->error(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaWarn(lua_State *L) -{ - logger->warn(luaL_checkstring(L, 1)); - return 0; +int LuaHook::luaDebug(lua_State *L) { + logger->debug(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaError(lua_State *L) -{ - logger->error(luaL_checkstring(L, 1)); - return 0; +void LuaHook::setupEnvironment() { + lua_pushlightuserdata(L, this); + lua_rawseti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + + lua_register(L, "info", &dispatch<&LuaHook::luaInfo>); + lua_register(L, "warn", &dispatch<&LuaHook::luaWarn>); + lua_register(L, "error", &dispatch<&LuaHook::luaError>); + lua_register(L, "debug", &dispatch<&LuaHook::luaDebug>); + + lua_register(L, "register_api_handler", + &dispatch<&LuaHook::luaRegisterApiHandler>); } -int LuaHook::luaDebug(lua_State *L) -{ - logger->debug(luaL_checkstring(L, 1)); - return 0; -} +void LuaHook::prepare() { + // Load Lua standard libraries + luaL_openlibs(L); -void LuaHook::setupEnvironment() -{ - lua_pushlightuserdata(L, this); - lua_rawseti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + // Load our Lua script + logger->debug("Loading Lua script: {}", script); - lua_register(L, "info", &dispatch<&LuaHook::luaInfo>); - lua_register(L, "warn", &dispatch<&LuaHook::luaWarn>); - lua_register(L, "error", &dispatch<&LuaHook::luaError>); - lua_register(L, "debug", &dispatch<&LuaHook::luaDebug>); + setupEnvironment(); + loadScript(); + lookupFunctions(); - lua_register(L, "register_api_handler", &dispatch<&LuaHook::luaRegisterApiHandler>); -} - -void LuaHook::prepare() -{ - // Load Lua standard libraries - luaL_openlibs(L); - - // Load our Lua script - logger->debug("Loading Lua script: {}", script); - - setupEnvironment(); - loadScript(); - lookupFunctions(); - - /* Check if we need to protect the Lua state with a mutex + /* Check if we need to protect the Lua state with a mutex * This is the case if we have a periodic callback defined * As periodic() gets called from the main thread */ - needsLocking = functions.periodic > 0; + needsLocking = functions.periodic > 0; - // Prepare Lua process() - if (functions.process) { - /* We currently do not support the alteration of + // Prepare Lua process() + if (functions.process) { + /* We currently do not support the alteration of * signal metadata in process() */ - signalsProcessed = signals; - } + signalsProcessed = signals; + } - // Prepare Lua expressions - if (hasExpressions) { - for (auto &expr : expressions) - expr.prepare(); + // Prepare Lua expressions + if (hasExpressions) { + for (auto &expr : expressions) + expr.prepare(); - signals = signalsExpressions; - } + signals = signalsExpressions; + } - if (!functions.process && !hasExpressions) - logger->warn("The hook has neither a script or expressions defined. It is a no-op!"); + if (!functions.process && !hasExpressions) + logger->warn( + "The hook has neither a script or expressions defined. It is a no-op!"); - if (functions.prepare) { - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + if (functions.prepare) { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - logger->debug("Executing Lua function: prepare()"); - lua_pushvalue(L, functions.prepare); - lua_pushjson(L, config); - int ret = lua_pcall(L, 1, 0, 0); - if (ret) - throw LuaError(L, ret); - } + logger->debug("Executing Lua function: prepare()"); + lua_pushvalue(L, functions.prepare); + lua_pushjson(L, config); + int ret = lua_pcall(L, 1, 0, 0); + if (ret) + throw LuaError(L, ret); + } } -void LuaHook::start() -{ - assert(state == State::PREPARED); +void LuaHook::start() { + assert(state == State::PREPARED); - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - if (functions.start) { - logger->debug("Executing Lua function: start()"); - lua_pushvalue(L, functions.start); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + if (functions.start) { + logger->debug("Executing Lua function: start()"); + lua_pushvalue(L, functions.start); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } - state = State::STARTED; + state = State::STARTED; } -void LuaHook::stop() -{ - assert(state == State::STARTED); +void LuaHook::stop() { + assert(state == State::STARTED); - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - if (functions.stop) { - logger->debug("Executing Lua function: stop()"); - lua_pushvalue(L, functions.stop); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + if (functions.stop) { + logger->debug("Executing Lua function: stop()"); + lua_pushvalue(L, functions.stop); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } - state = State::STOPPED; + state = State::STOPPED; } -void LuaHook::restart() -{ - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); +void LuaHook::restart() { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - assert(state == State::STARTED); + assert(state == State::STARTED); - if (functions.restart) { - logger->debug("Executing Lua function: restart()"); - lua_pushvalue(L, functions.restart); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } - else - Hook::restart(); + if (functions.restart) { + logger->debug("Executing Lua function: restart()"); + lua_pushvalue(L, functions.restart); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } else + Hook::restart(); } -void LuaHook::periodic() -{ - assert(state == State::STARTED); +void LuaHook::periodic() { + assert(state == State::STARTED); - if (functions.periodic) { - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + if (functions.periodic) { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - logger->debug("Executing Lua function: restart()"); - lua_pushvalue(L, functions.periodic); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + logger->debug("Executing Lua function: restart()"); + lua_pushvalue(L, functions.periodic); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } } -Hook::Reason LuaHook::process(struct Sample *smp) -{ - if (!functions.process && !hasExpressions) - return Reason::OK; +Hook::Reason LuaHook::process(struct Sample *smp) { + if (!functions.process && !hasExpressions) + return Reason::OK; - int rtype; - enum Reason reason; - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + int rtype; + enum Reason reason; + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - // First, run the process() function of the script - if (functions.process) { - logger->debug("Executing Lua function: process(smp)"); + // First, run the process() function of the script + if (functions.process) { + logger->debug("Executing Lua function: process(smp)"); - lua_pushsample(L, smp, useNames); + lua_pushsample(L, smp, useNames); - lua_pushvalue(L, functions.process); - lua_pushvalue(L, -2); // Push a copy since lua_pcall() will pop it - int ret = lua_pcall(L, 1, 1, 0); - if (ret) - throw LuaError(L, ret); + lua_pushvalue(L, functions.process); + lua_pushvalue(L, -2); // Push a copy since lua_pcall() will pop it + int ret = lua_pcall(L, 1, 1, 0); + if (ret) + throw LuaError(L, ret); - rtype = lua_type(L, -1); - if (rtype == LUA_TNUMBER) { - reason = (Reason) lua_tonumber(L, -1); - } - else { - logger->warn("Lua process() did not return a valid number. Assuming Reason::OK"); - reason = Reason::OK; - } + rtype = lua_type(L, -1); + if (rtype == LUA_TNUMBER) { + reason = (Reason)lua_tonumber(L, -1); + } else { + logger->warn( + "Lua process() did not return a valid number. Assuming Reason::OK"); + reason = Reason::OK; + } - lua_pop(L, 1); + lua_pop(L, 1); - lua_tosample(L, smp, signalsProcessed, useNames); - } - else - reason = Reason::OK; + lua_tosample(L, smp, signalsProcessed, useNames); + } else + reason = Reason::OK; - // After that evaluate expressions - if (hasExpressions) { - lua_pushsample(L, smp, useNames); - lua_setglobal(L, "smp"); + // After that evaluate expressions + if (hasExpressions) { + lua_pushsample(L, smp, useNames); + lua_setglobal(L, "smp"); - for (unsigned i = 0; i < expressions.size(); i++) { - auto sig = signalsExpressions->getByIndex(i); - if (!sig) - continue; + for (unsigned i = 0; i < expressions.size(); i++) { + auto sig = signalsExpressions->getByIndex(i); + if (!sig) + continue; - expressions[i].evaluate(&smp->data[i], sig->type); - } + expressions[i].evaluate(&smp->data[i], sig->type); + } - smp->length = expressions.size(); - } + smp->length = expressions.size(); + } - return reason; + return reason; } // Register hook static char n[] = "lua"; static char d[] = "Implement hook functions or expressions in Lua"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/ma.cpp b/lib/hooks/ma.cpp index 996767ab0..e2acc4f15 100644 --- a/lib/hooks/ma.cpp +++ b/lib/hooks/ma.cpp @@ -14,96 +14,90 @@ namespace node { class MovingAverageHook : public MultiSignalHook { protected: - std::vector> smpMemory; + std::vector> smpMemory; - double accumulator; - unsigned windowSize; - uint64_t smpMemoryPosition; + double accumulator; + unsigned windowSize; + uint64_t smpMemoryPosition; public: - MovingAverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - accumulator(0.0), - windowSize(10), - smpMemoryPosition(0) - { } + MovingAverageHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), accumulator(0.0), + windowSize(10), smpMemoryPosition(0) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - // Add signals - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Add signals + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The ma hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The ma hook can only operate on signals of type float!"); + } - // Initialize sample memory - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) - smpMemory.emplace_back(windowSize, 0.0); + // Initialize sample memory + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) + smpMemory.emplace_back(windowSize, 0.0); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "window_size", &windowSize - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-rms"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: i }", "window_size", &windowSize); + if (ret) + throw ConfigError(json, err, "node-config-hook-rms"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - unsigned i = 0; - for (auto index : signalIndices) { - // The new value - double newValue = smp->data[index].f; + unsigned i = 0; + for (auto index : signalIndices) { + // The new value + double newValue = smp->data[index].f; - // Append the new value to the history memory - smpMemory[i][smpMemoryPosition % windowSize] = newValue; + // Append the new value to the history memory + smpMemory[i][smpMemoryPosition % windowSize] = newValue; - // Get the old value from the history - double oldValue = smpMemory[i][(smpMemoryPosition + 1) % windowSize]; + // Get the old value from the history + double oldValue = smpMemory[i][(smpMemoryPosition + 1) % windowSize]; - // Update the accumulator - accumulator += newValue; - accumulator -= oldValue; + // Update the accumulator + accumulator += newValue; + accumulator -= oldValue; - smp->data[index].f = accumulator / windowSize; - i++; - } + smp->data[index].f = accumulator / windowSize; + i++; + } - smpMemoryPosition++; + smpMemoryPosition++; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ma"; -static char d[] = "A simple moving average filter over a fixed number of past samples"; -static HookPlugin p; +static char d[] = + "A simple moving average filter over a fixed number of past samples"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu.cpp b/lib/hooks/pmu.cpp index a93ccd535..a1a2459f5 100644 --- a/lib/hooks/pmu.cpp +++ b/lib/hooks/pmu.cpp @@ -11,240 +11,243 @@ namespace villas { namespace node { -PmuHook::PmuHook(Path *p, Node *n, int fl, int prio, bool en): - MultiSignalHook(p, n, fl, prio, en), - windows(), - windowsTs(), - timeAlignType(TimeAlign::CENTER), - windowType(WindowType::NONE), - sampleRate(1), - phasorRate(1.0), - nominalFreq(1.0), - numberPlc(1.), - windowSize(1), - channelNameEnable(true), - angleUnitFactor(1.0), - lastSequence(0), - nextRun({0}), - init(false), - initSampleCount(0), - phaseOffset(0.0), - amplitudeOffset(0.0), - frequencyOffset(0.0), - rocofOffset(0.0) -{ } +PmuHook::PmuHook(Path *p, Node *n, int fl, int prio, bool en) + : MultiSignalHook(p, n, fl, prio, en), windows(), windowsTs(), + timeAlignType(TimeAlign::CENTER), windowType(WindowType::NONE), + sampleRate(1), phasorRate(1.0), nominalFreq(1.0), numberPlc(1.), + windowSize(1), channelNameEnable(true), angleUnitFactor(1.0), + lastSequence(0), nextRun({0}), init(false), initSampleCount(0), + phaseOffset(0.0), amplitudeOffset(0.0), frequencyOffset(0.0), + rocofOffset(0.0) {} -void PmuHook::prepare() -{ - MultiSignalHook::prepare(); +void PmuHook::prepare() { + MultiSignalHook::prepare(); - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - // Add signals - auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); - auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); - auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad - auto rocofSig = std::make_shared("rocof", "Hz/s", SignalType::FLOAT); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + // Add signals + auto freqSig = + std::make_shared("frequency", "Hz", SignalType::FLOAT); + auto amplSig = + std::make_shared("amplitude", "V", SignalType::FLOAT); + auto phaseSig = std::make_shared( + "phase", (angleUnitFactor) ? "rad" : "deg", + SignalType::FLOAT); //angleUnitFactor==1 means rad + auto rocofSig = + std::make_shared("rocof", "Hz/s", SignalType::FLOAT); - if (!freqSig || !amplSig || !phaseSig || !rocofSig) - throw RuntimeError("Failed to create new signals"); + if (!freqSig || !amplSig || !phaseSig || !rocofSig) + throw RuntimeError("Failed to create new signals"); - if (channelNameEnable) { - auto suffix = fmt::format("_{}", signalNames[i]); + if (channelNameEnable) { + auto suffix = fmt::format("_{}", signalNames[i]); - freqSig->name += suffix; - amplSig->name += suffix; - phaseSig->name += suffix; - rocofSig->name += suffix; - } + freqSig->name += suffix; + amplSig->name += suffix; + phaseSig->name += suffix; + rocofSig->name += suffix; + } - signals->push_back(freqSig); - signals->push_back(amplSig); - signals->push_back(phaseSig); - signals->push_back(rocofSig); + signals->push_back(freqSig); + signals->push_back(amplSig); + signals->push_back(phaseSig); + signals->push_back(rocofSig); - lastPhasors.push_back({0.,0.,0.,0.}); - } + lastPhasors.push_back({0., 0., 0., 0.}); + } - windowSize = ceil(sampleRate * numberPlc / nominalFreq); + windowSize = ceil(sampleRate * numberPlc / nominalFreq); - for (unsigned i = 0; i < signalIndices.size(); i++) { - if (windowType == WindowType::NONE) - windows.push_back(new dsp::RectangularWindow(windowSize, 0.0)); - else if (windowType == WindowType::FLATTOP) - windows.push_back(new dsp::FlattopWindow(windowSize, 0.0)); - else if (windowType == WindowType::HAMMING) - windows.push_back(new dsp::HammingWindow(windowSize, 0.0)); - else if (windowType == WindowType::HANN) - windows.push_back(new dsp::HannWindow(windowSize, 0.0)); - else if (windowType == WindowType::NUTTAL) - windows.push_back(new dsp::NuttallWindow(windowSize, 0.0)); - else if (windowType == WindowType::BLACKMAN) - windows.push_back(new dsp::BlackmanWindow(windowSize, 0.0)); - } + for (unsigned i = 0; i < signalIndices.size(); i++) { + if (windowType == WindowType::NONE) + windows.push_back(new dsp::RectangularWindow(windowSize, 0.0)); + else if (windowType == WindowType::FLATTOP) + windows.push_back(new dsp::FlattopWindow(windowSize, 0.0)); + else if (windowType == WindowType::HAMMING) + windows.push_back(new dsp::HammingWindow(windowSize, 0.0)); + else if (windowType == WindowType::HANN) + windows.push_back(new dsp::HannWindow(windowSize, 0.0)); + else if (windowType == WindowType::NUTTAL) + windows.push_back(new dsp::NuttallWindow(windowSize, 0.0)); + else if (windowType == WindowType::BLACKMAN) + windows.push_back(new dsp::BlackmanWindow(windowSize, 0.0)); + } - windowsTs = new dsp::Window(windowSize, timespec{0}); + windowsTs = new dsp::Window(windowSize, timespec{0}); } -void PmuHook::parse(json_t *json) -{ - MultiSignalHook::parse(json); - int ret; +void PmuHook::parse(json_t *json) { + MultiSignalHook::parse(json); + int ret; - const char *windowTypeC = nullptr; - const char *angleUnitC = nullptr; - const char *timeAlignC = nullptr; + const char *windowTypeC = nullptr; + const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: F, s?: F, s?: F, s?: s, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", - "sample_rate", &sampleRate, - "dft_rate", &phasorRate, - "nominal_freq", &nominalFreq, - "number_plc", &numberPlc, - "window_type", &windowTypeC, - "angle_unit", &angleUnitC, - "add_channel_name", &channelNameEnable, - "timestamp_align", &timeAlignC, - "phase_offset", &phaseOffset, - "amplitude_offset", &litudeOffset, - "frequency_offset", &frequencyOffset, - "rocof_offset", &rocofOffset - ); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: i, s?: F, s?: F, s?: F, s?: s, s?: s, s?: b, s?: s, s?: F, s?: F, " + "s?: F, s?: F}", + "sample_rate", &sampleRate, "dft_rate", &phasorRate, "nominal_freq", + &nominalFreq, "number_plc", &numberPlc, "window_type", &windowTypeC, + "angle_unit", &angleUnitC, "add_channel_name", &channelNameEnable, + "timestamp_align", &timeAlignC, "phase_offset", &phaseOffset, + "amplitude_offset", &litudeOffset, "frequency_offset", + &frequencyOffset, "rocof_offset", &rocofOffset); - if (ret) - throw ConfigError(json, err, "node-config-hook-pmu"); + if (ret) + throw ConfigError(json, err, "node-config-hook-pmu"); - if (sampleRate <= 0) - throw ConfigError(json, "node-config-hook-pmu-sample_rate", "Sample rate cannot be less than 0 tried to set {}", sampleRate); + if (sampleRate <= 0) + throw ConfigError(json, "node-config-hook-pmu-sample_rate", + "Sample rate cannot be less than 0 tried to set {}", + sampleRate); - if (phasorRate <= 0) - throw ConfigError(json, "node-config-hook-pmu-phasor_rate", "Phasor rate cannot be less than 0 tried to set {}", phasorRate); + if (phasorRate <= 0) + throw ConfigError(json, "node-config-hook-pmu-phasor_rate", + "Phasor rate cannot be less than 0 tried to set {}", + phasorRate); - if (nominalFreq <= 0) - throw ConfigError(json, "node-config-hook-pmu-nominal_freq", "Nominal frequency cannot be less than 0 tried to set {}", nominalFreq); + if (nominalFreq <= 0) + throw ConfigError(json, "node-config-hook-pmu-nominal_freq", + "Nominal frequency cannot be less than 0 tried to set {}", + nominalFreq); - if (numberPlc <= 0) - throw ConfigError(json, "node-config-hook-pmu-number_plc", "Number of power line cycles cannot be less than 0 tried to set {}", numberPlc); + if (numberPlc <= 0) + throw ConfigError( + json, "node-config-hook-pmu-number_plc", + "Number of power line cycles cannot be less than 0 tried to set {}", + numberPlc); - if (!windowTypeC) - logger->info("No Window type given, assume no windowing"); - else if (strcmp(windowTypeC, "flattop") == 0) - windowType = WindowType::FLATTOP; - else if (strcmp(windowTypeC, "hamming") == 0) - windowType = WindowType::HAMMING; - else if (strcmp(windowTypeC, "hann") == 0) - windowType = WindowType::HANN; - else if (strcmp(windowTypeC, "nuttal") == 0) - windowType = WindowType::NUTTAL; - else if (strcmp(windowTypeC, "blackman") == 0) - windowType = WindowType::BLACKMAN; - else - throw ConfigError(json, "node-config-hook-pmu-window-type", "Invalid window type: {}", windowTypeC); + if (!windowTypeC) + logger->info("No Window type given, assume no windowing"); + else if (strcmp(windowTypeC, "flattop") == 0) + windowType = WindowType::FLATTOP; + else if (strcmp(windowTypeC, "hamming") == 0) + windowType = WindowType::HAMMING; + else if (strcmp(windowTypeC, "hann") == 0) + windowType = WindowType::HANN; + else if (strcmp(windowTypeC, "nuttal") == 0) + windowType = WindowType::NUTTAL; + else if (strcmp(windowTypeC, "blackman") == 0) + windowType = WindowType::BLACKMAN; + else + throw ConfigError(json, "node-config-hook-pmu-window-type", + "Invalid window type: {}", windowTypeC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-pmu-angle-unit", "Angle unit {} not recognized", angleUnitC); - - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-pmu-angle-unit", + "Angle unit {} not recognized", angleUnitC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); } -Hook::Reason PmuHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason PmuHook::process(struct Sample *smp) { + assert(state == State::STARTED); - initSampleCount++; + initSampleCount++; - if (smp->sequence - lastSequence > 1) - logger->warn("Calculation is not Realtime. {} sampled missed", smp->sequence - lastSequence); - lastSequence = smp->sequence; + if (smp->sequence - lastSequence > 1) + logger->warn("Calculation is not Realtime. {} sampled missed", + smp->sequence - lastSequence); + lastSequence = smp->sequence; - if (!init && initSampleCount > windowSize) - init = true; + if (!init && initSampleCount > windowSize) + init = true; - timespec timeDiff = time_diff(&nextRun, &smp->ts.origin); - double tmpTimeDiff = time_to_double(&timeDiff); - bool run = false; - if (tmpTimeDiff > 0. && init) - run = true; + timespec timeDiff = time_diff(&nextRun, &smp->ts.origin); + double tmpTimeDiff = time_to_double(&timeDiff); + bool run = false; + if (tmpTimeDiff > 0. && init) + run = true; - Status phasorStatus = Status::VALID; - timespec phasorTimestamp = {0}; - if (run) { - for (unsigned i = 0; i < signalIndices.size(); i++) { - lastPhasors[i] = estimatePhasor(windows[i], lastPhasors[i]); - if (lastPhasors[i].valid != Status::VALID) - phasorStatus = Status::INVALID; - } + Status phasorStatus = Status::VALID; + timespec phasorTimestamp = {0}; + if (run) { + for (unsigned i = 0; i < signalIndices.size(); i++) { + lastPhasors[i] = estimatePhasor(windows[i], lastPhasors[i]); + if (lastPhasors[i].valid != Status::VALID) + phasorStatus = Status::INVALID; + } - // Align time tag - double currentTimeTag = time_to_double(&smp->ts.origin); - double alignedTime = currentTimeTag - fmod(currentTimeTag, 1 / phasorRate); - nextRun = time_from_double(alignedTime + 1 / phasorRate); + // Align time tag + double currentTimeTag = time_to_double(&smp->ts.origin); + double alignedTime = currentTimeTag - fmod(currentTimeTag, 1 / phasorRate); + nextRun = time_from_double(alignedTime + 1 / phasorRate); - size_t tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = windowSize; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = 0; - else if (timeAlignType == TimeAlign::CENTER) - tsPos = windowSize / 2; - phasorTimestamp = (*windowsTs)[tsPos]; - } + size_t tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = windowSize; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = 0; + else if (timeAlignType == TimeAlign::CENTER) + tsPos = windowSize / 2; + phasorTimestamp = (*windowsTs)[tsPos]; + } - // Update sample memory - unsigned i = 0; - for (auto index : signalIndices) - windows[i++]->update(smp->data[index].f); - windowsTs->update(smp->ts.origin); + // Update sample memory + unsigned i = 0; + for (auto index : signalIndices) + windows[i++]->update(smp->data[index].f); + windowsTs->update(smp->ts.origin); - // Make sure to update phasors after window update but estimate them before - if(run) { - for (unsigned i = 0; i < signalIndices.size(); i++) { - smp->data[i * 4 + 0].f = lastPhasors[i].frequency + frequencyOffset; // Frequency - smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude - smp->data[i * 4 + 2].f = (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; // Phase - smp->data[i * 4 + 3].f = lastPhasors[i].rocof + rocofOffset; /* ROCOF */; - } - smp->ts.origin = phasorTimestamp; + // Make sure to update phasors after window update but estimate them before + if (run) { + for (unsigned i = 0; i < signalIndices.size(); i++) { + smp->data[i * 4 + 0].f = + lastPhasors[i].frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = + (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; // Phase + smp->data[i * 4 + 3].f = lastPhasors[i].rocof + rocofOffset; /* ROCOF */ + ; + } + smp->ts.origin = phasorTimestamp; - smp->length = signalIndices.size() * 4; - } + smp->length = signalIndices.size() * 4; + } - if (!run || phasorStatus != Status::VALID) - return Reason::SKIP_SAMPLE; + if (!run || phasorStatus != Status::VALID) + return Reason::SKIP_SAMPLE; - return Reason::OK; + return Reason::OK; } -PmuHook::Phasor PmuHook::estimatePhasor(dsp::CosineWindow *window, Phasor lastPhasor) -{ - return {0., 0., 0., 0., Status::INVALID}; +PmuHook::Phasor PmuHook::estimatePhasor(dsp::CosineWindow *window, + Phasor lastPhasor) { + return {0., 0., 0., 0., Status::INVALID}; } // Register hook static char n[] = "pmu"; static char d[] = "This hook estimates a phsor"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu_dft.cpp b/lib/hooks/pmu_dft.cpp index e0687eb00..bac7e49ed 100644 --- a/lib/hooks/pmu_dft.cpp +++ b/lib/hooks/pmu_dft.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include -#include +#include #include +#include #include #include @@ -25,653 +25,674 @@ namespace node { class PmuDftHook : public MultiSignalHook { protected: - enum class PaddingType { - ZERO, - SIG_REPEAT - }; + enum class PaddingType { ZERO, SIG_REPEAT }; - enum class WindowType { - NONE, - FLATTOP, - HANN, - HAMMING - }; + enum class WindowType { NONE, FLATTOP, HANN, HAMMING }; - enum class EstimationType { - NONE, - QUADRATIC, - IpDFT - }; + enum class EstimationType { NONE, QUADRATIC, IpDFT }; - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - struct Point { - double x; - std::complex y; - }; + struct Point { + double x; + std::complex y; + }; - struct DftEstimate { - double amplitude; - double frequency; - double phase; - }; + struct DftEstimate { + double amplitude; + double frequency; + double phase; + }; - struct Phasor { - double frequency; - double amplitude; - double phase; - double rocof; // Rate of change of frequency. - }; + struct Phasor { + double frequency; + double amplitude; + double phase; + double rocof; // Rate of change of frequency. + }; - enum WindowType windowType; - enum PaddingType paddingType; - enum EstimationType estType; - enum TimeAlign timeAlignType; + enum WindowType windowType; + enum PaddingType paddingType; + enum EstimationType estType; + enum TimeAlign timeAlignType; - std::vector> smpMemoryData; - std::vector smpMemoryTs; + std::vector> smpMemoryData; + std::vector smpMemoryTs; #ifdef DFT_MEM_DUMP - std::vector ppsMemory; + std::vector ppsMemory; #endif - std::vector>> matrix; - std::vector>> results; - std::vector filterWindowCoefficents; - std::vector> absResults; - std::vector absFrequencies; + std::vector>> matrix; + std::vector>> results; + std::vector filterWindowCoefficents; + std::vector> absResults; + std::vector absFrequencies; - uint64_t calcCount; - unsigned sampleRate; - double startFrequency; - double endFreqency; - double frequencyResolution; - unsigned rate; - unsigned ppsIndex; - unsigned windowSize; - unsigned windowMultiplier; // Multiplyer for the window to achieve frequency resolution - unsigned freqCount; // Number of requency bins that are calculated - bool channelNameEnable; // Rename the output values with channel name or only descriptive name + uint64_t calcCount; + unsigned sampleRate; + double startFrequency; + double endFreqency; + double frequencyResolution; + unsigned rate; + unsigned ppsIndex; + unsigned windowSize; + unsigned + windowMultiplier; // Multiplyer for the window to achieve frequency resolution + unsigned freqCount; // Number of requency bins that are calculated + bool + channelNameEnable; // Rename the output values with channel name or only descriptive name - uint64_t smpMemPos; - uint64_t lastSequence; + uint64_t smpMemPos; + uint64_t lastSequence; - std::complex omega; + std::complex omega; - double windowCorrectionFactor; - struct timespec lastCalc; - double nextCalc; + double windowCorrectionFactor; + struct timespec lastCalc; + double nextCalc; - std::vector lastResult; + std::vector lastResult; - std::string dumperPrefix; - bool dumperEnable; + std::string dumperPrefix; + bool dumperEnable; #ifdef DFT_MEM_DUMP - Dumper origSigSync; - Dumper windowdSigSync; - Dumper ppsSigSync; - Dumper phasorRocof; - Dumper phasorPhase; - Dumper phasorAmplitude; - Dumper phasorFreq; + Dumper origSigSync; + Dumper windowdSigSync; + Dumper ppsSigSync; + Dumper phasorRocof; + Dumper phasorPhase; + Dumper phasorAmplitude; + Dumper phasorFreq; #endif - double angleUnitFactor; - double phaseOffset; - double frequencyOffset; - double amplitudeOffset; - double rocofOffset; + double angleUnitFactor; + double phaseOffset; + double frequencyOffset; + double amplitudeOffset; + double rocofOffset; public: - PmuDftHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - windowType(WindowType::NONE), - paddingType(PaddingType::ZERO), - estType(EstimationType::NONE), - timeAlignType(TimeAlign::CENTER), - smpMemoryData(), - smpMemoryTs(), + PmuDftHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), windowType(WindowType::NONE), + paddingType(PaddingType::ZERO), estType(EstimationType::NONE), + timeAlignType(TimeAlign::CENTER), smpMemoryData(), smpMemoryTs(), #ifdef DFT_MEM_DUMP - ppsMemory(), + ppsMemory(), #endif - matrix(), - results(), - filterWindowCoefficents(), - absResults(), - absFrequencies(), - calcCount(0), - sampleRate(0), - startFrequency(0), - endFreqency(0), - frequencyResolution(0), - rate(0), - ppsIndex(0), - windowSize(0), - windowMultiplier(0), - freqCount(0), - channelNameEnable(1), - smpMemPos(0), - lastSequence(0), - windowCorrectionFactor(0), - lastCalc({0, 0}), - nextCalc(0.0), - lastResult(), - dumperPrefix("/tmp/plot/"), - dumperEnable(false), + matrix(), results(), filterWindowCoefficents(), absResults(), + absFrequencies(), calcCount(0), sampleRate(0), startFrequency(0), + endFreqency(0), frequencyResolution(0), rate(0), ppsIndex(0), + windowSize(0), windowMultiplier(0), freqCount(0), channelNameEnable(1), + smpMemPos(0), lastSequence(0), windowCorrectionFactor(0), + lastCalc({0, 0}), nextCalc(0.0), lastResult(), + dumperPrefix("/tmp/plot/"), dumperEnable(false), #ifdef DFT_MEM_DUMP - origSigSync(dumperPrefix + "origSigSync"), - windowdSigSync(dumperPrefix + "windowdSigSync"), - ppsSigSync(dumperPrefix + "ppsSigSync"), - phasorRocof(dumperPrefix + "phasorRocof"), - phasorPhase(dumperPrefix + "phasorPhase"), - phasorAmplitude(dumperPrefix + "phasorAmplitude"), - phasorFreq(dumperPrefix + "phasorFreq"), + origSigSync(dumperPrefix + "origSigSync"), + windowdSigSync(dumperPrefix + "windowdSigSync"), + ppsSigSync(dumperPrefix + "ppsSigSync"), + phasorRocof(dumperPrefix + "phasorRocof"), + phasorPhase(dumperPrefix + "phasorPhase"), + phasorAmplitude(dumperPrefix + "phasorAmplitude"), + phasorFreq(dumperPrefix + "phasorFreq"), #endif - angleUnitFactor(1), - phaseOffset(0.0), - frequencyOffset(0.0), - amplitudeOffset(0.0), - rocofOffset(0.0) - { } + angleUnitFactor(1), phaseOffset(0.0), frequencyOffset(0.0), + amplitudeOffset(0.0), rocofOffset(0.0) { + } - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - dumperEnable = logger->level() <= SPDLOG_LEVEL_DEBUG; + dumperEnable = logger->level() <= SPDLOG_LEVEL_DEBUG; - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - // Add signals - auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); - auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); - auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad - auto rocofSig = std::make_shared("rocof", "Hz/s", SignalType::FLOAT); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + // Add signals + auto freqSig = + std::make_shared("frequency", "Hz", SignalType::FLOAT); + auto amplSig = + std::make_shared("amplitude", "V", SignalType::FLOAT); + auto phaseSig = std::make_shared( + "phase", (angleUnitFactor) ? "rad" : "deg", + SignalType::FLOAT); //angleUnitFactor==1 means rad + auto rocofSig = + std::make_shared("rocof", "Hz/s", SignalType::FLOAT); - if (!freqSig || !amplSig || !phaseSig || !rocofSig) - throw RuntimeError("Failed to create new signals"); + if (!freqSig || !amplSig || !phaseSig || !rocofSig) + throw RuntimeError("Failed to create new signals"); - if (channelNameEnable) { - auto suffix = fmt::format("_{}", signalNames[i]); + if (channelNameEnable) { + auto suffix = fmt::format("_{}", signalNames[i]); - freqSig->name += suffix; - amplSig->name += suffix; - phaseSig->name += suffix; - rocofSig->name += suffix; - } + freqSig->name += suffix; + amplSig->name += suffix; + phaseSig->name += suffix; + rocofSig->name += suffix; + } - signals->push_back(freqSig); - signals->push_back(amplSig); - signals->push_back(phaseSig); - signals->push_back(rocofSig); - } + signals->push_back(freqSig); + signals->push_back(amplSig); + signals->push_back(phaseSig); + signals->push_back(rocofSig); + } - // Initialize sample memory - smpMemoryData.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - smpMemoryData.emplace_back(windowSize, 0.0); - } + // Initialize sample memory + smpMemoryData.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + smpMemoryData.emplace_back(windowSize, 0.0); + } - smpMemoryTs.clear(); - for (unsigned i = 0; i < windowSize; i++) { - smpMemoryTs.push_back({0}); - } + smpMemoryTs.clear(); + for (unsigned i = 0; i < windowSize; i++) { + smpMemoryTs.push_back({0}); + } - lastResult.clear(); - for (unsigned i = 0; i < windowSize; i++) { - lastResult.push_back({0,0,0,0}); - } + lastResult.clear(); + for (unsigned i = 0; i < windowSize; i++) { + lastResult.push_back({0, 0, 0, 0}); + } #ifdef DFT_MEM_DUMP - // Initialize temporary ppsMemory - ppsMemory.clear(); - ppsMemory.resize(windowSize, 0.0); + // Initialize temporary ppsMemory + ppsMemory.clear(); + ppsMemory.resize(windowSize, 0.0); #endif - // Calculate how much zero padding ist needed for a needed resolution - windowMultiplier = ceil(((double) sampleRate / windowSize) / frequencyResolution); - if (windowMultiplier > 1 && estType == EstimationType::IpDFT) - throw RuntimeError("Window multiplyer must be 1 if lpdft is used. Change resolution, window_size_factor or frequency range! Current window multiplyer factor is {}", windowMultiplier); + // Calculate how much zero padding ist needed for a needed resolution + windowMultiplier = + ceil(((double)sampleRate / windowSize) / frequencyResolution); + if (windowMultiplier > 1 && estType == EstimationType::IpDFT) + throw RuntimeError("Window multiplyer must be 1 if lpdft is used. Change " + "resolution, window_size_factor or frequency range! " + "Current window multiplyer factor is {}", + windowMultiplier); - freqCount = ceil((endFreqency - startFrequency) / frequencyResolution) + 1; + freqCount = ceil((endFreqency - startFrequency) / frequencyResolution) + 1; - // Initialize matrix of dft coeffients - matrix.clear(); - for (unsigned i = 0; i < freqCount; i++) - matrix.emplace_back(windowSize * windowMultiplier, 0.0); + // Initialize matrix of dft coeffients + matrix.clear(); + for (unsigned i = 0; i < freqCount; i++) + matrix.emplace_back(windowSize * windowMultiplier, 0.0); - // Initalize dft results matrix - results.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - results.emplace_back(freqCount, 0.0); - absResults.emplace_back(freqCount, 0.0); - } + // Initalize dft results matrix + results.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + results.emplace_back(freqCount, 0.0); + absResults.emplace_back(freqCount, 0.0); + } - filterWindowCoefficents.resize(windowSize); + filterWindowCoefficents.resize(windowSize); - for (unsigned i = 0; i < freqCount; i++) - absFrequencies.emplace_back(startFrequency + i * frequencyResolution); + for (unsigned i = 0; i < freqCount; i++) + absFrequencies.emplace_back(startFrequency + i * frequencyResolution); - generateDftMatrix(); - calculateWindow(windowType); + generateDftMatrix(); + calculateWindow(windowType); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - MultiSignalHook::parse(json); - int ret; - int windowSizeFactor = 1; + virtual void parse(json_t *json) { + MultiSignalHook::parse(json); + int ret; + int windowSizeFactor = 1; - const char *paddingTypeC = nullptr; - const char *windowTypeC = nullptr; - const char *estimateTypeC = nullptr; - const char *angleUnitC = nullptr; - const char *timeAlignC = nullptr; + const char *paddingTypeC = nullptr; + const char *windowTypeC = nullptr; + const char *estimateTypeC = nullptr; + const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: F, s?: F, s?: F, s?: i, s?: i, s?: s, s?: s, s?: s, s?: i, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", - "sample_rate", &sampleRate, - "start_freqency", &startFrequency, - "end_freqency", &endFreqency, - "frequency_resolution", &frequencyResolution, - "dft_rate", &rate, - "window_size_factor", &windowSizeFactor, - "window_type", &windowTypeC, - "padding_type", &paddingTypeC, - "estimate_type", &estimateTypeC, - "pps_index", &ppsIndex, - "angle_unit", &angleUnitC, - "add_channel_name", &channelNameEnable, - "timestamp_align", &timeAlignC, - "phase_offset", &phaseOffset, - "amplitude_offset", &litudeOffset, - "frequency_offset", &frequencyOffset, - "rocof_offset", &rocofOffset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-dft"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: i, s?: F, s?: F, s?: F, s?: i, s?: i, s?: s, s?: s, s?: s, s?: " + "i, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", + "sample_rate", &sampleRate, "start_freqency", &startFrequency, + "end_freqency", &endFreqency, "frequency_resolution", + &frequencyResolution, "dft_rate", &rate, "window_size_factor", + &windowSizeFactor, "window_type", &windowTypeC, "padding_type", + &paddingTypeC, "estimate_type", &estimateTypeC, "pps_index", &ppsIndex, + "angle_unit", &angleUnitC, "add_channel_name", &channelNameEnable, + "timestamp_align", &timeAlignC, "phase_offset", &phaseOffset, + "amplitude_offset", &litudeOffset, "frequency_offset", + &frequencyOffset, "rocof_offset", &rocofOffset); + if (ret) + throw ConfigError(json, err, "node-config-hook-dft"); - windowSize = sampleRate * windowSizeFactor / (double) rate; - logger->info("Set windows size to {} samples which fits {} times the rate {}s", windowSize, windowSizeFactor, 1.0 / rate); + windowSize = sampleRate * windowSizeFactor / (double)rate; + logger->info( + "Set windows size to {} samples which fits {} times the rate {}s", + windowSize, windowSizeFactor, 1.0 / rate); - if (!windowTypeC) - logger->info("No Window type given, assume no windowing"); - else if (strcmp(windowTypeC, "flattop") == 0) - windowType = WindowType::FLATTOP; - else if (strcmp(windowTypeC, "hamming") == 0) - windowType = WindowType::HAMMING; - else if (strcmp(windowTypeC, "hann") == 0) - windowType = WindowType::HANN; - else - throw ConfigError(json, "node-config-hook-dft-window-type", "Invalid window type: {}", windowTypeC); + if (!windowTypeC) + logger->info("No Window type given, assume no windowing"); + else if (strcmp(windowTypeC, "flattop") == 0) + windowType = WindowType::FLATTOP; + else if (strcmp(windowTypeC, "hamming") == 0) + windowType = WindowType::HAMMING; + else if (strcmp(windowTypeC, "hann") == 0) + windowType = WindowType::HANN; + else + throw ConfigError(json, "node-config-hook-dft-window-type", + "Invalid window type: {}", windowTypeC); - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-dft-angle-unit", "Angle unit {} not recognized", angleUnitC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-dft-angle-unit", + "Angle unit {} not recognized", angleUnitC); - if (!paddingTypeC) - logger->info("No Padding type given, assume no zeropadding"); - else if (strcmp(paddingTypeC, "zero") == 0) - paddingType = PaddingType::ZERO; - else if (strcmp(paddingTypeC, "signal_repeat") == 0) - paddingType = PaddingType::SIG_REPEAT; - else - throw ConfigError(json, "node-config-hook-dft-padding-type", "Padding type {} not recognized", paddingTypeC); + if (!paddingTypeC) + logger->info("No Padding type given, assume no zeropadding"); + else if (strcmp(paddingTypeC, "zero") == 0) + paddingType = PaddingType::ZERO; + else if (strcmp(paddingTypeC, "signal_repeat") == 0) + paddingType = PaddingType::SIG_REPEAT; + else + throw ConfigError(json, "node-config-hook-dft-padding-type", + "Padding type {} not recognized", paddingTypeC); - if (!estimateTypeC) { - logger->info("No Frequency estimation type given, assume no none"); - estType = EstimationType::NONE; - } else if (strcmp(estimateTypeC, "quadratic") == 0) - estType = EstimationType::QUADRATIC; - else if (strcmp(estimateTypeC, "ipdft") == 0) - estType = EstimationType::IpDFT; - state = State::PARSED; - } + if (!estimateTypeC) { + logger->info("No Frequency estimation type given, assume no none"); + estType = EstimationType::NONE; + } else if (strcmp(estimateTypeC, "quadratic") == 0) + estType = EstimationType::QUADRATIC; + else if (strcmp(estimateTypeC, "ipdft") == 0) + estType = EstimationType::IpDFT; + state = State::PARSED; + } - virtual - void check() - { - assert(state == State::PARSED); + virtual void check() { + assert(state == State::PARSED); - if (endFreqency < 0 || endFreqency > sampleRate) - throw RuntimeError("End frequency must be smaller than sampleRate {}", sampleRate); + if (endFreqency < 0 || endFreqency > sampleRate) + throw RuntimeError("End frequency must be smaller than sampleRate {}", + sampleRate); - if (frequencyResolution > (double) sampleRate / windowSize) - throw RuntimeError("The maximum frequency resolution with smaple_rate:{} and window_site:{} is {}", sampleRate, windowSize, ((double)sampleRate/windowSize)); + if (frequencyResolution > (double)sampleRate / windowSize) + throw RuntimeError("The maximum frequency resolution with smaple_rate:{} " + "and window_site:{} is {}", + sampleRate, windowSize, + ((double)sampleRate / windowSize)); - state = State::CHECKED; - } + state = State::CHECKED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // Update sample memory - unsigned i = 0; - for (auto index : signalIndices) { - smpMemoryData[i++][smpMemPos % windowSize] = smp->data[index].f; - } - smpMemoryTs[smpMemPos % windowSize] = smp->ts.origin; + // Update sample memory + unsigned i = 0; + for (auto index : signalIndices) { + smpMemoryData[i++][smpMemPos % windowSize] = smp->data[index].f; + } + smpMemoryTs[smpMemPos % windowSize] = smp->ts.origin; #ifdef DFT_MEM_DUMP - ppsMemory[smpMemPos % windowSize] = smp->data[ppsIndex].f; + ppsMemory[smpMemPos % windowSize] = smp->data[ppsIndex].f; #endif - bool run = false; - double smpNsec = smp->ts.origin.tv_sec * 1e9 + smp->ts.origin.tv_nsec; + bool run = false; + double smpNsec = smp->ts.origin.tv_sec * 1e9 + smp->ts.origin.tv_nsec; - if (smpNsec > nextCalc) { - run = true; - nextCalc = (smp->ts.origin.tv_sec + (((calcCount % rate) + 1) / (double) rate)) * 1e9; - } + if (smpNsec > nextCalc) { + run = true; + nextCalc = + (smp->ts.origin.tv_sec + (((calcCount % rate) + 1) / (double)rate)) * + 1e9; + } - if (run) { - lastCalc = smp->ts.origin; + if (run) { + lastCalc = smp->ts.origin; #ifdef DFT_MEM_DUMP - double tmpPPSWindow[windowSize]; + double tmpPPSWindow[windowSize]; - for (unsigned i = 0; i< windowSize; i++) - tmpPPSWindow[i] = ppsMemory[(i + smpMemPos) % windowSize]; + for (unsigned i = 0; i < windowSize; i++) + tmpPPSWindow[i] = ppsMemory[(i + smpMemPos) % windowSize]; - if (dumperEnable) - ppsSigSync.writeDataBinary(windowSize, tmpPPSWindow); + if (dumperEnable) + ppsSigSync.writeDataBinary(windowSize, tmpPPSWindow); #endif - #pragma omp parallel for - for (unsigned i = 0; i < signalIndices.size(); i++) { - Phasor currentResult = {0,0,0,0}; +#pragma omp parallel for + for (unsigned i = 0; i < signalIndices.size(); i++) { + Phasor currentResult = {0, 0, 0, 0}; - calculateDft(PaddingType::ZERO, smpMemoryData[i], results[i], smpMemPos); + calculateDft(PaddingType::ZERO, smpMemoryData[i], results[i], + smpMemPos); - unsigned maxPos = 0; - double absAmplitude = 0; + unsigned maxPos = 0; + double absAmplitude = 0; - for(unsigned j = 0; j < freqCount; j++) { - if (absAmplitude < abs(results[i][j])) { - absAmplitude = abs(results[i][j]); - maxPos = j; - } - } - - int multiplier = paddingType == PaddingType::ZERO - ? 1 - : windowMultiplier; - - DftEstimate dftEstimate = {0}; - - if ( (maxPos < 1 || maxPos >= freqCount - 1) && estType != EstimationType::NONE) { - logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); - dftEstimate = noEstimation({0}, { absFrequencies[maxPos + 0], results[i][maxPos + 0] }, {0}, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - } else { - Point a = { absFrequencies[maxPos - 1], results[i][maxPos - 1] }; - Point b = { absFrequencies[maxPos + 0], results[i][maxPos + 0] }; - Point c = { absFrequencies[maxPos + 1], results[i][maxPos + 1] }; - - if( estType == EstimationType::QUADRATIC ) - dftEstimate = quadraticEstimation(a, b, c, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - else if( estType == EstimationType::IpDFT ) - dftEstimate = lpdftEstimation(a, b, c, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - else - dftEstimate = noEstimation({0}, b, {0}, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - } - currentResult.frequency = dftEstimate.frequency; - currentResult.amplitude = dftEstimate.amplitude; - currentResult.phase = dftEstimate.phase * angleUnitFactor;//convert phase from rad to deg - - if (windowSize <= smpMemPos) { - - smp->data[i * 4 + 0].f = currentResult.frequency + frequencyOffset; // Frequency - smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude - smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; // Phase - smp->data[i * 4 + 3].f = ((currentResult.frequency - lastResult[i].frequency) * (double)rate) + rocofOffset; /* ROCOF */; - lastResult[i] = currentResult; - } - } -#ifdef DFT_MEM_DUMP - // The following is a debug output and currently only for channel 0 - if (dumperEnable && windowSize * 5 < smpMemPos){ - phasorFreq.writeDataBinary(1, &(smp->data[0 * 4 + 0].f)); - phasorPhase.writeDataBinary(1, &(smp->data[0 * 4 + 2].f)); - phasorAmplitude.writeDataBinary(1, &(smp->data[0 * 4 + 1].f)); - phasorRocof.writeDataBinary(1, &(smp->data[0 * 4 + 3].f)); - } -#endif - - smp->length = windowSize < smpMemPos ? signalIndices.size() * 4 : 0; - - if(smpMemPos >= windowSize) { - unsigned tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = smpMemPos; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = smpMemPos - windowSize; - else if (timeAlignType == TimeAlign::CENTER) { - tsPos = smpMemPos - (windowSize / 2); - } - - smp->ts.origin = smpMemoryTs[tsPos % windowSize]; - } - - calcCount++; - } - - if (smp->sequence - lastSequence > 1) - logger->warn("Calculation is not Realtime. {} sampled missed", smp->sequence - lastSequence); - - lastSequence = smp->sequence; - - if(smpMemPos >= 2 * windowSize) {//reset smpMemPos if greater than twice the window. Important to handle init - smpMemPos = windowSize; + for (unsigned j = 0; j < freqCount; j++) { + if (absAmplitude < abs(results[i][j])) { + absAmplitude = abs(results[i][j]); + maxPos = j; + } } - smpMemPos++; + int multiplier = + paddingType == PaddingType::ZERO ? 1 : windowMultiplier; - if (run && windowSize < smpMemPos) - return Reason::OK; + DftEstimate dftEstimate = {0}; - return Reason::SKIP_SAMPLE; - } + if ((maxPos < 1 || maxPos >= freqCount - 1) && + estType != EstimationType::NONE) { + logger->warn("Maximum frequency bin lies on window boundary. Using " + "non-estimated results!"); + dftEstimate = noEstimation( + {0}, {absFrequencies[maxPos + 0], results[i][maxPos + 0]}, {0}, + maxPos, startFrequency, frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + } else { + Point a = {absFrequencies[maxPos - 1], results[i][maxPos - 1]}; + Point b = {absFrequencies[maxPos + 0], results[i][maxPos + 0]}; + Point c = {absFrequencies[maxPos + 1], results[i][maxPos + 1]}; - /* - * This function generates the furie coeffients for the calculateDft function - */ - void generateDftMatrix() - { - using namespace std::complex_literals; + if (estType == EstimationType::QUADRATIC) + dftEstimate = quadraticEstimation( + a, b, c, maxPos, startFrequency, frequencyResolution, + multiplier, windowSize, windowCorrectionFactor); + else if (estType == EstimationType::IpDFT) + dftEstimate = lpdftEstimation(a, b, c, maxPos, startFrequency, + frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + else + dftEstimate = noEstimation({0}, b, {0}, maxPos, startFrequency, + frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + } + currentResult.frequency = dftEstimate.frequency; + currentResult.amplitude = dftEstimate.amplitude; + currentResult.phase = + dftEstimate.phase * angleUnitFactor; //convert phase from rad to deg - omega = exp((-2i * M_PI) / (double)(windowSize * windowMultiplier)); - unsigned startBin = floor(startFrequency / frequencyResolution); - - for (unsigned i = 0; i < freqCount ; i++) { - for (unsigned j = 0 ; j < windowSize * windowMultiplier ; j++) - matrix[i][j] = pow(omega, (i + startBin) * j); - } - } - - /* - * This function calculates the discrete furie transform of the input signal - */ - void calculateDft(enum PaddingType padding, std::vector &ringBuffer, std::vector> &results, unsigned ringBufferPos) - { - /* RingBuffer size needs to be equal to windowSize - * prepare sample window The following parts can be combined */ - double tmpSmpWindow[windowSize]; - - for (unsigned i = 0; i< windowSize; i++) - tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * filterWindowCoefficents[i]; + if (windowSize <= smpMemPos) { + smp->data[i * 4 + 0].f = + currentResult.frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; // Phase + smp->data[i * 4 + 3].f = + ((currentResult.frequency - lastResult[i].frequency) * + (double)rate) + + rocofOffset; /* ROCOF */ + ; + lastResult[i] = currentResult; + } + } #ifdef DFT_MEM_DUMP - if (dumperEnable) - origSigSync.writeDataBinary(windowSize, tmpSmpWindow); + // The following is a debug output and currently only for channel 0 + if (dumperEnable && windowSize * 5 < smpMemPos) { + phasorFreq.writeDataBinary(1, &(smp->data[0 * 4 + 0].f)); + phasorPhase.writeDataBinary(1, &(smp->data[0 * 4 + 2].f)); + phasorAmplitude.writeDataBinary(1, &(smp->data[0 * 4 + 1].f)); + phasorRocof.writeDataBinary(1, &(smp->data[0 * 4 + 3].f)); + } #endif - for (unsigned i = 0; i < freqCount; i++) { - results[i] = 0; + smp->length = windowSize < smpMemPos ? signalIndices.size() * 4 : 0; - for (unsigned j = 0; j < windowSize * windowMultiplier; j++) { - if (padding == PaddingType::ZERO) { - if (j < windowSize) - results[i] += tmpSmpWindow[j] * matrix[i][j]; - else - results[i] += 0; - } - else if (padding == PaddingType::SIG_REPEAT) // Repeat samples - results[i] += tmpSmpWindow[j % windowSize] * matrix[i][j]; - } - } - } + if (smpMemPos >= windowSize) { + unsigned tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = smpMemPos; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = smpMemPos - windowSize; + else if (timeAlignType == TimeAlign::CENTER) { + tsPos = smpMemPos - (windowSize / 2); + } - /* + smp->ts.origin = smpMemoryTs[tsPos % windowSize]; + } + + calcCount++; + } + + if (smp->sequence - lastSequence > 1) + logger->warn("Calculation is not Realtime. {} sampled missed", + smp->sequence - lastSequence); + + lastSequence = smp->sequence; + + if (smpMemPos >= + 2 * windowSize) { //reset smpMemPos if greater than twice the window. Important to handle init + smpMemPos = windowSize; + } + + smpMemPos++; + + if (run && windowSize < smpMemPos) + return Reason::OK; + + return Reason::SKIP_SAMPLE; + } + + /* + * This function generates the furie coeffients for the calculateDft function + */ + void generateDftMatrix() { + using namespace std::complex_literals; + + omega = exp((-2i * M_PI) / (double)(windowSize * windowMultiplier)); + unsigned startBin = floor(startFrequency / frequencyResolution); + + for (unsigned i = 0; i < freqCount; i++) { + for (unsigned j = 0; j < windowSize * windowMultiplier; j++) + matrix[i][j] = pow(omega, (i + startBin) * j); + } + } + + /* + * This function calculates the discrete furie transform of the input signal + */ + void calculateDft(enum PaddingType padding, std::vector &ringBuffer, + std::vector> &results, + unsigned ringBufferPos) { + /* RingBuffer size needs to be equal to windowSize + * prepare sample window The following parts can be combined */ + double tmpSmpWindow[windowSize]; + + for (unsigned i = 0; i < windowSize; i++) + tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * + filterWindowCoefficents[i]; + +#ifdef DFT_MEM_DUMP + if (dumperEnable) + origSigSync.writeDataBinary(windowSize, tmpSmpWindow); +#endif + + for (unsigned i = 0; i < freqCount; i++) { + results[i] = 0; + + for (unsigned j = 0; j < windowSize * windowMultiplier; j++) { + if (padding == PaddingType::ZERO) { + if (j < windowSize) + results[i] += tmpSmpWindow[j] * matrix[i][j]; + else + results[i] += 0; + } else if (padding == PaddingType::SIG_REPEAT) // Repeat samples + results[i] += tmpSmpWindow[j % windowSize] * matrix[i][j]; + } + } + } + + /* * This function prepares the selected window coefficents */ - void calculateWindow(enum WindowType windowTypeIn) - { - switch (windowTypeIn) { - case WindowType::FLATTOP: - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = 0.21557895 - - 0.41663158 * cos(2 * M_PI * i / (windowSize)) - + 0.277263158 * cos(4 * M_PI * i / (windowSize)) - - 0.083578947 * cos(6 * M_PI * i / (windowSize)) - + 0.006947368 * cos(8 * M_PI * i / (windowSize)); - windowCorrectionFactor += filterWindowCoefficents[i]; - } - break; + void calculateWindow(enum WindowType windowTypeIn) { + switch (windowTypeIn) { + case WindowType::FLATTOP: + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = + 0.21557895 - 0.41663158 * cos(2 * M_PI * i / (windowSize)) + + 0.277263158 * cos(4 * M_PI * i / (windowSize)) - + 0.083578947 * cos(6 * M_PI * i / (windowSize)) + + 0.006947368 * cos(8 * M_PI * i / (windowSize)); + windowCorrectionFactor += filterWindowCoefficents[i]; + } + break; - case WindowType::HAMMING: - case WindowType::HANN: { - double a0 = 0.5; // This is the hann window - if (windowTypeIn == WindowType::HAMMING) - a0 = 25./46; + case WindowType::HAMMING: + case WindowType::HANN: { + double a0 = 0.5; // This is the hann window + if (windowTypeIn == WindowType::HAMMING) + a0 = 25. / 46; - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = a0 - (1 - a0) * cos(2 * M_PI * i / (windowSize)); - windowCorrectionFactor += filterWindowCoefficents[i]; - } + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = + a0 - (1 - a0) * cos(2 * M_PI * i / (windowSize)); + windowCorrectionFactor += filterWindowCoefficents[i]; + } - break; - } + break; + } - default: - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = 1; - windowCorrectionFactor += filterWindowCoefficents[i]; - } - break; - } + default: + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = 1; + windowCorrectionFactor += filterWindowCoefficents[i]; + } + break; + } - windowCorrectionFactor /= windowSize; - } + windowCorrectionFactor /= windowSize; + } - DftEstimate noEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - // Frequency estimation - double f_est = startFrequency + maxFBin * frequencyResolution; + DftEstimate noEstimation(const Point &a, const Point &b, const Point &c, + unsigned maxFBin, double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, double windowCorrectionFactor) { + // Frequency estimation + double f_est = startFrequency + maxFBin * frequencyResolution; - // Amplitude estimation - double a_est = abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + // Amplitude estimation + double a_est = + abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - //Phase estimation - double phase_est = atan2(b.y.imag(), b.y.real()); + //Phase estimation + double phase_est = atan2(b.y.imag(), b.y.real()); - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } - /* + /* * This function is calculation the IpDFT based on the following paper: * * https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7980868&tag=1 * */ - DftEstimate lpdftEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - double delta = 0; + DftEstimate lpdftEstimation(const Point &a, const Point &b, const Point &c, + unsigned maxFBin, double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, + double windowCorrectionFactor) { + double delta = 0; - //paper eq 8 - if (abs(c.y) > abs(a.y)) { - delta = 1. * (2. * abs(c.y) - abs(b.y)) / (abs(b.y) + abs(c.y)); - } else { - delta = -1. * (2. * abs(a.y) - abs(b.y)) / (abs(b.y) + abs(a.y)); - } + //paper eq 8 + if (abs(c.y) > abs(a.y)) { + delta = 1. * (2. * abs(c.y) - abs(b.y)) / (abs(b.y) + abs(c.y)); + } else { + delta = -1. * (2. * abs(a.y) - abs(b.y)) / (abs(b.y) + abs(a.y)); + } - // Frequency estimation (eq 4) - double f_est = startFrequency + ( (double) maxFBin + delta) * frequencyResolution; + // Frequency estimation (eq 4) + double f_est = + startFrequency + ((double)maxFBin + delta) * frequencyResolution; - // Amplitude estimation (eq 9) - double a_est = abs(b.y) * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); - a_est *= 2 / (windowSize * windowCorrectionFactor * multiplier); + // Amplitude estimation (eq 9) + double a_est = abs(b.y) * abs((M_PI * delta) / sin(M_PI * delta)) * + abs(pow(delta, 2) - 1); + a_est *= 2 / (windowSize * windowCorrectionFactor * multiplier); - //Phase estimation (eq 10) - double phase_est = atan2(b.y.imag(), b.y.real()) - M_PI * delta; + //Phase estimation (eq 10) + double phase_est = atan2(b.y.imag(), b.y.real()) - M_PI * delta; - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } - /* + /* * This function is calculating the mximum based on a quadratic interpolation * * This function is based on the following paper: * https://mgasior.web.cern.ch/pap/biw2004.pdf (equation 10) (freq estimation) * https://dspguru.com/dsp/howtos/how-to-interpolate-fft-peak/ */ - DftEstimate quadraticEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - using namespace std::complex_literals; + DftEstimate quadraticEstimation(const Point &a, const Point &b, + const Point &c, unsigned maxFBin, + double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, + double windowCorrectionFactor) { + using namespace std::complex_literals; - double ay_abs = abs(a.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - double by_abs = abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - double cy_abs = abs(c.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double ay_abs = + abs(a.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double by_abs = + abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double cy_abs = + abs(c.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - // Frequency estimation - double maxBinEst = (double) maxFBin + (cy_abs - ay_abs) / (2 * (2 * by_abs - ay_abs - cy_abs)); - double f_est = startFrequency + maxBinEst * frequencyResolution; // convert bin to frequency + // Frequency estimation + double maxBinEst = (double)maxFBin + + (cy_abs - ay_abs) / (2 * (2 * by_abs - ay_abs - cy_abs)); + double f_est = startFrequency + + maxBinEst * frequencyResolution; // convert bin to frequency - // Amplitude estimation - double f = (a.x * (by_abs - cy_abs) + b.x * (cy_abs - ay_abs) + c.x * (ay_abs - by_abs)) / ((a.x - b.x) * (a.x - c.x) * (c.x - b.x)); - double g = (pow(a.x, 2) * (by_abs - cy_abs) + pow(b.x, 2) * (cy_abs - ay_abs) + pow(c.x, 2) * (ay_abs - by_abs)) / ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); - double h = (pow(a.x, 2) * (b.x * cy_abs - c.x * by_abs) + a.x * (pow(c.x, 2) * by_abs - pow(b.x,2) * cy_abs)+ b.x * c.x * ay_abs * (b.x - c.x)) / ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); - double a_est = f * pow(f_est,2) + g * f_est + h; + // Amplitude estimation + double f = (a.x * (by_abs - cy_abs) + b.x * (cy_abs - ay_abs) + + c.x * (ay_abs - by_abs)) / + ((a.x - b.x) * (a.x - c.x) * (c.x - b.x)); + double g = + (pow(a.x, 2) * (by_abs - cy_abs) + pow(b.x, 2) * (cy_abs - ay_abs) + + pow(c.x, 2) * (ay_abs - by_abs)) / + ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); + double h = (pow(a.x, 2) * (b.x * cy_abs - c.x * by_abs) + + a.x * (pow(c.x, 2) * by_abs - pow(b.x, 2) * cy_abs) + + b.x * c.x * ay_abs * (b.x - c.x)) / + ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); + double a_est = f * pow(f_est, 2) + g * f_est + h; - //Phase estimation - double phase_est = atan2(b.y.imag(), b.y.real()); + //Phase estimation + double phase_est = atan2(b.y.imag(), b.y.real()); - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } }; // Register hook static char n[] = "pmu_dft"; static char d[] = "This hook calculates the dft on a window"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu_ipdft.cpp b/lib/hooks/pmu_ipdft.cpp index 3faee9649..38ec4a7e4 100644 --- a/lib/hooks/pmu_ipdft.cpp +++ b/lib/hooks/pmu_ipdft.cpp @@ -13,146 +13,152 @@ namespace node { class IpDftPmuHook : public PmuHook { protected: - std::complex omega; - std::vector>> dftMatrix; - std::vector> dftResult; + std::complex omega; + std::vector>> dftMatrix; + std::vector> dftResult; - unsigned frequencyCount; // Number of requency bins that are calculated - double estimationRange; // The range around nominalFreq used for estimation + unsigned frequencyCount; // Number of requency bins that are calculated + double estimationRange; // The range around nominalFreq used for estimation public: - IpDftPmuHook(Path *p, Node *n, int fl, int prio, bool en = true): - PmuHook(p, n, fl, prio, en), - frequencyCount(0), - estimationRange(0) + IpDftPmuHook(Path *p, Node *n, int fl, int prio, bool en = true) + : PmuHook(p, n, fl, prio, en), frequencyCount(0), estimationRange(0) - { } + {} - void prepare() - { - PmuHook::prepare(); + void prepare() { + PmuHook::prepare(); - const double startFrequency = nominalFreq - estimationRange; - const double endFrequency = nominalFreq + estimationRange; - const double frequencyResolution = (double)sampleRate / windowSize; + const double startFrequency = nominalFreq - estimationRange; + const double endFrequency = nominalFreq + estimationRange; + const double frequencyResolution = (double)sampleRate / windowSize; - frequencyCount = ceil((endFrequency - startFrequency) / frequencyResolution); + frequencyCount = + ceil((endFrequency - startFrequency) / frequencyResolution); - // Initialize matrix of dft coeffients - dftMatrix.clear(); - for (unsigned i = 0; i < frequencyCount; i++) - dftMatrix.emplace_back(windowSize, 0.0); + // Initialize matrix of dft coeffients + dftMatrix.clear(); + for (unsigned i = 0; i < frequencyCount; i++) + dftMatrix.emplace_back(windowSize, 0.0); - using namespace std::complex_literals; + using namespace std::complex_literals; - omega = exp((-2i * M_PI) / (double)(windowSize)); - unsigned startBin = floor(startFrequency / frequencyResolution); + omega = exp((-2i * M_PI) / (double)(windowSize)); + unsigned startBin = floor(startFrequency / frequencyResolution); - for (unsigned i = 0; i < frequencyCount ; i++) { - for (unsigned j = 0 ; j < windowSize; j++) - dftMatrix[i][j] = pow(omega, (i + startBin) * j); - dftResult.push_back(0.0); - } - } + for (unsigned i = 0; i < frequencyCount; i++) { + for (unsigned j = 0; j < windowSize; j++) + dftMatrix[i][j] = pow(omega, (i + startBin) * j); + dftResult.push_back(0.0); + } + } - void parse(json_t *json) - { - PmuHook::parse(json); - int ret; + void parse(json_t *json) { + PmuHook::parse(json); + int ret; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F}", - "estimation_range", &estimationRange - ); + ret = json_unpack_ex(json, &err, 0, "{ s?: F}", "estimation_range", + &estimationRange); - if (ret) - throw ConfigError(json, err, "node-config-hook-ip-dft-pmu"); + if (ret) + throw ConfigError(json, err, "node-config-hook-ip-dft-pmu"); - if (estimationRange <= 0) - throw ConfigError(json, "node-config-hook-ip-dft-pmu-estimation_range", "Estimation range cannot be less or equal than 0 tried to set {}", estimationRange); + if (estimationRange <= 0) + throw ConfigError( + json, "node-config-hook-ip-dft-pmu-estimation_range", + "Estimation range cannot be less or equal than 0 tried to set {}", + estimationRange); + } - } + PmuHook::Phasor estimatePhasor(dsp::CosineWindow *window, + PmuHook::Phasor lastPhasor) { + PmuHook::Phasor phasor = {0}; - PmuHook::Phasor estimatePhasor(dsp::CosineWindow *window, PmuHook::Phasor lastPhasor) - { - PmuHook::Phasor phasor = {0}; + // Calculate DFT + for (unsigned i = 0; i < frequencyCount; i++) { + dftResult[i] = 0; - // Calculate DFT - for (unsigned i = 0; i < frequencyCount; i++) { - dftResult[i] = 0; + const unsigned size = (*window).size(); + for (unsigned j = 0; j < size; j++) + dftResult[i] += (*window)[j] * dftMatrix[i][j]; + } + // End calculate DFT - const unsigned size = (*window).size(); - for (unsigned j = 0; j < size; j++) - dftResult[i] += (*window)[j] * dftMatrix[i][j]; - } - // End calculate DFT + // Find max bin + unsigned maxBin = 0; + double absAmplitude = 0; - // Find max bin - unsigned maxBin = 0; - double absAmplitude = 0; + for (unsigned j = 0; j < frequencyCount; j++) { + if (absAmplitude < abs(dftResult[j])) { + absAmplitude = abs(dftResult[j]); + maxBin = j; + } + } + // End find max bin - for(unsigned j = 0; j < frequencyCount; j++) { - if (absAmplitude < abs(dftResult[j])) { - absAmplitude = abs(dftResult[j]); - maxBin = j; - } - } - // End find max bin + if (maxBin == 0 || maxBin == (frequencyCount - 1)) { + logger->warn("Maximum frequency bin lies on window boundary. Using " + "non-estimated results!"); + //TODO: add handling to not forward this phasor!! + } else { + const double startFrequency = nominalFreq - estimationRange; + const double frequencyResolution = (double)sampleRate / windowSize; - if (maxBin == 0 || maxBin == (frequencyCount - 1)) { - logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); - //TODO: add handling to not forward this phasor!! - } else { - const double startFrequency = nominalFreq - estimationRange; - const double frequencyResolution = (double)sampleRate / windowSize; + double a = abs(dftResult[maxBin - 1]); + double b = abs(dftResult[maxBin + 0]); + double c = abs(dftResult[maxBin + 1]); + double bPhase = atan2(dftResult[maxBin].imag(), dftResult[maxBin].real()); - double a = abs(dftResult[ maxBin - 1 ]); - double b = abs(dftResult[ maxBin + 0 ]); - double c = abs(dftResult[ maxBin + 1 ]); - double bPhase = atan2(dftResult[maxBin].imag(), dftResult[maxBin].real()); + // Estimate phasor + // Based on https://ieeexplore.ieee.org/document/7980868 + double delta = 0; - // Estimate phasor - // Based on https://ieeexplore.ieee.org/document/7980868 - double delta = 0; + // Paper eq 8 + if (c > a) { + delta = 1. * (2. * c - b) / (b + c); + } else { + delta = -1. * (2. * a - b) / (b + a); + } - // Paper eq 8 - if (c > a) { - delta = 1. * (2. * c - b) / (b + c); - } else { - delta = -1. * (2. * a - b) / (b + a); - } + // Frequency estimation (eq 4) + phasor.frequency = + startFrequency + ((double)maxBin + delta) * frequencyResolution; - // Frequency estimation (eq 4) - phasor.frequency = startFrequency + ( (double) maxBin + delta) * frequencyResolution; + // Amplitude estimation (eq 9) + phasor.amplitude = + b * abs((M_PI * delta) / sin(M_PI * delta)) * abs(pow(delta, 2) - 1); + phasor.amplitude *= 2 / (windowSize * window->getCorrectionFactor()); - // Amplitude estimation (eq 9) - phasor.amplitude = b * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); - phasor.amplitude *= 2 / (windowSize * window->getCorrectionFactor()); + // Phase estimation (eq 10) + phasor.phase = bPhase - M_PI * delta; - // Phase estimation (eq 10) - phasor.phase = bPhase - M_PI * delta; + // ROCOF estimation + phasor.rocof = + ((phasor.frequency - lastPhasor.frequency) * (double)phasorRate); + // End estimate phasor + } - // ROCOF estimation - phasor.rocof = ((phasor.frequency - lastPhasor.frequency) * (double)phasorRate); - // End estimate phasor - } + if (lastPhasor.frequency != + 0) // Check if we already calculated a phasor before + phasor.valid = Status::VALID; - if (lastPhasor.frequency != 0) // Check if we already calculated a phasor before - phasor.valid = Status::VALID; - - return phasor; - } + return phasor; + } }; // Register hook static char n[] = "ip-dft-pmu"; static char d[] = "This hook calculates a phasor based on ipDFT"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/power.cpp b/lib/hooks/power.cpp index 6716f8262..2862a9e5d 100644 --- a/lib/hooks/power.cpp +++ b/lib/hooks/power.cpp @@ -22,315 +22,320 @@ namespace node { class PowerHook : public MultiSignalHook { protected: - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - struct PowerPairing { - int voltageIndex; - int currentIndex; - }; + struct PowerPairing { + int voltageIndex; + int currentIndex; + }; - struct PairingsStr { - std::string voltage; - std::string current; - }; + struct PairingsStr { + std::string voltage; + std::string current; + }; - std::vector pairingsStr; - std::vector> smpMemory; - std::vector pairings; - std::vector smpMemoryTs; + std::vector pairingsStr; + std::vector> smpMemory; + std::vector pairings; + std::vector smpMemoryTs; - std::vector accumulator_u; // Integral over u - std::vector accumulator_i; // Integral over I - std::vector accumulator_ui; // Integral over U*I + std::vector accumulator_u; // Integral over u + std::vector accumulator_i; // Integral over I + std::vector accumulator_ui; // Integral over U*I - unsigned windowSize; - uint64_t smpMemoryPosition; - bool calcActivePower; - bool calcReactivePower; - bool caclApparentPower; - bool calcCosPhi; - bool channelNameEnable; // Rename the output values with channel name or only descriptive name - double angleUnitFactor; - enum TimeAlign timeAlignType; + unsigned windowSize; + uint64_t smpMemoryPosition; + bool calcActivePower; + bool calcReactivePower; + bool caclApparentPower; + bool calcCosPhi; + bool + channelNameEnable; // Rename the output values with channel name or only descriptive name + double angleUnitFactor; + enum TimeAlign timeAlignType; public: - PowerHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - pairings(), - smpMemoryTs(), - windowSize(0), - smpMemoryPosition(0), - calcActivePower(true), - calcReactivePower(true), - caclApparentPower(true), - calcCosPhi(true), - channelNameEnable(false), - angleUnitFactor(1), - timeAlignType(TimeAlign::CENTER) - { } + PowerHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), pairings(), + smpMemoryTs(), windowSize(0), smpMemoryPosition(0), + calcActivePower(true), calcReactivePower(true), caclApparentPower(true), + calcCosPhi(true), channelNameEnable(false), angleUnitFactor(1), + timeAlignType(TimeAlign::CENTER) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - for (unsigned i = 0; i < pairingsStr.size(); i++) { - PowerPairing p = {.voltageIndex = signals->getIndexByName(pairingsStr[i].voltage), .currentIndex = signals->getIndexByName(pairingsStr[i].current)}; + for (unsigned i = 0; i < pairingsStr.size(); i++) { + PowerPairing p = { + .voltageIndex = signals->getIndexByName(pairingsStr[i].voltage), + .currentIndex = signals->getIndexByName(pairingsStr[i].current)}; - if (p.currentIndex == -1) - throw RuntimeError("Pairings signal name not recognized {}", pairingsStr[i].current); - if (p.voltageIndex == -1) - throw RuntimeError("Pairings signal name not recognized {}", pairingsStr[i].voltage); + if (p.currentIndex == -1) + throw RuntimeError("Pairings signal name not recognized {}", + pairingsStr[i].current); + if (p.voltageIndex == -1) + throw RuntimeError("Pairings signal name not recognized {}", + pairingsStr[i].voltage); - pairings.push_back(p); - } + pairings.push_back(p); + } - if ((pairingsStr.size() * 2) != signalIndices.size()) - throw RuntimeError("Number of signals and parings don not match!"); + if ((pairingsStr.size() * 2) != signalIndices.size()) + throw RuntimeError("Number of signals and parings don not match!"); - // Check Signal Data Type - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Check Signal Data Type + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The power hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The power hook can only operate on signals of type float!"); + } - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - std::string suffix = ""; - if (channelNameEnable) - suffix = fmt::format("_{}", signalNames[i]); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + std::string suffix = ""; + if (channelNameEnable) + suffix = fmt::format("_{}", signalNames[i]); - // Add signals - if (calcActivePower) { - auto activeSig = std::make_shared("active", "W", SignalType::FLOAT); - activeSig->name += suffix; - if (!activeSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(activeSig); - } + // Add signals + if (calcActivePower) { + auto activeSig = + std::make_shared("active", "W", SignalType::FLOAT); + activeSig->name += suffix; + if (!activeSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(activeSig); + } - if (calcReactivePower) { - auto reactiveSig = std::make_shared("reactive", "Var", SignalType::FLOAT); - reactiveSig->name += suffix; - if (!reactiveSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(reactiveSig); - } + if (calcReactivePower) { + auto reactiveSig = + std::make_shared("reactive", "Var", SignalType::FLOAT); + reactiveSig->name += suffix; + if (!reactiveSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(reactiveSig); + } - if (caclApparentPower) { - auto apparentSig = std::make_shared("apparent", "VA", SignalType::FLOAT); - apparentSig->name += suffix; - if (!apparentSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(apparentSig); - } + if (caclApparentPower) { + auto apparentSig = + std::make_shared("apparent", "VA", SignalType::FLOAT); + apparentSig->name += suffix; + if (!apparentSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(apparentSig); + } - if (calcCosPhi) { - auto cosPhiSig = std::make_shared("cos_phi", "deg", SignalType::FLOAT); - cosPhiSig->name += suffix; - if (!cosPhiSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(cosPhiSig); - } - } + if (calcCosPhi) { + auto cosPhiSig = + std::make_shared("cos_phi", "deg", SignalType::FLOAT); + cosPhiSig->name += suffix; + if (!cosPhiSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(cosPhiSig); + } + } - // Initialize sampMemory to 0 - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) - smpMemory.emplace_back(windowSize, 0.0); + // Initialize sampMemory to 0 + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) + smpMemory.emplace_back(windowSize, 0.0); - smpMemoryTs.clear(); - for (unsigned i = 0; i < windowSize; i++) - smpMemoryTs.push_back({0}); + smpMemoryTs.clear(); + for (unsigned i = 0; i < windowSize; i++) + smpMemoryTs.push_back({0}); - // Init empty accumulators for each pairing - for (size_t i = 0; i < pairings.size(); i++) { - accumulator_i.push_back(0.0); - accumulator_u.push_back(0.0); - accumulator_ui.push_back(0.0); - } + // Init empty accumulators for each pairing + for (size_t i = 0; i < pairings.size(); i++) { + accumulator_i.push_back(0.0); + accumulator_u.push_back(0.0); + accumulator_ui.push_back(0.0); + } - // Signal state prepared - state = State::PREPARED; - } + // Signal state prepared + state = State::PREPARED; + } - // Read configuration JSON and configure hook accordingly - virtual - void parse(json_t *json) - { - // Ensure hook is not yet running - assert(state != State::STARTED); + // Read configuration JSON and configure hook accordingly + virtual void parse(json_t *json) { + // Ensure hook is not yet running + assert(state != State::STARTED); - int result = 0; + int result = 0; - const char *timeAlignC = nullptr; - const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; + const char *angleUnitC = nullptr; - json_error_t json_error; + json_error_t json_error; - int windowSizeIn = 0; // Size of window in samples + int windowSizeIn = 0; // Size of window in samples - json_t *json_pairings = nullptr; + json_t *json_pairings = nullptr; - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - result = json_unpack_ex(json, &json_error, 0, "{ s: i , s: o, s?: b, s?: b, s?: b, s?: b, s?: b, s? : s, s? : s }", - "window_size", &windowSizeIn, - "pairings", &json_pairings, - "add_channel_name", &channelNameEnable, - "active_power", &calcActivePower, - "reactive_power", &calcReactivePower, - "apparent_power", &caclApparentPower, - "cos_phi", &calcCosPhi, - "timestamp_align", &timeAlignC, - "angle_unit", &angleUnitC - ); + result = json_unpack_ex( + json, &json_error, 0, + "{ s: i , s: o, s?: b, s?: b, s?: b, s?: b, s?: b, s? : s, s? : s }", + "window_size", &windowSizeIn, "pairings", &json_pairings, + "add_channel_name", &channelNameEnable, "active_power", + &calcActivePower, "reactive_power", &calcReactivePower, + "apparent_power", &caclApparentPower, "cos_phi", &calcCosPhi, + "timestamp_align", &timeAlignC, "angle_unit", &angleUnitC); - if (result) - throw ConfigError(json, json_error, "node-config-hook-power"); + if (result) + throw ConfigError(json, json_error, "node-config-hook-power"); - if (windowSizeIn < 1) - throw ConfigError(json, "node-config-hook-power", "Window size must be greater 0 but is set to {}", windowSizeIn); + if (windowSizeIn < 1) + throw ConfigError(json, "node-config-hook-power", + "Window size must be greater 0 but is set to {}", + windowSizeIn); - windowSize = (unsigned)windowSizeIn; + windowSize = (unsigned)windowSizeIn; - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-dft-angle-unit", "Angle unit {} not recognized", angleUnitC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-dft-angle-unit", + "Angle unit {} not recognized", angleUnitC); - // Pairings - if (!json_is_array(json_pairings)) - throw ConfigError(json_pairings, "node-config-hook-power", "Pairings are expected as json array"); + // Pairings + if (!json_is_array(json_pairings)) + throw ConfigError(json_pairings, "node-config-hook-power", + "Pairings are expected as json array"); - size_t i = 0; - json_t *json_pairings_value; - json_array_foreach(json_pairings, i, json_pairings_value) { - const char *voltageNameC = nullptr; - const char *currentNameC = nullptr; + size_t i = 0; + json_t *json_pairings_value; + json_array_foreach(json_pairings, i, json_pairings_value) { + const char *voltageNameC = nullptr; + const char *currentNameC = nullptr; - json_unpack_ex(json_pairings_value, &json_error, 0, "{ s: s, s: s}", - "voltage", &voltageNameC, - "current", ¤tNameC - ); - pairingsStr.push_back((PairingsStr){ .voltage = voltageNameC, .current = currentNameC}); + json_unpack_ex(json_pairings_value, &json_error, 0, "{ s: s, s: s}", + "voltage", &voltageNameC, "current", ¤tNameC); + pairingsStr.push_back( + (PairingsStr){.voltage = voltageNameC, .current = currentNameC}); + } - } + state = State::PARSED; + } - state = State::PARSED; - } + // This function does the actual processing of the hook when a new sample is passed through. + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // This function does the actual processing of the hook when a new sample is passed through. - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + uint sigIndex = 0; //used to set the pos of value in output sampel array - uint sigIndex = 0; //used to set the pos of value in output sampel array + smpMemoryTs[smpMemoryPosition % windowSize] = smp->ts.origin; - smpMemoryTs[smpMemoryPosition % windowSize] = smp->ts.origin; + // Loop over all pairings + for (size_t i = 0; i < pairings.size(); i++) { + auto pair = pairings[i]; - // Loop over all pairings - for (size_t i = 0; i < pairings.size(); i++) { - auto pair = pairings[i]; + // Update U integral + double oldValueU = + smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize]; + double newValueU = smp->data[pair.voltageIndex].f; + smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize] = + newValueU; // Save for later - // Update U integral - double oldValueU = smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize]; - double newValueU = smp->data[pair.voltageIndex].f; - smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize] = newValueU; // Save for later + accumulator_u[i] -= oldValueU * oldValueU; + accumulator_u[i] += newValueU * newValueU; - accumulator_u[i] -= oldValueU * oldValueU; - accumulator_u[i] += newValueU * newValueU; + // Update I integral + double newValueI = smp->data[pair.currentIndex].f; + double oldValueI = + smpMemory[pair.currentIndex][smpMemoryPosition % windowSize]; + smpMemory[pair.currentIndex][smpMemoryPosition % windowSize] = + newValueI; // Save for later - // Update I integral - double newValueI = smp->data[pair.currentIndex].f; - double oldValueI = smpMemory[pair.currentIndex][smpMemoryPosition % windowSize]; - smpMemory[pair.currentIndex][smpMemoryPosition % windowSize] = newValueI; // Save for later + accumulator_i[i] -= oldValueI * oldValueI; + accumulator_i[i] += newValueI * newValueI; - accumulator_i[i] -= oldValueI * oldValueI; - accumulator_i[i] += newValueI * newValueI; + // Update UI Integral + accumulator_ui[i] -= oldValueI * oldValueU; + accumulator_ui[i] += newValueI * newValueU; - // Update UI Integral - accumulator_ui[i] -= oldValueI * oldValueU; - accumulator_ui[i] += newValueI * newValueU; + // Calc active power power + double P = (1.0 / windowSize) * accumulator_ui[i]; - // Calc active power power - double P = (1.0 / windowSize) * accumulator_ui[i]; + // Calc apparent power + double S = + (1.0 / windowSize) * pow(accumulator_i[i] * accumulator_u[i], 0.5); - // Calc apparent power - double S = (1.0 / windowSize) * pow(accumulator_i[i] * accumulator_u[i], 0.5); + // Calc reactive power + double Q = pow(S * S - P * P, 0.5); - // Calc reactive power - double Q = pow(S * S - P * P, 0.5); + // Calc cos phi + double PHI = atan2(Q, P) * angleUnitFactor; - // Calc cos phi - double PHI = atan2(Q, P) * angleUnitFactor; + if (smpMemoryPosition >= windowSize) { + // Write to samples + if (calcActivePower) + smp->data[sigIndex++].f = P; + if (calcReactivePower) + smp->data[sigIndex++].f = Q; + if (caclApparentPower) + smp->data[sigIndex++].f = S; + if (calcCosPhi) + smp->data[sigIndex++].f = PHI; + } + } - if (smpMemoryPosition >= windowSize) { - // Write to samples - if(calcActivePower) - smp->data[sigIndex++].f = P; - if(calcReactivePower) - smp->data[sigIndex++].f = Q; - if(caclApparentPower) - smp->data[sigIndex++].f = S; - if(calcCosPhi) - smp->data[sigIndex++].f = PHI; - } - } + smp->length = sigIndex; - smp->length = sigIndex; + if (smpMemoryPosition >= windowSize) { + unsigned tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = smpMemoryPosition; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = smpMemoryPosition - windowSize; + else if (timeAlignType == TimeAlign::CENTER) + tsPos = smpMemoryPosition - (windowSize / 2); - if (smpMemoryPosition >= windowSize) { - unsigned tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = smpMemoryPosition; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = smpMemoryPosition - windowSize; - else if (timeAlignType == TimeAlign::CENTER) - tsPos = smpMemoryPosition - (windowSize / 2); + smp->ts.origin = smpMemoryTs[tsPos % windowSize]; + } - smp->ts.origin = smpMemoryTs[tsPos % windowSize]; - } + if (smpMemoryPosition >= + 2 * windowSize) //reset smpMemPos if greater than twice the window. Important to handle init + smpMemoryPosition = windowSize; - if (smpMemoryPosition >= 2 * windowSize) //reset smpMemPos if greater than twice the window. Important to handle init - smpMemoryPosition = windowSize; + smpMemoryPosition++; // Move write head for sample history foreward by one + if (windowSize < smpMemoryPosition) + return Reason::OK; - smpMemoryPosition++; // Move write head for sample history foreward by one - if (windowSize < smpMemoryPosition) - return Reason::OK; - - return Reason::SKIP_SAMPLE; - } + return Reason::SKIP_SAMPLE; + } }; // Register hook static char n[] = "power"; -static char d[] = "This hook calculates the Active and Reactive Power for a given signal "; -static HookPlugin p; +static char d[] = + "This hook calculates the Active and Reactive Power for a given signal "; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pps_ts.cpp b/lib/hooks/pps_ts.cpp index 33084ffa6..a43010bdf 100644 --- a/lib/hooks/pps_ts.cpp +++ b/lib/hooks/pps_ts.cpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -18,211 +18,204 @@ namespace node { class PpsTsHook : public SingleSignalHook { protected: - enum Mode { - SIMPLE, - HORIZON, - } mode; + enum Mode { + SIMPLE, + HORIZON, + } mode; - uint64_t lastSequence; + uint64_t lastSequence; - double lastValue; - double threshold; + double lastValue; + double threshold; - bool isSynced; - bool isLocked; - struct timespec tsVirt; - double timeError; // In seconds - double periodEstimate; // In seconds - double periodErrorCompensation; // In seconds - double period; // In seconds - uintmax_t cntEdges; - uintmax_t cntSmps; - uintmax_t cntSmpsTotal; - unsigned horizonCompensation; - unsigned horizonEstimation; - unsigned currentSecond; - std::vector filterWindow; + bool isSynced; + bool isLocked; + struct timespec tsVirt; + double timeError; // In seconds + double periodEstimate; // In seconds + double periodErrorCompensation; // In seconds + double period; // In seconds + uintmax_t cntEdges; + uintmax_t cntSmps; + uintmax_t cntSmpsTotal; + unsigned horizonCompensation; + unsigned horizonEstimation; + unsigned currentSecond; + std::vector filterWindow; public: - PpsTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - SingleSignalHook(p, n, fl, prio, en), - mode(Mode::SIMPLE), - lastSequence(0), - lastValue(0), - threshold(1.5), - isSynced(false), - isLocked(false), - timeError(0.0), - periodEstimate(0.0), - periodErrorCompensation(0.0), - period(0.0), - cntEdges(0), - cntSmps(0), - cntSmpsTotal(0), - horizonCompensation(10), - horizonEstimation(10), - currentSecond(0), - filterWindow(horizonEstimation + 1, 0) - { } + PpsTsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : SingleSignalHook(p, n, fl, prio, en), mode(Mode::SIMPLE), + lastSequence(0), lastValue(0), threshold(1.5), isSynced(false), + isLocked(false), timeError(0.0), periodEstimate(0.0), + periodErrorCompensation(0.0), period(0.0), cntEdges(0), cntSmps(0), + cntSmpsTotal(0), horizonCompensation(10), horizonEstimation(10), + currentSecond(0), filterWindow(horizonEstimation + 1, 0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - SingleSignalHook::parse(json); + SingleSignalHook::parse(json); - const char *mode_str = nullptr; + const char *mode_str = nullptr; - double fSmps = 1.0; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: f, s?: F, s?: i, s?: i }", - "mode", &mode_str, - "threshold", &threshold, - "expected_smp_rate", &fSmps, - "horizon_estimation", &horizonEstimation, - "horizon_compensation", &horizonCompensation - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-pps_ts"); + double fSmps = 1.0; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: f, s?: F, s?: i, s?: i }", + "mode", &mode_str, "threshold", &threshold, + "expected_smp_rate", &fSmps, "horizon_estimation", + &horizonEstimation, "horizon_compensation", + &horizonCompensation); + if (ret) + throw ConfigError(json, err, "node-config-hook-pps_ts"); - period = 1.0 / fSmps; - currentSecond = time(nullptr); + period = 1.0 / fSmps; + currentSecond = time(nullptr); - if (mode_str) { - if (!strcmp(mode_str, "simple")) - mode = Mode::SIMPLE; - else if (!strcmp(mode_str, "horizon")) - mode = Mode::HORIZON; - else - throw ConfigError(json, "node-config-hook-pps_ts-mode", "Unsupported mode: {}", mode_str); - } + if (mode_str) { + if (!strcmp(mode_str, "simple")) + mode = Mode::SIMPLE; + else if (!strcmp(mode_str, "horizon")) + mode = Mode::HORIZON; + else + throw ConfigError(json, "node-config-hook-pps_ts-mode", + "Unsupported mode: {}", mode_str); + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - villas::node::Hook::Reason process(struct Sample *smp) - { - switch (mode) { - case Mode::SIMPLE: - return processSimple(smp); + virtual villas::node::Hook::Reason process(struct Sample *smp) { + switch (mode) { + case Mode::SIMPLE: + return processSimple(smp); - case Mode::HORIZON: - return processHorizon(smp); + case Mode::HORIZON: + return processHorizon(smp); - default: - return Reason::ERROR; - } - } + default: + return Reason::ERROR; + } + } - villas::node::Hook::Reason processSimple(struct Sample *smp) - { - assert(state == State::STARTED); + villas::node::Hook::Reason processSimple(struct Sample *smp) { + assert(state == State::STARTED); - // Get value of PPS signal - float value = smp->data[signalIndex].f; // TODO check if it is really float + // Get value of PPS signal + float value = smp->data[signalIndex].f; // TODO check if it is really float - // Detect Edge - bool isEdge = lastValue < threshold && value > threshold; - if (isEdge) { - tsVirt.tv_sec = currentSecond + 1; - tsVirt.tv_nsec = 0; - period = 1.0 / cntSmps; - cntSmps = 0; - cntEdges++; - currentSecond = 0; - } else { - struct timespec tsPeriod = time_from_double(period); - tsVirt = time_add(&tsVirt, &tsPeriod); - } + // Detect Edge + bool isEdge = lastValue < threshold && value > threshold; + if (isEdge) { + tsVirt.tv_sec = currentSecond + 1; + tsVirt.tv_nsec = 0; + period = 1.0 / cntSmps; + cntSmps = 0; + cntEdges++; + currentSecond = 0; + } else { + struct timespec tsPeriod = time_from_double(period); + tsVirt = time_add(&tsVirt, &tsPeriod); + } - lastValue = value; - cntSmps++; + lastValue = value; + cntSmps++; - if (!currentSecond && tsVirt.tv_nsec > 0.5e9)//take the second somewere in the center of the last second to reduce impact of system clock error - currentSecond = time(nullptr); + if (!currentSecond && + tsVirt.tv_nsec > + 0.5e9) //take the second somewere in the center of the last second to reduce impact of system clock error + currentSecond = time(nullptr); - if (cntEdges < 5) - return Hook::Reason::SKIP_SAMPLE; + if (cntEdges < 5) + return Hook::Reason::SKIP_SAMPLE; - smp->ts.origin = tsVirt; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->ts.origin = tsVirt; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - if ((smp->sequence - lastSequence) > 1) - logger->warn("Samples missed: {} sampled missed", smp->sequence - lastSequence); + if ((smp->sequence - lastSequence) > 1) + logger->warn("Samples missed: {} sampled missed", + smp->sequence - lastSequence); - lastSequence = smp->sequence; - return Hook::Reason::OK; - } + lastSequence = smp->sequence; + return Hook::Reason::OK; + } - villas::node::Hook::Reason processHorizon(struct Sample *smp) - { - assert(state == State::STARTED); + villas::node::Hook::Reason processHorizon(struct Sample *smp) { + assert(state == State::STARTED); - // Get value of PPS signal - float value = smp->data[signalIndex].f; // TODO check if it is really float + // Get value of PPS signal + float value = smp->data[signalIndex].f; // TODO check if it is really float - // Detect Edge - bool isEdge = lastValue < threshold && value > threshold; + // Detect Edge + bool isEdge = lastValue < threshold && value > threshold; - lastValue = value; + lastValue = value; - if (isEdge) { - if (isSynced) { - if(tsVirt.tv_nsec > 0.5e9) - timeError += 1.0 - (tsVirt.tv_nsec / 1.0e9); - else - timeError -= (tsVirt.tv_nsec / 1.0e9); + if (isEdge) { + if (isSynced) { + if (tsVirt.tv_nsec > 0.5e9) + timeError += 1.0 - (tsVirt.tv_nsec / 1.0e9); + else + timeError -= (tsVirt.tv_nsec / 1.0e9); - filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal; - // Estimated sample period over last 'horizonEstimation' seconds - unsigned int tmp = cntEdges < filterWindow.size() ? cntEdges : horizonEstimation; - double cntSmpsAvg = (cntSmpsTotal - filterWindow[(cntEdges - tmp) % filterWindow.size()]) / tmp; - periodEstimate = 1.0 / cntSmpsAvg; - periodErrorCompensation = timeError / (cntSmpsAvg * horizonCompensation); - period = periodEstimate + periodErrorCompensation; - } - else { - tsVirt.tv_sec = time(nullptr); - tsVirt.tv_nsec = 0; - isSynced = true; - cntEdges = 0; - cntSmpsTotal = 0; - } - cntSmps = 0; - cntEdges++; + filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal; + // Estimated sample period over last 'horizonEstimation' seconds + unsigned int tmp = + cntEdges < filterWindow.size() ? cntEdges : horizonEstimation; + double cntSmpsAvg = + (cntSmpsTotal - + filterWindow[(cntEdges - tmp) % filterWindow.size()]) / + tmp; + periodEstimate = 1.0 / cntSmpsAvg; + periodErrorCompensation = + timeError / (cntSmpsAvg * horizonCompensation); + period = periodEstimate + periodErrorCompensation; + } else { + tsVirt.tv_sec = time(nullptr); + tsVirt.tv_nsec = 0; + isSynced = true; + cntEdges = 0; + cntSmpsTotal = 0; + } + cntSmps = 0; + cntEdges++; - logger->debug("Time Error is: {} periodEstimate {} periodErrorCompensation {}", timeError, periodEstimate, periodErrorCompensation); - } + logger->debug( + "Time Error is: {} periodEstimate {} periodErrorCompensation {}", + timeError, periodEstimate, periodErrorCompensation); + } - cntSmps++; - cntSmpsTotal++; + cntSmps++; + cntSmpsTotal++; - if (cntEdges < 5) - return Hook::Reason::SKIP_SAMPLE; + if (cntEdges < 5) + return Hook::Reason::SKIP_SAMPLE; - smp->ts.origin = tsVirt; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->ts.origin = tsVirt; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - struct timespec tsPeriod = time_from_double(period); - tsVirt = time_add(&tsVirt, &tsPeriod); + struct timespec tsPeriod = time_from_double(period); + tsVirt = time_add(&tsVirt, &tsPeriod); - if ((smp->sequence - lastSequence) > 1) - logger->warn("Samples missed: {} sampled missed", smp->sequence - lastSequence); + if ((smp->sequence - lastSequence) > 1) + logger->warn("Samples missed: {} sampled missed", + smp->sequence - lastSequence); - lastSequence = smp->sequence; + lastSequence = smp->sequence; - return Hook::Reason::OK; - } + return Hook::Reason::OK; + } }; // Register hook static char n[] = "pps_ts"; static char d[] = "Timestamp samples based GPS PPS signal"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/print.cpp b/lib/hooks/print.cpp index d4c10e372..29b5553c6 100644 --- a/lib/hooks/print.cpp +++ b/lib/hooks/print.cpp @@ -8,11 +8,11 @@ #include #include -#include +#include #include +#include #include #include -#include namespace villas { namespace node { @@ -20,121 +20,109 @@ namespace node { class PrintHook : public Hook { protected: - Format::Ptr formatter; + Format::Ptr formatter; - std::string prefix; - std::string output_path; + std::string prefix; + std::string output_path; - FILE *output; - std::vector output_buffer; + FILE *output; + std::vector output_buffer; public: - PrintHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - output(nullptr) - { } + PrintHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), output(nullptr) {} - virtual - void start() - { - assert(state == State::PREPARED || - state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - if (!output_path.empty()) { - output = fopen(output_path.c_str(), "w+"); - if (!output) - throw SystemError("Failed to open file"); - } - else - output_buffer = std::vector(DEFAULT_FORMAT_BUFFER_LENGTH); + if (!output_path.empty()) { + output = fopen(output_path.c_str(), "w+"); + if (!output) + throw SystemError("Failed to open file"); + } else + output_buffer = std::vector(DEFAULT_FORMAT_BUFFER_LENGTH); - formatter->start(signals); + formatter->start(signals); - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() { - if (output) - fclose(output); - } + virtual void stop() { + if (output) + fclose(output); + } - virtual - void parse(json_t *json) - { - const char *p = nullptr; - const char *o = nullptr; - int ret; - json_error_t err; - json_t *json_format = nullptr; + virtual void parse(json_t *json) { + const char *p = nullptr; + const char *o = nullptr; + int ret; + json_error_t err; + json_t *json_format = nullptr; - assert(state == State::INITIALIZED || - state == State::CHECKED || - state == State::PARSED); + assert(state == State::INITIALIZED || state == State::CHECKED || + state == State::PARSED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: s }", - "prefix", &p, - "format", &json_format, - "output", &o - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-print"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: s }", "prefix", &p, + "format", &json_format, "output", &o); + if (ret) + throw ConfigError(json, err, "node-config-hook-print"); - if (p && o) { - throw ConfigError(json, "node-config-hook-print", "Prefix and output settings are exclusive."); - } + if (p && o) { + throw ConfigError(json, "node-config-hook-print", + "Prefix and output settings are exclusive."); + } - if (p) - prefix = p; + if (p) + prefix = p; - if (o) - output_path = o; + if (o) + output_path = o; - // Format - auto *fmt = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); + // Format + auto *fmt = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); - formatter = Format::Ptr(fmt); - if (!formatter) - throw ConfigError(json_format, "node-config-hook-print-format", "Invalid format configuration"); + formatter = Format::Ptr(fmt); + if (!formatter) + throw ConfigError(json_format, "node-config-hook-print-format", + "Invalid format configuration"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - if (!output) { - char *buf = output_buffer.data(); - size_t buflen = output_buffer.size(); - size_t wbytes; + if (!output) { + char *buf = output_buffer.data(); + size_t buflen = output_buffer.size(); + size_t wbytes; - formatter->sprint(buf, buflen, &wbytes, smp); + formatter->sprint(buf, buflen, &wbytes, smp); - if (wbytes > 0 && buf[wbytes-1] == '\n') - buf[wbytes-1] = 0; + if (wbytes > 0 && buf[wbytes - 1] == '\n') + buf[wbytes - 1] = 0; - if (node) - logger->info("{}{} {}", prefix, node->getName(), buf); - else if (path) - logger->info("{}{} {}", prefix, path->toString(), buf); - } - else - formatter->print(output, smp); + if (node) + logger->info("{}{} {}", prefix, node->getName(), buf); + else if (path) + logger->info("{}{} {}", prefix, path->toString(), buf); + } else + formatter->print(output, smp); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "print"; static char d[] = "Print the message to stdout or a file"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index 1dbbd4481..38c43c79f 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include #include -#include #include #include @@ -21,140 +21,124 @@ namespace node { class ReorderTsHook : public Hook { protected: - std::vector window; - std::size_t window_size; - Sample *buffer; + std::vector window; + std::size_t window_size; + Sample *buffer; - void swapSample(Sample *lhs, Sample *rhs) - { - if (buffer) { - sample_copy(buffer, lhs); - sample_copy(lhs, rhs); - sample_copy(rhs, buffer); - } else { - buffer = sample_clone(lhs); - sample_copy(lhs, rhs); - sample_copy(rhs, buffer); - } - } + void swapSample(Sample *lhs, Sample *rhs) { + if (buffer) { + sample_copy(buffer, lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } else { + buffer = sample_clone(lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } + } public: - ReorderTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - window{}, - window_size(16), - buffer(nullptr) - { } + ReorderTsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), window{}, window_size(16), buffer(nullptr) {} - virtual - void parse(json_t *json) - { - assert(state != State::STARTED); + virtual void parse(json_t *json) { + assert(state != State::STARTED); - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "window_size", &window_size - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-reorder-ts"); + json_error_t err; + int ret = + json_unpack_ex(json, &err, 0, "{ s?: i }", "window_size", &window_size); + if (ret) + throw ConfigError(json, err, "node-config-hook-reorder-ts"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED || state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - window.reserve(window_size); + window.reserve(window_size); - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - for (auto sample : window) - sample_free(sample); + for (auto sample : window) + sample_free(sample); - if (buffer) - sample_free(buffer); + if (buffer) + sample_free(buffer); - window.clear(); + window.clear(); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(Sample *smp) - { - assert(state == State::STARTED); - assert(smp); + virtual Hook::Reason process(Sample *smp) { + assert(state == State::STARTED); + assert(smp); - if (window.empty()) { - window.push_back(sample_clone(smp)); + if (window.empty()) { + window.push_back(sample_clone(smp)); - logger->debug("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); - return Hook::Reason::SKIP_SAMPLE; - } + return Hook::Reason::SKIP_SAMPLE; + } - for (std::size_t i = window.size() - 1;; i--) { - if (time_cmp(&smp->ts.origin, &window[i]->ts.origin) >= 0) { - if (i != window.size() - 1) - logger->warn("Fixing reordered Sample"); + for (std::size_t i = window.size() - 1;; i--) { + if (time_cmp(&smp->ts.origin, &window[i]->ts.origin) >= 0) { + if (i != window.size() - 1) + logger->warn("Fixing reordered Sample"); - if (window.size() == window_size) { - Sample *window_sample = window.front(); - std::copy( - ++std::begin(window), - std::next(std::begin(window), i + 1), - std::begin(window)); - window[i] = window_sample; - swapSample(window_sample, smp); + if (window.size() == window_size) { + Sample *window_sample = window.front(); + std::copy(++std::begin(window), std::next(std::begin(window), i + 1), + std::begin(window)); + window[i] = window_sample; + swapSample(window_sample, smp); - return Hook::Reason::OK; - } else { - window.push_back(nullptr); - std::copy_backward( - std::next(std::begin(window), i + 1), - --std::end(window), - std::end(window)); - window[i + 1] = sample_clone(smp); + return Hook::Reason::OK; + } else { + window.push_back(nullptr); + std::copy_backward(std::next(std::begin(window), i + 1), + --std::end(window), std::end(window)); + window[i + 1] = sample_clone(smp); - logger->debug("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); - return Hook::Reason::SKIP_SAMPLE; - } - } + return Hook::Reason::SKIP_SAMPLE; + } + } - if (!i) - break; - } + if (!i) + break; + } - logger->error("Could not reorder Sample"); + logger->error("Could not reorder Sample"); - return Hook::Reason::SKIP_SAMPLE; - } + return Hook::Reason::SKIP_SAMPLE; + } - virtual - void restart() - { - assert(state == State::STARTED); + virtual void restart() { + assert(state == State::STARTED); - for (auto sample : window) - sample_free(sample); + for (auto sample : window) + sample_free(sample); - window.clear(); - } + window.clear(); + } }; // Register hook static char n[] = "reorder_ts"; static char d[] = "Reorder messages by their timestamp"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/restart.cpp b/lib/hooks/restart.cpp index d0e07d7e4..216a932b1 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -17,68 +17,66 @@ namespace node { class RestartHook : public Hook { protected: - struct Sample *prev; + struct Sample *prev; public: - using Hook::Hook; + using Hook::Hook; - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - prev = nullptr; + prev = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (prev) - sample_decref(prev); + if (prev) + sample_decref(prev); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - if (prev) { - // A wrap around of the sequence no should not be treated as a simulation restart - if (smp->sequence == 0 && prev->sequence != 0 && prev->sequence < UINT64_MAX - 16) { - logger->warn("Simulation from node {} restarted (previous->sequence={}, current->sequence={})", - node->getName(), prev->sequence, smp->sequence); + if (prev) { + // A wrap around of the sequence no should not be treated as a simulation restart + if (smp->sequence == 0 && prev->sequence != 0 && + prev->sequence < UINT64_MAX - 16) { + logger->warn("Simulation from node {} restarted " + "(previous->sequence={}, current->sequence={})", + node->getName(), prev->sequence, smp->sequence); - smp->flags |= (int) SampleFlags::IS_FIRST; + smp->flags |= (int)SampleFlags::IS_FIRST; - // Restart hooks - for (auto k : node->in.hooks) - k->restart(); + // Restart hooks + for (auto k : node->in.hooks) + k->restart(); - for (auto k : node->out.hooks) - k->restart(); - } - } + for (auto k : node->out.hooks) + k->restart(); + } + } - sample_incref(smp); - if (prev) - sample_decref(prev); + sample_incref(smp); + if (prev) + sample_decref(prev); - prev = smp; + prev = smp; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "restart"; static char d[] = "Call restart hooks for current node"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/rms.cpp b/lib/hooks/rms.cpp index 44689d24c..49b9310d5 100644 --- a/lib/hooks/rms.cpp +++ b/lib/hooks/rms.cpp @@ -14,105 +14,101 @@ namespace node { class RMSHook : public MultiSignalHook { protected: - std::vector> smpMemory; + std::vector> smpMemory; - std::vector accumulator; - unsigned windowSize; - uint64_t smpMemoryPosition; + std::vector accumulator; + unsigned windowSize; + uint64_t smpMemoryPosition; public: - RMSHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - windowSize(0), - smpMemoryPosition(0) - { } + RMSHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), windowSize(0), + smpMemoryPosition(0) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - // Add signals - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Add signals + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The rms hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The rms hook can only operate on signals of type float!"); + } - /* Initialize memory for each channel*/ - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++){ - accumulator.push_back(0.0); - smpMemory.emplace_back(windowSize, 0.0); - } + /* Initialize memory for each channel*/ + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + accumulator.push_back(0.0); + smpMemory.emplace_back(windowSize, 0.0); + } - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - int windowSizeIn; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + int windowSizeIn; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "window_size", &windowSizeIn - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-rms"); + ret = + json_unpack_ex(json, &err, 0, "{ s: i }", "window_size", &windowSizeIn); + if (ret) + throw ConfigError(json, err, "node-config-hook-rms"); - if (windowSizeIn < 1) - throw ConfigError(json, "node-config-hook-rms", "Window size must be greater 0 but is set to {}", windowSizeIn); + if (windowSizeIn < 1) + throw ConfigError(json, "node-config-hook-rms", + "Window size must be greater 0 but is set to {}", + windowSizeIn); - windowSize = (unsigned)windowSizeIn; + windowSize = (unsigned)windowSizeIn; - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - unsigned i = 0; - for (auto index : signalIndices) { - // Square the new value - double newValue = pow(smp->data[index].f, 2); + unsigned i = 0; + for (auto index : signalIndices) { + // Square the new value + double newValue = pow(smp->data[index].f, 2); - // Get the old value from the history - double oldValue = smpMemory[i][smpMemoryPosition % windowSize]; + // Get the old value from the history + double oldValue = smpMemory[i][smpMemoryPosition % windowSize]; - // Append the new value to the history memory - smpMemory[i][smpMemoryPosition % windowSize] = newValue; + // Append the new value to the history memory + smpMemory[i][smpMemoryPosition % windowSize] = newValue; - // Update the accumulator - accumulator[index] += newValue; - accumulator[index] -= oldValue; + // Update the accumulator + accumulator[index] += newValue; + accumulator[index] -= oldValue; - auto rms = pow(accumulator[index] / windowSize, 0.5); + auto rms = pow(accumulator[index] / windowSize, 0.5); - smp->data[index].f = rms; - i++; - } + smp->data[index].f = rms; + i++; + } - smpMemoryPosition++; + smpMemoryPosition++; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "rms"; static char d[] = "This hook calculates the root-mean-square (RMS) on a window"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/round.cpp b/lib/hooks/round.cpp index 658e7ec85..5c5b36da7 100644 --- a/lib/hooks/round.cpp +++ b/lib/hooks/round.cpp @@ -16,63 +16,61 @@ namespace node { class RoundHook : public MultiSignalHook { protected: - unsigned precision; + unsigned precision; public: - RoundHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - precision(1) - { } + RoundHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), precision(1) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i}", - "precision", &precision - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-round"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i}", "precision", &precision); + if (ret) + throw ConfigError(json, err, "node-config-hook-round"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - for (auto index : signalIndices) { - assert(index < smp->length); - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + for (auto index : signalIndices) { + assert(index < smp->length); + assert(state == State::STARTED); - switch (sample_format(smp, index)) { - case SignalType::FLOAT: - smp->data[index].f = round(smp->data[index].f * pow(10, precision)) / pow(10, precision); - break; + switch (sample_format(smp, index)) { + case SignalType::FLOAT: + smp->data[index].f = + round(smp->data[index].f * pow(10, precision)) / pow(10, precision); + break; - case SignalType::COMPLEX: - smp->data[index].z = std::complex( - round(smp->data[index].z.real() * pow(10, precision)) / pow(10, precision), - round(smp->data[index].z.imag() * pow(10, precision)) / pow(10, precision) - ); - break; - default: { } - } - } + case SignalType::COMPLEX: + smp->data[index].z = std::complex( + round(smp->data[index].z.real() * pow(10, precision)) / + pow(10, precision), + round(smp->data[index].z.imag() * pow(10, precision)) / + pow(10, precision)); + break; + default: { + } + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "round"; static char d[] = "Round signals to a set number of digits"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/scale.cpp b/lib/hooks/scale.cpp index 956abfcf7..696ec451c 100644 --- a/lib/hooks/scale.cpp +++ b/lib/hooks/scale.cpp @@ -16,71 +16,66 @@ namespace node { class ScaleHook : public MultiSignalHook { protected: - double scale; - double offset; + double scale; + double offset; public: - ScaleHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - scale(1.0), - offset(0.0) - { } + ScaleHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), scale(1.0), offset(0.0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", - "scale", &scale, - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-scale"); + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", "scale", &scale, + "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-scale"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - for (auto index : signalIndices) { - assert(index < smp->length); - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + for (auto index : signalIndices) { + assert(index < smp->length); + assert(state == State::STARTED); - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - smp->data[index].i *= scale; - smp->data[index].i += offset; - break; + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + smp->data[index].i *= scale; + smp->data[index].i += offset; + break; - case SignalType::FLOAT: - smp->data[index].f *= scale; - smp->data[index].f += offset; - break; + case SignalType::FLOAT: + smp->data[index].f *= scale; + smp->data[index].f += offset; + break; - case SignalType::COMPLEX: - smp->data[index].z *= scale; - smp->data[index].z += offset; - break; + case SignalType::COMPLEX: + smp->data[index].z *= scale; + smp->data[index].z += offset; + break; - default: { } - } - } + default: { + } + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "scale"; static char d[] = "Scale signals by a factor and add offset"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/shift_seq.cpp b/lib/hooks/shift_seq.cpp index 59b1fa3e9..9f242c99b 100644 --- a/lib/hooks/shift_seq.cpp +++ b/lib/hooks/shift_seq.cpp @@ -14,46 +14,41 @@ namespace node { class ShiftSequenceHook : public Hook { protected: - int offset; + int offset; public: + using Hook::Hook; - using Hook::Hook; + virtual void parse(json_t *json) { + json_error_t err; + int ret; - virtual - void parse(json_t *json) - { - json_error_t err; - int ret; + assert(state != State::STARTED); - assert(state != State::STARTED); + Hook::parse(json); - Hook::parse(json); + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-shift_seq"); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-shift_seq"); + state = State::PARSED; + } - state = State::PARSED; - } + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + smp->sequence += offset; - smp->sequence += offset; - - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "shift_seq"; static char d[] = "Shift sequence number of samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/shift_ts.cpp b/lib/hooks/shift_ts.cpp index a06ad428d..dd8ecbacb 100644 --- a/lib/hooks/shift_ts.cpp +++ b/lib/hooks/shift_ts.cpp @@ -8,8 +8,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -17,81 +17,73 @@ namespace node { class ShiftTimestampHook : public Hook { protected: - timespec offset; - enum { - SHIFT_ORIGIN, - SHIFT_RECEIVED - } mode; + timespec offset; + enum { SHIFT_ORIGIN, SHIFT_RECEIVED } mode; public: - ShiftTimestampHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - mode(SHIFT_ORIGIN) - { } + ShiftTimestampHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), mode(SHIFT_ORIGIN) {} - virtual - void parse(json_t *json) - { - double o; - const char *m = nullptr; - int ret; - json_error_t err; + virtual void parse(json_t *json) { + double o; + const char *m = nullptr; + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: F }", - "mode", &m, - "offset", &o - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-shift_ts"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: F }", "mode", &m, "offset", + &o); + if (ret) + throw ConfigError(json, err, "node-config-hook-shift_ts"); - if (m) { - if (!strcmp(m, "origin")) - mode = SHIFT_ORIGIN; - else if (!strcmp(m, "received")) - mode = SHIFT_RECEIVED; - else - throw ConfigError(json, "node-config-hook-shift_ts-mode", "Invalid mode parameter '{}'", m); - } + if (m) { + if (!strcmp(m, "origin")) + mode = SHIFT_ORIGIN; + else if (!strcmp(m, "received")) + mode = SHIFT_RECEIVED; + else + throw ConfigError(json, "node-config-hook-shift_ts-mode", + "Invalid mode parameter '{}'", m); + } - offset = time_from_double(o); + offset = time_from_double(o); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - timespec *ts; + virtual Hook::Reason process(struct Sample *smp) { + timespec *ts; - assert(state == State::STARTED); + assert(state == State::STARTED); - switch (mode) { - case SHIFT_ORIGIN: - ts = &smp->ts.origin; - break; + switch (mode) { + case SHIFT_ORIGIN: + ts = &smp->ts.origin; + break; - case SHIFT_RECEIVED: - ts = &smp->ts.received; - break; + case SHIFT_RECEIVED: + ts = &smp->ts.received; + break; - default: - return Hook::Reason::ERROR; - } + default: + return Hook::Reason::ERROR; + } - *ts = time_add(ts, &offset); + *ts = time_add(ts, &offset); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "shift_ts"; static char d[] = "Shift timestamps of samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/skip_first.cpp b/lib/hooks/skip_first.cpp index a90fc5881..a50ef5bd7 100644 --- a/lib/hooks/skip_first.cpp +++ b/lib/hooks/skip_first.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include namespace villas { namespace node { @@ -15,120 +15,110 @@ namespace node { class SkipFirstHook : public Hook { protected: - 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 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 class Mode { - SECONDS, - SAMPLES - } mode; + enum class Mode { SECONDS, SAMPLES } mode; - union { - struct { - timespec until; - timespec wait; // Absolute point in time from where we accept samples. - } seconds; + union { + struct { + timespec until; + timespec wait; // Absolute point in time from where we accept samples. + } seconds; - struct { - uint64_t until; - int wait; - } samples; - }; + struct { + uint64_t until; + int wait; + } samples; + }; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json) - { - double s; + virtual void parse(json_t *json) { + double s; - int ret; - json_error_t err; + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: F }", "seconds", &s); - if (!ret) { - seconds.wait = time_from_double(s); - mode = Mode::SECONDS; + ret = json_unpack_ex(json, &err, 0, "{ s: F }", "seconds", &s); + if (!ret) { + seconds.wait = time_from_double(s); + mode = Mode::SECONDS; - state = State::PARSED; - return; - } + state = State::PARSED; + return; + } - ret = json_unpack_ex(json, &err, 0, "{ s: i }", "samples", &samples.wait); - if (!ret) { - mode = Mode::SAMPLES; + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "samples", &samples.wait); + if (!ret) { + mode = Mode::SAMPLES; - state = State::PARSED; - return; - } + state = State::PARSED; + return; + } - throw ConfigError(json, err, "node-config-hook-skip_first"); - } + throw ConfigError(json, err, "node-config-hook-skip_first"); + } - virtual - void start() - { - skip_state = SkipState::STARTED; - state = State::STARTED; - } + virtual void start() { + skip_state = SkipState::STARTED; + state = State::STARTED; + } - virtual - void restart() - { - skip_state = SkipState::STARTED; - } + virtual void restart() { skip_state = SkipState::STARTED; } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // Remember sequence no or timestamp of first sample. - if (skip_state == SkipState::STARTED) { - switch (mode) { - case Mode::SAMPLES: - samples.until = smp->sequence + samples.wait; - break; + // Remember sequence no or timestamp of first sample. + if (skip_state == SkipState::STARTED) { + switch (mode) { + case Mode::SAMPLES: + samples.until = smp->sequence + samples.wait; + break; - case Mode::SECONDS: - seconds.until = time_add(&smp->ts.origin, &seconds.wait); - break; - } + case Mode::SECONDS: + seconds.until = time_add(&smp->ts.origin, &seconds.wait); + break; + } - skip_state = SkipState::SKIPPING; - } + skip_state = SkipState::SKIPPING; + } - switch (mode) { - case Mode::SAMPLES: - if (samples.until > smp->sequence) - return Hook::Reason::SKIP_SAMPLE; - break; + switch (mode) { + case Mode::SAMPLES: + if (samples.until > smp->sequence) + return Hook::Reason::SKIP_SAMPLE; + break; - case Mode::SECONDS: - if (time_delta(&seconds.until, &smp->ts.origin) < 0) - return Hook::Reason::SKIP_SAMPLE; - break; + case Mode::SECONDS: + if (time_delta(&seconds.until, &smp->ts.origin) < 0) + return Hook::Reason::SKIP_SAMPLE; + break; - default: - break; - } + default: + break; + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "skip_first"; static char d[] = "Skip the first samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/stats.cpp b/lib/hooks/stats.cpp index df5b75ac3..14ad81a0f 100644 --- a/lib/hooks/stats.cpp +++ b/lib/hooks/stats.cpp @@ -9,9 +9,9 @@ #include #include +#include #include #include -#include #include namespace villas { @@ -22,257 +22,227 @@ class StatsHook; class StatsWriteHook : public Hook { protected: - StatsHook *parent; + StatsHook *parent; public: - StatsWriteHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - parent(pa) - { - // This hook has no config. We never call parse() for it - state = State::PARSED; - } + StatsWriteHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, + bool en = true) + : Hook(p, n, fl, prio, en), parent(pa) { + // This hook has no config. We never call parse() for it + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; class StatsReadHook : public Hook { protected: - struct Sample *last; + struct Sample *last; - StatsHook *parent; + StatsHook *parent; public: - StatsReadHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - last(nullptr), - parent(pa) - { - // This hook has no config. We never call parse() for it - state = State::PARSED; - } + StatsReadHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, + bool en = true) + : Hook(p, n, fl, prio, en), last(nullptr), parent(pa) { + // This hook has no config. We never call parse() for it + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - last = nullptr; + last = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (last) - sample_decref(last); + if (last) + sample_decref(last); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; class StatsHook : public Hook { - friend StatsReadHook; - friend StatsWriteHook; + friend StatsReadHook; + friend StatsWriteHook; protected: - std::shared_ptr readHook; - std::shared_ptr writeHook; + std::shared_ptr readHook; + std::shared_ptr writeHook; - enum Stats::Format format; - int verbose; - int warmup; - int buckets; + enum Stats::Format format; + int verbose; + int warmup; + int buckets; - std::shared_ptr stats; + std::shared_ptr stats; - FILE *output; - std::string uri; + FILE *output; + std::string uri; public: + StatsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), format(Stats::Format::HUMAN), verbose(0), + warmup(500), buckets(20), output(nullptr), uri() { + readHook = std::make_shared(this, p, n, fl, prio, en); + writeHook = std::make_shared(this, p, n, fl, prio, en); - StatsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - format(Stats::Format::HUMAN), - verbose(0), - warmup(500), - buckets(20), - output(nullptr), - uri() - { - readHook = std::make_shared(this, p, n, fl, prio, en); - writeHook = std::make_shared(this, p, n, fl, prio, en); + if (!readHook || !writeHook) + throw MemoryAllocationError(); - if (!readHook || !writeHook) - throw MemoryAllocationError(); + // Add child hooks + if (node) { + node->in.hooks.push_back(readHook); + node->out.hooks.push_back(writeHook); + } + } - // Add child hooks - if (node) { - node->in.hooks.push_back(readHook); - node->out.hooks.push_back(writeHook); - } - } + StatsHook &operator=(const StatsHook &) = delete; + StatsHook(const StatsHook &) = delete; - StatsHook & operator=(const StatsHook&) = delete; - StatsHook(const StatsHook&) = delete; + virtual void start() { + assert(state == State::PREPARED); - virtual - void start() - { - assert(state == State::PREPARED); + if (!uri.empty()) { + output = fopen(uri.c_str(), "w+"); + if (!output) + throw RuntimeError("Failed to open file '{}' for writing", uri); + } - if (!uri.empty()) { - output = fopen(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); - virtual - void stop() - { - assert(state == State::STARTED); + stats->print(uri.empty() ? stdout : output, format, verbose); - stats->print(uri.empty() ? stdout : output, format, verbose); + if (!uri.empty()) + fclose(output); - if (!uri.empty()) - fclose(output); + state = State::STOPPED; + } - state = State::STOPPED; - } + virtual void restart() { + assert(state == State::STARTED); - virtual - void restart() - { - assert(state == State::STARTED); + stats->reset(); + } - stats->reset(); - } + virtual Hook::Reason process(struct Sample *smp) { + // Only call readHook if it hasnt been added to the node's hook list + if (!node) + return readHook->process(smp); - virtual - Hook::Reason process(struct Sample *smp) - { - // Only call readHook if it hasnt been added to the node's hook list - if (!node) - return readHook->process(smp); + return Hook::Reason::OK; + } - return Hook::Reason::OK; - } + virtual void periodic() { + assert(state == State::STARTED); - virtual - void periodic() - { - assert(state == State::STARTED); + stats->printPeriodic(uri.empty() ? stdout : output, format, node); + } - stats->printPeriodic(uri.empty() ? stdout : output, format, node); - } + virtual void parse(json_t *json) { + int ret; + json_error_t err; - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + assert(state != State::STARTED); - assert(state != State::STARTED); + Hook::parse(json); - Hook::parse(json); + const char *f = nullptr; + const char *u = nullptr; - const char *f = nullptr; - const char *u = nullptr; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i, s?: i, s?: s }", + "format", &f, "verbose", &verbose, "warmup", &warmup, + "buckets", &buckets, "output", &u); + if (ret) + throw ConfigError(json, err, "node-config-hook-stats"); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i, s?: i, s?: s }", - "format", &f, - "verbose", &verbose, - "warmup", &warmup, - "buckets", &buckets, - "output", &u - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-stats"); + if (f) { + try { + format = Stats::lookupFormat(f); + } catch (const std::invalid_argument &e) { + throw ConfigError(json, "node-config-hook-stats", + "Invalid statistic output format: {}", f); + } + } - if (f) { - try { - format = Stats::lookupFormat(f); - } catch (const std::invalid_argument &e) { - throw ConfigError(json, "node-config-hook-stats", "Invalid statistic output format: {}", f); - } - } + if (u) + uri = u; - if (u) - uri = u; + state = State::PARSED; + } - state = State::PARSED; - } + virtual void prepare() { + assert(state == State::CHECKED); - virtual - void prepare() - { - assert(state == State::CHECKED); + stats = std::make_shared(buckets, warmup); - stats = std::make_shared(buckets, warmup); + if (node) + node->setStats(stats); - if (node) - node->setStats(stats); - - state = State::PREPARED; - } + state = State::PREPARED; + } }; -Hook::Reason StatsWriteHook::process(struct Sample *smp) -{ - timespec now = time_now(); +Hook::Reason StatsWriteHook::process(struct Sample *smp) { + timespec now = time_now(); - parent->stats->update(Stats::Metric::AGE, time_delta(&smp->ts.received, &now)); + parent->stats->update(Stats::Metric::AGE, + time_delta(&smp->ts.received, &now)); - return Reason::OK; + return Reason::OK; } -Hook::Reason StatsReadHook::process(struct Sample *smp) -{ - if (last) { - if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_RECEIVED) - parent->stats->update(Stats::Metric::GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received)); +Hook::Reason StatsReadHook::process(struct Sample *smp) { + if (last) { + if (smp->flags & last->flags & (int)SampleFlags::HAS_TS_RECEIVED) + parent->stats->update(Stats::Metric::GAP_RECEIVED, + time_delta(&last->ts.received, &smp->ts.received)); - if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_ORIGIN) - parent->stats->update(Stats::Metric::GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin)); + if (smp->flags & last->flags & (int)SampleFlags::HAS_TS_ORIGIN) + parent->stats->update(Stats::Metric::GAP_SAMPLE, + time_delta(&last->ts.origin, &smp->ts.origin)); - if ((smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) && (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)) - parent->stats->update(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)) + parent->stats->update(Stats::Metric::OWD, + time_delta(&smp->ts.origin, &smp->ts.received)); - if (smp->flags & last->flags & (int) SampleFlags::HAS_SEQUENCE) { - int dist = smp->sequence - (int32_t) last->sequence; - if (dist != 1) - parent->stats->update(Stats::Metric::SMPS_REORDERED, dist); - } - } + if (smp->flags & last->flags & (int)SampleFlags::HAS_SEQUENCE) { + int dist = smp->sequence - (int32_t)last->sequence; + if (dist != 1) + parent->stats->update(Stats::Metric::SMPS_REORDERED, dist); + } + } - parent->stats->update(Stats::Metric::SIGNAL_COUNT, smp->length); + parent->stats->update(Stats::Metric::SIGNAL_COUNT, smp->length); - sample_incref(smp); + sample_incref(smp); - if (last) - sample_decref(last); + if (last) + sample_decref(last); - last = smp; + last = smp; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "stats"; static char d[] = "Collect statistics for the current node"; -static HookPlugin p; +static HookPlugin p; } // namespace node } // namespace villas diff --git a/lib/hooks/ts.cpp b/lib/hooks/ts.cpp index 85c58b28a..0cd305b42 100644 --- a/lib/hooks/ts.cpp +++ b/lib/hooks/ts.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include namespace villas { namespace node { @@ -15,23 +15,25 @@ namespace node { class TsHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - smp->ts.origin = smp->ts.received; + smp->ts.origin = smp->ts.received; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ts"; -static char d[] = "Overwrite origin timestamp of samples with receive timestamp"; -static HookPlugin p; +static char d[] = + "Overwrite origin timestamp of samples with receive timestamp"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/kernel/if.cpp b/lib/kernel/if.cpp index 8dd2eb549..08aca8255 100644 --- a/lib/kernel/if.cpp +++ b/lib/kernel/if.cpp @@ -11,17 +11,17 @@ #include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include +#include #include #include -#include -#include #include @@ -30,172 +30,173 @@ using namespace villas::node; using namespace villas::utils; using namespace villas::kernel; -Interface::Interface(struct rtnl_link *link, int aff) : - nl_link(link), - tc_qdisc(nullptr), - affinity(aff) -{ - logger = logging.get(fmt::format("kernel:if:{}", getName())); +Interface::Interface(struct rtnl_link *link, int aff) + : nl_link(link), tc_qdisc(nullptr), affinity(aff) { + logger = logging.get(fmt::format("kernel:if:{}", getName())); - int n = getIRQs(); - if (n) - logger->warn("Did not found any interrupts"); + int n = getIRQs(); + if (n) + logger->warn("Did not found any interrupts"); - logger->debug("Found {} IRQs", irqs.size()); + logger->debug("Found {} IRQs", irqs.size()); } -Interface::~Interface() -{ - if (tc_qdisc) - rtnl_qdisc_put(tc_qdisc); +Interface::~Interface() { + if (tc_qdisc) + rtnl_qdisc_put(tc_qdisc); } -int Interface::start() -{ - logger->info("Starting interface which is used by {} nodes", nodes.size()); +int Interface::start() { + logger->info("Starting interface which is used by {} nodes", nodes.size()); - // Set affinity for network interfaces (skip _loopback_ dev) - if (affinity) - setAffinity(affinity); + // Set affinity for network interfaces (skip _loopback_ dev) + if (affinity) + setAffinity(affinity); - // Assign fwmark's to nodes which have netem options - int ret, fwmark = 0; - for (auto *n : nodes) { - if (n->tc_qdisc && n->fwmark < 0) - n->fwmark = 1 + fwmark++; - } + // Assign fwmark's to nodes which have netem options + int ret, fwmark = 0; + for (auto *n : nodes) { + if (n->tc_qdisc && n->fwmark < 0) + n->fwmark = 1 + fwmark++; + } - // Abort if no node is using netem - if (fwmark == 0) - return 0; + // Abort if no node is using netem + if (fwmark == 0) + return 0; - if (getuid() != 0) - throw RuntimeError("Network emulation requires super-user privileges!"); + if (getuid() != 0) + throw RuntimeError("Network emulation requires super-user privileges!"); - // Replace root qdisc - ret = tc::prio(this, &tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, fwmark); - if (ret) - throw RuntimeError("Failed to setup priority queuing discipline: {}", nl_geterror(ret)); + // Replace root qdisc + ret = tc::prio(this, &tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, fwmark); + if (ret) + throw RuntimeError("Failed to setup priority queuing discipline: {}", + nl_geterror(ret)); - // Create netem qdisks and appropriate filter per netem node - for (auto *n : nodes) { - if (n->tc_qdisc) { - ret = tc::mark(this, &n->tc_classifier, TC_HANDLE(1, n->fwmark), n->fwmark); - if (ret) - throw RuntimeError("Failed to setup FW mark classifier: {}", nl_geterror(ret)); + // Create netem qdisks and appropriate filter per netem node + for (auto *n : nodes) { + if (n->tc_qdisc) { + ret = + tc::mark(this, &n->tc_classifier, TC_HANDLE(1, n->fwmark), n->fwmark); + if (ret) + throw RuntimeError("Failed to setup FW mark classifier: {}", + nl_geterror(ret)); - char *buf = tc::netem_print(n->tc_qdisc); - logger->debug("Starting network emulation for FW mark {}: {}", n->fwmark, buf); - free(buf); + char *buf = tc::netem_print(n->tc_qdisc); + logger->debug("Starting network emulation for FW mark {}: {}", n->fwmark, + buf); + free(buf); - ret = tc::netem(this, &n->tc_qdisc, TC_HANDLE(0x1000+n->fwmark, 0), TC_HANDLE(1, n->fwmark)); - if (ret) - throw RuntimeError("Failed to setup netem qdisc: {}", nl_geterror(ret)); - } - } + ret = tc::netem(this, &n->tc_qdisc, TC_HANDLE(0x1000 + n->fwmark, 0), + TC_HANDLE(1, n->fwmark)); + if (ret) + throw RuntimeError("Failed to setup netem qdisc: {}", nl_geterror(ret)); + } + } - return 0; + return 0; } -int Interface::stop() -{ - logger->info("Stopping interface"); +int Interface::stop() { + logger->info("Stopping interface"); - if (affinity) - setAffinity(-1L); + if (affinity) + setAffinity(-1L); - if (tc_qdisc) - tc::reset(this); + if (tc_qdisc) + tc::reset(this); - return 0; + return 0; } -std::string Interface::getName() const -{ - auto str = rtnl_link_get_name(nl_link); +std::string Interface::getName() const { + auto str = rtnl_link_get_name(nl_link); - return std::string(str); + return std::string(str); } -Interface * Interface::getEgress(struct sockaddr *sa, SuperNode *sn) -{ - struct rtnl_link *link; +Interface *Interface::getEgress(struct sockaddr *sa, SuperNode *sn) { + struct rtnl_link *link; - Logger logger = logging.get("kernel:if"); + Logger logger = logging.get("kernel:if"); - auto & interfaces = sn->getInterfaces(); - auto affinity = sn->getAffinity(); + auto &interfaces = sn->getInterfaces(); + auto affinity = sn->getAffinity(); - // Determine outgoing interface - link = nl::get_egress_link(sa); - if (!link) - throw RuntimeError("Failed to get interface for socket address '{}'", socket_print_addr(sa)); + // Determine outgoing interface + link = nl::get_egress_link(sa); + if (!link) + throw RuntimeError("Failed to get interface for socket address '{}'", + socket_print_addr(sa)); - // Search of existing interface with correct ifindex - for (auto *i : interfaces) { - if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) - return i; - } + // Search of existing interface with correct ifindex + for (auto *i : interfaces) { + if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) + return i; + } - // If not found, create a new interface - auto *i = new Interface(link, affinity); - if (!i) - throw MemoryAllocationError(); + // If not found, create a new interface + auto *i = new Interface(link, affinity); + if (!i) + throw MemoryAllocationError(); - interfaces.push_back(i); + interfaces.push_back(i); - return i; + return i; } -int Interface::getIRQs() -{ - int irq; +int Interface::getIRQs() { + int irq; - auto dirname = fmt::format("/sys/class/net/{}/device/msi_irqs/", getName()); - DIR *dir = opendir(dirname.c_str()); - if (dir) { - irqs.clear(); + auto dirname = fmt::format("/sys/class/net/{}/device/msi_irqs/", getName()); + DIR *dir = opendir(dirname.c_str()); + if (dir) { + irqs.clear(); - struct dirent *entry; - while ((entry = readdir(dir))) { - irq = atoi(entry->d_name); - if (irq) - irqs.push_back(irq); - } + struct dirent *entry; + while ((entry = readdir(dir))) { + irq = atoi(entry->d_name); + if (irq) + irqs.push_back(irq); + } - closedir(dir); - } + closedir(dir); + } - return 0; + return 0; } -int Interface::setAffinity(int affinity) -{ - assert(affinity != 0); +int Interface::setAffinity(int affinity) { + assert(affinity != 0); - if (getuid() != 0) { - logger->warn("Failed to tune IRQ affinity. Please run as super-user"); - return 0; - } + if (getuid() != 0) { + logger->warn("Failed to tune IRQ affinity. Please run as super-user"); + return 0; + } - FILE *file; + FILE *file; - CpuSet cset_pin(affinity); + CpuSet cset_pin(affinity); - for (int irq : irqs) { - std::string filename = fmt::format("/proc/irq/{}/smp_affinity", irq); + for (int irq : irqs) { + std::string filename = fmt::format("/proc/irq/{}/smp_affinity", irq); - file = fopen(filename.c_str(), "w"); - if (file) { - if (fprintf(file, "%8lx", (unsigned long) cset_pin) < 0) - throw SystemError("Failed to set affinity for for IRQ {} on interface '{}'", irq, getName()); + file = fopen(filename.c_str(), "w"); + if (file) { + if (fprintf(file, "%8lx", (unsigned long)cset_pin) < 0) + throw SystemError( + "Failed to set affinity for for IRQ {} on interface '{}'", irq, + getName()); - fclose(file); - logger->debug("Set affinity of IRQ {} to {} {}", irq, cset_pin.count() == 1 ? "core" : "cores", (std::string) cset_pin); - } - else - throw SystemError("Failed to set affinity for for IRQ {} on interface '{}'", irq, getName()); - } + fclose(file); + logger->debug("Set affinity of IRQ {} to {} {}", irq, + cset_pin.count() == 1 ? "core" : "cores", + (std::string)cset_pin); + } else + throw SystemError( + "Failed to set affinity for for IRQ {} on interface '{}'", irq, + getName()); + } - return 0; + return 0; } diff --git a/lib/kernel/nl.cpp b/lib/kernel/nl.cpp index e84360b75..2f74dba95 100644 --- a/lib/kernel/nl.cpp +++ b/lib/kernel/nl.cpp @@ -11,145 +11,145 @@ #include -#include #include +#include -#include #include #include +#include // Singleton for global netlink socket -static -struct nl_sock *sock = nullptr; +static struct nl_sock *sock = nullptr; using namespace villas; using namespace villas::kernel::nl; -struct nl_sock * villas::kernel::nl::init() -{ - int ret; +struct nl_sock *villas::kernel::nl::init() { + int ret; - if (!sock) { - // Create connection to netlink - sock = nl_socket_alloc(); - if (!sock) - throw MemoryAllocationError(); + if (!sock) { + // Create connection to netlink + sock = nl_socket_alloc(); + if (!sock) + throw MemoryAllocationError(); - ret = nl_connect(sock, NETLINK_ROUTE); - if (ret) - throw RuntimeError("Failed to connect to kernel: {}", nl_geterror(ret)); + ret = nl_connect(sock, NETLINK_ROUTE); + if (ret) + throw RuntimeError("Failed to connect to kernel: {}", nl_geterror(ret)); - // Fill some caches - struct nl_cache *cache; - ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); - if (ret) - throw RuntimeError("Failed to get list of interfaces: {}", nl_geterror(ret)); + // Fill some caches + struct nl_cache *cache; + ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); + if (ret) + throw RuntimeError("Failed to get list of interfaces: {}", + nl_geterror(ret)); - nl_cache_mngt_provide(cache); - } + nl_cache_mngt_provide(cache); + } - return sock; + return sock; } -void villas::kernel::nl::shutdown() -{ - nl_close(sock); - nl_socket_free(sock); +void villas::kernel::nl::shutdown() { + nl_close(sock); + nl_socket_free(sock); - sock = nullptr; + sock = nullptr; } -static -int egress_cb(struct nl_msg *msg, void *arg) -{ - struct rtnl_route **route = (struct rtnl_route **) arg; +static int egress_cb(struct nl_msg *msg, void *arg) { + struct rtnl_route **route = (struct rtnl_route **)arg; - if (rtnl_route_parse(nlmsg_hdr(msg), route)) - return NL_SKIP; + if (rtnl_route_parse(nlmsg_hdr(msg), route)) + return NL_SKIP; - return NL_STOP; + return NL_STOP; } -int villas::kernel::nl::get_egress(struct nl_addr *addr) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct nl_cb *cb; - struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETROUTE, 0); - struct rtnl_route *route = nullptr; +int villas::kernel::nl::get_egress(struct nl_addr *addr) { + int ret; + struct nl_sock *sock = nl::init(); + struct nl_cb *cb; + struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETROUTE, 0); + struct rtnl_route *route = nullptr; - // Build message - struct rtmsg rmsg = { - .rtm_family = (unsigned char) nl_addr_get_family(addr), - .rtm_dst_len = (unsigned char) nl_addr_get_prefixlen(addr), - }; + // Build message + struct rtmsg rmsg = { + .rtm_family = (unsigned char)nl_addr_get_family(addr), + .rtm_dst_len = (unsigned char)nl_addr_get_prefixlen(addr), + }; - ret = nlmsg_append(msg, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); - if (ret) - goto out; + ret = nlmsg_append(msg, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); + if (ret) + goto out; - ret = nla_put_addr(msg, RTA_DST, addr); - if (ret) - goto out; + ret = nla_put_addr(msg, RTA_DST, addr); + if (ret) + goto out; - // Send message - ret = nl_send_auto(sock, msg); - if (ret < 0) - goto out; + // Send message + ret = nl_send_auto(sock, msg); + if (ret < 0) + goto out; - // Hook into receive chain - cb = nl_cb_alloc(NL_CB_CUSTOM); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, egress_cb, &route); + // Hook into receive chain + cb = nl_cb_alloc(NL_CB_CUSTOM); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, egress_cb, &route); - // Receive message - nl_recvmsgs_report(sock, cb); - nl_wait_for_ack(sock); + // Receive message + nl_recvmsgs_report(sock, cb); + nl_wait_for_ack(sock); - // Check result - if (!route || rtnl_route_get_nnexthops(route) != 1) { - ret = -1; - goto out2; - } + // Check result + if (!route || rtnl_route_get_nnexthops(route) != 1) { + ret = -1; + goto out2; + } - ret = rtnl_route_nh_get_ifindex(rtnl_route_nexthop_n(route, 0)); + ret = rtnl_route_nh_get_ifindex(rtnl_route_nexthop_n(route, 0)); - rtnl_route_put(route); + rtnl_route_put(route); -out2: nl_cb_put(cb); -out: nlmsg_free(msg); +out2: + nl_cb_put(cb); +out: + nlmsg_free(msg); - return ret; + return ret; } -struct rtnl_link * villas::kernel::nl::get_egress_link(struct sockaddr *sa) -{ - int ifindex = -1; +struct rtnl_link *villas::kernel::nl::get_egress_link(struct sockaddr *sa) { + int ifindex = -1; - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: { - struct sockaddr_in *sin = (struct sockaddr_in *) sa; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; - struct nl_addr *addr = (sa->sa_family == AF_INET) - ? nl_addr_build(sin->sin_family, &sin->sin_addr.s_addr, sizeof(sin->sin_addr.s_addr)) - : nl_addr_build(sin6->sin6_family, sin6->sin6_addr.s6_addr, sizeof(sin6->sin6_addr)); + struct nl_addr *addr = + (sa->sa_family == AF_INET) + ? nl_addr_build(sin->sin_family, &sin->sin_addr.s_addr, + sizeof(sin->sin_addr.s_addr)) + : nl_addr_build(sin6->sin6_family, sin6->sin6_addr.s6_addr, + sizeof(sin6->sin6_addr)); - ifindex = nl::get_egress(addr); nl_addr_put(addr); - if (ifindex < 0) - throw RuntimeError("Netlink error: {}", nl_geterror(ifindex)); - break; - } + ifindex = nl::get_egress(addr); + nl_addr_put(addr); + if (ifindex < 0) + throw RuntimeError("Netlink error: {}", nl_geterror(ifindex)); + break; + } - case AF_PACKET: { - struct sockaddr_ll *sll = (struct sockaddr_ll *) sa; + case AF_PACKET: { + struct sockaddr_ll *sll = (struct sockaddr_ll *)sa; - ifindex = sll->sll_ifindex; - break; - } - } + ifindex = sll->sll_ifindex; + break; + } + } - struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct nl_cache *cache = nl_cache_mngt_require("route/link"); - return rtnl_link_get(cache, ifindex); + return rtnl_link_get(cache, ifindex); } diff --git a/lib/kernel/tc.cpp b/lib/kernel/tc.cpp index 241f5d996..30f7907fe 100644 --- a/lib/kernel/tc.cpp +++ b/lib/kernel/tc.cpp @@ -12,83 +12,84 @@ #include -#include #include -#include #include -#include +#include #include +#include +#include using namespace villas; using namespace villas::kernel; -int villas::kernel::tc::prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent, int bands) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_qdisc *q = rtnl_qdisc_alloc(); +int villas::kernel::tc::prio(Interface *i, struct rtnl_qdisc **qd, + tc_hdl_t handle, tc_hdl_t parent, int bands) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_qdisc *q = rtnl_qdisc_alloc(); - ret = kernel::loadModule("sch_prio"); - if (ret) - throw RuntimeError("Failed to load kernel module: sch_prio ({})", ret); + ret = kernel::loadModule("sch_prio"); + if (ret) + throw RuntimeError("Failed to load kernel module: sch_prio ({})", ret); - /* This is the default priomap used by the tc-prio qdisc + /* This is the default priomap used by the tc-prio qdisc * We will use the first 'bands' bands internally */ - uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; - for (unsigned i = 0; i < ARRAY_LEN(map); i++) - map[i] += bands; + uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; + for (unsigned i = 0; i < ARRAY_LEN(map); i++) + map[i] += bands; - rtnl_tc_set_link(TC_CAST(q), i->nl_link); - rtnl_tc_set_parent(TC_CAST(q), parent); - rtnl_tc_set_handle(TC_CAST(q), handle); - rtnl_tc_set_kind(TC_CAST(q), "prio"); + rtnl_tc_set_link(TC_CAST(q), i->nl_link); + rtnl_tc_set_parent(TC_CAST(q), parent); + rtnl_tc_set_handle(TC_CAST(q), handle); + rtnl_tc_set_kind(TC_CAST(q), "prio"); - rtnl_qdisc_prio_set_bands(q, bands + 3); - rtnl_qdisc_prio_set_priomap(q, map, sizeof(map)); + rtnl_qdisc_prio_set_bands(q, bands + 3); + rtnl_qdisc_prio_set_priomap(q, map, sizeof(map)); - ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); + ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); - *qd = q; + *qd = q; - auto logger = logging.get("kernel"); - logger->debug("Added prio qdisc with {} bands to interface '{}'", bands, rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added prio qdisc with {} bands to interface '{}'", bands, + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } -int villas::kernel::tc::mark(Interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_cls *c = rtnl_cls_alloc(); +int villas::kernel::tc::mark(Interface *i, struct rtnl_cls **cls, + tc_hdl_t flowid, uint32_t mark) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_cls *c = rtnl_cls_alloc(); - ret = kernel::loadModule("cls_fw"); - if (ret) - throw RuntimeError("Failed to load kernel module: cls_fw"); + ret = kernel::loadModule("cls_fw"); + if (ret) + throw RuntimeError("Failed to load kernel module: cls_fw"); - rtnl_tc_set_link(TC_CAST(c), i->nl_link); - rtnl_tc_set_handle(TC_CAST(c), mark); - rtnl_tc_set_kind(TC_CAST(c), "fw"); + rtnl_tc_set_link(TC_CAST(c), i->nl_link); + rtnl_tc_set_handle(TC_CAST(c), mark); + rtnl_tc_set_kind(TC_CAST(c), "fw"); - rtnl_cls_set_protocol(c, ETH_P_ALL); + rtnl_cls_set_protocol(c, ETH_P_ALL); - rtnl_fw_set_classid(c, flowid); - rtnl_fw_set_mask(c, 0xFFFFFFFF); + rtnl_fw_set_classid(c, flowid); + rtnl_fw_set_mask(c, 0xFFFFFFFF); - ret = rtnl_cls_add(sock, c, NLM_F_CREATE); + ret = rtnl_cls_add(sock, c, NLM_F_CREATE); - *cls = c; + *cls = c; - auto logger = logging.get("kernel"); - logger->debug("Added fwmark classifier with mark {} to interface '{}'", mark, rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added fwmark classifier with mark {} to interface '{}'", mark, + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } -int villas::kernel::tc::reset(Interface *i) -{ - struct nl_sock *sock = nl::init(); +int villas::kernel::tc::reset(Interface *i) { + struct nl_sock *sock = nl::init(); - // We restore the default pfifo_fast qdisc, by deleting ours - return rtnl_qdisc_delete(sock, i->tc_qdisc); + // We restore the default pfifo_fast qdisc, by deleting ours + return rtnl_qdisc_delete(sock, i->tc_qdisc); } diff --git a/lib/kernel/tc_netem.cpp b/lib/kernel/tc_netem.cpp index b62e2d667..0b9ab2625 100644 --- a/lib/kernel/tc_netem.cpp +++ b/lib/kernel/tc_netem.cpp @@ -7,275 +7,279 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::kernel; -static -const double max_percent_value = 0xffffffff; +static const double max_percent_value = 0xffffffff; /* * Set the delay distribution. Latency/jitter must be set before applying. * @arg qdisc Netem qdisc. * @return 0 on success, error code on failure. */ -static -int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, short *data, size_t len) -{ - struct rtnl_netem *netem; +static int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, + short *data, size_t len) { + struct rtnl_netem *netem; - if (!(netem = (struct rtnl_netem *) rtnl_tc_data(TC_CAST(qdisc)))) - return -1; + if (!(netem = (struct rtnl_netem *)rtnl_tc_data(TC_CAST(qdisc)))) + return -1; - if (len > MAXDIST) - return -NLE_INVAL; + if (len > MAXDIST) + return -NLE_INVAL; - netem->qnm_dist.dist_data = (int16_t *) calloc(len, sizeof(int16_t)); + netem->qnm_dist.dist_data = (int16_t *)calloc(len, sizeof(int16_t)); - size_t i; - for (i = 0; i < len; i++) - netem->qnm_dist.dist_data[i] = data[i]; + size_t i; + for (i = 0; i < len; i++) + netem->qnm_dist.dist_data[i] = data[i]; - netem->qnm_dist.dist_size = len; - netem->qnm_mask |= SCH_NETEM_ATTR_DIST; + netem->qnm_dist.dist_size = len; + netem->qnm_mask |= SCH_NETEM_ATTR_DIST; - return 0; + return 0; } // Customized version of rtnl_netem_set_delay_distribution() of libnl -static -int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) -{ - if (json_is_string(json)) - return rtnl_netem_set_delay_distribution(qdisc, json_string_value(json)); - else if (json_is_array(json)) { - json_t *elm; - size_t idx; - size_t len = json_array_size(json); +static int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) { + if (json_is_string(json)) + return rtnl_netem_set_delay_distribution(qdisc, json_string_value(json)); + else if (json_is_array(json)) { + json_t *elm; + size_t idx; + size_t len = json_array_size(json); - int16_t *data = new int16_t[len]; - if (!data) - throw MemoryAllocationError(); + int16_t *data = new int16_t[len]; + if (!data) + throw MemoryAllocationError(); - json_array_foreach(json, idx, elm) { - if (!json_is_integer(elm)) - return -1; + json_array_foreach(json, idx, elm) { + if (!json_is_integer(elm)) + return -1; - data[idx] = json_integer_value(elm); - } + data[idx] = json_integer_value(elm); + } - return rtnl_netem_set_delay_distribution_data(qdisc, data, len); - } + return rtnl_netem_set_delay_distribution_data(qdisc, data, len); + } - return 0; + return 0; } -int villas::kernel::tc::netem_parse(struct rtnl_qdisc **netem, json_t *json) -{ - int ret, val; +int villas::kernel::tc::netem_parse(struct rtnl_qdisc **netem, json_t *json) { + int ret, val; - json_t *json_limit = nullptr; - json_t *json_delay = nullptr; - json_t *json_delay_distribution = nullptr; - json_t *json_delay_correlation = nullptr; - json_t *json_jitter = nullptr; - json_t *json_loss = nullptr; - json_t *json_duplicate = nullptr; - json_t *json_corruption = nullptr; + json_t *json_limit = nullptr; + json_t *json_delay = nullptr; + json_t *json_delay_distribution = nullptr; + json_t *json_delay_correlation = nullptr; + json_t *json_jitter = nullptr; + json_t *json_loss = nullptr; + json_t *json_duplicate = nullptr; + json_t *json_corruption = nullptr; - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o }", - "distribution", &json_delay_distribution, - "correlation", &json_delay_correlation, - "limit", &json_limit, - "delay", &json_delay, - "jitter", &json_jitter, - "loss", &json_loss, - "duplicate", &json_duplicate, - "corruption", &json_corruption - ); - if (ret) - throw ConfigError(json, err, "node-config-netem", "Failed to parse setting network emulation settings"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o }", + "distribution", &json_delay_distribution, "correlation", + &json_delay_correlation, "limit", &json_limit, "delay", &json_delay, + "jitter", &json_jitter, "loss", &json_loss, "duplicate", &json_duplicate, + "corruption", &json_corruption); + if (ret) + throw ConfigError(json, err, "node-config-netem", + "Failed to parse setting network emulation settings"); - struct rtnl_qdisc *ne = rtnl_qdisc_alloc(); - if (!ne) - throw MemoryAllocationError(); + struct rtnl_qdisc *ne = rtnl_qdisc_alloc(); + if (!ne) + throw MemoryAllocationError(); - rtnl_tc_set_kind(TC_CAST(ne), "netem"); + rtnl_tc_set_kind(TC_CAST(ne), "netem"); - if (json_delay_distribution) { - if (set_delay_distribution(ne, json_delay_distribution)) - throw ConfigError(json_delay_distribution, "node-config-netem-distrobution", "Invalid delay distribution in netem config"); - } + if (json_delay_distribution) { + if (set_delay_distribution(ne, json_delay_distribution)) + throw ConfigError(json_delay_distribution, + "node-config-netem-distrobution", + "Invalid delay distribution in netem config"); + } - if (json_delay_correlation) { - double dval = json_number_value(json_delay_correlation); + if (json_delay_correlation) { + double dval = json_number_value(json_delay_correlation); - if (!json_is_number(json_delay_correlation) || dval < 0 || dval > 100) - throw ConfigError(json_delay_correlation, "Setting 'correlation' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_delay_correlation) || dval < 0 || dval > 100) + throw ConfigError(json_delay_correlation, + "Setting 'correlation' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_delay_correlation(ne, val); - } - else - rtnl_netem_set_delay_correlation(ne, 0); + rtnl_netem_set_delay_correlation(ne, val); + } else + rtnl_netem_set_delay_correlation(ne, 0); - if (json_limit) { - val = json_integer_value(json_limit); + if (json_limit) { + val = json_integer_value(json_limit); - if (!json_is_integer(json_limit) || val <= 0) - throw ConfigError(json_limit, "Setting 'limit' must be a positive integer"); + if (!json_is_integer(json_limit) || val <= 0) + throw ConfigError(json_limit, + "Setting 'limit' must be a positive integer"); - rtnl_netem_set_limit(ne, val); - } - else - rtnl_netem_set_limit(ne, 0); + rtnl_netem_set_limit(ne, val); + } else + rtnl_netem_set_limit(ne, 0); - if (json_delay) { - val = json_integer_value(json_delay); + if (json_delay) { + val = json_integer_value(json_delay); - if (!json_is_integer(json_delay) || val <= 0) - throw ConfigError(json_delay, "Setting 'delay' must be a positive integer"); + if (!json_is_integer(json_delay) || val <= 0) + throw ConfigError(json_delay, + "Setting 'delay' must be a positive integer"); - rtnl_netem_set_delay(ne, val); - } + rtnl_netem_set_delay(ne, val); + } - if (json_jitter) { - val = json_integer_value(json_jitter); + if (json_jitter) { + val = json_integer_value(json_jitter); - if (!json_is_integer(json_jitter) || val <= 0) - throw ConfigError(json_jitter, "Setting 'jitter' must be a positive integer"); + if (!json_is_integer(json_jitter) || val <= 0) + throw ConfigError(json_jitter, + "Setting 'jitter' must be a positive integer"); - rtnl_netem_set_jitter(ne, val); - } + rtnl_netem_set_jitter(ne, val); + } - if (json_loss) { - double dval = json_number_value(json_loss); + if (json_loss) { + double dval = json_number_value(json_loss); - if (!json_is_number(json_loss) || dval < 0 || dval > 100) - throw ConfigError(json_loss, "Setting 'loss' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_loss) || dval < 0 || dval > 100) + throw ConfigError(json_loss, "Setting 'loss' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_loss(ne, val); - } + rtnl_netem_set_loss(ne, val); + } - if (json_duplicate) { - double dval = json_number_value(json_duplicate); + if (json_duplicate) { + double dval = json_number_value(json_duplicate); - if (!json_is_number(json_duplicate) || dval < 0 || dval > 100) - throw ConfigError(json_duplicate, "Setting 'duplicate' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_duplicate) || dval < 0 || dval > 100) + throw ConfigError(json_duplicate, + "Setting 'duplicate' must be a positive integer within " + "the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_duplicate(ne, val); - } + rtnl_netem_set_duplicate(ne, val); + } - if (json_corruption) { - double dval = json_number_value(json_corruption); + if (json_corruption) { + double dval = json_number_value(json_corruption); - if (!json_is_number(json_corruption) || dval < 0 || dval > 100) - throw ConfigError(json_corruption, "Setting 'corruption' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_corruption) || dval < 0 || dval > 100) + throw ConfigError(json_corruption, + "Setting 'corruption' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_corruption_probability(ne, val); - } + rtnl_netem_set_corruption_probability(ne, val); + } - *netem = ne; + *netem = ne; - return 0; + return 0; } -char * villas::kernel::tc::netem_print(struct rtnl_qdisc *ne) -{ - char *buf = nullptr; +char *villas::kernel::tc::netem_print(struct rtnl_qdisc *ne) { + char *buf = nullptr; - if (rtnl_netem_get_limit(ne) > 0) - strcatf(&buf, "limit %upkts", rtnl_netem_get_limit(ne)); + if (rtnl_netem_get_limit(ne) > 0) + strcatf(&buf, "limit %upkts", rtnl_netem_get_limit(ne)); - if (rtnl_netem_get_delay(ne) > 0) { - strcatf(&buf, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); + if (rtnl_netem_get_delay(ne) > 0) { + strcatf(&buf, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); - if (rtnl_netem_get_jitter(ne) > 0) { - strcatf(&buf, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); + if (rtnl_netem_get_jitter(ne) > 0) { + strcatf(&buf, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); - if (rtnl_netem_get_delay_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_delay_correlation(ne)); - } - } + if (rtnl_netem_get_delay_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_delay_correlation(ne)); + } + } - if (rtnl_netem_get_loss(ne) > 0) { - strcatf(&buf, "loss %u%% ", rtnl_netem_get_loss(ne)); + if (rtnl_netem_get_loss(ne) > 0) { + strcatf(&buf, "loss %u%% ", rtnl_netem_get_loss(ne)); - if (rtnl_netem_get_loss_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_loss_correlation(ne)); - } + if (rtnl_netem_get_loss_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_loss_correlation(ne)); + } - if (rtnl_netem_get_reorder_probability(ne) > 0) { - strcatf(&buf, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); + if (rtnl_netem_get_reorder_probability(ne) > 0) { + strcatf(&buf, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); - if (rtnl_netem_get_reorder_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); - } + if (rtnl_netem_get_reorder_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); + } - if (rtnl_netem_get_corruption_probability(ne) > 0) { - strcatf(&buf, "corruption %u%% ", rtnl_netem_get_corruption_probability(ne)); + if (rtnl_netem_get_corruption_probability(ne) > 0) { + strcatf(&buf, "corruption %u%% ", + rtnl_netem_get_corruption_probability(ne)); - if (rtnl_netem_get_corruption_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); - } + if (rtnl_netem_get_corruption_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); + } - if (rtnl_netem_get_duplicate(ne) > 0) { - strcatf(&buf, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); + if (rtnl_netem_get_duplicate(ne) > 0) { + strcatf(&buf, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); - if (rtnl_netem_get_duplicate_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); - } + if (rtnl_netem_get_duplicate_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); + } - return buf; + return buf; } -int villas::kernel::tc::netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_qdisc *q = *qd; +int villas::kernel::tc::netem(Interface *i, struct rtnl_qdisc **qd, + tc_hdl_t handle, tc_hdl_t parent) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_qdisc *q = *qd; - ret = kernel::loadModule("sch_netem"); - if (ret) - throw RuntimeError("Failed to load kernel module: sch_netem ({})", ret); + ret = kernel::loadModule("sch_netem"); + if (ret) + throw RuntimeError("Failed to load kernel module: sch_netem ({})", ret); - rtnl_tc_set_link(TC_CAST(q), i->nl_link); - rtnl_tc_set_parent(TC_CAST(q), parent); - rtnl_tc_set_handle(TC_CAST(q), handle); - //rtnl_tc_set_kind(TC_CAST(q), "netem"); + rtnl_tc_set_link(TC_CAST(q), i->nl_link); + rtnl_tc_set_parent(TC_CAST(q), parent); + rtnl_tc_set_handle(TC_CAST(q), handle); + //rtnl_tc_set_kind(TC_CAST(q), "netem"); - ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE); + ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE); - *qd = q; + *qd = q; - auto logger = logging.get("kernel"); - logger->debug("Added netem qdisc to interface '{}'", rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added netem qdisc to interface '{}'", + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } diff --git a/lib/mapping.cpp b/lib/mapping.cpp index f4ad98fa3..5fec8fb31 100644 --- a/lib/mapping.cpp +++ b/lib/mapping.cpp @@ -5,351 +5,332 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include -#include -#include -#include #include +#include +#include #include +#include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int MappingEntry::parseString(const std::string &str) -{ - std::smatch mr; - std::regex re(RE_MAPPING); +int MappingEntry::parseString(const std::string &str) { + std::smatch mr; + std::regex re(RE_MAPPING); - if (!std::regex_match(str, mr, re)) - goto invalid_format; + if (!std::regex_match(str, mr, re)) + goto invalid_format; - if (mr[1].matched) - nodeName = mr.str(1); + if (mr[1].matched) + nodeName = mr.str(1); - if (mr[9].matched) - nodeName = mr.str(9); + if (mr[9].matched) + nodeName = mr.str(9); - if (mr[6].matched) { - data.first = strdup(mr.str(6).c_str()); - data.last = mr[7].matched - ? strdup(mr.str(7).c_str()) - : nullptr; + if (mr[6].matched) { + data.first = strdup(mr.str(6).c_str()); + data.last = mr[7].matched ? strdup(mr.str(7).c_str()) : nullptr; - type = Type::DATA; - } - else if (mr[10].matched) { - data.first = strdup(mr.str(10).c_str()); - data.last = mr[11].matched - ? strdup(mr.str(11).c_str()) - : nullptr; + type = Type::DATA; + } else if (mr[10].matched) { + data.first = strdup(mr.str(10).c_str()); + data.last = mr[11].matched ? strdup(mr.str(11).c_str()) : nullptr; - type = Type::DATA; - } - else if (mr[8].matched) { - data.first = strdup(mr.str(8).c_str()); - data.last = nullptr; + type = Type::DATA; + } else if (mr[8].matched) { + data.first = strdup(mr.str(8).c_str()); + data.last = nullptr; - type = Type::DATA; - } - else if (mr[2].matched) { - stats.type = Stats::lookupType(mr.str(3)); - stats.metric = Stats::lookupMetric(mr.str(2)); + type = Type::DATA; + } else if (mr[2].matched) { + stats.type = Stats::lookupType(mr.str(3)); + stats.metric = Stats::lookupMetric(mr.str(2)); - type = Type::STATS; - } - else if (mr[5].matched) { - if (mr.str(5) == "origin") - timestamp.type = TimestampType::ORIGIN; - else if (mr.str(5) == "received") - timestamp.type = TimestampType::RECEIVED; - else - goto invalid_format; + type = Type::STATS; + } else if (mr[5].matched) { + if (mr.str(5) == "origin") + timestamp.type = TimestampType::ORIGIN; + else if (mr.str(5) == "received") + timestamp.type = TimestampType::RECEIVED; + else + goto invalid_format; - type = Type::TIMESTAMP; - } - else if (mr[4].matched) { - if (mr.str(4) == "sequence") - header.type = HeaderType::SEQUENCE; - else if (mr.str(4) == "length") - header.type = HeaderType::LENGTH; - else - goto invalid_format; + type = Type::TIMESTAMP; + } else if (mr[4].matched) { + if (mr.str(4) == "sequence") + header.type = HeaderType::SEQUENCE; + else if (mr.str(4) == "length") + header.type = HeaderType::LENGTH; + else + goto invalid_format; - type = Type::HEADER; - } - // Only node name given.. We map all data - else if (!nodeName.empty()) { - data.first = nullptr; - data.last = nullptr; + type = Type::HEADER; + } + // Only node name given.. We map all data + else if (!nodeName.empty()) { + data.first = nullptr; + data.last = nullptr; - type = Type::DATA; - } + type = Type::DATA; + } - return 0; + return 0; invalid_format: - throw RuntimeError("Failed to parse mapping expression: {}", str); + throw RuntimeError("Failed to parse mapping expression: {}", str); } -MappingEntry::MappingEntry() : - node(nullptr), - type(Type::UNKNOWN), - length(0), - offset(0), - nodeName() -{ } +MappingEntry::MappingEntry() + : node(nullptr), type(Type::UNKNOWN), length(0), offset(0), nodeName() {} -int MappingEntry::parse(json_t *json) -{ - const char *str; +int MappingEntry::parse(json_t *json) { + const char *str; - str = json_string_value(json); - if (!str) - return -1; + str = json_string_value(json); + if (!str) + return -1; - return parseString(str); + return parseString(str); } -int MappingEntry::update(struct Sample *remapped, const struct Sample *original) const -{ - unsigned len = length; +int MappingEntry::update(struct Sample *remapped, + const struct Sample *original) const { + unsigned len = length; - if (offset + len > remapped->capacity) - return -1; + if (offset + len > remapped->capacity) + return -1; - switch (type) { - case Type::STATS: - remapped->data[offset] = node->getStats()->getValue(stats.metric, stats.type); - break; + switch (type) { + case Type::STATS: + remapped->data[offset] = + node->getStats()->getValue(stats.metric, stats.type); + break; - case Type::TIMESTAMP: { - const struct timespec *ts; + case Type::TIMESTAMP: { + const struct timespec *ts; - switch (timestamp.type) { - case TimestampType::RECEIVED: - ts = &original->ts.received; - break; - case TimestampType::ORIGIN: - ts = &original->ts.origin; - break; - default: - return -1; - } + switch (timestamp.type) { + case TimestampType::RECEIVED: + ts = &original->ts.received; + break; + case TimestampType::ORIGIN: + ts = &original->ts.origin; + break; + default: + return -1; + } - remapped->data[offset + 0].i = ts->tv_sec; - remapped->data[offset + 1].i = ts->tv_nsec; - break; - } + remapped->data[offset + 0].i = ts->tv_sec; + remapped->data[offset + 1].i = ts->tv_nsec; + break; + } - case Type::HEADER: - switch (header.type) { - case HeaderType::LENGTH: - remapped->data[offset].i = original->length; - break; + case Type::HEADER: + switch (header.type) { + case HeaderType::LENGTH: + remapped->data[offset].i = original->length; + break; - case HeaderType::SEQUENCE: - remapped->data[offset].i = original->sequence; - break; + case HeaderType::SEQUENCE: + remapped->data[offset].i = original->sequence; + break; - default: - return -1; - } - break; + default: + return -1; + } + break; - case Type::DATA: - for (unsigned j = data.offset, - i = offset; - j < MIN(original->length, (unsigned) (data.offset + length)); - j++, - i++) - { - if (j >= original->length) - remapped->data[i].f = -1; - else - remapped->data[i] = original->data[j]; - } + case Type::DATA: + for (unsigned j = data.offset, i = offset; + j < MIN(original->length, (unsigned)(data.offset + length)); + j++, i++) { + if (j >= original->length) + remapped->data[i].f = -1; + else + remapped->data[i] = original->data[j]; + } - len = MIN((unsigned) length, original->length - data.offset); - break; + len = MIN((unsigned)length, original->length - data.offset); + break; - case Type::UNKNOWN: - return -1; - } + case Type::UNKNOWN: + return -1; + } - if (offset + len > remapped->length) - remapped->length = offset + len; + if (offset + len > remapped->length) + remapped->length = offset + len; - return 0; + return 0; } -int MappingEntry::prepare(NodeList &nodes) -{ - if (!nodeName.empty() && node == nullptr) { - node = nodes.lookup(nodeName); - if (!node) - throw RuntimeError("Invalid node name in mapping: {}", nodeName); - } +int MappingEntry::prepare(NodeList &nodes) { + if (!nodeName.empty() && node == nullptr) { + node = nodes.lookup(nodeName); + if (!node) + throw RuntimeError("Invalid node name in mapping: {}", nodeName); + } - if (type == Type::DATA) { - int first = -1, last = -1; + if (type == Type::DATA) { + int first = -1, last = -1; - if (data.first) { - if (node) - first = node->getInputSignals()->getIndexByName(data.first); + if (data.first) { + if (node) + first = node->getInputSignals()->getIndexByName(data.first); - if (first < 0) { - char *endptr; - first = strtoul(data.first, &endptr, 10); - if (endptr != data.first + strlen(data.first)) - throw RuntimeError("Failed to parse data index in mapping: {}", data.first); - } - } - else { - // Map all signals - data.offset = 0; - length = -1; - goto end; - } + if (first < 0) { + char *endptr; + first = strtoul(data.first, &endptr, 10); + if (endptr != data.first + strlen(data.first)) + throw RuntimeError("Failed to parse data index in mapping: {}", + data.first); + } + } else { + // Map all signals + data.offset = 0; + length = -1; + goto end; + } - if (data.last) { - if (node) - last = node->getInputSignals()->getIndexByName(data.last); + if (data.last) { + if (node) + last = node->getInputSignals()->getIndexByName(data.last); - if (last < 0) { - char *endptr; - last = strtoul(data.last, &endptr, 10); - if (endptr != data.last + strlen(data.last)) - throw RuntimeError("Failed to parse data index in mapping: {}", data.last); - } - } - else - last = first; // single element: data[5] => data[5-5] + if (last < 0) { + char *endptr; + last = strtoul(data.last, &endptr, 10); + if (endptr != data.last + strlen(data.last)) + throw RuntimeError("Failed to parse data index in mapping: {}", + data.last); + } + } else + last = first; // single element: data[5] => data[5-5] - if (last < first) - throw RuntimeError("Invalid data range indices for mapping: {} < {}", last, first); + if (last < first) + throw RuntimeError("Invalid data range indices for mapping: {} < {}", + last, first); - data.offset = first; - length = last - first + 1; - } - else { - length = 1; - } + data.offset = first; + length = last - first + 1; + } else { + length = 1; + } end: - if (length < 0) - length = node->getInputSignals()->size(); + if (length < 0) + length = node->getInputSignals()->size(); - return 0; + return 0; } -std::string MappingEntry::toString(unsigned index) const -{ - assert(length == 0 || (int) index < length); +std::string MappingEntry::toString(unsigned index) const { + assert(length == 0 || (int)index < length); - std::stringstream ss; + std::stringstream ss; - if (node) - ss << node->getNameShort() << "."; + if (node) + ss << node->getNameShort() << "."; - switch (type) { - case Type::STATS: - ss << "stats."; - ss << Stats::metrics[stats.metric].name << "."; - ss << Stats::types[stats.type].name; - break; + switch (type) { + case Type::STATS: + ss << "stats."; + ss << Stats::metrics[stats.metric].name << "."; + ss << Stats::types[stats.type].name; + break; - case Type::HEADER: - ss << "hdr."; - switch (header.type) { - case HeaderType::LENGTH: - ss << "length"; - break; + case Type::HEADER: + ss << "hdr."; + switch (header.type) { + case HeaderType::LENGTH: + ss << "length"; + break; - case HeaderType::SEQUENCE: - ss << "sequence"; - break; + case HeaderType::SEQUENCE: + ss << "sequence"; + break; - default: {} - } - break; + default: { + } + } + break; - case Type::TIMESTAMP: - ss << "ts."; - switch (timestamp.type) { - case TimestampType::ORIGIN: - ss << "origin."; - break; + case Type::TIMESTAMP: + ss << "ts."; + switch (timestamp.type) { + case TimestampType::ORIGIN: + ss << "origin."; + break; - case TimestampType::RECEIVED: - ss << "received."; - break; + case TimestampType::RECEIVED: + ss << "received."; + break; - default: {} - } + default: { + } + } - ss << (index == 0 ? "sec" : "nsec"); - break; + ss << (index == 0 ? "sec" : "nsec"); + break; - case Type::DATA: - if (node && index < node->getInputSignals()->size()) { - auto s = node->getInputSignals()->getByIndex(index); + case Type::DATA: + if (node && index < node->getInputSignals()->size()) { + auto s = node->getInputSignals()->getByIndex(index); - ss << "data[" << s->name << "]"; - } - else - ss << "data[" << index << "]"; - break; + ss << "data[" << s->name << "]"; + } else + ss << "data[" << index << "]"; + break; - case Type::UNKNOWN: - return ""; - } + case Type::UNKNOWN: + return ""; + } - return ss.str(); + return ss.str(); } -Signal::Ptr MappingEntry::toSignal(unsigned index) const -{ - auto name = toString(index); +Signal::Ptr MappingEntry::toSignal(unsigned index) const { + auto name = toString(index); - switch (type) { - case MappingEntry::Type::STATS: - return std::make_shared(name, Stats::metrics[stats.metric].unit, - Stats::types[stats.type].signal_type); + switch (type) { + case MappingEntry::Type::STATS: + return std::make_shared(name, Stats::metrics[stats.metric].unit, + Stats::types[stats.type].signal_type); - case MappingEntry::Type::HEADER: - switch (header.type) { - case MappingEntry::HeaderType::LENGTH: - case MappingEntry::HeaderType::SEQUENCE: - return std::make_shared(name, "", SignalType::INTEGER); - } - break; + case MappingEntry::Type::HEADER: + switch (header.type) { + case MappingEntry::HeaderType::LENGTH: + case MappingEntry::HeaderType::SEQUENCE: + return std::make_shared(name, "", SignalType::INTEGER); + } + break; - case MappingEntry::Type::TIMESTAMP: - switch (index) { - case 0: - return std::make_shared(name, "s", SignalType::INTEGER); - case 1: - return std::make_shared(name, "ns", SignalType::INTEGER); - } - break; + case MappingEntry::Type::TIMESTAMP: + switch (index) { + case 0: + return std::make_shared(name, "s", SignalType::INTEGER); + case 1: + return std::make_shared(name, "ns", SignalType::INTEGER); + } + break; - case MappingEntry::Type::DATA: { - auto sig = std::make_shared(data.signal->name, data.signal->unit, data.signal->type); + case MappingEntry::Type::DATA: { + auto sig = std::make_shared(data.signal->name, data.signal->unit, + data.signal->type); - sig->init = data.signal->init; + sig->init = data.signal->init; - return sig; - } + return sig; + } - case MappingEntry::Type::UNKNOWN: - break; - } + case MappingEntry::Type::UNKNOWN: + break; + } - return std::shared_ptr(); + return std::shared_ptr(); } diff --git a/lib/mapping_list.cpp b/lib/mapping_list.cpp index 504b606fb..82a62cd35 100644 --- a/lib/mapping_list.cpp +++ b/lib/mapping_list.cpp @@ -5,74 +5,72 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::node; -int MappingList::parse(json_t *json) -{ - int ret; +int MappingList::parse(json_t *json) { + int ret; - size_t i; - json_t *json_entry; - json_t *json_mapping; + size_t i; + json_t *json_entry; + json_t *json_mapping; - if (json_is_string(json)) { - json_mapping = json_array(); - json_array_append(json_mapping, json); - } - else if (json_is_array(json)) - json_mapping = json_incref(json); - else - return -1; + if (json_is_string(json)) { + json_mapping = json_array(); + json_array_append(json_mapping, json); + } else if (json_is_array(json)) + json_mapping = json_incref(json); + else + return -1; - json_array_foreach(json_mapping, i, json_entry) { - auto me = std::make_shared(); - if (!me) - throw MemoryAllocationError(); + json_array_foreach(json_mapping, i, json_entry) { + auto me = std::make_shared(); + if (!me) + throw MemoryAllocationError(); - ret = me->parse(json_entry); - if (ret) - goto out; + ret = me->parse(json_entry); + if (ret) + goto out; - push_back(me); - } + push_back(me); + } - ret = 0; + ret = 0; -out: json_decref(json_mapping); +out: + json_decref(json_mapping); - return ret; + return ret; } -int MappingList::remap(struct Sample *remapped, const struct Sample *original) const -{ - int ret; +int MappingList::remap(struct Sample *remapped, + const struct Sample *original) const { + int ret; - for (auto me : *this) { - ret = me->update(remapped, original); - if (ret) - return ret; - } + for (auto me : *this) { + ret = me->update(remapped, original); + if (ret) + return ret; + } - return 0; + return 0; } -int MappingList::prepare(NodeList &nodes) -{ - int ret; +int MappingList::prepare(NodeList &nodes) { + int ret; - unsigned off = 0; - for (auto me : *this) { - ret = me->prepare(nodes); - if (ret) - return ret; + unsigned off = 0; + for (auto me : *this) { + ret = me->prepare(nodes); + if (ret) + return ret; - me->offset = off; - off += me->length; - } + me->offset = off; + off += me->length; + } - return 0; + return 0; } diff --git a/lib/memory.cpp b/lib/memory.cpp index 739ca737d..9475dc5fa 100644 --- a/lib/memory.cpp +++ b/lib/memory.cpp @@ -7,151 +7,149 @@ #include -#include -#include #include +#include #include +#include -#include -#include #include +#include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::node::memory; -static -std::unordered_map allocations; -static -Logger logger; +static std::unordered_map allocations; +static Logger logger; -int villas::node::memory::init(int hugepages) -{ - int ret; +int villas::node::memory::init(int hugepages) { + int ret; - logger = logging.get("memory"); + logger = logging.get("memory"); - logger->info("Initialize memory sub-system: #hugepages={}", hugepages); + logger->info("Initialize memory sub-system: #hugepages={}", hugepages); - ret = mmap_init(hugepages); - if (ret < 0) - return ret; + ret = mmap_init(hugepages); + if (ret < 0) + return ret; - size_t lock_sz = kernel::getHugePageSize() * hugepages; + size_t lock_sz = kernel::getHugePageSize() * hugepages; - ret = lock(lock_sz); - if (ret) - return ret; + ret = lock(lock_sz); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::memory::lock(size_t sz) -{ - int ret; +int villas::node::memory::lock(size_t sz) { + int ret; - if (!utils::isPrivileged()) { - logger->warn("Running in an unprivileged environment. Memory is not locked to RAM!"); - return 0; - } + if (!utils::isPrivileged()) { + logger->warn( + "Running in an unprivileged environment. Memory is not locked to RAM!"); + return 0; + } #ifdef __linux__ #ifndef __arm__ - struct rlimit l; + struct rlimit l; - // Increase ressource limit for locked memory - ret = getrlimit(RLIMIT_MEMLOCK, &l); - if (ret) - return ret; + // Increase ressource limit for locked memory + ret = getrlimit(RLIMIT_MEMLOCK, &l); + if (ret) + return ret; - if (l.rlim_cur < sz) { - if (l.rlim_max < sz) { - if (getuid() != 0) { - logger->warn("Failed to increase ressource limit of locked memory. Please increase manually by running as root:"); - logger->warn(" $ ulimit -Hl {}", sz); + if (l.rlim_cur < sz) { + if (l.rlim_max < sz) { + if (getuid() != 0) { + logger->warn("Failed to increase ressource limit of locked memory. " + "Please increase manually by running as root:"); + logger->warn(" $ ulimit -Hl {}", sz); - return 0; - } + return 0; + } - l.rlim_max = sz; - } + l.rlim_max = sz; + } - l.rlim_cur = sz; + l.rlim_cur = sz; - ret = setrlimit(RLIMIT_MEMLOCK, &l); - if (ret) - return ret; + ret = setrlimit(RLIMIT_MEMLOCK, &l); + if (ret) + return ret; - logger->debug("Increased ressource limit of locked memory to {} bytes", sz); - } + logger->debug("Increased ressource limit of locked memory to {} bytes", sz); + } #endif // __arm__ #ifdef _POSIX_MEMLOCK - // Lock all current and future memory allocations - ret = mlockall(MCL_CURRENT | MCL_FUTURE); - if (ret) - return -1; + // Lock all current and future memory allocations + ret = mlockall(MCL_CURRENT | MCL_FUTURE); + if (ret) + return -1; #endif // _POSIX_MEMLOCK #endif // __linux__ - return 0; + return 0; } -void * villas::node::memory::alloc(size_t len, struct Type *m) -{ - return alloc_aligned(len, sizeof(void *), m); +void *villas::node::memory::alloc(size_t len, struct Type *m) { + return alloc_aligned(len, sizeof(void *), m); } -void * villas::node::memory::alloc_aligned(size_t len, size_t alignment, struct Type *m) -{ - struct Allocation *ma = m->alloc(len, alignment, m); - if (ma == nullptr) { - logger->warn("Memory allocation of type {} failed. reason={}", m->name, strerror(errno)); - return nullptr; - } +void *villas::node::memory::alloc_aligned(size_t len, size_t alignment, + struct Type *m) { + struct Allocation *ma = m->alloc(len, alignment, m); + if (ma == nullptr) { + logger->warn("Memory allocation of type {} failed. reason={}", m->name, + strerror(errno)); + return nullptr; + } - allocations[ma->address] = ma; + allocations[ma->address] = ma; - logger->debug("Allocated {:#x} bytes of {:#x}-byte-aligned {} memory: {}", ma->length, ma->alignment, ma->type->name, ma->address); + logger->debug("Allocated {:#x} bytes of {:#x}-byte-aligned {} memory: {}", + ma->length, ma->alignment, ma->type->name, ma->address); - return ma->address; + return ma->address; } -int villas::node::memory::free(void *ptr) -{ - int ret; +int villas::node::memory::free(void *ptr) { + int ret; - // Find corresponding memory allocation entry - struct Allocation *ma = allocations[ptr]; - if (!ma) - return -1; + // Find corresponding memory allocation entry + struct Allocation *ma = allocations[ptr]; + if (!ma) + return -1; - logger->debug("Releasing {:#x} bytes of {} memory: {}", ma->length, ma->type->name, ma->address); + logger->debug("Releasing {:#x} bytes of {} memory: {}", ma->length, + ma->type->name, ma->address); - ret = ma->type->free(ma, ma->type); - if (ret) - return ret; + ret = ma->type->free(ma, ma->type); + if (ret) + return ret; - // Remove allocation entry - auto iter = allocations.find(ptr); - if (iter == allocations.end()) - return -1; + // Remove allocation entry + auto iter = allocations.find(ptr); + if (iter == allocations.end()) + return -1; - allocations.erase(iter); - delete ma; + allocations.erase(iter); + delete ma; - return 0; + return 0; } -struct Allocation * villas::node::memory::get_allocation(void *ptr) -{ - return allocations[ptr]; +struct Allocation *villas::node::memory::get_allocation(void *ptr) { + return allocations[ptr]; } struct Type *villas::node::memory::default_type = nullptr; diff --git a/lib/memory/heap.cpp b/lib/memory/heap.cpp index bb891324a..2b6c03bbd 100644 --- a/lib/memory/heap.cpp +++ b/lib/memory/heap.cpp @@ -7,53 +7,48 @@ #include -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -struct Allocation * heap_alloc(size_t len, size_t alignment, struct Type *m) -{ - int ret; +static struct Allocation *heap_alloc(size_t len, size_t alignment, + struct Type *m) { + int ret; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->alignment = alignment; - ma->type = m; - ma->length = len; + ma->alignment = alignment; + ma->type = m; + ma->length = len; - if (ma->alignment < sizeof(void *)) - ma->alignment = sizeof(void *); + if (ma->alignment < sizeof(void *)) + ma->alignment = sizeof(void *); - ret = posix_memalign(&ma->address, ma->alignment, ma->length); - if (ret) { - delete ma; - return nullptr; - } + ret = posix_memalign(&ma->address, ma->alignment, ma->length); + if (ret) { + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int heap_free(struct Allocation *ma, struct Type *m) -{ - ::free(ma->address); +static int heap_free(struct Allocation *ma, struct Type *m) { + ::free(ma->address); - return 0; + return 0; } // List of available memory types -struct Type villas::node::memory::heap = { - .name = "heap", - .flags = (int) Flags::HEAP, - .alignment = 1, - .alloc = heap_alloc, - .free = heap_free -}; +struct Type villas::node::memory::heap = {.name = "heap", + .flags = (int)Flags::HEAP, + .alignment = 1, + .alloc = heap_alloc, + .free = heap_free}; diff --git a/lib/memory/ib.cpp b/lib/memory/ib.cpp index 6421488f5..5a2bce3c0 100644 --- a/lib/memory/ib.cpp +++ b/lib/memory/ib.cpp @@ -7,88 +7,85 @@ #include -#include -#include -#include -#include #include +#include +#include #include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::node::memory; -struct ibv_mr * villas::node::memory::ib_get_mr(void *ptr) -{ - auto *ma = get_allocation(ptr); +struct ibv_mr *villas::node::memory::ib_get_mr(void *ptr) { + auto *ma = get_allocation(ptr); - return ma->ib.mr; + return ma->ib.mr; } -static -struct Allocation * ib_alloc(size_t len, size_t alignment, struct Type *m) -{ - auto *mi = (struct IB *) m->_vd; +static struct Allocation *ib_alloc(size_t len, size_t alignment, + struct Type *m) { + auto *mi = (struct IB *)m->_vd; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->type = m; - ma->length = len; - ma->alignment = alignment; + ma->type = m; + ma->length = len; + ma->alignment = alignment; - ma->parent = mi->parent->alloc(len + sizeof(struct ibv_mr *), alignment, mi->parent); - ma->address = ma->parent->address; + ma->parent = + mi->parent->alloc(len + sizeof(struct ibv_mr *), alignment, mi->parent); + ma->address = ma->parent->address; - if (!mi->pd) { - auto logger = logging.get("memory:ib"); - logger->error("Protection domain is not registered!"); - } + if (!mi->pd) { + auto logger = logging.get("memory:ib"); + logger->error("Protection domain is not registered!"); + } - ma->ib.mr = ibv_reg_mr(mi->pd, ma->address, ma->length, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); - if (!ma->ib.mr) { - mi->parent->free(ma->parent, mi->parent); - delete ma; - return nullptr; - } + ma->ib.mr = ibv_reg_mr(mi->pd, ma->address, ma->length, + IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); + if (!ma->ib.mr) { + mi->parent->free(ma->parent, mi->parent); + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int ib_free(struct Allocation *ma, struct Type *m) -{ - int ret; - auto *mi = (struct IB *) m->_vd; +static int ib_free(struct Allocation *ma, struct Type *m) { + int ret; + auto *mi = (struct IB *)m->_vd; - ibv_dereg_mr(ma->ib.mr); + ibv_dereg_mr(ma->ib.mr); - ret = mi->parent->free(ma->parent, mi->parent); - if (ret) - return ret; + ret = mi->parent->free(ma->parent, mi->parent); + if (ret) + return ret; - return 0; + return 0; } -struct Type * villas::node::memory::ib(NodeCompat *n, struct Type *parent) -{ - auto *i = n->getData(); - auto *mt = (struct Type *) malloc(sizeof(struct Type)); +struct Type *villas::node::memory::ib(NodeCompat *n, struct Type *parent) { + auto *i = n->getData(); + auto *mt = (struct Type *)malloc(sizeof(struct Type)); - mt->name = "ib"; - mt->flags = 0; - mt->alloc = ib_alloc; - mt->free = ib_free; - mt->alignment = 1; + mt->name = "ib"; + mt->flags = 0; + mt->alloc = ib_alloc; + mt->free = ib_free; + mt->alignment = 1; - mt->_vd = malloc(sizeof(struct IB)); + mt->_vd = malloc(sizeof(struct IB)); - auto *mi = (struct memory::IB *) mt->_vd; + auto *mi = (struct memory::IB *)mt->_vd; - mi->pd = i->ctx.pd; - mi->parent = parent; + mi->pd = i->ctx.pd; + mi->parent = parent; - return mt; + return mt; } diff --git a/lib/memory/managed.cpp b/lib/memory/managed.cpp index e977e502a..3a29bc4dc 100644 --- a/lib/memory/managed.cpp +++ b/lib/memory/managed.cpp @@ -5,181 +5,172 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) -{ - // Simple first-fit allocation - struct Block *first = (struct Block *) m->_vd; - struct Block *block; +static struct Allocation *managed_alloc(size_t len, size_t alignment, + struct Type *m) { + // Simple first-fit allocation + struct Block *first = (struct Block *)m->_vd; + struct Block *block; - for (block = first; block != nullptr; block = block->next) { - if (block->used) - continue; + for (block = first; block != nullptr; block = block->next) { + if (block->used) + continue; - char* cptr = (char *) block + sizeof(struct Block); - size_t avail = block->length; - uintptr_t uptr = (uintptr_t) cptr; + char *cptr = (char *)block + sizeof(struct Block); + size_t avail = block->length; + uintptr_t uptr = (uintptr_t)cptr; - /* Check alignment first; leave a gap at start of block to assure + /* Check alignment first; leave a gap at start of block to assure * alignment if necessary */ - uintptr_t rem = uptr % alignment; - uintptr_t gap = 0; - if (rem != 0) { - gap = alignment - rem; - if (gap > avail) - continue; // Next aligned address isn't in this block anymore + uintptr_t rem = uptr % alignment; + uintptr_t gap = 0; + if (rem != 0) { + gap = alignment - rem; + if (gap > avail) + continue; // Next aligned address isn't in this block anymore - cptr += gap; - avail -= gap; - } + cptr += gap; + avail -= gap; + } - if (avail >= len) { - if (gap > sizeof(struct Block)) { - /* The alignment gap is big enough to fit another block. + if (avail >= len) { + if (gap > sizeof(struct Block)) { + /* The alignment gap is big enough to fit another block. * The original block descriptor is already at the correct * position, so we just change its len and create a new block * descriptor for the actual block we're handling. */ - block->length = gap - sizeof(struct Block); - struct Block *newblock = (struct Block *) (cptr - sizeof(struct Block)); - newblock->prev = block; - newblock->next = block->next; - block->next = newblock; - newblock->used = false; - newblock->length = len; - block = newblock; - } - else { - /* The gap is too small to fit another block descriptor, so we + block->length = gap - sizeof(struct Block); + struct Block *newblock = (struct Block *)(cptr - sizeof(struct Block)); + newblock->prev = block; + newblock->next = block->next; + block->next = newblock; + newblock->used = false; + newblock->length = len; + block = newblock; + } else { + /* The gap is too small to fit another block descriptor, so we * must account for the gap length in the block length. */ - block->length = len + gap; - } + block->length = len + gap; + } - if (avail > len + sizeof(struct Block)) { - // Imperfect fit, so create another block for the remaining part - struct Block *newblock = (struct Block *) (cptr + len); - newblock->prev = block; - newblock->next = block->next; - block->next = newblock; + if (avail > len + sizeof(struct Block)) { + // Imperfect fit, so create another block for the remaining part + struct Block *newblock = (struct Block *)(cptr + len); + newblock->prev = block; + newblock->next = block->next; + block->next = newblock; - if (newblock->next) - newblock->next->prev = newblock; + if (newblock->next) + newblock->next->prev = newblock; - newblock->used = false; - newblock->length = avail - len - sizeof(struct Block); - } - else { - /* If this block was larger than the requested length, but only + newblock->used = false; + newblock->length = avail - len - sizeof(struct Block); + } else { + /* If this block was larger than the requested length, but only * by less than sizeof(struct Block), we may have wasted * memory by previous assignments to block->length. */ - block->length = avail; - } + block->length = avail; + } - block->used = true; + block->used = true; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->address = cptr; - ma->type = m; - ma->alignment = alignment; - ma->length = len; - ma->managed.block = block; + ma->address = cptr; + ma->type = m; + ma->alignment = alignment; + ma->length = len; + ma->managed.block = block; - return ma; - } - } + return ma; + } + } - // No suitable block found - return nullptr; + // No suitable block found + return nullptr; } -static -int managed_free(struct Allocation *ma, struct Type *m) -{ - struct Block *block = ma->managed.block; +static int managed_free(struct Allocation *ma, struct Type *m) { + struct Block *block = ma->managed.block; - // Try to merge it with neighbouring free blocks - if (block->prev && !block->prev->used && - block->next && !block->next->used) { - // Special case first: both previous and next block are unused - block->prev->length += block->length + block->next->length + 2 * sizeof(struct Block); - block->prev->next = block->next->next; - if (block->next->next) - block->next->next->prev = block->prev; - } - else if (block->prev && !block->prev->used) { - block->prev->length += block->length + sizeof(struct Block); - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else if (block->next && !block->next->used) { - block->length += block->next->length + sizeof(struct Block); - block->next = block->next->next; - if (block->next) - block->next->prev = block; - } - else { - // no neighbouring free block, so just mark it as free - block->used = false; - } + // Try to merge it with neighbouring free blocks + if (block->prev && !block->prev->used && block->next && !block->next->used) { + // Special case first: both previous and next block are unused + block->prev->length += + block->length + block->next->length + 2 * sizeof(struct Block); + block->prev->next = block->next->next; + if (block->next->next) + block->next->next->prev = block->prev; + } else if (block->prev && !block->prev->used) { + block->prev->length += block->length + sizeof(struct Block); + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else if (block->next && !block->next->used) { + block->length += block->next->length + sizeof(struct Block); + block->next = block->next->next; + if (block->next) + block->next->prev = block; + } else { + // no neighbouring free block, so just mark it as free + block->used = false; + } - return 0; + return 0; } -struct Type * villas::node::memory::managed(void *ptr, size_t len) -{ - struct Type *mt = (struct Type *) ptr; - struct Block *mb; - char *cptr = (char *) ptr; +struct Type *villas::node::memory::managed(void *ptr, size_t len) { + struct Type *mt = (struct Type *)ptr; + struct Block *mb; + char *cptr = (char *)ptr; - if (len < sizeof(struct Type) + sizeof(struct Block)) { - auto logger = logging.get("memory:managed"); - logger->info("Passed region is too small"); - return nullptr; - } + if (len < sizeof(struct Type) + sizeof(struct Block)) { + auto logger = logging.get("memory:managed"); + logger->info("Passed region is too small"); + return nullptr; + } - // Initialize type - mt->name = "managed"; - mt->flags = 0; - mt->alloc = managed_alloc; - mt->free = managed_free; - mt->alignment = 1; + // Initialize type + mt->name = "managed"; + mt->flags = 0; + mt->alloc = managed_alloc; + mt->free = managed_free; + mt->alignment = 1; - cptr += ALIGN(sizeof(struct Type), sizeof(void *)); + cptr += ALIGN(sizeof(struct Type), sizeof(void *)); - // Initialize first free memory block - mb = (struct Block *) cptr; - mb->prev = nullptr; - mb->next = nullptr; - mb->used = false; + // Initialize first free memory block + mb = (struct Block *)cptr; + mb->prev = nullptr; + mb->next = nullptr; + mb->used = false; - cptr += ALIGN(sizeof(struct Block), sizeof(void *)); + cptr += ALIGN(sizeof(struct Block), sizeof(void *)); - mb->length = len - (cptr - (char *) ptr); + mb->length = len - (cptr - (char *)ptr); - mt->_vd = (void *) mb; + mt->_vd = (void *)mb; - return mt; + return mt; } diff --git a/lib/memory/mmap.cpp b/lib/memory/mmap.cpp index 5b18bb57d..3023ce374 100644 --- a/lib/memory/mmap.cpp +++ b/lib/memory/mmap.cpp @@ -5,169 +5,162 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include -#include #include +#include #include // Required to allocate hugepages on Apple OS X #ifdef __MACH__ - #include +#include #endif // __MACH__ +#include #include +#include #include #include -#include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -size_t pgsz = -1; +static size_t pgsz = -1; -static -size_t hugepgsz = -1; +static size_t hugepgsz = -1; -static -Logger logger; +static Logger logger; -int villas::node::memory::mmap_init(int hugepages) -{ - logger = logging.get("memory:mmap"); +int villas::node::memory::mmap_init(int hugepages) { + logger = logging.get("memory:mmap"); - pgsz = kernel::getPageSize(); - if (pgsz < 0) - return -1; + pgsz = kernel::getPageSize(); + if (pgsz < 0) + return -1; - if (hugepages == 0) { - logger->warn("Hugepage allocator disabled."); + if (hugepages == 0) { + logger->warn("Hugepage allocator disabled."); - default_type = &mmap; - return 0; - } + default_type = &mmap; + return 0; + } - if (!utils::isPrivileged()) { - logger->warn("Running in an unprivileged environment. Hugepages are not used!"); + if (!utils::isPrivileged()) { + logger->warn( + "Running in an unprivileged environment. Hugepages are not used!"); - default_type = &mmap; - return 0; - } + default_type = &mmap; + return 0; + } - hugepgsz = kernel::getHugePageSize(); - if (hugepgsz < 0) { - logger->warn("Failed to determine hugepage size."); + hugepgsz = kernel::getHugePageSize(); + if (hugepgsz < 0) { + logger->warn("Failed to determine hugepage size."); - return -1; - } + return -1; + } #if defined(__linux__) && defined(__x86_64__) - int ret, pagecnt; + int ret, pagecnt; - pagecnt = kernel::getNrHugepages(); - if (pagecnt < hugepages) { - ret = kernel::setNrHugepages(hugepages); - if (ret) { - logger->warn("Failed to reserved hugepages. Please reserve manually by running as root:"); - logger->warn(" $ echo {} > /proc/sys/vm/nr_hugepages", hugepages); + pagecnt = kernel::getNrHugepages(); + if (pagecnt < hugepages) { + ret = kernel::setNrHugepages(hugepages); + if (ret) { + logger->warn("Failed to reserved hugepages. Please reserve manually by " + "running as root:"); + logger->warn(" $ echo {} > /proc/sys/vm/nr_hugepages", hugepages); - return -1; - } + return -1; + } - logger->debug("Increased number of reserved hugepages from {} to {}", pagecnt, hugepages); - } + logger->debug("Increased number of reserved hugepages from {} to {}", + pagecnt, hugepages); + } - default_type = &mmap_hugetlb; + default_type = &mmap_hugetlb; #else - logger->debug("Hugepages not supported on this system. Falling back to standard mmap() allocator."); + logger->debug("Hugepages not supported on this system. Falling back to " + "standard mmap() allocator."); - default_type = &mmap; + default_type = &mmap; #endif - return 0; + return 0; } // Allocate memory backed by mmaps with malloc() like interface -static -struct Allocation * mmap_alloc(size_t len, size_t alignment, struct Type *m) -{ - int flags, fd; - size_t sz; +static struct Allocation *mmap_alloc(size_t len, size_t alignment, + struct Type *m) { + int flags, fd; + size_t sz; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - if (m->flags & (int) Flags::HUGEPAGE) { + if (m->flags & (int)Flags::HUGEPAGE) { #ifdef __linux__ - flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB; + flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB; #else - flags = MAP_PRIVATE | MAP_ANONYMOUS; + flags = MAP_PRIVATE | MAP_ANONYMOUS; #endif #ifdef __MACH__ - fd = VM_FLAGS_SUPERPAGE_SIZE_2MB; + fd = VM_FLAGS_SUPERPAGE_SIZE_2MB; #else - fd = -1; + fd = -1; #endif - sz = hugepgsz; - } - else { - flags = MAP_PRIVATE | MAP_ANONYMOUS; - fd = -1; + sz = hugepgsz; + } else { + flags = MAP_PRIVATE | MAP_ANONYMOUS; + fd = -1; - sz = pgsz; - } + sz = pgsz; + } - /* We must make sure that len is a multiple of the page size + /* We must make sure that len is a multiple of the page size * * See: https://lkml.org/lkml/2014/10/22/925 */ - ma->length = ALIGN(len, sz); - ma->alignment = ALIGN(alignment, sz); - ma->type = m; + ma->length = ALIGN(len, sz); + ma->alignment = ALIGN(alignment, sz); + ma->type = m; - ma->address = ::mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); - if (ma->address == MAP_FAILED) { - delete ma; - return nullptr; - } + ma->address = + ::mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); + if (ma->address == MAP_FAILED) { + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int mmap_free(struct Allocation *ma, struct Type *m) -{ - int ret; +static int mmap_free(struct Allocation *ma, struct Type *m) { + int ret; - ret = munmap(ma->address, ma->length); - if (ret) - return ret; + ret = munmap(ma->address, ma->length); + if (ret) + return ret; - return 0; + return 0; } -struct Type memory::mmap = { - .name = "mmap", - .flags = (int) Flags::MMAP, - .alignment = 12, // 4k page - .alloc = mmap_alloc, - .free = mmap_free -}; +struct Type memory::mmap = {.name = "mmap", + .flags = (int)Flags::MMAP, + .alignment = 12, // 4k page + .alloc = mmap_alloc, + .free = mmap_free}; -struct Type memory::mmap_hugetlb = { - .name = "mmap_hugetlb", - .flags = (int) Flags::MMAP | (int) Flags::HUGEPAGE, - .alignment = 21, // 2 MiB hugepage - .alloc = mmap_alloc, - .free = mmap_free -}; +struct Type memory::mmap_hugetlb = {.name = "mmap_hugetlb", + .flags = + (int)Flags::MMAP | (int)Flags::HUGEPAGE, + .alignment = 21, // 2 MiB hugepage + .alloc = mmap_alloc, + .free = mmap_free}; diff --git a/lib/node.cpp b/lib/node.cpp index 99597b5db..483573e9a 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -5,522 +5,478 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include #include +#include #ifdef __linux__ - #include - #include +#include +#include #endif -#include +#include #include #include -#include +#include #include +#include +#include #include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #ifdef WITH_NETEM - #include - #include - #include - #include +#include +#include +#include +#include #endif // WITH_NETEM using namespace villas; using namespace villas::node; using namespace villas::utils; -Node::Node(const uuid_t &id, const std::string &name) : - logger(logging.get("node")), - sequence_init(0), - sequence(0), - in(NodeDirection::Direction::IN, this), - out(NodeDirection::Direction::OUT, this), +Node::Node(const uuid_t &id, const std::string &name) + : logger(logging.get("node")), sequence_init(0), sequence(0), + in(NodeDirection::Direction::IN, this), + out(NodeDirection::Direction::OUT, this), #ifdef __linux__ - fwmark(-1), + fwmark(-1), #endif // __linux__ #ifdef WITH_NETEM - tc_qdisc(nullptr), - tc_classifier(nullptr), + tc_qdisc(nullptr), tc_classifier(nullptr), #endif // WITH_NETEM - state(State::INITIALIZED), - enabled(true), - config(nullptr), - name_short(name), - affinity(-1), // all cores - factory(nullptr) -{ - if (uuid_is_null(id)) { - uuid_generate_random(uuid); - } else { - uuid_copy(uuid, id); - } + state(State::INITIALIZED), enabled(true), config(nullptr), + name_short(name), affinity(-1), // all cores + factory(nullptr) { + if (uuid_is_null(id)) { + uuid_generate_random(uuid); + } else { + uuid_copy(uuid, id); + } - if (!name_short.empty()) { - name_long = fmt::format(CLR_RED("{}"), name_short); - } - else if (name_short.empty()) { - name_short = ""; - name_long = CLR_RED(""); - } + if (!name_short.empty()) { + name_long = fmt::format(CLR_RED("{}"), name_short); + } else if (name_short.empty()) { + name_short = ""; + name_long = CLR_RED(""); + } } -Node::~Node() -{ +Node::~Node() { #ifdef WITH_NETEM - rtnl_qdisc_put(tc_qdisc); - rtnl_cls_put(tc_classifier); + rtnl_qdisc_put(tc_qdisc); + rtnl_cls_put(tc_classifier); #endif // WITH_NETEM - factory->instances.remove(this); + factory->instances.remove(this); } -int Node::prepare() -{ - int ret; +int Node::prepare() { + int ret; - ret = in.prepare(); - if (ret) - return ret; + ret = in.prepare(); + if (ret) + return ret; - ret = out.prepare(); - if (ret) - return ret; + ret = out.prepare(); + if (ret) + return ret; - state = State::PREPARED; + state = State::PREPARED; - return 0; + return 0; } -int Node::parse(json_t *json) -{ - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED); +int Node::parse(json_t *json) { + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED); - int ret, en = enabled, init_seq = -1; + int ret, en = enabled, init_seq = -1; - json_error_t err; - json_t *json_netem = nullptr; + json_error_t err; + json_t *json_netem = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i }", - "enabled", &en, - "initial_sequenceno", &init_seq - ); - if (ret) - return ret; + ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i }", "enabled", &en, + "initial_sequenceno", &init_seq); + if (ret) + return ret; - if (init_seq >= 0) - sequence_init = init_seq; + if (init_seq >= 0) + sequence_init = init_seq; #ifdef __linux__ - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", - "out", - "netem", &json_netem, - "fwmark", &fwmark - ); - if (ret) - return ret; + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", "out", + "netem", &json_netem, "fwmark", &fwmark); + if (ret) + return ret; #endif // __linux__ - enabled = en; + enabled = en; - if (json_netem) { + if (json_netem) { #ifdef WITH_NETEM - int enabled = 1; + int enabled = 1; - ret = json_unpack_ex(json_netem, &err, 0, "{ s?: b }", "enabled", &enabled); - if (ret) - return ret; + ret = json_unpack_ex(json_netem, &err, 0, "{ s?: b }", "enabled", &enabled); + if (ret) + return ret; - if (enabled) - kernel::tc::netem_parse(&tc_qdisc, json_netem); - else - tc_qdisc = nullptr; + if (enabled) + kernel::tc::netem_parse(&tc_qdisc, json_netem); + else + tc_qdisc = nullptr; #endif // WITH_NETEM - } + } - struct { - const char *str; - struct NodeDirection *dir; - } dirs[] = { - { "in", &in }, - { "out", &out } - }; + struct { + const char *str; + struct NodeDirection *dir; + } dirs[] = {{"in", &in}, {"out", &out}}; - const char *fields[] = { "signals", "builtin", "vectorize", "hooks" }; + const char *fields[] = {"signals", "builtin", "vectorize", "hooks"}; - for (unsigned j = 0; j < ARRAY_LEN(dirs); j++) { - json_t *json_dir = json_object_get(json, dirs[j].str); + for (unsigned j = 0; j < ARRAY_LEN(dirs); j++) { + json_t *json_dir = json_object_get(json, dirs[j].str); - // Skip if direction is unused - if (!json_dir) { - json_dir = json_pack("{ s: b }", "enabled", 0); - } + // Skip if direction is unused + if (!json_dir) { + json_dir = json_pack("{ s: b }", "enabled", 0); + } - // Copy missing fields from main node config to direction config - for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { - json_t *json_field_dir = json_object_get(json_dir, fields[i]); - json_t *json_field_node = json_object_get(json, fields[i]); + // Copy missing fields from main node config to direction config + for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { + json_t *json_field_dir = json_object_get(json_dir, fields[i]); + json_t *json_field_node = json_object_get(json, fields[i]); - if (json_field_node && !json_field_dir) - json_object_set(json_dir, fields[i], json_field_node); - } + if (json_field_node && !json_field_dir) + json_object_set(json_dir, fields[i], json_field_node); + } - ret = dirs[j].dir->parse(json_dir); - if (ret) - return ret; - } + ret = dirs[j].dir->parse(json_dir); + if (ret) + return ret; + } - config = json; + config = json; - return 0; + return 0; } -int Node::check() -{ - assert(state == State::CHECKED || - state == State::PARSED || - state == State::INITIALIZED); +int Node::check() { + assert(state == State::CHECKED || state == State::PARSED || + state == State::INITIALIZED); - in.check(); - out.check(); + in.check(); + out.check(); - state = State::CHECKED; + state = State::CHECKED; - return 0; + return 0; } -int Node::start() -{ - int ret; +int Node::start() { + int ret; - assert(state == State::PREPARED); + assert(state == State::PREPARED); - logger->info("Starting node {}", getNameFull()); + logger->info("Starting node {}", getNameFull()); - ret = in.start(); - if (ret) - return ret; + ret = in.start(); + if (ret) + return ret; - ret = out.start(); - if (ret) - return ret; + ret = out.start(); + if (ret) + return ret; #ifdef __linux__ - // Set fwmark for outgoing packets if netem is enabled for this node - if (fwmark >= 0) { - for (int fd : getNetemFDs()) { - ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); - if (ret) - throw RuntimeError("Failed to set FW mark for outgoing packets"); - else - logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); - } - } + // Set fwmark for outgoing packets if netem is enabled for this node + if (fwmark >= 0) { + for (int fd : getNetemFDs()) { + ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); + if (ret) + throw RuntimeError("Failed to set FW mark for outgoing packets"); + else + logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); + } + } #endif // __linux__ - state = State::STARTED; - sequence = sequence_init; + state = State::STARTED; + sequence = sequence_init; - return 0; + return 0; } -int Node::stop() -{ - int ret; +int Node::stop() { + int ret; - if (state != State::STOPPING && - state != State::STARTED && - state != State::CONNECTED && - state != State::PENDING_CONNECT) - return 0; + if (state != State::STOPPING && state != State::STARTED && + state != State::CONNECTED && state != State::PENDING_CONNECT) + return 0; - logger->info("Stopping node"); - setState(State::STOPPING); + logger->info("Stopping node"); + setState(State::STOPPING); - ret = in.stop(); - if (ret) - return ret; + ret = in.stop(); + if (ret) + return ret; - ret = out.stop(); - if (ret) - return ret; + ret = out.stop(); + if (ret) + return ret; - return 0; + return 0; } -int Node::restart() -{ - int ret; +int Node::restart() { + int ret; - assert(state == State::STARTED); + assert(state == State::STARTED); - logger->info("Restarting node"); + logger->info("Restarting node"); - ret = stop(); - if (ret) - return ret; + ret = stop(); + if (ret) + return ret; - ret = start(); - if (ret) - return ret; + ret = start(); + if (ret) + return ret; - return 0; + return 0; } -int Node::read(struct Sample * smps[], unsigned cnt) -{ - int toread, readd, nread = 0; - unsigned vect; +int Node::read(struct Sample *smps[], unsigned cnt) { + int toread, readd, nread = 0; + unsigned vect; - if (state == State::PAUSED || state == State::PENDING_CONNECT) - return 0; - else if (state != State::STARTED && state != State::CONNECTED) - return -1; + if (state == State::PAUSED || state == State::PENDING_CONNECT) + return 0; + else if (state != State::STARTED && state != State::CONNECTED) + return -1; - vect = factory->getVectorize(); - if (!vect) - vect = cnt; + vect = factory->getVectorize(); + if (!vect) + vect = cnt; - while (cnt - nread > 0) { - toread = MIN(cnt - nread, vect); - readd = _read(&smps[nread], toread); - if (readd < 0) - return readd; + while (cnt - nread > 0) { + toread = MIN(cnt - nread, vect); + readd = _read(&smps[nread], toread); + if (readd < 0) + return readd; - nread += readd; - } + nread += readd; + } #ifdef WITH_HOOKS - // Run read hooks - int rread = in.hooks.process(smps, nread); - if (rread < 0) - return rread; + // Run read hooks + int rread = in.hooks.process(smps, nread); + if (rread < 0) + return rread; - int skipped = nread - rread; - if (skipped > 0) { - if (stats != nullptr) - stats->update(Stats::Metric::SMPS_SKIPPED, skipped); + int skipped = nread - rread; + if (skipped > 0) { + if (stats != nullptr) + stats->update(Stats::Metric::SMPS_SKIPPED, skipped); - logger->debug("Received {} samples of which {} have been skipped", nread, skipped); - } - else - logger->debug("Received {} samples", nread); + logger->debug("Received {} samples of which {} have been skipped", nread, + skipped); + } else + logger->debug("Received {} samples", nread); - return rread; + return rread; #else - logger->debug("Received {} samples", nread); + logger->debug("Received {} samples", nread); - return nread; + return nread; #endif // WITH_HOOKS } -int Node::write(struct Sample * smps[], unsigned cnt) -{ - int tosend, sent, nsent = 0; - unsigned vect; +int Node::write(struct Sample *smps[], unsigned cnt) { + int tosend, sent, nsent = 0; + unsigned vect; - if (state == State::PAUSED || state == State::PENDING_CONNECT) - return 0; - else if (state != State::STARTED && state != State::CONNECTED) - return -1; + if (state == State::PAUSED || state == State::PENDING_CONNECT) + return 0; + else if (state != State::STARTED && state != State::CONNECTED) + return -1; #ifdef WITH_HOOKS - // Run write hooks - cnt = out.hooks.process(smps, cnt); - if (cnt <= 0) - return cnt; + // Run write hooks + cnt = out.hooks.process(smps, cnt); + if (cnt <= 0) + return cnt; #endif // WITH_HOOKS - vect = getFactory()->getVectorize(); - if (!vect) - vect = cnt; + vect = getFactory()->getVectorize(); + if (!vect) + vect = cnt; - while (cnt - nsent > 0) { - tosend = MIN(cnt - nsent, vect); - sent = _write(&smps[nsent], tosend); - if (sent < 0) - return sent; + while (cnt - nsent > 0) { + tosend = MIN(cnt - nsent, vect); + sent = _write(&smps[nsent], tosend); + if (sent < 0) + return sent; - nsent += sent; - logger->debug("Sent {} samples", sent); - } + nsent += sent; + logger->debug("Sent {} samples", sent); + } - return nsent; + return nsent; } -const std::string & Node::getNameFull() -{ - if (name_full.empty()) { - name_full = fmt::format("{}: uuid={}, #in.signals={}/{}, #in.hooks={}, #out.hooks={}, in.vectorize={}, out.vectorize={}", - getName(), uuid::toString(uuid).c_str(), - getInputSignals(false)->size(), - getInputSignals(true)->size(), - in.hooks.size(), out.hooks.size(), - in.vectorize, out.vectorize - ); +const std::string &Node::getNameFull() { + if (name_full.empty()) { + name_full = fmt::format("{}: uuid={}, #in.signals={}/{}, #in.hooks={}, " + "#out.hooks={}, in.vectorize={}, out.vectorize={}", + getName(), uuid::toString(uuid).c_str(), + getInputSignals(false)->size(), + getInputSignals(true)->size(), in.hooks.size(), + out.hooks.size(), in.vectorize, out.vectorize); #ifdef WITH_NETEM - name_full += fmt::format(", out.netem={}", tc_qdisc ? "yes" : "no"); + name_full += fmt::format(", out.netem={}", tc_qdisc ? "yes" : "no"); - if (tc_qdisc) - name_full += fmt::format(", fwmark={}", fwmark); + if (tc_qdisc) + name_full += fmt::format(", fwmark={}", fwmark); #endif // WITH_NETEM - if (out.path) { - name_full += fmt::format(", #out.signals={}/{}", - getOutputSignals(false) ? getOutputSignals(false)->size() : 0, - getOutputSignals() ? getOutputSignals()->size() : 0); + if (out.path) { + name_full += fmt::format( + ", #out.signals={}/{}", + getOutputSignals(false) ? getOutputSignals(false)->size() : 0, + getOutputSignals() ? getOutputSignals()->size() : 0); - name_full += fmt::format(", out.path={}", out.path->toString()); - } + name_full += fmt::format(", out.path={}", out.path->toString()); + } - // Append node-type specific details - auto details = getDetails(); - if (!details.empty()) - name_full += fmt::format(", {}", details); - } + // Append node-type specific details + auto details = getDetails(); + if (!details.empty()) + name_full += fmt::format(", {}", details); + } - return name_full; + return name_full; } -SignalList::Ptr Node::getInputSignals(bool after_hooks) const -{ - return in.getSignals(after_hooks); +SignalList::Ptr Node::getInputSignals(bool after_hooks) const { + return in.getSignals(after_hooks); } -SignalList::Ptr Node::getOutputSignals(bool after_hooks) const -{ - if (out.path) - return out.path->getOutputSignals(); +SignalList::Ptr Node::getOutputSignals(bool after_hooks) const { + if (out.path) + return out.path->getOutputSignals(); - return nullptr; + return nullptr; } -unsigned Node::getInputSignalsMaxCount() const -{ - return in.getSignalsMaxCount(); +unsigned Node::getInputSignalsMaxCount() const { + return in.getSignalsMaxCount(); } -unsigned Node::getOutputSignalsMaxCount() const -{ - if (out.path) - return out.path->getOutputSignalsMaxCount(); +unsigned Node::getOutputSignalsMaxCount() const { + if (out.path) + return out.path->getOutputSignalsMaxCount(); - return 0; + return 0; } -bool Node::isValidName(const std::string &name) -{ - std::regex re(RE_NODE_NAME); +bool Node::isValidName(const std::string &name) { + std::regex re(RE_NODE_NAME); - return std::regex_match(name, re); + return std::regex_match(name, re); } -json_t * Node::toJson() const -{ - json_t *json_node; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; +json_t *Node::toJson() const { + json_t *json_node; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - json_signals_in = getInputSignals()->toJson(); + json_signals_in = getInputSignals()->toJson(); - auto output_signals = getOutputSignals(); - if (output_signals) - json_signals_out = output_signals->toJson(); + auto output_signals = getOutputSignals(); + if (output_signals) + json_signals_out = output_signals->toJson(); - json_node = json_pack("{ s: s, s: s, s: s, s: i, s: { s: i, s: o? }, s: { s: i, s: o? } }", - "name", getNameShort().c_str(), - "uuid", uuid::toString(uuid).c_str(), - "state", stateToString(state).c_str(), - "affinity", affinity, - "in", - "vectorize", in.vectorize, - "signals", json_signals_in, - "out", - "vectorize", out.vectorize, - "signals", json_signals_out - ); + json_node = json_pack( + "{ s: s, s: s, s: s, s: i, s: { s: i, s: o? }, s: { s: i, s: o? } }", + "name", getNameShort().c_str(), "uuid", uuid::toString(uuid).c_str(), + "state", stateToString(state).c_str(), "affinity", affinity, "in", + "vectorize", in.vectorize, "signals", json_signals_in, "out", "vectorize", + out.vectorize, "signals", json_signals_out); - if (stats) - json_object_set_new(json_node, "stats", stats->toJson()); + if (stats) + json_object_set_new(json_node, "stats", stats->toJson()); - auto *status = _readStatus(); - if (status) - json_object_set_new(json_node, "status", status); + auto *status = _readStatus(); + if (status) + json_object_set_new(json_node, "status", status); - /* Add all additional fields of node here. + /* Add all additional fields of node here. * This can be used for metadata */ - json_object_update(json_node, config); + json_object_update(json_node, config); - return json_node; + return json_node; } -void Node::swapSignals() { - SWAP(in.signals, out.signals); +void Node::swapSignals() { SWAP(in.signals, out.signals); } + +Node *NodeFactory::make(json_t *json, const uuid_t &id, + const std::string &name) { + int ret; + std::string type; + Node *n; + + if (json_is_object(json)) + throw ConfigError(json, "node-config-node", + "Node configuration must be an object"); + + json_t *json_type = json_object_get(json, "type"); + + type = json_string_value(json_type); + + n = NodeFactory::make(type, id, name); + if (!n) + return nullptr; + + ret = n->parse(json); + if (ret) { + delete n; + return nullptr; + } + + return n; } -Node * NodeFactory::make(json_t *json, const uuid_t &id, const std::string &name) -{ - int ret; - std::string type; - Node *n; +Node *NodeFactory::make(const std::string &type, const uuid_t &id, + const std::string &name) { + NodeFactory *nf = plugin::registry->lookup(type); + if (!nf) + throw RuntimeError("Unknown node-type: {}", type); - if (json_is_object(json)) - throw ConfigError(json, "node-config-node", "Node configuration must be an object"); - - json_t *json_type = json_object_get(json, "type"); - - type = json_string_value(json_type); - - n = NodeFactory::make(type, id, name); - if (!n) - return nullptr; - - ret = n->parse(json); - if (ret) { - delete n; - return nullptr; - } - - return n; + return nf->make(id, name); } -Node * NodeFactory::make(const std::string &type, const uuid_t &id, const std::string &name) -{ - NodeFactory *nf = plugin::registry->lookup(type); - if (!nf) - throw RuntimeError("Unknown node-type: {}", type); +int NodeFactory::start(SuperNode *sn) { + getLogger()->info("Initialized node type which is used by {} nodes", + instances.size()); - return nf->make(id, name); + state = State::STARTED; + + return 0; } -int NodeFactory::start(SuperNode *sn) -{ - getLogger()->info("Initialized node type which is used by {} nodes", instances.size()); +int NodeFactory::stop() { + getLogger()->info("De-initialized node type"); - state = State::STARTED; + state = State::STOPPED; - return 0; -} - -int NodeFactory::stop() -{ - getLogger()->info("De-initialized node type"); - - state = State::STOPPED; - - return 0; + return 0; } diff --git a/lib/node_capi.cpp b/lib/node_capi.cpp index a0fcea568..92ee338e5 100644 --- a/lib/node_capi.cpp +++ b/lib/node_capi.cpp @@ -8,216 +8,183 @@ #include extern "C" { - #include +#include } using namespace villas; using namespace villas::node; -vnode * node_new(const char *id_str, const char *json_str) -{ - json_error_t err; - uuid_t id; - uuid_parse(id_str, id); - auto *json = json_loads(json_str, 0, &err); - return (vnode *) NodeFactory::make(json, id); +vnode *node_new(const char *id_str, const char *json_str) { + json_error_t err; + uuid_t id; + uuid_parse(id_str, id); + auto *json = json_loads(json_str, 0, &err); + return (vnode *)NodeFactory::make(json, id); } -int node_prepare(vnode *n) -{ - auto *nc = (Node *) n; - return nc->prepare(); +int node_prepare(vnode *n) { + auto *nc = (Node *)n; + return nc->prepare(); } -int node_check(vnode *n) -{ - auto *nc = (Node *) n; - return nc->check(); +int node_check(vnode *n) { + auto *nc = (Node *)n; + return nc->check(); } -int node_start(vnode *n) -{ - auto *nc = (Node *) n; - return nc->start(); +int node_start(vnode *n) { + auto *nc = (Node *)n; + return nc->start(); } -int node_stop(vnode *n) -{ - auto *nc = (Node *) n; - return nc->stop(); +int node_stop(vnode *n) { + auto *nc = (Node *)n; + return nc->stop(); } -int node_pause(vnode *n) -{ - auto *nc = (Node *) n; - return nc->pause(); +int node_pause(vnode *n) { + auto *nc = (Node *)n; + return nc->pause(); } -int node_resume(vnode *n) -{ - auto *nc = (Node *) n; - return nc->resume(); +int node_resume(vnode *n) { + auto *nc = (Node *)n; + return nc->resume(); } -int node_restart(vnode *n) -{ - auto *nc = (Node *) n; - return nc->restart(); +int node_restart(vnode *n) { + auto *nc = (Node *)n; + return nc->restart(); } -int node_destroy(vnode *n) -{ - auto *nc = (Node *) n; - nc->~Node(); - return 0; +int node_destroy(vnode *n) { + auto *nc = (Node *)n; + nc->~Node(); + return 0; } -const char * node_name(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getName().c_str(); +const char *node_name(vnode *n) { + auto *nc = (Node *)n; + return nc->getName().c_str(); } -const char * node_name_short(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getNameShort().c_str(); +const char *node_name_short(vnode *n) { + auto *nc = (Node *)n; + return nc->getNameShort().c_str(); } -const char * node_name_full(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getNameFull().c_str(); +const char *node_name_full(vnode *n) { + auto *nc = (Node *)n; + return nc->getNameFull().c_str(); } -const char * node_details(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getDetails().c_str(); +const char *node_details(vnode *n) { + auto *nc = (Node *)n; + return nc->getDetails().c_str(); } -unsigned node_input_signals_max_cnt(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getInputSignalsMaxCount(); +unsigned node_input_signals_max_cnt(vnode *n) { + auto *nc = (Node *)n; + return nc->getInputSignalsMaxCount(); } -unsigned node_output_signals_max_cnt(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getOutputSignalsMaxCount(); +unsigned node_output_signals_max_cnt(vnode *n) { + auto *nc = (Node *)n; + return nc->getOutputSignalsMaxCount(); } -int node_reverse(vnode *n) -{ - auto *nc = (Node *) n; - return nc->reverse(); +int node_reverse(vnode *n) { + auto *nc = (Node *)n; + return nc->reverse(); } -int node_read(vnode *n, vsample **smps, unsigned cnt) -{ - auto *nc = (Node *) n; - return nc->read((villas::node::Sample**) smps, cnt); +int node_read(vnode *n, vsample **smps, unsigned cnt) { + auto *nc = (Node *)n; + return nc->read((villas::node::Sample **)smps, cnt); } -int node_write(vnode *n, vsample **smps, unsigned cnt) -{ - auto *nc = (Node *) n; - return nc->write((villas::node::Sample**) smps, cnt); +int node_write(vnode *n, vsample **smps, unsigned cnt) { + auto *nc = (Node *)n; + return nc->write((villas::node::Sample **)smps, cnt); } -int node_poll_fds(vnode *n, int fds[]) -{ - auto *nc = (Node *) n; - auto l = nc->getPollFDs(); +int node_poll_fds(vnode *n, int fds[]) { + auto *nc = (Node *)n; + auto l = nc->getPollFDs(); - for (unsigned i = 0; i < l.size() && i < 16; i++) - fds[i] = l[i]; + for (unsigned i = 0; i < l.size() && i < 16; i++) + fds[i] = l[i]; - return l.size(); + return l.size(); } -int node_netem_fds(vnode *n, int fds[]) -{ - auto *nc = (Node *) n; - auto l = nc->getNetemFDs(); +int node_netem_fds(vnode *n, int fds[]) { + auto *nc = (Node *)n; + auto l = nc->getNetemFDs(); - for (unsigned i = 0; i < l.size() && i < 16; i++) - fds[i] = l[i]; + for (unsigned i = 0; i < l.size() && i < 16; i++) + fds[i] = l[i]; - return l.size(); + return l.size(); } -bool node_is_valid_name(const char *name) -{ - return Node::isValidName(name); +bool node_is_valid_name(const char *name) { return Node::isValidName(name); } + +bool node_is_enabled(const vnode *n) { + auto *nc = (Node *)n; + return nc->isEnabled(); } -bool node_is_enabled(const vnode *n) -{ - auto *nc = (Node *) n; - return nc->isEnabled(); +json_t *node_to_json(const vnode *n) { + auto *nc = (Node *)n; + return nc->toJson(); } -json_t * node_to_json(const vnode *n) -{ - auto *nc = (Node *) n; - return nc->toJson(); +const char *node_to_json_str(vnode *n) { + auto json = node_to_json(n); + return json_dumps(json, 0); } -const char * node_to_json_str(vnode *n) -{ - auto json = node_to_json(n); - return json_dumps(json, 0); +vsample *sample_alloc(unsigned len) { return (vsample *)sample_alloc_mem(len); } + +unsigned sample_length(vsample *s) { + auto *smp = (Sample *)s; + return smp->length; } -vsample * sample_alloc(unsigned len) -{ - return (vsample *) sample_alloc_mem(len); +vsample *sample_pack(unsigned seq, struct timespec *ts_origin, + struct timespec *ts_received, unsigned len, + double *values) { + auto *smp = sample_alloc_mem(len); + + smp->sequence = seq; + smp->ts.origin = *ts_origin; + smp->ts.received = *ts_received; + smp->length = len; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN; + + memcpy((double *)smp->data, values, sizeof(double) * len); + + return (vsample *)smp; } -unsigned sample_length(vsample *s) -{ - auto *smp = (Sample *) s; - return smp->length; +void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, + struct timespec *ts_received, int *flags, unsigned *len, + double *values) { + auto *smp = (Sample *)s; + + *seq = smp->sequence; + + *ts_origin = smp->ts.origin; + *ts_received = smp->ts.received; + + *flags = smp->flags; + *len = smp->length; + + memcpy(values, (double *)smp->data, sizeof(double) * *len); } -vsample * sample_pack(unsigned seq, struct timespec *ts_origin, struct timespec *ts_received, unsigned len, double *values) -{ - auto *smp = sample_alloc_mem(len); +void sample_decref(vsample *smp) { sample_decref((Sample *)smp); } - smp->sequence = seq; - smp->ts.origin = *ts_origin; - smp->ts.received = *ts_received; - smp->length = len; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN; - - memcpy((double *) smp->data, values, sizeof(double) * len); - - return (vsample *) smp; -} - -void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, struct timespec *ts_received, int *flags, unsigned *len, double *values) -{ - auto *smp = (Sample *) s; - - *seq = smp->sequence; - - *ts_origin = smp->ts.origin; - *ts_received = smp->ts.received; - - *flags =smp->flags; - *len = smp->length; - - memcpy(values, (double *) smp->data, sizeof(double) * *len); -} - -void sample_decref(vsample *smp) -{ - sample_decref((Sample *) smp); -} - -int memory_init(int hugepages) -{ - return memory::init(hugepages); -} +int memory_init(int hugepages) { return memory::init(hugepages); } diff --git a/lib/node_compat.cpp b/lib/node_compat.cpp index 588ec531b..589fde594 100644 --- a/lib/node_compat.cpp +++ b/lib/node_compat.cpp @@ -5,318 +5,255 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include using namespace villas; using namespace villas::node; -NodeCompat::NodeCompat(struct NodeCompatType *vt, const uuid_t &id, const std::string &name) : - Node(id, name), - _vt(vt) -{ - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); +NodeCompat::NodeCompat(struct NodeCompatType *vt, const uuid_t &id, + const std::string &name) + : Node(id, name), _vt(vt) { + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memset(_vd, 0, _vt->size); + memset(_vd, 0, _vt->size); - int ret = _vt->init - ? _vt->init(this) - : 0; - if (ret) - throw RuntimeError("Failed to initialize node"); + int ret = _vt->init ? _vt->init(this) : 0; + if (ret) + throw RuntimeError("Failed to initialize node"); } -NodeCompat::NodeCompat(const NodeCompat& n) : - Node(n) -{ - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); +NodeCompat::NodeCompat(const NodeCompat &n) : Node(n) { + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memcpy(_vd, n._vd, _vt->size); + memcpy(_vd, n._vd, _vt->size); - int ret = _vt->init - ? _vt->init(this) - : 0; - if (ret) - throw RuntimeError("Failed to initialize node"); + int ret = _vt->init ? _vt->init(this) : 0; + if (ret) + throw RuntimeError("Failed to initialize node"); } -NodeCompat & NodeCompat::operator=(const NodeCompat& n) -{ - if (&n != this) { - *this = n; +NodeCompat &NodeCompat::operator=(const NodeCompat &n) { + if (&n != this) { + *this = n; - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memcpy(_vd, n._vd, _vt->size); - } + memcpy(_vd, n._vd, _vt->size); + } - return *this; + return *this; } -NodeCompat::~NodeCompat() -{ - assert(state == State::STOPPED || - state == State::PREPARED || - state == State::CHECKED || - state == State::PARSED || - state == State::INITIALIZED); +NodeCompat::~NodeCompat() { + assert(state == State::STOPPED || state == State::PREPARED || + state == State::CHECKED || state == State::PARSED || + state == State::INITIALIZED); - int ret __attribute__((unused)); - ret = _vt->destroy - ? _vt->destroy(this) - : 0; + int ret __attribute__((unused)); + ret = _vt->destroy ? _vt->destroy(this) : 0; - delete[] (char *) _vd; + delete[] (char *)_vd; } -int NodeCompat::prepare() -{ - assert(state == State::CHECKED); +int NodeCompat::prepare() { + assert(state == State::CHECKED); - int ret = _vt->prepare - ? _vt->prepare(this) - : 0; - if (ret) - return ret; + int ret = _vt->prepare ? _vt->prepare(this) : 0; + if (ret) + return ret; - return Node::prepare(); + return Node::prepare(); } -int NodeCompat::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int NodeCompat::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - ret = _vt->parse - ? _vt->parse(this, json) - : 0; - if (!ret) - state = State::PARSED; + ret = _vt->parse ? _vt->parse(this, json) : 0; + if (!ret) + state = State::PARSED; - return ret; + return ret; } -int NodeCompat::check() -{ - int ret = Node::check(); - if (ret) - return ret; +int NodeCompat::check() { + int ret = Node::check(); + if (ret) + return ret; - ret = _vt->check - ? _vt->check(this) - : 0; - if (!ret) - state = State::CHECKED; + ret = _vt->check ? _vt->check(this) : 0; + if (!ret) + state = State::CHECKED; - return ret; + return ret; } -int NodeCompat::pause() -{ - int ret; +int NodeCompat::pause() { + int ret; - ret = Node::pause(); - if (ret) - return ret; + ret = Node::pause(); + if (ret) + return ret; - ret = _vt->pause - ? _vt->pause(this) - : 0; - if (!ret) - state = State::PAUSED; + ret = _vt->pause ? _vt->pause(this) : 0; + if (!ret) + state = State::PAUSED; - return ret; + return ret; } -int NodeCompat::resume() -{ - int ret; +int NodeCompat::resume() { + int ret; - ret = Node::resume(); - if (ret) - return ret; + ret = Node::resume(); + if (ret) + return ret; - ret = _vt->resume - ? _vt->resume(this) - : 0; - if (!ret) - state = State::STARTED; + ret = _vt->resume ? _vt->resume(this) : 0; + if (!ret) + state = State::STARTED; - return ret; + return ret; } -int NodeCompat::restart() -{ - return _vt->restart - ? _vt->restart(this) - : Node::restart(); +int NodeCompat::restart() { + return _vt->restart ? _vt->restart(this) : Node::restart(); } -int NodeCompat::_read(struct Sample * smps[], unsigned cnt) -{ - return _vt->read - ? _vt->read(this, smps, cnt) - : -1; +int NodeCompat::_read(struct Sample *smps[], unsigned cnt) { + return _vt->read ? _vt->read(this, smps, cnt) : -1; } -int NodeCompat::_write(struct Sample * smps[], unsigned cnt) -{ - return _vt->write - ? _vt->write(this, smps, cnt) - : -1; +int NodeCompat::_write(struct Sample *smps[], unsigned cnt) { + return _vt->write ? _vt->write(this, smps, cnt) : -1; } /* Reverse local and remote socket address. * * @see node_type::reverse */ -int NodeCompat::reverse() -{ - return _vt->reverse - ? _vt->reverse(this) - : -1; +int NodeCompat::reverse() { return _vt->reverse ? _vt->reverse(this) : -1; } + +std::vector NodeCompat::getPollFDs() { + if (_vt->poll_fds) { + int ret, fds[16]; + + ret = _vt->poll_fds(this, fds); + if (ret < 0) + return {}; + + return std::vector(fds, fds + ret); + } + + return {}; } -std::vector NodeCompat::getPollFDs() -{ - if (_vt->poll_fds) { - int ret, fds[16]; +std::vector NodeCompat::getNetemFDs() { + if (_vt->netem_fds) { + int ret, fds[16]; - ret = _vt->poll_fds(this, fds); - if (ret < 0) - return {}; + ret = _vt->netem_fds(this, fds); + if (ret < 0) + return {}; - return std::vector(fds, fds+ret); - } + return std::vector(fds, fds + ret); + } - return {}; + return {}; } -std::vector NodeCompat::getNetemFDs() -{ - if (_vt->netem_fds) { - int ret, fds[16]; - - ret = _vt->netem_fds(this, fds); - if (ret < 0) - return {}; - - return std::vector(fds, fds+ret); - } - - return {}; +struct memory::Type *NodeCompat::getMemoryType() { + return _vt->memory_type ? _vt->memory_type(this, memory::default_type) + : memory::default_type; } -struct memory::Type * NodeCompat::getMemoryType() -{ - return _vt->memory_type - ? _vt->memory_type(this, memory::default_type) - : memory::default_type; +int NodeCompat::start() { + assert(state == State::PREPARED || state == State::PAUSED); + + int ret = _vt->start ? _vt->start(this) : 0; + if (ret) + return ret; + + ret = Node::start(); + if (!ret) + state = State::STARTED; + + return ret; } -int NodeCompat::start() -{ - assert(state == State::PREPARED || - state == State::PAUSED); +int NodeCompat::stop() { + assert(state == State::STARTED || state == State::PAUSED || + state == State::STOPPING); - int ret = _vt->start - ? _vt->start(this) - : 0; - if (ret) - return ret; + int ret = Node::stop(); + if (ret) + return ret; - ret = Node::start(); - if (!ret) - state = State::STARTED; + ret = _vt->stop ? _vt->stop(this) : 0; + if (!ret) + state = State::STOPPED; - return ret; + return ret; } -int NodeCompat::stop() -{ - assert(state == State::STARTED || - state == State::PAUSED || - state == State::STOPPING); +const std::string &NodeCompat::getDetails() { + if (_vt->print && _details.empty()) { + auto *d = _vt->print(this); + _details = std::string(d); + free(d); + } - int ret = Node::stop(); - if (ret) - return ret; - - ret = _vt->stop - ? _vt->stop(this) : - 0; - if (!ret) - state = State::STOPPED; - - return ret; + return _details; } -const std::string & NodeCompat::getDetails() -{ - if (_vt->print && _details.empty()) { - auto *d = _vt->print(this); - _details = std::string(d); - free(d); - } +Node *NodeCompatFactory::make(const uuid_t &id, const std::string &name) { + auto *n = new NodeCompat(_vt, id, name); - return _details; + init(n); + + return n; } -Node * NodeCompatFactory::make(const uuid_t &id, const std::string &name) -{ - auto *n = new NodeCompat(_vt, id, name); +int NodeCompatFactory::start(SuperNode *sn) { + assert(state == State::INITIALIZED); - init(n); + int ret = _vt->type.start ? _vt->type.start(sn) : 0; + if (ret) + return ret; - return n; + return NodeFactory::start(sn); } -int NodeCompatFactory::start(SuperNode *sn) -{ - assert(state == State::INITIALIZED); +int NodeCompatFactory::stop() { + assert(state == State::STARTED); - int ret = _vt->type.start - ? _vt->type.start(sn) - : 0; - if (ret) - return ret; + int ret = _vt->type.stop ? _vt->type.stop() : 0; + if (ret) + return ret; - return NodeFactory::start(sn); + return NodeFactory::stop(); } -int NodeCompatFactory::stop() -{ - assert(state == State::STARTED); +int NodeCompatFactory::getFlags() const { + int flags = _vt->flags; - int ret = _vt->type.stop - ? _vt->type.stop() - : 0; - if (ret) - return ret; + if (_vt->read) + flags |= (int)NodeFactory::Flags::SUPPORTS_READ; - return NodeFactory::stop(); -} - -int NodeCompatFactory::getFlags() const -{ - int flags = _vt->flags; - - if (_vt->read) - flags |= (int) NodeFactory::Flags::SUPPORTS_READ; - - if (_vt->write) - flags |= (int) NodeFactory::Flags::SUPPORTS_WRITE; - - if (_vt->poll_fds) - flags |= (int) NodeFactory::Flags::SUPPORTS_POLL; - - return flags; + if (_vt->write) + flags |= (int)NodeFactory::Flags::SUPPORTS_WRITE; + + if (_vt->poll_fds) + flags |= (int)NodeFactory::Flags::SUPPORTS_POLL; + + return flags; } diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index a3c74a887..39088b014 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -6,179 +6,165 @@ */ #include -#include +#include #include #include #include -#include -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) : - direction(dir), - path(nullptr), - node(n), - enabled(1), - builtin(1), - vectorize(1), - config(nullptr) -{ } +NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) + : direction(dir), path(nullptr), node(n), enabled(1), builtin(1), + vectorize(1), config(nullptr) {} -int NodeDirection::parse(json_t *json) -{ - int ret; +int NodeDirection::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_hooks = nullptr; - json_t *json_signals = nullptr; + json_error_t err; + json_t *json_hooks = nullptr; + json_t *json_signals = nullptr; - config = json; + config = json; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: i, s?: b, s?: b }", - "hooks", &json_hooks, - "signals", &json_signals, - "vectorize", &vectorize, - "builtin", &builtin, - "enabled", &enabled - ); - if (ret) - throw ConfigError(json, err, "node-config-node-in"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: i, s?: b, s?: b }", + "hooks", &json_hooks, "signals", &json_signals, + "vectorize", &vectorize, "builtin", &builtin, "enabled", + &enabled); + if (ret) + throw ConfigError(json, err, "node-config-node-in"); - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::PROVIDES_SIGNALS) { - // Do nothing.. Node-type will provide signals - signals = std::make_shared(); - if (!signals) - throw MemoryAllocationError(); - } - else if (json_is_object(json_signals) || json_is_array(json_signals)) { - signals = std::make_shared(); - if (!signals) - throw MemoryAllocationError(); + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::PROVIDES_SIGNALS) { + // Do nothing.. Node-type will provide signals + signals = std::make_shared(); + if (!signals) + throw MemoryAllocationError(); + } else if (json_is_object(json_signals) || json_is_array(json_signals)) { + signals = std::make_shared(); + if (!signals) + throw MemoryAllocationError(); - if (json_is_object(json_signals)) { - json_t *json_name, *json_signal = json_signals; - int count; + if (json_is_object(json_signals)) { + json_t *json_name, *json_signal = json_signals; + int count; - ret = json_unpack_ex(json_signal, &err, 0, "{ s: i }", - "count", &count - ); - if (ret) - throw ConfigError(json_signals, "node-config-node-signals", "Invalid signal definition"); + ret = json_unpack_ex(json_signal, &err, 0, "{ s: i }", "count", &count); + if (ret) + throw ConfigError(json_signals, "node-config-node-signals", + "Invalid signal definition"); - json_signals = json_array(); - for (int i = 0; i < count; i++) { - json_t *json_signal_copy = json_copy(json_signal); + json_signals = json_array(); + for (int i = 0; i < count; i++) { + json_t *json_signal_copy = json_copy(json_signal); - json_object_del(json_signal, "count"); + json_object_del(json_signal, "count"); - // Append signal index - json_name = json_object_get(json_signal_copy, "name"); - if (json_name) { - const char *name = json_string_value(json_name); - char *name_new; + // Append signal index + json_name = json_object_get(json_signal_copy, "name"); + if (json_name) { + const char *name = json_string_value(json_name); + char *name_new; - int ret __attribute__((unused)); - ret = asprintf(&name_new, "%s%d", name, i); + int ret __attribute__((unused)); + ret = asprintf(&name_new, "%s%d", name, i); - json_string_set(json_name, name_new); - } + json_string_set(json_name, name_new); + } - json_array_append_new(json_signals, json_signal_copy); - } - json_object_set_new(json, "signals", json_signals); - } + json_array_append_new(json_signals, json_signal_copy); + } + json_object_set_new(json, "signals", json_signals); + } - ret = signals->parse(json_signals); - if (ret) - throw ConfigError(json_signals, "node-config-node-signals", "Failed to parse signal definition"); - } - else if (json_is_string(json_signals)) { - const char *dt = json_string_value(json_signals); + ret = signals->parse(json_signals); + if (ret) + throw ConfigError(json_signals, "node-config-node-signals", + "Failed to parse signal definition"); + } else if (json_is_string(json_signals)) { + const char *dt = json_string_value(json_signals); - signals = std::make_shared(dt); - if (!signals) - return -1; - } - else { - signals = std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); - if (!signals) - return -1; - } + signals = std::make_shared(dt); + if (!signals) + return -1; + } else { + signals = + std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); + if (!signals) + return -1; + } #ifdef WITH_HOOKS - if (json_hooks) { - int m = direction == NodeDirection::Direction::OUT - ? (int) Hook::Flags::NODE_WRITE - : (int) Hook::Flags::NODE_READ; + if (json_hooks) { + int m = direction == NodeDirection::Direction::OUT + ? (int)Hook::Flags::NODE_WRITE + : (int)Hook::Flags::NODE_READ; - hooks.parse(json_hooks, m, nullptr, node); - } + hooks.parse(json_hooks, m, nullptr, node); + } #endif // WITH_HOOKS - return 0; + return 0; } -void NodeDirection::check() -{ - if (vectorize <= 0) - throw RuntimeError("Invalid setting 'vectorize' with value {}. Must be natural number!", vectorize); +void NodeDirection::check() { + if (vectorize <= 0) + throw RuntimeError( + "Invalid setting 'vectorize' with value {}. Must be natural number!", + vectorize); #ifdef WITH_HOOKS - hooks.check(); + hooks.check(); #endif // WITH_HOOKS } -int NodeDirection::prepare() -{ +int NodeDirection::prepare() { #ifdef WITH_HOOKS - int t = direction == NodeDirection::Direction::OUT ? (int) Hook::Flags::NODE_WRITE : (int) Hook::Flags::NODE_READ; - int m = builtin ? t | (int) Hook::Flags::BUILTIN : 0; + int t = direction == NodeDirection::Direction::OUT + ? (int)Hook::Flags::NODE_WRITE + : (int)Hook::Flags::NODE_READ; + int m = builtin ? t | (int)Hook::Flags::BUILTIN : 0; - hooks.prepare(signals, m, nullptr, node); + hooks.prepare(signals, m, nullptr, node); #endif // WITH_HOOKS - return 0; + return 0; } -int NodeDirection::start() -{ +int NodeDirection::start() { #ifdef WITH_HOOKS - hooks.start(); + hooks.start(); #endif // WITH_HOOKS - return 0; + return 0; } -int NodeDirection::stop() -{ +int NodeDirection::stop() { #ifdef WITH_HOOKS - hooks.stop(); + hooks.stop(); #endif // WITH_HOOKS - return 0; + return 0; } -SignalList::Ptr NodeDirection::getSignals(int after_hooks) const -{ +SignalList::Ptr NodeDirection::getSignals(int after_hooks) const { #ifdef WITH_HOOKS - if (after_hooks && hooks.size() > 0) - return hooks.getSignals(); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif // WITH_HOOKS - return signals; + return signals; } -unsigned NodeDirection::getSignalsMaxCount() const -{ +unsigned NodeDirection::getSignalsMaxCount() const { #ifdef WITH_HOOKS - if (hooks.size() > 0) - return MAX(signals->size(), hooks.getSignalsMaxCount()); + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif // WITH_HOOKS - return signals->size(); + return signals->size(); } diff --git a/lib/node_list.cpp b/lib/node_list.cpp index 10b40fbc1..86b8397e6 100644 --- a/lib/node_list.cpp +++ b/lib/node_list.cpp @@ -5,94 +5,91 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; -Node * NodeList::lookup(const uuid_t &uuid) -{ - for (auto *n : *this) { - if (!uuid_compare(uuid, n->getUuid())) - return n; - } +Node *NodeList::lookup(const uuid_t &uuid) { + for (auto *n : *this) { + if (!uuid_compare(uuid, n->getUuid())) + return n; + } - return nullptr; + return nullptr; } -Node * NodeList::lookup(const std::string &name) -{ - for (auto *n : *this) { - if (name == n->getNameShort()) - return n; - } +Node *NodeList::lookup(const std::string &name) { + for (auto *n : *this) { + if (name == n->getNameShort()) + return n; + } - return nullptr; + return nullptr; } -int NodeList::parse(json_t *json, NodeList &all) -{ - Node *node; - const char *str; +int NodeList::parse(json_t *json, NodeList &all) { + Node *node; + const char *str; - size_t index; - json_t *elm; + size_t index; + json_t *elm; - auto logger = logging.get("node"); + auto logger = logging.get("node"); - switch (json_typeof(json)) { - case JSON_STRING: - str = json_string_value(json); - node = all.lookup(str); - if (!node) - goto invalid2; + switch (json_typeof(json)) { + case JSON_STRING: + str = json_string_value(json); + node = all.lookup(str); + if (!node) + goto invalid2; - push_back(node); - break; + push_back(node); + break; - case JSON_ARRAY: - json_array_foreach(json, index, elm) { - if (!json_is_string(elm)) - goto invalid; + case JSON_ARRAY: + json_array_foreach(json, index, elm) { + if (!json_is_string(elm)) + goto invalid; - str = json_string_value(elm); - node = all.lookup(str); - if (!node) - goto invalid; + str = json_string_value(elm); + node = all.lookup(str); + if (!node) + goto invalid; - push_back(node); - } - break; + push_back(node); + } + break; - default: - goto invalid; - } + default: + goto invalid; + } - return 0; + return 0; invalid: - throw RuntimeError("The node list must be an a single or an array of strings referring to the keys of the 'nodes' section"); + throw RuntimeError("The node list must be an a single or an array of strings " + "referring to the keys of the 'nodes' section"); - return -1; + return -1; invalid2: - std::stringstream allss; - for (auto *n : all) - allss << " " << n->getNameShort(); + std::stringstream allss; + for (auto *n : all) + allss << " " << n->getNameShort(); - throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str()); + throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str()); - return 0; + return 0; } -json_t * NodeList::toJson() const -{ - json_t *json_nodes = json_array(); +json_t *NodeList::toJson() const { + json_t *json_nodes = json_array(); - for (const auto *n : *this) - json_array_append_new(json_nodes, n->toJson()); + for (const auto *n : *this) + json_array_append_new(json_nodes, n->toJson()); - return json_nodes; + return json_nodes; } diff --git a/lib/nodes/amqp.cpp b/lib/nodes/amqp.cpp index fc3cb1d04..07da7a5a6 100644 --- a/lib/nodes/amqp.cpp +++ b/lib/nodes/amqp.cpp @@ -17,424 +17,399 @@ #include #endif +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void amqp_default_ssl_info(struct amqp_ssl_info *s) -{ - s->verify_peer = 1; - s->verify_hostname = 1; - s->client_key = nullptr; - s->client_cert = nullptr; - s->ca_cert = nullptr; +static void amqp_default_ssl_info(struct amqp_ssl_info *s) { + s->verify_peer = 1; + s->verify_hostname = 1; + s->client_key = nullptr; + s->client_cert = nullptr; + s->ca_cert = nullptr; } -static -amqp_bytes_t amqp_bytes_strdup(const char *str) -{ - size_t len = strlen(str) + 1; - amqp_bytes_t buf = amqp_bytes_malloc(len); +static amqp_bytes_t amqp_bytes_strdup(const char *str) { + size_t len = strlen(str) + 1; + amqp_bytes_t buf = amqp_bytes_malloc(len); - memcpy(buf.bytes, str, len); + memcpy(buf.bytes, str, len); - return buf; + return buf; } -static -amqp_connection_state_t amqp_connect(NodeCompat *n, struct amqp_connection_info *ci, struct amqp_ssl_info *ssl) -{ - int ret; - amqp_rpc_reply_t rep; - amqp_connection_state_t conn; - amqp_socket_t *sock; +static amqp_connection_state_t amqp_connect(NodeCompat *n, + struct amqp_connection_info *ci, + struct amqp_ssl_info *ssl) { + int ret; + amqp_rpc_reply_t rep; + amqp_connection_state_t conn; + amqp_socket_t *sock; - conn = amqp_new_connection(); - if (!conn) - throw MemoryAllocationError(); + conn = amqp_new_connection(); + if (!conn) + throw MemoryAllocationError(); - if (ci->ssl) { - sock = amqp_ssl_socket_new(conn); - if (!sock) - throw MemoryAllocationError(); + if (ci->ssl) { + sock = amqp_ssl_socket_new(conn); + if (!sock) + throw MemoryAllocationError(); - amqp_ssl_socket_set_verify_peer(sock, ssl->verify_peer); - amqp_ssl_socket_set_verify_hostname(sock, ssl->verify_hostname); + amqp_ssl_socket_set_verify_peer(sock, ssl->verify_peer); + amqp_ssl_socket_set_verify_hostname(sock, ssl->verify_hostname); - if (ssl->ca_cert) { - ret = amqp_ssl_socket_set_cacert(sock, ssl->ca_cert); - if (ret) { - n->logger->error("Failed to set CA cert: {}", amqp_error_string2(ret)); - return nullptr; - } - } + if (ssl->ca_cert) { + ret = amqp_ssl_socket_set_cacert(sock, ssl->ca_cert); + if (ret) { + n->logger->error("Failed to set CA cert: {}", amqp_error_string2(ret)); + return nullptr; + } + } - if (ssl->client_key && ssl->client_cert) { - ret = amqp_ssl_socket_set_key(sock, ssl->client_cert, ssl->client_key); - if (ret) { - n->logger->error("Failed to set client cert: {}", amqp_error_string2(ret)); - return nullptr; - } - } - } - else { - sock = amqp_tcp_socket_new(conn); - if (!sock) - throw MemoryAllocationError(); - } + if (ssl->client_key && ssl->client_cert) { + ret = amqp_ssl_socket_set_key(sock, ssl->client_cert, ssl->client_key); + if (ret) { + n->logger->error("Failed to set client cert: {}", + amqp_error_string2(ret)); + return nullptr; + } + } + } else { + sock = amqp_tcp_socket_new(conn); + if (!sock) + throw MemoryAllocationError(); + } - ret = amqp_socket_open(sock, ci->host, ci->port); - if (ret != AMQP_STATUS_OK) { - n->logger->error("Failed to open socket: {}", amqp_error_string2(ret)); - return nullptr; - } + ret = amqp_socket_open(sock, ci->host, ci->port); + if (ret != AMQP_STATUS_OK) { + n->logger->error("Failed to open socket: {}", amqp_error_string2(ret)); + return nullptr; + } - rep = amqp_login(conn, ci->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, ci->user, ci->password); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to login"); - return nullptr; - } + rep = amqp_login(conn, ci->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, + ci->user, ci->password); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to login"); + return nullptr; + } - amqp_channel_open(conn, 1); - rep = amqp_get_rpc_reply(conn); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to open channel"); - return nullptr; - } + amqp_channel_open(conn, 1); + rep = amqp_get_rpc_reply(conn); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to open channel"); + return nullptr; + } - return conn; + return conn; } -static -int amqp_close(NodeCompat *n, amqp_connection_state_t conn) -{ - amqp_rpc_reply_t rep; +static int amqp_close(NodeCompat *n, amqp_connection_state_t conn) { + amqp_rpc_reply_t rep; - rep = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to close channel"); - return -1; - } + rep = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to close channel"); + return -1; + } - rep = amqp_connection_close(conn, AMQP_REPLY_SUCCESS); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to close connection"); - return -1; - }; + rep = amqp_connection_close(conn, AMQP_REPLY_SUCCESS); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to close connection"); + return -1; + }; - return 0; + return 0; } -int villas::node::amqp_init(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_init(NodeCompat *n) { + auto *a = n->getData(); - // Default values - amqp_default_ssl_info(&a->ssl_info); - amqp_default_connection_info(&a->connection_info); + // Default values + amqp_default_ssl_info(&a->ssl_info); + amqp_default_connection_info(&a->connection_info); - a->formatter = nullptr; + a->formatter = nullptr; - return 0; + return 0; } -int villas::node::amqp_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *a = n->getData(); +int villas::node::amqp_parse(NodeCompat *n, json_t *json) { + int ret; + auto *a = n->getData(); - int port = 5672; - const char *uri = nullptr; - const char *host = "localhost"; - const char *vhost = "/"; - const char *username = "guest"; - const char *password = "guest"; - const char *exchange, *routing_key; + int port = 5672; + const char *uri = nullptr; + const char *host = "localhost"; + const char *vhost = "/"; + const char *username = "guest"; + const char *password = "guest"; + const char *exchange, *routing_key; - json_error_t err; + json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: s, s?: s, s?: i, s: s, s: s, s?: o, s?: o }", - "uri", &uri, - "host", &host, - "vhost", &vhost, - "username", &username, - "password", &password, - "port", &port, - "exchange", &exchange, - "routing_key", &routing_key, - "format", &json_format, - "ssl", &json_ssl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-amqp"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: s, s?: s, s?: s, s?: s, s?: s, s?: i, s: s, s: s, s?: o, s?: o }", + "uri", &uri, "host", &host, "vhost", &vhost, "username", &username, + "password", &password, "port", &port, "exchange", &exchange, + "routing_key", &routing_key, "format", &json_format, "ssl", &json_ssl); + if (ret) + throw ConfigError(json, err, "node-config-node-amqp"); - a->exchange = amqp_bytes_strdup(exchange); - a->routing_key = amqp_bytes_strdup(routing_key); + a->exchange = amqp_bytes_strdup(exchange); + a->routing_key = amqp_bytes_strdup(routing_key); - if (uri) - a->uri = strdup(uri); - else - a->uri = strf("%s://%s:%s@%s:%d/%s", json_ssl ? "amqps" : "amqp", username, password, host, port, vhost); + if (uri) + a->uri = strdup(uri); + else + a->uri = strf("%s://%s:%s@%s:%d/%s", json_ssl ? "amqps" : "amqp", username, + password, host, port, vhost); - ret = amqp_parse_url(a->uri, &a->connection_info); - if (ret != AMQP_STATUS_OK) - throw ConfigError(json, "node-config-node-uri", "Failed to parse URI '{}'", uri); + ret = amqp_parse_url(a->uri, &a->connection_info); + if (ret != AMQP_STATUS_OK) + throw ConfigError(json, "node-config-node-uri", "Failed to parse URI '{}'", + uri); - if (json_ssl) { - const char *ca_cert = nullptr; - const char *client_cert = nullptr; - const char *client_key = nullptr; + if (json_ssl) { + const char *ca_cert = nullptr; + const char *client_cert = nullptr; + const char *client_key = nullptr; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s }", - "verify_peer", &a->ssl_info.verify_peer, - "verify_hostname", &a->ssl_info.verify_hostname, - "ca_cert", &ca_cert, - "client_key", &client_key, - "client_cert", &client_cert - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-amqp-ssl", "Failed to parse SSL configuration"); + ret = json_unpack_ex( + json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s }", + "verify_peer", &a->ssl_info.verify_peer, "verify_hostname", + &a->ssl_info.verify_hostname, "ca_cert", &ca_cert, "client_key", + &client_key, "client_cert", &client_cert); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-amqp-ssl", + "Failed to parse SSL configuration"); - if (ca_cert) - a->ssl_info.ca_cert = strdup(ca_cert); + if (ca_cert) + a->ssl_info.ca_cert = strdup(ca_cert); - if (client_cert) - a->ssl_info.client_cert = strdup(client_cert); + if (client_cert) + a->ssl_info.client_cert = strdup(client_cert); - if (client_key) - a->ssl_info.client_key = strdup(client_key); - } + if (client_key) + a->ssl_info.client_key = strdup(client_key); + } - // Format - if (a->formatter) - delete a->formatter; - a->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!a->formatter) - throw ConfigError(json_format, "node-config-node-amqp-format", "Invalid format configuration"); + // Format + if (a->formatter) + delete a->formatter; + a->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!a->formatter) + throw ConfigError(json_format, "node-config-node-amqp-format", + "Invalid format configuration"); - return 0; + return 0; } -char * villas::node::amqp_print(NodeCompat *n) -{ - auto *a = n->getData(); +char *villas::node::amqp_print(NodeCompat *n) { + auto *a = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "uri=%s://%s:%s@%s:%d%s, exchange=%s, routing_key=%s", - a->connection_info.ssl ? "amqps" : "amqp", - a->connection_info.user, - a->connection_info.password, - a->connection_info.host, - a->connection_info.port, - a->connection_info.vhost, - (char *) a->exchange.bytes, - (char *) a->routing_key.bytes - ); + strcatf(&buf, "uri=%s://%s:%s@%s:%d%s, exchange=%s, routing_key=%s", + a->connection_info.ssl ? "amqps" : "amqp", a->connection_info.user, + a->connection_info.password, a->connection_info.host, + a->connection_info.port, a->connection_info.vhost, + (char *)a->exchange.bytes, (char *)a->routing_key.bytes); - if (a->connection_info.ssl) { - strcatf(&buf, ", ssl_info.verify_peer=%s, ssl_info.verify_hostname=%s", - a->ssl_info.verify_peer ? "true" : "false", - a->ssl_info.verify_hostname ? "true" : "false" - ); + if (a->connection_info.ssl) { + strcatf(&buf, ", ssl_info.verify_peer=%s, ssl_info.verify_hostname=%s", + a->ssl_info.verify_peer ? "true" : "false", + a->ssl_info.verify_hostname ? "true" : "false"); - if (a->ssl_info.ca_cert) - strcatf(&buf, ", ssl_info.ca_cert=%s", a->ssl_info.ca_cert); + if (a->ssl_info.ca_cert) + strcatf(&buf, ", ssl_info.ca_cert=%s", a->ssl_info.ca_cert); - if (a->ssl_info.client_cert) - strcatf(&buf, ", ssl_info.client_cert=%s", a->ssl_info.client_cert); + if (a->ssl_info.client_cert) + strcatf(&buf, ", ssl_info.client_cert=%s", a->ssl_info.client_cert); - if (a->ssl_info.client_key) - strcatf(&buf, ", ssl_info.client_key=%s", a->ssl_info.client_key); - } + if (a->ssl_info.client_key) + strcatf(&buf, ", ssl_info.client_key=%s", a->ssl_info.client_key); + } - return buf; + return buf; } -int villas::node::amqp_start(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_start(NodeCompat *n) { + auto *a = n->getData(); - amqp_bytes_t queue; - amqp_rpc_reply_t rep; - amqp_queue_declare_ok_t *r; + amqp_bytes_t queue; + amqp_rpc_reply_t rep; + amqp_queue_declare_ok_t *r; - a->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + a->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Connect producer - a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); - if (!a->producer) - return -1; + // Connect producer + a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); + if (!a->producer) + return -1; - // Connect consumer - a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); - if (!a->consumer) - return -1; + // Connect consumer + a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); + if (!a->consumer) + return -1; - // Declare exchange - amqp_exchange_declare(a->producer, 1, a->exchange, amqp_cstring_bytes("direct"), 0, 0, 0, 0, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Declare exchange + amqp_exchange_declare(a->producer, 1, a->exchange, + amqp_cstring_bytes("direct"), 0, 0, 0, 0, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - // Declare private queue - r = amqp_queue_declare(a->consumer, 1, amqp_empty_bytes, 0, 0, 0, 1, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Declare private queue + r = amqp_queue_declare(a->consumer, 1, amqp_empty_bytes, 0, 0, 0, 1, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - queue = amqp_bytes_malloc_dup(r->queue); - if (queue.bytes == nullptr) - return -1; + queue = amqp_bytes_malloc_dup(r->queue); + if (queue.bytes == nullptr) + return -1; - // Bind queue to exchange - amqp_queue_bind(a->consumer, 1, queue, a->exchange, a->routing_key, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Bind queue to exchange + amqp_queue_bind(a->consumer, 1, queue, a->exchange, a->routing_key, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - // Start consumer - amqp_basic_consume(a->consumer, 1, queue, amqp_empty_bytes, 0, 1, 0, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Start consumer + amqp_basic_consume(a->consumer, 1, queue, amqp_empty_bytes, 0, 1, 0, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - amqp_bytes_free(queue); + amqp_bytes_free(queue); - return 0; + return 0; } -int villas::node::amqp_stop(NodeCompat *n) -{ - int ret; - auto *a = n->getData(); +int villas::node::amqp_stop(NodeCompat *n) { + int ret; + auto *a = n->getData(); - ret = amqp_close(n, a->consumer); - if (ret) - return ret; + ret = amqp_close(n, a->consumer); + if (ret) + return ret; - ret = amqp_close(n, a->producer); - if (ret) - return ret; + ret = amqp_close(n, a->producer); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *a = n->getData(); - amqp_envelope_t env; - amqp_rpc_reply_t rep; +int villas::node::amqp_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *a = n->getData(); + amqp_envelope_t env; + amqp_rpc_reply_t rep; - rep = amqp_consume_message(a->consumer, &env, nullptr, 0); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + rep = amqp_consume_message(a->consumer, &env, nullptr, 0); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - ret = a->formatter->sscan(static_cast(env.message.body.bytes), env.message.body.len, nullptr, smps, cnt); + ret = a->formatter->sscan(static_cast(env.message.body.bytes), + env.message.body.len, nullptr, smps, cnt); - amqp_destroy_envelope(&env); + amqp_destroy_envelope(&env); - return ret; + return ret; } -int villas::node::amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *a = n->getData(); - char data[1500]; - size_t wbytes; +int villas::node::amqp_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *a = n->getData(); + char data[1500]; + size_t wbytes; - ret = a->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = a->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - amqp_bytes_t message = { - .len = wbytes, - .bytes = data - }; + amqp_bytes_t message = {.len = wbytes, .bytes = data}; - // Send message - ret = amqp_basic_publish(a->producer, 1, - a->exchange, - a->routing_key, - 0, 0, nullptr, message); + // Send message + ret = amqp_basic_publish(a->producer, 1, a->exchange, a->routing_key, 0, 0, + nullptr, message); - if (ret != AMQP_STATUS_OK) - return -1; + if (ret != AMQP_STATUS_OK) + return -1; - return cnt; + return cnt; } -int villas::node::amqp_poll_fds(NodeCompat *n, int fds[]) -{ - auto *a = n->getData(); +int villas::node::amqp_poll_fds(NodeCompat *n, int fds[]) { + auto *a = n->getData(); - amqp_socket_t *sock = amqp_get_socket(a->consumer); + amqp_socket_t *sock = amqp_get_socket(a->consumer); - fds[0] = amqp_socket_get_sockfd(sock); + fds[0] = amqp_socket_get_sockfd(sock); - return 1; + return 1; } -int villas::node::amqp_destroy(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_destroy(NodeCompat *n) { + auto *a = n->getData(); - if (a->uri) - free(a->uri); + if (a->uri) + free(a->uri); - if (a->ssl_info.client_cert) - free(a->ssl_info.client_cert); + if (a->ssl_info.client_cert) + free(a->ssl_info.client_cert); - if (a->ssl_info.client_key) - free(a->ssl_info.client_key); + if (a->ssl_info.client_key) + free(a->ssl_info.client_key); - if (a->ssl_info.ca_cert) - free(a->ssl_info.ca_cert); + if (a->ssl_info.ca_cert) + free(a->ssl_info.ca_cert); - if (a->producer) - amqp_destroy_connection(a->producer); + if (a->producer) + amqp_destroy_connection(a->producer); - if (a->consumer) - amqp_destroy_connection(a->consumer); + if (a->consumer) + amqp_destroy_connection(a->consumer); - if (a->formatter) - delete a->formatter; + if (a->formatter) + delete a->formatter; - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "amqp"; - p.description = "Advanced Message Queueing Protoocl (rabbitmq-c)"; - p.vectorize = 0; - p.size = sizeof(struct amqp); - p.init = amqp_init; - p.destroy = amqp_destroy; - p.parse = amqp_parse; - p.print = amqp_print; - p.start = amqp_start; - p.stop = amqp_stop; - p.read = amqp_read; - p.write = amqp_write; - p.poll_fds = amqp_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "amqp"; + p.description = "Advanced Message Queueing Protoocl (rabbitmq-c)"; + p.vectorize = 0; + p.size = sizeof(struct amqp); + p.init = amqp_init; + p.destroy = amqp_destroy; + p.parse = amqp_parse; + p.print = amqp_print; + p.start = amqp_start; + p.stop = amqp_stop; + p.read = amqp_read; + p.write = amqp_write; + p.poll_fds = amqp_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/api.cpp b/lib/nodes/api.cpp index 68c3b48cb..63c7cace5 100644 --- a/lib/nodes/api.cpp +++ b/lib/nodes/api.cpp @@ -8,121 +8,114 @@ #include -#include #include +#include #include using namespace villas; using namespace villas::node; using namespace villas::node::api::universal; -APINode::APINode(const uuid_t &id, const std::string &name) : - Node(id, name), - read(), - write() -{ - int ret; - auto dirs = std::vector{&read, &write}; +APINode::APINode(const uuid_t &id, const std::string &name) + : Node(id, name), read(), write() { + int ret; + auto dirs = std::vector{&read, &write}; - for (auto dir : dirs) { - ret = pthread_mutex_init(&dir->mutex, nullptr); - if (ret) - throw RuntimeError("failed to initialize mutex"); + for (auto dir : dirs) { + ret = pthread_mutex_init(&dir->mutex, nullptr); + if (ret) + throw RuntimeError("failed to initialize mutex"); - ret = pthread_cond_init(&dir->cv, nullptr); - if (ret) - throw RuntimeError("failed to initialize mutex"); - } + ret = pthread_cond_init(&dir->cv, nullptr); + if (ret) + throw RuntimeError("failed to initialize mutex"); + } } -int APINode::prepare() -{ - auto signals_in = getInputSignals(false); +int APINode::prepare() { + auto signals_in = getInputSignals(false); - read.sample = sample_alloc_mem(signals_in->size()); - if (!read.sample) - throw MemoryAllocationError(); + read.sample = sample_alloc_mem(signals_in->size()); + if (!read.sample) + throw MemoryAllocationError(); - write.sample = sample_alloc_mem(64); - if (!write.sample) - throw MemoryAllocationError(); + write.sample = sample_alloc_mem(64); + if (!write.sample) + throw MemoryAllocationError(); - unsigned j = 0; - for (auto sig : *signals_in) - read.sample->data[j++] = sig->init; + unsigned j = 0; + for (auto sig : *signals_in) + read.sample->data[j++] = sig->init; - read.sample->length = j; - read.sample->signals = signals_in; + read.sample->length = j; + read.sample->signals = signals_in; - return Node::prepare(); + return Node::prepare(); } -int APINode::check() -{ - for (auto &ch : read.channels) { - if (ch->payload != PayloadType::SAMPLES) - return -1; - } +int APINode::check() { + for (auto &ch : read.channels) { + if (ch->payload != PayloadType::SAMPLES) + return -1; + } - for (auto &ch : write.channels) { - if (ch->payload != PayloadType::SAMPLES) - return -1; - } + for (auto &ch : write.channels) { + if (ch->payload != PayloadType::SAMPLES) + return -1; + } - return 0; + return 0; } -int APINode::_read(struct Sample *smps[], unsigned cnt) -{ - assert(cnt == 1); +int APINode::_read(struct Sample *smps[], unsigned cnt) { + assert(cnt == 1); - pthread_cond_wait(&read.cv, &read.mutex); + pthread_cond_wait(&read.cv, &read.mutex); - sample_copy(smps[0], read.sample); + sample_copy(smps[0], read.sample); - return 1; + return 1; } -int APINode::_write(struct Sample *smps[], unsigned cnt) -{ - assert(cnt == 1); +int APINode::_write(struct Sample *smps[], unsigned cnt) { + assert(cnt == 1); - sample_copy(write.sample, smps[0]); + sample_copy(write.sample, smps[0]); - pthread_cond_signal(&write.cv); + pthread_cond_signal(&write.cv); - return 1; + return 1; } -int APINode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int APINode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o }, s?: { s?: o } }", - "in", - "signals", &json_signals_in, - "out", - "signals", &json_signals_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api"); + json_error_t err; + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o }, s?: { s?: o } }", "in", + "signals", &json_signals_in, "out", "signals", + &json_signals_out); + if (ret) + throw ConfigError(json, err, "node-config-node-api"); - if (json_signals_in) - read.channels.parse(json_signals_in, false, true); + if (json_signals_in) + read.channels.parse(json_signals_in, false, true); - if (json_signals_out) - write.channels.parse(json_signals_out, true, false); + if (json_signals_out) + write.channels.parse(json_signals_out, true, false); - return 0; + return 0; } // Register node static char n[] = "api"; static char d[] = "A node providing a HTTP REST interface"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/can.cpp b/lib/nodes/can.cpp index 2b313f04f..e4544c139 100644 --- a/lib/nodes/can.cpp +++ b/lib/nodes/can.cpp @@ -11,520 +11,506 @@ #include #include -#include -#include #include +#include +#include #include #include #include +#include #include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Forward declarations -static -NodeCompatType p; +static NodeCompatType p; -int villas::node::can_init(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_init(NodeCompat *n) { + auto *c = n->getData(); - c->interface_name = nullptr; - c->socket = 0; - c->sample_buf = nullptr; - c->sample_buf_num = 0; - c->in = nullptr; - c->out = nullptr; + c->interface_name = nullptr; + c->socket = 0; + c->sample_buf = nullptr; + c->sample_buf_num = 0; + c->in = nullptr; + c->out = nullptr; - return 0; + return 0; } -int villas::node::can_destroy(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_destroy(NodeCompat *n) { + auto *c = n->getData(); - if (c->socket != 0) - close(c->socket); + if (c->socket != 0) + close(c->socket); - free(c->sample_buf); + free(c->sample_buf); - if (c->in) - free(c->in); + if (c->in) + free(c->in); - if (c->out) - free(c->out); + if (c->out) + free(c->out); - return 0; + return 0; } -static -int can_parse_signal(json_t *json, SignalList::Ptr node_signals, struct can_signal *can_signals, size_t signal_index) -{ - const char *name = nullptr; - uint64_t can_id = 0; - int can_size = 8; - int can_offset = 0; - int ret = 1; - json_error_t err; +static int can_parse_signal(json_t *json, SignalList::Ptr node_signals, + struct can_signal *can_signals, + size_t signal_index) { + const char *name = nullptr; + uint64_t can_id = 0; + int can_size = 8; + int can_offset = 0; + int ret = 1; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: i, s?: i, s?: i }", - "name", &name, - "can_id", &can_id, - "can_size", &can_size, - "can_offset", &can_offset - ); - if (ret) - throw ConfigError(json, err, "node-config-node-can-signals"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: i, s?: i, s?: i }", "name", + &name, "can_id", &can_id, "can_size", &can_size, + "can_offset", &can_offset); + if (ret) + throw ConfigError(json, err, "node-config-node-can-signals"); - if (can_size > 8 || can_size <= 0) - throw ConfigError(json, "node-config-node-can-can-size", "can_size of {} for signal '{}' is invalid. You must satisfy 0 < can_size <= 8.", can_size, name); + if (can_size > 8 || can_size <= 0) + throw ConfigError(json, "node-config-node-can-can-size", + "can_size of {} for signal '{}' is invalid. You must " + "satisfy 0 < can_size <= 8.", + can_size, name); - if (can_offset > 8 || can_offset < 0) - throw ConfigError(json, "node-config-node-can-can-offset", "can_offset of {} for signal '{}' is invalid. You must satisfy 0 <= can_offset <= 8.", can_offset, name); + if (can_offset > 8 || can_offset < 0) + throw ConfigError(json, "node-config-node-can-can-offset", + "can_offset of {} for signal '{}' is invalid. You must " + "satisfy 0 <= can_offset <= 8.", + can_offset, name); - auto sig = node_signals->getByIndex(signal_index); - if ((!name && sig->name.empty()) || (name && sig->name == name)) { - can_signals[signal_index].id = can_id; - can_signals[signal_index].size = can_size; - can_signals[signal_index].offset = can_offset; - ret = 0; - goto out; - } - else - throw ConfigError(json, "node-config-node-can-signa;s", "Signal configuration inconsistency detected: Signal with index {} '{}' does not match can_signal '{}'", signal_index, sig->name, name); + auto sig = node_signals->getByIndex(signal_index); + if ((!name && sig->name.empty()) || (name && sig->name == name)) { + can_signals[signal_index].id = can_id; + can_signals[signal_index].size = can_size; + can_signals[signal_index].offset = can_offset; + ret = 0; + goto out; + } else + throw ConfigError(json, "node-config-node-can-signa;s", + "Signal configuration inconsistency detected: Signal " + "with index {} '{}' does not match can_signal '{}'", + signal_index, sig->name, name); -out: return ret; +out: + return ret; } -int villas::node::can_parse(NodeCompat *n, json_t *json) -{ - int ret = 1; - auto *c = n->getData(); - size_t i; - json_t *json_in_signals; - json_t *json_out_signals; - json_t *json_signal; - json_error_t err; +int villas::node::can_parse(NodeCompat *n, json_t *json) { + int ret = 1; + auto *c = n->getData(); + size_t i; + json_t *json_in_signals; + json_t *json_out_signals; + json_t *json_signal; + json_error_t err; - c->in = nullptr; - c->out = nullptr; + c->in = nullptr; + c->out = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: { s?: o }, s?: { s?: o } }", - "interface_name", &c->interface_name, - "in", - "signals", &json_in_signals, - "out", - "signals", &json_out_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-can"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: { s?: o }, s?: { s?: o } }", + "interface_name", &c->interface_name, "in", "signals", + &json_in_signals, "out", "signals", &json_out_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-can"); - c->in = (struct can_signal*) calloc( - json_array_size(json_in_signals), - sizeof(struct can_signal)); - if (!c->in) - throw MemoryAllocationError(); + c->in = (struct can_signal *)calloc(json_array_size(json_in_signals), + sizeof(struct can_signal)); + if (!c->in) + throw MemoryAllocationError(); - c->out = (struct can_signal*) calloc( - json_array_size(json_out_signals), - sizeof(struct can_signal)); - if (!c->out) - throw MemoryAllocationError(); + c->out = (struct can_signal *)calloc(json_array_size(json_out_signals), + sizeof(struct can_signal)); + if (!c->out) + throw MemoryAllocationError(); - json_array_foreach(json_in_signals, i, json_signal) { - ret = can_parse_signal(json_signal, n->in.signals, c->in, i); - if (ret) - throw RuntimeError("at signal {}.",i); - } + json_array_foreach(json_in_signals, i, json_signal) { + ret = can_parse_signal(json_signal, n->in.signals, c->in, i); + if (ret) + throw RuntimeError("at signal {}.", i); + } - json_array_foreach(json_out_signals, i, json_signal) { - ret = can_parse_signal(json_signal, n->out.signals, c->out, i); - if (ret) - throw RuntimeError("at signal {}.", i); - } + json_array_foreach(json_out_signals, i, json_signal) { + ret = can_parse_signal(json_signal, n->out.signals, c->out, i); + if (ret) + throw RuntimeError("at signal {}.", i); + } - ret = 0; + ret = 0; - return ret; + return ret; } -char * villas::node::can_print(NodeCompat *n) -{ - auto *c = n->getData(); +char *villas::node::can_print(NodeCompat *n) { + auto *c = n->getData(); - return strf("interface_name={}", c->interface_name); + return strf("interface_name={}", c->interface_name); } -int villas::node::can_check(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_check(NodeCompat *n) { + auto *c = n->getData(); - if (c->interface_name == nullptr || strlen(c->interface_name) == 0) - throw RuntimeError("Empty interface_name. Please specify the name of the CAN interface!"); + if (c->interface_name == nullptr || strlen(c->interface_name) == 0) + throw RuntimeError( + "Empty interface_name. Please specify the name of the CAN interface!"); - return 0; + return 0; } -int villas::node::can_prepare(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_prepare(NodeCompat *n) { + auto *c = n->getData(); - c->sample_buf = (union SignalData*) calloc(n->getInputSignals(false)->size(), sizeof(union SignalData)); + c->sample_buf = (union SignalData *)calloc(n->getInputSignals(false)->size(), + sizeof(union SignalData)); - return (c->sample_buf != 0 ? 0 : 1); + return (c->sample_buf != 0 ? 0 : 1); } -int villas::node::can_start(NodeCompat *n) -{ - int ret = 1; - struct sockaddr_can addr = {0}; - struct ifreq ifr; +int villas::node::can_start(NodeCompat *n) { + int ret = 1; + struct sockaddr_can addr = {0}; + struct ifreq ifr; - auto *c = n->getData(); - c->start_time = time_now(); + auto *c = n->getData(); + c->start_time = time_now(); - c->socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (c->socket < 0) - throw SystemError("Error while opening CAN socket"); + c->socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (c->socket < 0) + throw SystemError("Error while opening CAN socket"); - strcpy(ifr.ifr_name, c->interface_name); + strcpy(ifr.ifr_name, c->interface_name); - ret = ioctl(c->socket, SIOCGIFINDEX, &ifr); - if (ret != 0) - throw SystemError("Could not find interface with name '{}'.", c->interface_name); + ret = ioctl(c->socket, SIOCGIFINDEX, &ifr); + if (ret != 0) + throw SystemError("Could not find interface with name '{}'.", + c->interface_name); - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; + addr.can_family = AF_CAN; + addr.can_ifindex = ifr.ifr_ifindex; - ret = bind(c->socket, (struct sockaddr *)&addr, sizeof(addr)); - if (ret < 0) - throw SystemError("Could not bind to interface with name '{}' ({}).", c->interface_name, ifr.ifr_ifindex); + ret = bind(c->socket, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) + throw SystemError("Could not bind to interface with name '{}' ({}).", + c->interface_name, ifr.ifr_ifindex); - return 0; + return 0; } -int villas::node::can_stop(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_stop(NodeCompat *n) { + auto *c = n->getData(); - if (c->socket != 0) { - close(c->socket); - c->socket = 0; - } + if (c->socket != 0) { + close(c->socket); + c->socket = 0; + } - return 0; + return 0; } -static -int can_convert_to_raw(const union SignalData *sig, const Signal::Ptr from, void *to, int size) -{ - if (size <= 0 || size > 8) - throw RuntimeError("Signal size cannot be larger than 8!"); +static int can_convert_to_raw(const union SignalData *sig, + const Signal::Ptr from, void *to, int size) { + if (size <= 0 || size > 8) + throw RuntimeError("Signal size cannot be larger than 8!"); - switch(from->type) { - case SignalType::BOOLEAN: - *(uint8_t*)to = sig->b; - return 0; + switch (from->type) { + case SignalType::BOOLEAN: + *(uint8_t *)to = sig->b; + return 0; - case SignalType::INTEGER: - switch(size) { - case 1: - *(int8_t*)to = (int8_t)sig->i; - return 0; + case SignalType::INTEGER: + switch (size) { + case 1: + *(int8_t *)to = (int8_t)sig->i; + return 0; - case 2: - *(int16_t*)to = (int16_t)sig->i; - return 0; + case 2: + *(int16_t *)to = (int16_t)sig->i; + return 0; - case 3: - *(int16_t*)to = (int16_t)sig->i; - *((int8_t*)to+2) = (int8_t)(sig->i >> 16); - return 0; + case 3: + *(int16_t *)to = (int16_t)sig->i; + *((int8_t *)to + 2) = (int8_t)(sig->i >> 16); + return 0; - case 4: - *(int32_t*)to = (int32_t)sig->i; - return 0; + case 4: + *(int32_t *)to = (int32_t)sig->i; + return 0; - case 8: - *(int64_t*)to = sig->i; - return 0; + case 8: + *(int64_t *)to = sig->i; + return 0; - default: - goto fail; - } - case SignalType::FLOAT: - switch(size) { - case 4: - assert(sizeof(float) == 4); - *(float*)to = (float)sig->f; - return 0; + default: + goto fail; + } + case SignalType::FLOAT: + switch (size) { + case 4: + assert(sizeof(float) == 4); + *(float *)to = (float)sig->f; + return 0; - case 8: - *(double*)to = sig->f; - return 0; + case 8: + *(double *)to = sig->f; + return 0; - default: - goto fail; - } - case SignalType::COMPLEX: - if (size != 8) - goto fail; + default: + goto fail; + } + case SignalType::COMPLEX: + if (size != 8) + goto fail; - *(float*)to = sig->z.real(); - *((float*)to+1) = sig->z.imag(); - return 0; + *(float *)to = sig->z.real(); + *((float *)to + 1) = sig->z.imag(); + return 0; - default: - goto fail; - } + default: + goto fail; + } fail: - throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", signalTypeToString(from->type), to, size); + throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", + signalTypeToString(from->type), to, size); - return 1; + return 1; } -static -int can_conv_from_raw(union SignalData *sig, void *from, int size, Signal::Ptr to) -{ - if (size <= 0 || size > 8) - throw RuntimeError("Signal size cannot be larger than 8!"); +static int can_conv_from_raw(union SignalData *sig, void *from, int size, + Signal::Ptr to) { + if (size <= 0 || size > 8) + throw RuntimeError("Signal size cannot be larger than 8!"); - switch(to->type) { - case SignalType::BOOLEAN: - sig->b = (bool)*(uint8_t*)from; - return 0; - case SignalType::INTEGER: - switch(size) { - case 1: - sig->i = (int64_t)*(int8_t*)from; - return 0; + switch (to->type) { + case SignalType::BOOLEAN: + sig->b = (bool)*(uint8_t *)from; + return 0; + case SignalType::INTEGER: + switch (size) { + case 1: + sig->i = (int64_t) * (int8_t *)from; + return 0; - case 2: - sig->i = (int64_t)*(int16_t*)from; - return 0; + case 2: + sig->i = (int64_t) * (int16_t *)from; + return 0; - case 3: - sig->i = (int64_t)*(int16_t*)from; - sig->i += ((int64_t)*((int8_t*)(from)+2)) << 16; - return 0; + case 3: + sig->i = (int64_t) * (int16_t *)from; + sig->i += ((int64_t) * ((int8_t *)(from) + 2)) << 16; + return 0; - case 4: - sig->i = (int64_t)*(int32_t*)from; - return 0; + case 4: + sig->i = (int64_t) * (int32_t *)from; + return 0; - case 8: - sig->i = *(uint64_t*)from; - return 0; + case 8: + sig->i = *(uint64_t *)from; + return 0; - default: - goto fail; - } - case SignalType::FLOAT: - switch(size) { - case 4: - assert(sizeof(float) == 4); - sig->f = (double)*(float*)from; - return 0; + default: + goto fail; + } + case SignalType::FLOAT: + switch (size) { + case 4: + assert(sizeof(float) == 4); + sig->f = (double)*(float *)from; + return 0; - case 8: - sig->f = *(double*)from; - return 0; + case 8: + sig->f = *(double *)from; + return 0; - default: - goto fail; - } - case SignalType::COMPLEX: - if (size != 8) - goto fail; + default: + goto fail; + } + case SignalType::COMPLEX: + if (size != 8) + goto fail; - sig->z = std::complex(*(float*)from, *((float*)from+1)); - return 0; + sig->z = std::complex(*(float *)from, *((float *)from + 1)); + return 0; - default: - goto fail; - } + default: + goto fail; + } fail: - throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", signalTypeToString(to->type), from, size); + throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", + signalTypeToString(to->type), from, size); - return 1; + return 1; } -int villas::node::can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret = 0; - int nbytes; - unsigned nread = 0; - struct can_frame frame; - struct timeval tv; - bool found_id = false; +int villas::node::can_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret = 0; + int nbytes; + unsigned nread = 0; + struct can_frame frame; + struct timeval tv; + bool found_id = false; - auto *c = n->getData(); + auto *c = n->getData(); - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - nbytes = read(c->socket, &frame, sizeof(struct can_frame)); - if (nbytes == -1) - throw RuntimeError("CAN read() returned -1. Is the CAN interface up?"); + nbytes = read(c->socket, &frame, sizeof(struct can_frame)); + if (nbytes == -1) + throw RuntimeError("CAN read() returned -1. Is the CAN interface up?"); - if ((unsigned)nbytes != sizeof(struct can_frame)) - throw RuntimeError("CAN read() error. Returned {} bytes but expected {}", nbytes, sizeof(struct can_frame)); + if ((unsigned)nbytes != sizeof(struct can_frame)) + throw RuntimeError("CAN read() error. Returned {} bytes but expected {}", + nbytes, sizeof(struct can_frame)); - n->logger->debug("Received can message: (id={}, len={}, data={:#x}:{:#x})", - frame.can_id, - frame.can_dlc, - ((uint32_t*)&frame.data)[0], - ((uint32_t*)&frame.data)[1]); + n->logger->debug("Received can message: (id={}, len={}, data={:#x}:{:#x})", + frame.can_id, frame.can_dlc, ((uint32_t *)&frame.data)[0], + ((uint32_t *)&frame.data)[1]); - if (ioctl(c->socket, SIOCGSTAMP, &tv) == 0) { - TIMEVAL_TO_TIMESPEC(&tv, &smps[nread]->ts.received); - smps[nread]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + if (ioctl(c->socket, SIOCGSTAMP, &tv) == 0) { + TIMEVAL_TO_TIMESPEC(&tv, &smps[nread]->ts.received); + smps[nread]->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - for (size_t i=0; i < n->getInputSignals(false)->size(); i++) { - if (c->in[i].id == frame.can_id) { - if (can_conv_from_raw(&c->sample_buf[i], - ((uint8_t*)&frame.data) + c->in[i].offset, - c->in[i].size, - n->getInputSignals(false)->getByIndex(i)) != 0) { - goto out; - } + for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { + if (c->in[i].id == frame.can_id) { + if (can_conv_from_raw( + &c->sample_buf[i], ((uint8_t *)&frame.data) + c->in[i].offset, + c->in[i].size, n->getInputSignals(false)->getByIndex(i)) != 0) { + goto out; + } - c->sample_buf_num++; - found_id = true; - } - } + c->sample_buf_num++; + found_id = true; + } + } - if (!found_id) - throw RuntimeError("Did not find signal for can id {}", frame.can_id); + if (!found_id) + throw RuntimeError("Did not find signal for can id {}", frame.can_id); - n->logger->debug("Received {} signals", c->sample_buf_num); + n->logger->debug("Received {} signals", c->sample_buf_num); - // Copy signal data to sample only when all signals have been received - if (c->sample_buf_num == n->getInputSignals(false)->size()) { - smps[nread]->length = c->sample_buf_num; - memcpy(smps[nread]->data, c->sample_buf, c->sample_buf_num*sizeof(union SignalData)); - c->sample_buf_num = 0; - smps[nread]->flags |= (int) SampleFlags::HAS_DATA; - ret = 1; - } - else { - smps[nread]->length = 0; - ret = 0; - } + // Copy signal data to sample only when all signals have been received + if (c->sample_buf_num == n->getInputSignals(false)->size()) { + smps[nread]->length = c->sample_buf_num; + memcpy(smps[nread]->data, c->sample_buf, + c->sample_buf_num * sizeof(union SignalData)); + c->sample_buf_num = 0; + smps[nread]->flags |= (int)SampleFlags::HAS_DATA; + ret = 1; + } else { + smps[nread]->length = 0; + ret = 0; + } - out: // Set signals, because other VILLASnode parts expect us to - smps[nread]->signals = n->getInputSignals(false); +out: // Set signals, because other VILLASnode parts expect us to + smps[nread]->signals = n->getInputSignals(false); - return ret; + return ret; } -int villas::node::can_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int nbytes; - unsigned nwrite; - struct can_frame *frame; - size_t fsize = 0; // number of frames in use +int villas::node::can_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int nbytes; + unsigned nwrite; + struct can_frame *frame; + size_t fsize = 0; // number of frames in use - auto *c = n->getData(); + auto *c = n->getData(); - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - frame = (struct can_frame*) calloc(sizeof(struct can_frame), n->getOutputSignals()->size()); + frame = (struct can_frame *)calloc(sizeof(struct can_frame), + n->getOutputSignals()->size()); - for (nwrite=0; nwrite < cnt; nwrite++) { - for (size_t i=0; i < n->getOutputSignals()->size(); i++) { - if (c->out[i].offset != 0) // frame is shared - continue; + for (nwrite = 0; nwrite < cnt; nwrite++) { + for (size_t i = 0; i < n->getOutputSignals()->size(); i++) { + if (c->out[i].offset != 0) // frame is shared + continue; - frame[fsize].can_dlc = c->out[i].size; - frame[fsize].can_id = c->out[i].id; + frame[fsize].can_dlc = c->out[i].size; + frame[fsize].can_id = c->out[i].id; - can_convert_to_raw( - &smps[nwrite]->data[i], - n->getOutputSignals()->getByIndex(i), - &frame[fsize].data, - c->out[i].size); + can_convert_to_raw(&smps[nwrite]->data[i], + n->getOutputSignals()->getByIndex(i), + &frame[fsize].data, c->out[i].size); - fsize++; - } + fsize++; + } - for (size_t i=0; i < n->getOutputSignals(false)->size(); i++) { - if (c->out[i].offset == 0) { // frame already stored - continue; - } + for (size_t i = 0; i < n->getOutputSignals(false)->size(); i++) { + if (c->out[i].offset == 0) { // frame already stored + continue; + } - for (size_t j=0; j < fsize; j++) { - if (c->out[i].id != frame[j].can_id) - continue; + for (size_t j = 0; j < fsize; j++) { + if (c->out[i].id != frame[j].can_id) + continue; - frame[j].can_dlc += c->out[i].size; - can_convert_to_raw( - &smps[nwrite]->data[i], - n->getOutputSignals(false)->getByIndex(i), - (uint8_t*)&frame[j].data + c->out[i].offset, - c->out[i].size); - break; - } - } + frame[j].can_dlc += c->out[i].size; + can_convert_to_raw( + &smps[nwrite]->data[i], n->getOutputSignals(false)->getByIndex(i), + (uint8_t *)&frame[j].data + c->out[i].offset, c->out[i].size); + break; + } + } - for (size_t j=0; j < fsize; j++) { - n->logger->debug("Writing CAN message: (id={}, dlc={}, data={:#x}:{:#x})", - frame[j].can_id, - frame[j].can_dlc, - ((uint32_t*)&frame[j].data)[0], - ((uint32_t*)&frame[j].data)[1] - ); + for (size_t j = 0; j < fsize; j++) { + n->logger->debug("Writing CAN message: (id={}, dlc={}, data={:#x}:{:#x})", + frame[j].can_id, frame[j].can_dlc, + ((uint32_t *)&frame[j].data)[0], + ((uint32_t *)&frame[j].data)[1]); - if ((nbytes = write(c->socket, &frame[j], sizeof(struct can_frame))) == -1) - throw RuntimeError("CAN write() returned -1. Is the CAN interface up?"); + if ((nbytes = write(c->socket, &frame[j], sizeof(struct can_frame))) == + -1) + throw RuntimeError("CAN write() returned -1. Is the CAN interface up?"); - if ((unsigned)nbytes != sizeof(struct can_frame)) - throw RuntimeError("CAN write() returned {} bytes but expected {}", - nbytes, sizeof(struct can_frame)); - } - } + if ((unsigned)nbytes != sizeof(struct can_frame)) + throw RuntimeError("CAN write() returned {} bytes but expected {}", + nbytes, sizeof(struct can_frame)); + } + } - return nwrite; + return nwrite; } -int villas::node::can_poll_fds(NodeCompat *n, int fds[]) -{ - auto *c = n->getData(); +int villas::node::can_poll_fds(NodeCompat *n, int fds[]) { + auto *c = n->getData(); - fds[0] = c->socket; + fds[0] = c->socket; - return 1; // The number of file descriptors which have been set in fds + return 1; // The number of file descriptors which have been set in fds } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "can"; - p.description = "Receive CAN messages using the socketCAN driver"; - p.vectorize = 0; - p.flags = 0; - p.size = sizeof(struct can); - p.init = can_init; - p.destroy = can_destroy; - p.prepare = can_prepare; - p.parse = can_parse; - p.print = can_print; - p.check = can_check; - p.start = can_start; - p.stop = can_stop; - p.read = can_read; - p.write = can_write; - p.poll_fds = can_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "can"; + p.description = "Receive CAN messages using the socketCAN driver"; + p.vectorize = 0; + p.flags = 0; + p.size = sizeof(struct can); + p.init = can_init; + p.destroy = can_destroy; + p.prepare = can_prepare; + p.parse = can_parse; + p.print = can_print; + p.check = can_check; + p.start = can_start; + p.stop = can_stop; + p.read = can_read; + p.write = can_write; + p.poll_fds = can_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index 5932a4d17..803d8ce09 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -6,627 +6,625 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include +#include +#include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Utility functions to dump a comedi_cmd graciously taken from comedilib demo -static -char* comedi_cmd_trigger_src(unsigned int src, char *buf); -static -void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); +static char *comedi_cmd_trigger_src(unsigned int src, char *buf); +static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); -static -int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t *json) -{ - int ret; +static int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, + json_t *json) { + int ret; - json_t *json_chans; - json_error_t err; + json_t *json_chans; + json_error_t err; - // Default values - d->subdevice = -1; - d->buffer_size = 16; + // Default values + d->subdevice = -1; + d->buffer_size = 16; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: i, s: o, s: i }", - "subdevice", &d->subdevice, - "bufsize", &d->buffer_size, - "signals", &json_chans, - "rate", &d->sample_rate_hz - ); - if (ret) - throw ConfigError(json, err, "node-config-node-comedi"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: i, s: o, s: i }", + "subdevice", &d->subdevice, "bufsize", &d->buffer_size, + "signals", &json_chans, "rate", &d->sample_rate_hz); + if (ret) + throw ConfigError(json, err, "node-config-node-comedi"); - if (!json_is_array(json_chans)) - return -1; + if (!json_is_array(json_chans)) + return -1; - // Convert kilobytes to bytes - d->buffer_size = d->buffer_size << 10; + // Convert kilobytes to bytes + d->buffer_size = d->buffer_size << 10; - size_t i; - json_t *json_chan; + size_t i; + json_t *json_chan; - d->chanlist_len = json_array_size(json_chans); - if (d->chanlist_len == 0) - throw ConfigError(json_chans, "node-config-node-channels", "No channels configured"); + d->chanlist_len = json_array_size(json_chans); + if (d->chanlist_len == 0) + throw ConfigError(json_chans, "node-config-node-channels", + "No channels configured"); - d->chanlist = new unsigned int[d->chanlist_len]; - if (!d->chanlist) - throw MemoryAllocationError(); + d->chanlist = new unsigned int[d->chanlist_len]; + if (!d->chanlist) + throw MemoryAllocationError(); - d->chanspecs = new comedi_chanspec[d->chanlist_len]; - if (!d->chanspecs) - throw MemoryAllocationError(); + d->chanspecs = new comedi_chanspec[d->chanlist_len]; + if (!d->chanspecs) + throw MemoryAllocationError(); - json_array_foreach(json_chans, i, json_chan) { - int num, range, aref; - ret = json_unpack_ex(json_chan, &err, 0, "{ s: i, s: i, s: i }", - "channel", &num, - "range", &range, - "aref", &aref - ); - if (ret) - throw ConfigError(json_chan, err, "node-config-node-comedi"); + json_array_foreach(json_chans, i, json_chan) { + int num, range, aref; + ret = json_unpack_ex(json_chan, &err, 0, "{ s: i, s: i, s: i }", "channel", + &num, "range", &range, "aref", &aref); + if (ret) + throw ConfigError(json_chan, err, "node-config-node-comedi"); - if (aref < AREF_GROUND || aref > AREF_OTHER) - throw ConfigError(json_chan, "node-config-node-comedi-aref", "Invalid value for analog reference: aref={}", aref); + if (aref < AREF_GROUND || aref > AREF_OTHER) + throw ConfigError(json_chan, "node-config-node-comedi-aref", + "Invalid value for analog reference: aref={}", aref); - d->chanlist[i] = CR_PACK(num, range, aref); - } + d->chanlist[i] = CR_PACK(num, range, aref); + } - return 0; + return 0; } -static -int comedi_start_common(NodeCompat *n) -{ - auto *c = n->getData(); - struct comedi_direction* directions[2] = { &c->in, &c->out }; +static int comedi_start_common(NodeCompat *n) { + auto *c = n->getData(); + struct comedi_direction *directions[2] = {&c->in, &c->out}; - comedi_set_global_oor_behavior(COMEDI_OOR_NAN); + comedi_set_global_oor_behavior(COMEDI_OOR_NAN); - for (int dirIdx = 0; dirIdx < 2; dirIdx++) { - struct comedi_direction* d = directions[dirIdx]; - int ret; + for (int dirIdx = 0; dirIdx < 2; dirIdx++) { + struct comedi_direction *d = directions[dirIdx]; + int ret; - if (!d->present) - continue; + if (!d->present) + continue; - // Sanity-check channel config and populate chanspec for later - for (unsigned i = 0; i < d->chanlist_len; i++) { - const unsigned int channel = CR_CHAN(d->chanlist[i]); - const int range = CR_RANGE(d->chanlist[i]); + // Sanity-check channel config and populate chanspec for later + for (unsigned i = 0; i < d->chanlist_len; i++) { + const unsigned int channel = CR_CHAN(d->chanlist[i]); + const int range = CR_RANGE(d->chanlist[i]); - ret = comedi_get_n_ranges(c->dev, d->subdevice, channel); - if (ret < 0) - throw RuntimeError("Failed to get ranges for channel {} on subdevice {}", channel, d->subdevice); + ret = comedi_get_n_ranges(c->dev, d->subdevice, channel); + if (ret < 0) + throw RuntimeError( + "Failed to get ranges for channel {} on subdevice {}", channel, + d->subdevice); - if (range >= ret) - throw RuntimeError("Invalid range for channel {} on subdevice {}: range={}", channel, d->subdevice, range); + if (range >= ret) + throw RuntimeError( + "Invalid range for channel {} on subdevice {}: range={}", channel, + d->subdevice, range); - ret = comedi_get_maxdata(c->dev, d->subdevice, channel); - if (ret <= 0) - throw RuntimeError("Failed to get max. data value for channel {} on subdevice {}", channel, d->subdevice); + ret = comedi_get_maxdata(c->dev, d->subdevice, channel); + if (ret <= 0) + throw RuntimeError( + "Failed to get max. data value for channel {} on subdevice {}", + channel, d->subdevice); - d->chanspecs[i].maxdata = ret; - d->chanspecs[i].range = comedi_get_range(c->dev, d->subdevice, - channel, range); + d->chanspecs[i].maxdata = ret; + d->chanspecs[i].range = + comedi_get_range(c->dev, d->subdevice, channel, range); - n->logger->info("{} channel: {} aref={} range={} maxdata={}", - (d == &c->in ? "Input" : "Output"), channel, - CR_AREF(d->chanlist[i]), range, d->chanspecs[i].maxdata); - } + n->logger->info("{} channel: {} aref={} range={} maxdata={}", + (d == &c->in ? "Input" : "Output"), channel, + CR_AREF(d->chanlist[i]), range, d->chanspecs[i].maxdata); + } - const int flags = comedi_get_subdevice_flags(c->dev, d->subdevice); - d->sample_size = (flags & SDF_LSAMPL) ? sizeof(lsampl_t) : sizeof(sampl_t); + const int flags = comedi_get_subdevice_flags(c->dev, d->subdevice); + d->sample_size = (flags & SDF_LSAMPL) ? sizeof(lsampl_t) : sizeof(sampl_t); - // Set buffer size - comedi_set_buffer_size(c->dev, d->subdevice, d->buffer_size); - comedi_set_max_buffer_size(c->dev, d->subdevice, d->buffer_size); - ret = comedi_get_buffer_size(c->dev, d->subdevice); - if (ret != d->buffer_size) - throw RuntimeError("Failed to set buffer size for subdevice {}", d->subdevice); + // Set buffer size + comedi_set_buffer_size(c->dev, d->subdevice, d->buffer_size); + comedi_set_max_buffer_size(c->dev, d->subdevice, d->buffer_size); + ret = comedi_get_buffer_size(c->dev, d->subdevice); + if (ret != d->buffer_size) + throw RuntimeError("Failed to set buffer size for subdevice {}", + d->subdevice); - n->logger->info("Set buffer size for subdevice {} to {} bytes", d->subdevice, d->buffer_size); + n->logger->info("Set buffer size for subdevice {} to {} bytes", + d->subdevice, d->buffer_size); - ret = comedi_lock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - } + ret = comedi_lock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + } - return 0; + return 0; } -static -int comedi_start_in(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +static int comedi_start_in(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - // Try to find first analog input subdevice if not specified in config - if (d->subdevice < 0) { - d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AI, 0); - if (d->subdevice < 0) - throw RuntimeError("Cannot find analog input device for node '{}'"); - } - else { - // Check if subdevice is usable - ret = comedi_get_subdevice_type(c->dev, d->subdevice); - if (ret != COMEDI_SUBD_AI) - throw RuntimeError("Input subdevice is not an analog input"); - } + // Try to find first analog input subdevice if not specified in config + if (d->subdevice < 0) { + d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AI, 0); + if (d->subdevice < 0) + throw RuntimeError("Cannot find analog input device for node '{}'"); + } else { + // Check if subdevice is usable + ret = comedi_get_subdevice_type(c->dev, d->subdevice); + if (ret != COMEDI_SUBD_AI) + throw RuntimeError("Input subdevice is not an analog input"); + } - ret = comedi_get_subdevice_flags(c->dev, d->subdevice); - if (ret < 0 || !(ret & SDF_CMD_READ)) - throw RuntimeError("Input subdevice does not support 'read' commands"); + ret = comedi_get_subdevice_flags(c->dev, d->subdevice); + if (ret < 0 || !(ret & SDF_CMD_READ)) + throw RuntimeError("Input subdevice does not support 'read' commands"); - comedi_set_read_subdevice(c->dev, d->subdevice); - ret = comedi_get_read_subdevice(c->dev); - if (ret < 0 || ret != d->subdevice) - throw RuntimeError("Failed to change 'read' subdevice from {} to {}", ret, d->subdevice); + comedi_set_read_subdevice(c->dev, d->subdevice); + ret = comedi_get_read_subdevice(c->dev); + if (ret < 0 || ret != d->subdevice) + throw RuntimeError("Failed to change 'read' subdevice from {} to {}", ret, + d->subdevice); - comedi_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); + comedi_cmd cmd; + memset(&cmd, 0, sizeof(cmd)); - cmd.subdev = d->subdevice; + cmd.subdev = d->subdevice; - /* Make card send interrupts after every sample, not only when fifo is half + /* Make card send interrupts after every sample, not only when fifo is half * full (TODO: evaluate if this makes sense, leave as reminder) */ - //cmd.flags = TRIG_WAKE_EOS; + //cmd.flags = TRIG_WAKE_EOS; - // Start right now - cmd.start_src = TRIG_NOW; + // Start right now + cmd.start_src = TRIG_NOW; - // Trigger scans periodically - cmd.scan_begin_src = TRIG_TIMER; - cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; + // Trigger scans periodically + cmd.scan_begin_src = TRIG_TIMER; + cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; - // Do conversions in serial with 1ns inter-conversion delay - cmd.convert_src = TRIG_TIMER; - cmd.convert_arg = 1; // Inter-conversion delay in nanoseconds + // Do conversions in serial with 1ns inter-conversion delay + cmd.convert_src = TRIG_TIMER; + cmd.convert_arg = 1; // Inter-conversion delay in nanoseconds - // Terminate scan after each channel has been converted - cmd.scan_end_src = TRIG_COUNT; - cmd.scan_end_arg = d->chanlist_len; + // Terminate scan after each channel has been converted + cmd.scan_end_src = TRIG_COUNT; + cmd.scan_end_arg = d->chanlist_len; - // Contionous sampling - cmd.stop_src = TRIG_NONE; + // Contionous sampling + cmd.stop_src = TRIG_NONE; - cmd.chanlist = d->chanlist; - cmd.chanlist_len = d->chanlist_len; + cmd.chanlist = d->chanlist; + cmd.chanlist_len = d->chanlist_len; - // First run might change command, second should return successfully - ret = comedi_command_test(c->dev, &cmd); - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + // First run might change command, second should return successfully + ret = comedi_command_test(c->dev, &cmd); + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - n->logger->info("Input command:"); - comedi_dump_cmd(n->logger, &cmd); + n->logger->info("Input command:"); + comedi_dump_cmd(n->logger, &cmd); - ret = comedi_command(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Failed to issue command to input subdevice"); + ret = comedi_command(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Failed to issue command to input subdevice"); - d->started = time_now(); - d->counter = 0; - d->running = true; + d->started = time_now(); + d->counter = 0; + d->running = true; #if COMEDI_USE_READ - // Be prepared to consume one entire buffer - c->buf = new char[c->in.buffer_size]; - c->bufptr = c->buf; - if (!c->buf) - throw MemoryAllocationError(); + // Be prepared to consume one entire buffer + c->buf = new char[c->in.buffer_size]; + c->bufptr = c->buf; + if (!c->buf) + throw MemoryAllocationError(); - n->logger->info("Compiled for kernel read() interface"); + n->logger->info("Compiled for kernel read() interface"); #else - n->logger->info("Compiled for kernel mmap() interface"); + n->logger->info("Compiled for kernel mmap() interface"); #endif - return 0; + return 0; } -static -int comedi_start_out(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +static int comedi_start_out(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - // Try to find first analog output subdevice if not specified in config - if (d->subdevice < 0) { - d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AO, 0); - if (d->subdevice < 0) - throw RuntimeError("Cannot find analog output device"); - } - else { - ret = comedi_get_subdevice_type(c->dev, d->subdevice); - if (ret != COMEDI_SUBD_AO) - throw RuntimeError("Output subdevice is not an analog output"); - } + // Try to find first analog output subdevice if not specified in config + if (d->subdevice < 0) { + d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AO, 0); + if (d->subdevice < 0) + throw RuntimeError("Cannot find analog output device"); + } else { + ret = comedi_get_subdevice_type(c->dev, d->subdevice); + if (ret != COMEDI_SUBD_AO) + throw RuntimeError("Output subdevice is not an analog output"); + } - ret = comedi_get_subdevice_flags(c->dev, d->subdevice); - if (ret < 0 || !(ret & SDF_CMD_WRITE)) - throw RuntimeError("Output subdevice does not support 'write' commands"); + ret = comedi_get_subdevice_flags(c->dev, d->subdevice); + if (ret < 0 || !(ret & SDF_CMD_WRITE)) + throw RuntimeError("Output subdevice does not support 'write' commands"); - comedi_set_write_subdevice(c->dev, d->subdevice); - ret = comedi_get_write_subdevice(c->dev); - if (ret < 0 || ret != d->subdevice) - throw RuntimeError("Failed to change 'write' subdevice from {} to {}", ret, d->subdevice); + comedi_set_write_subdevice(c->dev, d->subdevice); + ret = comedi_get_write_subdevice(c->dev); + if (ret < 0 || ret != d->subdevice) + throw RuntimeError("Failed to change 'write' subdevice from {} to {}", ret, + d->subdevice); - comedi_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); + comedi_cmd cmd; + memset(&cmd, 0, sizeof(cmd)); - cmd.subdev = d->subdevice; + cmd.subdev = d->subdevice; - cmd.flags = CMDF_WRITE; + cmd.flags = CMDF_WRITE; - // Wait for internal trigger, we will have to fill the buffer first - cmd.start_src = TRIG_INT; - cmd.start_arg = 0; + // Wait for internal trigger, we will have to fill the buffer first + cmd.start_src = TRIG_INT; + cmd.start_arg = 0; - cmd.scan_begin_src = TRIG_TIMER; - cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; + cmd.scan_begin_src = TRIG_TIMER; + cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; - cmd.convert_src = TRIG_NOW; - cmd.convert_arg = 0; + cmd.convert_src = TRIG_NOW; + cmd.convert_arg = 0; - cmd.scan_end_src = TRIG_COUNT; - cmd.scan_end_arg = d->chanlist_len; + cmd.scan_end_src = TRIG_COUNT; + cmd.scan_end_arg = d->chanlist_len; - // Continous sampling - cmd.stop_src = TRIG_NONE; - cmd.stop_arg = 0; + // Continous sampling + cmd.stop_src = TRIG_NONE; + cmd.stop_arg = 0; - cmd.chanlist = d->chanlist; - cmd.chanlist_len = d->chanlist_len; + cmd.chanlist = d->chanlist; + cmd.chanlist_len = d->chanlist_len; - // First run might change command, second should return successfully - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + // First run might change command, second should return successfully + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - n->logger->info("Output command:"); - comedi_dump_cmd(n->logger, &cmd); + n->logger->info("Output command:"); + comedi_dump_cmd(n->logger, &cmd); - ret = comedi_command(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Failed to issue command to input subdevice of node '{}'"); + ret = comedi_command(c->dev, &cmd); + if (ret < 0) + throw RuntimeError( + "Failed to issue command to input subdevice of node '{}'"); - // Output will only start after the internal trigger - d->running = false; - d->last_debug = time_now(); + // Output will only start after the internal trigger + d->running = false; + d->last_debug = time_now(); - // Allocate buffer for one complete VILLAS sample - // TODO: maybe increase buffer size according to c->vectorize - const size_t local_buffer_size = d->sample_size * d->chanlist_len; - d->buffer = new char[local_buffer_size]; - d->bufptr = d->buffer; - if (!d->buffer) - throw MemoryAllocationError(); + // Allocate buffer for one complete VILLAS sample + // TODO: maybe increase buffer size according to c->vectorize + const size_t local_buffer_size = d->sample_size * d->chanlist_len; + d->buffer = new char[local_buffer_size]; + d->bufptr = d->buffer; + if (!d->buffer) + throw MemoryAllocationError(); - // Initialize local buffer used for write() syscalls - for (unsigned channel = 0; channel < d->chanlist_len; channel++) { - const unsigned raw = comedi_from_phys(0.0f, d->chanspecs[channel].range, d->chanspecs[channel].maxdata); + // Initialize local buffer used for write() syscalls + for (unsigned channel = 0; channel < d->chanlist_len; channel++) { + const unsigned raw = comedi_from_phys(0.0f, d->chanspecs[channel].range, + d->chanspecs[channel].maxdata); - if (d->sample_size == sizeof(sampl_t)) - *((sampl_t *)d->bufptr) = raw; - else - *((lsampl_t *)d->bufptr) = raw; + if (d->sample_size == sizeof(sampl_t)) + *((sampl_t *)d->bufptr) = raw; + else + *((lsampl_t *)d->bufptr) = raw; - d->bufptr += d->sample_size; - } + d->bufptr += d->sample_size; + } - // Preload comedi output buffer - for (unsigned i = 0; i < d->buffer_size / local_buffer_size; i++) { - size_t written = write(comedi_fileno(c->dev), d->buffer, local_buffer_size); - if (written != local_buffer_size) { - throw RuntimeError("Cannot preload Comedi buffer"); - } - } + // Preload comedi output buffer + for (unsigned i = 0; i < d->buffer_size / local_buffer_size; i++) { + size_t written = write(comedi_fileno(c->dev), d->buffer, local_buffer_size); + if (written != local_buffer_size) { + throw RuntimeError("Cannot preload Comedi buffer"); + } + } - const size_t villas_samples_in_kernel_buf = d->buffer_size / (d->sample_size * d->chanlist_len); - const double latencyMs = (double) villas_samples_in_kernel_buf / d->sample_rate_hz * 1e3; - n->logger->info("Added latency due to buffering: {:4.1f} ms", latencyMs); + const size_t villas_samples_in_kernel_buf = + d->buffer_size / (d->sample_size * d->chanlist_len); + const double latencyMs = + (double)villas_samples_in_kernel_buf / d->sample_rate_hz * 1e3; + n->logger->info("Added latency due to buffering: {:4.1f} ms", latencyMs); - return 0; + return 0; } -static -int comedi_stop_in(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +static int comedi_stop_in(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - comedi_cancel(c->dev, d->subdevice); + comedi_cancel(c->dev, d->subdevice); - ret = comedi_unlock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + ret = comedi_unlock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - return 0; + return 0; } -static -int comedi_stop_out(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +static int comedi_stop_out(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - comedi_cancel(c->dev, d->subdevice); + comedi_cancel(c->dev, d->subdevice); - ret = comedi_unlock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + ret = comedi_unlock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - return 0; + return 0; } -int villas::node::comedi_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *c = n->getData(); +int villas::node::comedi_parse(NodeCompat *n, json_t *json) { + int ret; + auto *c = n->getData(); - const char *device; + const char *device; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_error_t err; + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: o }", - "device", &device, - "in", &json_in, - "out", &json_out); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: o }", "device", + &device, "in", &json_in, "out", &json_out); - if (ret) - throw ConfigError(json, err, "node-config-node-comedi"); + if (ret) + throw ConfigError(json, err, "node-config-node-comedi"); - c->in.present = json_in != nullptr; - c->in.enabled = false; - c->in.running = false; + c->in.present = json_in != nullptr; + c->in.enabled = false; + c->in.running = false; - c->out.present = json_out != nullptr; - c->out.enabled = false; - c->out.running = false; + c->out.present = json_out != nullptr; + c->out.enabled = false; + c->out.running = false; - if (c->in.present) { - ret = comedi_parse_direction(c, &c->in, json_in); - if (ret) - return ret; - } + if (c->in.present) { + ret = comedi_parse_direction(c, &c->in, json_in); + if (ret) + return ret; + } - if (c->out.present) { - ret = comedi_parse_direction(c, &c->out, json_out); - if (ret) - return ret; - } + if (c->out.present) { + ret = comedi_parse_direction(c, &c->out, json_out); + if (ret) + return ret; + } - c->device = strdup(device); + c->device = strdup(device); - return 0; + return 0; } -char * villas::node::comedi_print(NodeCompat *n) -{ - auto *c = n->getData(); +char *villas::node::comedi_print(NodeCompat *n) { + auto *c = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - const char *board = comedi_get_board_name(c->dev); - const char *driver = comedi_get_driver_name(c->dev); + const char *board = comedi_get_board_name(c->dev); + const char *driver = comedi_get_driver_name(c->dev); - strcatf(&buf, "board=%s, driver=%s, device=%s", board, driver, c->device); + strcatf(&buf, "board=%s, driver=%s, device=%s", board, driver, c->device); - return buf; + return buf; } -int villas::node::comedi_start(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::comedi_start(NodeCompat *n) { + auto *c = n->getData(); - c->dev = comedi_open(c->device); - if (!c->dev) - throw RuntimeError("Failed to open device: {}", comedi_strerror(comedi_errno())); + c->dev = comedi_open(c->device); + if (!c->dev) + throw RuntimeError("Failed to open device: {}", + comedi_strerror(comedi_errno())); - // Enable non-blocking syscalls - // TODO: verify if this works with both input and output, so comment out - //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) - // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); + // Enable non-blocking syscalls + // TODO: verify if this works with both input and output, so comment out + //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) + // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); - comedi_start_common(n); + comedi_start_common(n); - if (c->in.present) { - int ret = comedi_start_in(n); - if (ret) - return ret; + if (c->in.present) { + int ret = comedi_start_in(n); + if (ret) + return ret; - c->in.enabled = true; - } + c->in.enabled = true; + } - if (c->out.present) { - int ret = comedi_start_out(n); - if (ret) - return ret; + if (c->out.present) { + int ret = comedi_start_out(n); + if (ret) + return ret; - c->out.enabled = true; - } + c->out.enabled = true; + } #if !COMEDI_USE_READ - n->logger->info("Mapping Comedi buffer of {} bytes", c->in.buffer_size); - c->map = mmap(nullptr, c->in.buffer_size, PROT_READ, MAP_SHARED, comedi_fileno(c->dev), 0); - if (c->map == MAP_FAILED) - throw RuntimeError("Failed to map Comedi buffer"); + n->logger->info("Mapping Comedi buffer of {} bytes", c->in.buffer_size); + c->map = mmap(nullptr, c->in.buffer_size, PROT_READ, MAP_SHARED, + comedi_fileno(c->dev), 0); + if (c->map == MAP_FAILED) + throw RuntimeError("Failed to map Comedi buffer"); - c->front = 0; - c->back = 0; - c->bufpos = 0; + c->front = 0; + c->back = 0; + c->bufpos = 0; #endif - return 0; + return 0; } -int villas::node::comedi_stop(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); +int villas::node::comedi_stop(NodeCompat *n) { + int ret; + auto *c = n->getData(); - if (c->in.enabled) - comedi_stop_in(n); + if (c->in.enabled) + comedi_stop_in(n); - if (c->out.enabled) - comedi_stop_out(n); + if (c->out.enabled) + comedi_stop_out(n); - ret = comedi_close(c->dev); - if (ret) - return ret; + ret = comedi_close(c->dev); + if (ret) + return ret; - return 0; + return 0; } #if COMEDI_USE_READ -int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; - const size_t villas_sample_size = d->chanlist_len * d->sample_size; +int villas::node::comedi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; + const size_t villas_sample_size = d->chanlist_len * d->sample_size; - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - fd_set rdset; - FD_ZERO(&rdset); - FD_SET(comedi_fileno(c->dev), &rdset); + fd_set rdset; + FD_ZERO(&rdset); + FD_SET(comedi_fileno(c->dev), &rdset); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 5000; + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 5000; - ret = select(comedi_fileno(c->dev) + 1, &rdset, nullptr, nullptr, &timeout); - if (ret < 0) - throw RuntimeError("Failed select()"); - else if (ret == 0) // hit timeout - return 0; - else if (FD_ISSET(comedi_fileno(c->dev), &rdset)) { // comedi file descriptor became ready - const size_t buffer_bytes_free = d->buffer_size - (c->bufptr - c->buf); - const size_t bytes_requested = cnt * villas_sample_size; + ret = select(comedi_fileno(c->dev) + 1, &rdset, nullptr, nullptr, &timeout); + if (ret < 0) + throw RuntimeError("Failed select()"); + else if (ret == 0) // hit timeout + return 0; + else if (FD_ISSET(comedi_fileno(c->dev), + &rdset)) { // comedi file descriptor became ready + const size_t buffer_bytes_free = d->buffer_size - (c->bufptr - c->buf); + const size_t bytes_requested = cnt * villas_sample_size; - ret = read(comedi_fileno(c->dev), c->bufptr, MIN(bytes_requested, buffer_bytes_free)); - if (ret < 0) { - if (errno == EAGAIN) - throw RuntimeError("Failed read()"); - else - return 0; - } - else if (ret == 0) { - n->logger->warn("Timeout in select(), no samples available"); - return 0; - } - else { - // Sample handling here - const size_t bytes_available = ret; - const size_t raw_samples_available = bytes_available / d->sample_size; - const size_t villas_samples_available = raw_samples_available / d->chanlist_len; + ret = read(comedi_fileno(c->dev), c->bufptr, + MIN(bytes_requested, buffer_bytes_free)); + if (ret < 0) { + if (errno == EAGAIN) + throw RuntimeError("Failed read()"); + else + return 0; + } else if (ret == 0) { + n->logger->warn("Timeout in select(), no samples available"); + return 0; + } else { + // Sample handling here + const size_t bytes_available = ret; + const size_t raw_samples_available = bytes_available / d->sample_size; + const size_t villas_samples_available = + raw_samples_available / d->chanlist_len; - n->logger->info("There are {} bytes available ({} requested) => {} VILLAS samples", - bytes_available, bytes_requested, villas_samples_available); + n->logger->info( + "There are {} bytes available ({} requested) => {} VILLAS samples", + bytes_available, bytes_requested, villas_samples_available); - if (cnt > villas_samples_available) - cnt = villas_samples_available; + if (cnt > villas_samples_available) + cnt = villas_samples_available; - for (size_t i = 0; i < cnt; i++) { - d->counter++; + for (size_t i = 0; i < cnt; i++) { + d->counter++; - smps[i]->signals = n->getInputSignals(false); - smps[i]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - smps[i]->sequence = d->counter / d->chanlist_len; + smps[i]->signals = n->getInputSignals(false); + smps[i]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + smps[i]->sequence = d->counter / d->chanlist_len; - struct timespec offset = time_from_double(d->counter * 1.0 / d->sample_rate_hz); - smps[i]->ts.origin = time_add(&d->started, &offset); + struct timespec offset = + time_from_double(d->counter * 1.0 / d->sample_rate_hz); + smps[i]->ts.origin = time_add(&d->started, &offset); - smps[i]->length = d->chanlist_len; + smps[i]->length = d->chanlist_len; - if (smps[i]->capacity < d->chanlist_len) - throw RuntimeError("Sample has insufficient capacity: {} < {}", smps[i]->capacity, d->chanlist_len); + if (smps[i]->capacity < d->chanlist_len) + throw RuntimeError("Sample has insufficient capacity: {} < {}", + smps[i]->capacity, d->chanlist_len); - for (unsigned si = 0; si < d->chanlist_len; si++) { - unsigned int raw; + for (unsigned si = 0; si < d->chanlist_len; si++) { + unsigned int raw; - if (d->sample_size == sizeof(sampl_t)) - raw = *((sampl_t *)(c->bufptr)); - else - raw = *((lsampl_t *)(c->bufptr)); + if (d->sample_size == sizeof(sampl_t)) + raw = *((sampl_t *)(c->bufptr)); + else + raw = *((lsampl_t *)(c->bufptr)); - c->bufptr += d->sample_size; + c->bufptr += d->sample_size; - smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); + smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, + d->chanspecs[si].maxdata); - if (std::isnan(smps[i]->data[si].f)) - n->logger->warn("Input: channel {} clipped", CR_CHAN(d->chanlist[si])); - } - } + if (std::isnan(smps[i]->data[si].f)) + n->logger->warn("Input: channel {} clipped", + CR_CHAN(d->chanlist[si])); + } + } - const size_t bytes_consumed = cnt * villas_sample_size; - const size_t bytes_left = bytes_available - bytes_consumed; - if (bytes_left > 0) { - // Move leftover bytes to the beginning of buffer - // TODO: optimize? - memmove(c->buf, c->bufptr, bytes_left); - } + const size_t bytes_consumed = cnt * villas_sample_size; + const size_t bytes_left = bytes_available - bytes_consumed; + if (bytes_left > 0) { + // Move leftover bytes to the beginning of buffer + // TODO: optimize? + memmove(c->buf, c->bufptr, bytes_left); + } - n->logger->info("Consumed {} bytes", bytes_consumed); + n->logger->info("Consumed {} bytes", bytes_consumed); - // Start at the beginning again - c->bufptr = c->buf; + // Start at the beginning again + c->bufptr = c->buf; - return cnt; - } - } - else - // unknown file descriptor became ready - n->logger->warn("Unknown file descriptor ready"); + return cnt; + } + } else + // unknown file descriptor became ready + n->logger->warn("Unknown file descriptor ready"); - return -1; + return -1; } #else -int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +int villas::node::comedi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - const size_t villas_sample_size = d->chanlist_len * d->sample_size; + const size_t villas_sample_size = d->chanlist_len * d->sample_size; - comedi_set_read_subdevice(c->dev, d->subdevice); + comedi_set_read_subdevice(c->dev, d->subdevice); - n->logger->info("Current bufpos={}", c->bufpos); + n->logger->info("Current bufpos={}", c->bufpos); #if 0 if (c->bufpos > (d->buffer_size - villas_sample_size)) { @@ -639,23 +637,24 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret == 0) - return 0; - else if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret == 0) + return 0; + else if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - const size_t bytes_available = ret; - const size_t raw_sample_count = bytes_available / d->sample_size; - size_t villas_sample_count = raw_sample_count / d->chanlist_len; - if (villas_sample_count == 0) - return 0; + const size_t bytes_available = ret; + const size_t raw_sample_count = bytes_available / d->sample_size; + size_t villas_sample_count = raw_sample_count / d->chanlist_len; + if (villas_sample_count == 0) + return 0; - n->logger->info("There are {} VILLAS samples ({} raw bytes, {} channels)", villas_sample_count, bytes_available, d->chanlist_len); + n->logger->info("There are {} VILLAS samples ({} raw bytes, {} channels)", + villas_sample_count, bytes_available, d->chanlist_len); #if 0 if (villas_sample_count == 1) @@ -669,8 +668,8 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - if (cnt > villas_sample_count) - cnt = villas_sample_count; + if (cnt > villas_sample_count) + cnt = villas_sample_count; #if 0 if (bytes_available != 0 && bytes_available < villas_sample_size) { @@ -684,74 +683,81 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - const size_t samples_total_bytes = cnt * villas_sample_size; + const size_t samples_total_bytes = cnt * villas_sample_size; - ret = comedi_mark_buffer_read(c->dev, d->subdevice, samples_total_bytes); - if (ret == 0) { - n->logger->warn("Marking read buffer ({} bytes) not working, try again later", samples_total_bytes); - return 0; - } - else if (ret != samples_total_bytes) { - n->logger->warn("Can only mark {} bytes as read, reducing samples", ret); - return 0; - } - else - n->logger->info("Consume {} bytes", ret); + ret = comedi_mark_buffer_read(c->dev, d->subdevice, samples_total_bytes); + if (ret == 0) { + n->logger->warn( + "Marking read buffer ({} bytes) not working, try again later", + samples_total_bytes); + return 0; + } else if (ret != samples_total_bytes) { + n->logger->warn("Can only mark {} bytes as read, reducing samples", ret); + return 0; + } else + n->logger->info("Consume {} bytes", ret); - // Align front to whole samples - c->front = c->back + samples_total_bytes; + // Align front to whole samples + c->front = c->back + samples_total_bytes; - for (size_t i = 0; i < cnt; i++) { - d->counter++; + for (size_t i = 0; i < cnt; i++) { + d->counter++; - smps[i]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - smps[i]->sequence = d->counter / d->chanlist_len; + smps[i]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + smps[i]->sequence = d->counter / d->chanlist_len; - struct timespec offset = time_from_double(d->counter * 1.0 / d->sample_rate_hz); - smps[i]->ts.origin = time_add(&d->started, &offset); + struct timespec offset = + time_from_double(d->counter * 1.0 / d->sample_rate_hz); + smps[i]->ts.origin = time_add(&d->started, &offset); - smps[i]->length = d->chanlist_len; + smps[i]->length = d->chanlist_len; - if (smps[i]->capacity < d->chanlist_len) - throw RuntimeError("Sample has insufficient capacity: {} < {}", smps[i]->capacity, d->chanlist_len); + if (smps[i]->capacity < d->chanlist_len) + throw RuntimeError("Sample has insufficient capacity: {} < {}", + smps[i]->capacity, d->chanlist_len); - for (int si = 0; si < d->chanlist_len; si++) { - unsigned int raw; + for (int si = 0; si < d->chanlist_len; si++) { + unsigned int raw; - if (d->sample_size == sizeof(sampl_t)) - raw = *((sampl_t *)(c->map + c->bufpos)); - else - raw = *((lsampl_t *)(c->map + c->bufpos)); + if (d->sample_size == sizeof(sampl_t)) + raw = *((sampl_t *)(c->map + c->bufpos)); + else + raw = *((lsampl_t *)(c->map + c->bufpos)); - smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); + smps[i]->data[si].f = + comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); - if (isnan(smps[i]->data[si].f)) - throw RuntimeError("Got nan"); + if (isnan(smps[i]->data[si].f)) + throw RuntimeError("Got nan"); -// smps[i]->data[si].i = raw; + // smps[i]->data[si].i = raw; - c->bufpos += d->sample_size; - if (c->bufpos >= d->buffer_size) { - n->logger->warn("Read buffer wraparound"); -// c->bufpos = 0; - } - } - } + c->bufpos += d->sample_size; + if (c->bufpos >= d->buffer_size) { + n->logger->warn("Read buffer wraparound"); + // c->bufpos = 0; + } + } + } -// const size_t bytes_consumed = c->front - c->back; + // const size_t bytes_consumed = c->front - c->back; -// n->logger->info("Advance Comedi buffer by {} bytes", bytes_consumed); + // n->logger->info("Advance Comedi buffer by {} bytes", bytes_consumed); - ret = comedi_get_buffer_read_offset(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() != EPIPE) - throw RuntimeError("Failed to get read buffer offset: {}, Comedi error {}", ret, comedi_strerror(comedi_errno())); - else - ret = c->bufpos; - } + ret = comedi_get_buffer_read_offset(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() != EPIPE) + throw RuntimeError( + "Failed to get read buffer offset: {}, Comedi error {}", ret, + comedi_strerror(comedi_errno())); + else + ret = c->bufpos; + } - n->logger->warn("Change bufpos: {} to {}", c->bufpos, ret); - c->bufpos = ret; + n->logger->warn("Change bufpos: {} to {}", c->bufpos, ret); + c->bufpos = ret; #if 0 ret = comedi_mark_buffer_read(c->dev, d->subdevice, bytes_consumed); @@ -785,207 +791,217 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif -// n->logger->info("New bufpos: {}", c->bufpos); + // n->logger->info("New bufpos: {}", c->bufpos); - c->back = c->front; + c->back = c->front; - return cnt; + return cnt; } #endif -int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +int villas::node::comedi_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - if (!d->enabled) { - n->logger->warn("Attempting to write, but output is not enabled"); - return 0; - } + if (!d->enabled) { + n->logger->warn("Attempting to write, but output is not enabled"); + return 0; + } - if (!d->running) { - // Output was not yet running, so start now - ret = comedi_internal_trigger(c->dev, d->subdevice, 0); - if (ret < 0) - throw RuntimeError("Failed to trigger-start output"); + if (!d->running) { + // Output was not yet running, so start now + ret = comedi_internal_trigger(c->dev, d->subdevice, 0); + if (ret < 0) + throw RuntimeError("Failed to trigger-start output"); - d->started = time_now(); - d->counter = 0; - d->running = true; + d->started = time_now(); + d->counter = 0; + d->running = true; - n->logger->info("Starting output"); - } + n->logger->info("Starting output"); + } - const size_t buffer_capacity_raw = d->buffer_size / d->sample_size; - const size_t buffer_capacity_villas = buffer_capacity_raw / d->chanlist_len; - const size_t villas_sample_size = d->sample_size * d->chanlist_len; + const size_t buffer_capacity_raw = d->buffer_size / d->sample_size; + const size_t buffer_capacity_villas = buffer_capacity_raw / d->chanlist_len; + const size_t villas_sample_size = d->sample_size * d->chanlist_len; - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - const size_t bytes_in_buffer = ret; - const size_t raw_samples_in_buffer = bytes_in_buffer / d->sample_size; - const size_t villas_samples_in_buffer = raw_samples_in_buffer / d->chanlist_len; + const size_t bytes_in_buffer = ret; + const size_t raw_samples_in_buffer = bytes_in_buffer / d->sample_size; + const size_t villas_samples_in_buffer = + raw_samples_in_buffer / d->chanlist_len; - if (villas_samples_in_buffer == buffer_capacity_villas) { - n->logger->warn("Comedi buffer is full"); - return 0; - } - else { - struct timespec now = time_now(); - if (time_delta(&d->last_debug, &now) >= 1) { - n->logger->debug("Comedi write buffer: {} VILLAS samples ({}% of buffer)", - villas_samples_in_buffer, - (100.0f * villas_samples_in_buffer / buffer_capacity_villas)); + if (villas_samples_in_buffer == buffer_capacity_villas) { + n->logger->warn("Comedi buffer is full"); + return 0; + } else { + struct timespec now = time_now(); + if (time_delta(&d->last_debug, &now) >= 1) { + n->logger->debug( + "Comedi write buffer: {} VILLAS samples ({}% of buffer)", + villas_samples_in_buffer, + (100.0f * villas_samples_in_buffer / buffer_capacity_villas)); - d->last_debug = time_now(); - } - } + d->last_debug = time_now(); + } + } - size_t villas_samples_written = 0; + size_t villas_samples_written = 0; - while (villas_samples_written < cnt) { - const struct Sample *sample = smps[villas_samples_written]; - if (sample->length != d->chanlist_len) - throw RuntimeError("Value count in sample ({}) != configured output channels ({})", sample->length, d->chanlist_len); + while (villas_samples_written < cnt) { + const struct Sample *sample = smps[villas_samples_written]; + if (sample->length != d->chanlist_len) + throw RuntimeError( + "Value count in sample ({}) != configured output channels ({})", + sample->length, d->chanlist_len); - d->bufptr = d->buffer; + d->bufptr = d->buffer; - // Move samples from villas into local buffer for comedi - for (unsigned si = 0; si < sample->length; si++) { - unsigned raw_value = 0; + // Move samples from villas into local buffer for comedi + for (unsigned si = 0; si < sample->length; si++) { + unsigned raw_value = 0; - switch (sample_format(sample, si)) { - case SignalType::FLOAT: - raw_value = comedi_from_phys(sample->data[si].f, d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + switch (sample_format(sample, si)) { + case SignalType::FLOAT: + raw_value = comedi_from_phys(sample->data[si].f, d->chanspecs[si].range, + d->chanspecs[si].maxdata); + break; - case SignalType::INTEGER: - // Treat sample as already raw DAC value - raw_value = sample->data[si].i; - break; + case SignalType::INTEGER: + // Treat sample as already raw DAC value + raw_value = sample->data[si].i; + break; - case SignalType::BOOLEAN: - raw_value = comedi_from_phys(sample->data[si].b ? 1 : 0, d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + case SignalType::BOOLEAN: + raw_value = + comedi_from_phys(sample->data[si].b ? 1 : 0, d->chanspecs[si].range, + d->chanspecs[si].maxdata); + break; - case SignalType::COMPLEX: - // We only output the real part - raw_value = comedi_from_phys(std::real(sample->data[si].z), d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + case SignalType::COMPLEX: + // We only output the real part + raw_value = + comedi_from_phys(std::real(sample->data[si].z), + d->chanspecs[si].range, d->chanspecs[si].maxdata); + break; - case SignalType::INVALID: - raw_value = 0; - break; - } + case SignalType::INVALID: + raw_value = 0; + break; + } - if (d->sample_size == sizeof(sampl_t)) - *((sampl_t *)d->bufptr) = raw_value; - else - *((lsampl_t *)d->bufptr) = raw_value; + if (d->sample_size == sizeof(sampl_t)) + *((sampl_t *)d->bufptr) = raw_value; + else + *((lsampl_t *)d->bufptr) = raw_value; - d->bufptr += d->sample_size; - } + d->bufptr += d->sample_size; + } - // Try to write one complete villas sample to comedi - size_t written = write(comedi_fileno(c->dev), d->buffer, villas_sample_size); - if (written < 0) - throw RuntimeError("write() failed"); - else if (written == 0) - break; // Comedi doesn't accept any more samples at the moment - else if (written == villas_sample_size) - villas_samples_written++; - else - throw RuntimeError("Only partial sample written ({} bytes), oops", written); - } + // Try to write one complete villas sample to comedi + size_t written = + write(comedi_fileno(c->dev), d->buffer, villas_sample_size); + if (written < 0) + throw RuntimeError("write() failed"); + else if (written == 0) + break; // Comedi doesn't accept any more samples at the moment + else if (written == villas_sample_size) + villas_samples_written++; + else + throw RuntimeError("Only partial sample written ({} bytes), oops", + written); + } - if (villas_samples_written == 0) - n->logger->warn("Nothing done"); + if (villas_samples_written == 0) + n->logger->warn("Nothing done"); - d->counter += villas_samples_written; + d->counter += villas_samples_written; - return villas_samples_written; + return villas_samples_written; } -static -char* comedi_cmd_trigger_src(unsigned int src, char *buf) -{ - buf[0] = 0; +static char *comedi_cmd_trigger_src(unsigned int src, char *buf) { + buf[0] = 0; - if (src & TRIG_NONE) strcat(buf, "none|"); - if (src & TRIG_NOW) strcat(buf, "now|"); - if (src & TRIG_FOLLOW) strcat(buf, "follow|"); - if (src & TRIG_TIME) strcat(buf, "time|"); - if (src & TRIG_TIMER) strcat(buf, "timer|"); - if (src & TRIG_COUNT) strcat(buf, "count|"); - if (src & TRIG_EXT) strcat(buf, "ext|"); - if (src & TRIG_INT) strcat(buf, "int|"); + if (src & TRIG_NONE) + strcat(buf, "none|"); + if (src & TRIG_NOW) + strcat(buf, "now|"); + if (src & TRIG_FOLLOW) + strcat(buf, "follow|"); + if (src & TRIG_TIME) + strcat(buf, "time|"); + if (src & TRIG_TIMER) + strcat(buf, "timer|"); + if (src & TRIG_COUNT) + strcat(buf, "count|"); + if (src & TRIG_EXT) + strcat(buf, "ext|"); + if (src & TRIG_INT) + strcat(buf, "int|"); - if (strlen(buf) == 0) - sprintf(buf, "unknown(0x%08x)", src); - else - buf[strlen(buf) - 1] = 0; + if (strlen(buf) == 0) + sprintf(buf, "unknown(0x%08x)", src); + else + buf[strlen(buf) - 1] = 0; - return buf; + return buf; } -static -void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) -{ - char buf[256]; - char* src; +static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) { + char buf[256]; + char *src; - logger->debug("subdevice: {}", cmd->subdev); + logger->debug("subdevice: {}", cmd->subdev); - src = comedi_cmd_trigger_src(cmd->start_src, buf); - logger->debug("start: {:-8s} {}", src, cmd->start_arg); + src = comedi_cmd_trigger_src(cmd->start_src, buf); + logger->debug("start: {:-8s} {}", src, cmd->start_arg); - src = comedi_cmd_trigger_src(cmd->scan_begin_src, buf); - logger->debug("scan_begin: {:-8s} {}", src, cmd->scan_begin_arg); + src = comedi_cmd_trigger_src(cmd->scan_begin_src, buf); + logger->debug("scan_begin: {:-8s} {}", src, cmd->scan_begin_arg); - src = comedi_cmd_trigger_src(cmd->convert_src, buf); - logger->debug("convert: {:-8s} {}", src, cmd->convert_arg); + src = comedi_cmd_trigger_src(cmd->convert_src, buf); + logger->debug("convert: {:-8s} {}", src, cmd->convert_arg); - src = comedi_cmd_trigger_src(cmd->scan_end_src, buf); - logger->debug("scan_end: {:-8s} {}", src, cmd->scan_end_arg); + src = comedi_cmd_trigger_src(cmd->scan_end_src, buf); + logger->debug("scan_end: {:-8s} {}", src, cmd->scan_end_arg); - src = comedi_cmd_trigger_src(cmd->stop_src,buf); - logger->debug("stop: {:-8s} {}", src, cmd->stop_arg); + src = comedi_cmd_trigger_src(cmd->stop_src, buf); + logger->debug("stop: {:-8s} {}", src, cmd->stop_arg); } -int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) -{ - auto *c = n->getData(); +int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) { + auto *c = n->getData(); - fds[0] = comedi_fileno(c->dev); + fds[0] = comedi_fileno(c->dev); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "comedi"; - p.description = "Comedi-compatible DAQ/ADC cards"; - p.vectorize = 0; - p.size = sizeof(struct comedi); - p.parse = comedi_parse; - p.print = comedi_print; - p.start = comedi_start; - p.stop = comedi_stop; - p.read = comedi_read; - p.write = comedi_write; - p.poll_fds = comedi_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "comedi"; + p.description = "Comedi-compatible DAQ/ADC cards"; + p.vectorize = 0; + p.size = sizeof(struct comedi); + p.parse = comedi_parse; + p.print = comedi_print; + p.start = comedi_start; + p.stop = comedi_stop; + p.read = comedi_read; + p.write = comedi_write; + p.poll_fds = comedi_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index 5c8df874d..3b2944637 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -9,18 +9,17 @@ #include -#include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::node; // Forward declartions -static -NodeCompatType p; +static NodeCompatType p; // Constants #define NSEC_PER_SEC (1000000000) @@ -30,430 +29,411 @@ NodeCompatType p; int master_id = 0; int alias = 0; -static -ec_master_t *master = nullptr; +static ec_master_t *master = nullptr; struct coupler { - int position; - int vendor_id; - int product_code; + int position; + int vendor_id; + int product_code; - ec_slave_config_t *sc; -} coupler = { - .position = 0, - .vendor_id = ETHERCAT_VID_BECKHOFF, - .product_code = ETHERCAT_PID_EK1100, - .sc = nullptr -}; + ec_slave_config_t *sc; +} coupler = {.position = 0, + .vendor_id = ETHERCAT_VID_BECKHOFF, + .product_code = ETHERCAT_PID_EK1100, + .sc = nullptr}; -static -void ethercat_cyclic_task(NodeCompat *n) -{ - int ret; - struct Sample *smp; - auto *w = n->getData(); +static void ethercat_cyclic_task(NodeCompat *n) { + int ret; + struct Sample *smp; + auto *w = n->getData(); - while (true) { - w->task.wait(); + while (true) { + w->task.wait(); - // Receive process data - ecrt_master_receive(master); - ecrt_domain_process(w->domain); + // Receive process data + ecrt_master_receive(master); + ecrt_domain_process(w->domain); - // Receive process data - smp = sample_alloc(&w->pool); - if (!smp) { - n->logger->warn("Pool underrun"); - continue; - } + // Receive process data + smp = sample_alloc(&w->pool); + if (!smp) { + n->logger->warn("Pool underrun"); + continue; + } - smp->length = MIN(w->in.num_channels, smp->capacity); - smp->flags = (int) SampleFlags::HAS_DATA; - smp->signals = n->getInputSignals(false); + smp->length = MIN(w->in.num_channels, smp->capacity); + smp->flags = (int)SampleFlags::HAS_DATA; + smp->signals = n->getInputSignals(false); - // Read process data - for (unsigned i = 0; i < smp->length; i++) { - int16_t ain_value = EC_READ_S16(w->domain_pd + w->in.offsets[i]); + // Read process data + for (unsigned i = 0; i < smp->length; i++) { + int16_t ain_value = EC_READ_S16(w->domain_pd + w->in.offsets[i]); - smp->data[i].f = w->in.range * (float) ain_value / INT16_MAX; - } + smp->data[i].f = w->in.range * (float)ain_value / INT16_MAX; + } - ret = queue_signalled_push(&w->queue, smp); - if (ret) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push(&w->queue, smp); + if (ret) + n->logger->warn("Failed to enqueue samples"); - // Write process data - smp = w->send.exchange(nullptr); + // Write process data + smp = w->send.exchange(nullptr); - for (unsigned i = 0; i < w->out.num_channels; i++) { - int16_t aout_value = (smp->data[i].f / w->out.range) * INT16_MAX; + for (unsigned i = 0; i < w->out.num_channels; i++) { + int16_t aout_value = (smp->data[i].f / w->out.range) * INT16_MAX; - EC_WRITE_S16(w->domain_pd + w->out.offsets[i], aout_value); - } + EC_WRITE_S16(w->domain_pd + w->out.offsets[i], aout_value); + } - sample_decref(smp); + sample_decref(smp); - // send process data - ecrt_domain_queue(w->domain); - ecrt_master_send(master); - } + // send process data + ecrt_domain_queue(w->domain); + ecrt_master_send(master); + } } -int villas::node::ethercat_type_start(villas::node::SuperNode *sn) -{ - int ret; - json_error_t err; +int villas::node::ethercat_type_start(villas::node::SuperNode *sn) { + int ret; + json_error_t err; - if (sn == nullptr) - throw RuntimeError("EtherCAT node-type requires super-node"); + if (sn == nullptr) + throw RuntimeError("EtherCAT node-type requires super-node"); - json_t *json = sn->getConfig(); - if (json) { - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?:i, s?: { s?: { s?: i, s?: i, s?: i } } }", - "ethernet", - "master", &master_id, - "alias", &alias, - "coupler", - "position", &coupler.position, - "product_code", &coupler.product_code, - "vendor_id", &coupler.vendor_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ethercat"); - } + json_t *json = sn->getConfig(); + if (json) { + ret = json_unpack_ex( + json, &err, 0, "{ s?: i, s?:i, s?: { s?: { s?: i, s?: i, s?: i } } }", + "ethernet", "master", &master_id, "alias", &alias, "coupler", + "position", &coupler.position, "product_code", &coupler.product_code, + "vendor_id", &coupler.vendor_id); + if (ret) + throw ConfigError(json, err, "node-config-node-ethercat"); + } - master = ecrt_request_master(master_id); - if (!master) - return -1; + master = ecrt_request_master(master_id); + if (!master) + return -1; - // Create configuration for bus coupler - coupler.sc = ecrt_master_slave_config(master, alias, coupler.position, coupler.vendor_id, coupler.product_code); - if (!coupler.sc) - return -1; + // Create configuration for bus coupler + coupler.sc = ecrt_master_slave_config( + master, alias, coupler.position, coupler.vendor_id, coupler.product_code); + if (!coupler.sc) + return -1; - return 0; + return 0; } -int villas::node::ethercat_type_stop() -{ - auto logger = logging.get("node:ethercat"); +int villas::node::ethercat_type_stop() { + auto logger = logging.get("node:ethercat"); - logger->info("Releasing EtherCAT master"); + logger->info("Releasing EtherCAT master"); - ecrt_release_master(master); + ecrt_release_master(master); - return 0; + return 0; } -int villas::node::ethercat_parse(NodeCompat *n, json_t *json) -{ - auto *w = n->getData(); +int villas::node::ethercat_parse(NodeCompat *n, json_t *json) { + auto *w = n->getData(); - int ret; - json_error_t err; + int ret; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: { s: i, s?: F, s?: i, s?: i, s?: i }, s?: { s: i, s?: F, s?: i, s?: i, s?: i } }", - "rate", &w->rate, - "out", - "num_channels", &w->out.num_channels, - "range", &w->out.range, - "position", &w->out.position, - "product_code", &w->out.product_code, - "vendor_id", &w->out.vendor_id, - "in", - "num_channels", &w->in.num_channels, - "range", &w->in.range, - "position", &w->in.position, - "product_code", &w->in.product_code, - "vendor_id", &w->in.vendor_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ethercat"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: F, s?: { s: i, s?: F, s?: i, s?: i, s?: i }, s?: " + "{ s: i, s?: F, s?: i, s?: i, s?: i } }", + "rate", &w->rate, "out", "num_channels", + &w->out.num_channels, "range", &w->out.range, "position", + &w->out.position, "product_code", &w->out.product_code, + "vendor_id", &w->out.vendor_id, "in", "num_channels", + &w->in.num_channels, "range", &w->in.range, "position", + &w->in.position, "product_code", &w->in.product_code, + "vendor_id", &w->in.vendor_id); + if (ret) + throw ConfigError(json, err, "node-config-node-ethercat"); - return 0; + return 0; } -char * villas::node::ethercat_print(NodeCompat *n) -{ - auto *w = n->getData(); - std::stringstream ss; +char *villas::node::ethercat_print(NodeCompat *n) { + auto *w = n->getData(); + std::stringstream ss; - ss << "alias=" << alias; - ss << ", in.range=" << w->in.range << ", in.num_channels=" << w->in.num_channels; - ss << ", out.range=" << w->out.range << ", out.num_channels=" << w->out.num_channels; + ss << "alias=" << alias; + ss << ", in.range=" << w->in.range + << ", in.num_channels=" << w->in.num_channels; + ss << ", out.range=" << w->out.range + << ", out.num_channels=" << w->out.num_channels; - return strdup(ss.str().c_str()); + return strdup(ss.str().c_str()); } -int villas::node::ethercat_check(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::ethercat_check(NodeCompat *n) { + auto *w = n->getData(); - // Some parts of the configuration are still hard-coded for this specific setup - if (w->in.product_code != ETHERCAT_PID_EL3008 || - w->in.vendor_id != ETHERCAT_VID_BECKHOFF || - w->out.product_code != ETHERCAT_PID_EL4038 || - w->out.vendor_id != ETHERCAT_VID_BECKHOFF || - coupler.product_code != ETHERCAT_PID_EK1100 || - coupler.vendor_id != ETHERCAT_VID_BECKHOFF - ) - return -1; + // Some parts of the configuration are still hard-coded for this specific setup + if (w->in.product_code != ETHERCAT_PID_EL3008 || + w->in.vendor_id != ETHERCAT_VID_BECKHOFF || + w->out.product_code != ETHERCAT_PID_EL4038 || + w->out.vendor_id != ETHERCAT_VID_BECKHOFF || + coupler.product_code != ETHERCAT_PID_EK1100 || + coupler.vendor_id != ETHERCAT_VID_BECKHOFF) + return -1; - return 0; + return 0; } -int villas::node::ethercat_prepare(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_prepare(NodeCompat *n) { + int ret; + auto *w = n->getData(); - ret = pool_init(&w->pool, DEFAULT_ETHERCAT_QUEUE_LENGTH, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&w->pool, DEFAULT_ETHERCAT_QUEUE_LENGTH, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&w->queue, DEFAULT_ETHERCAT_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_signalled_init(&w->queue, DEFAULT_ETHERCAT_QUEUE_LENGTH); + if (ret) + return ret; - w->in.offsets = new unsigned[w->in.num_channels]; - if (!w->in.offsets) - throw MemoryAllocationError(); + w->in.offsets = new unsigned[w->in.num_channels]; + if (!w->in.offsets) + throw MemoryAllocationError(); - w->out.offsets = new unsigned[w->out.num_channels]; - if (!w->out.offsets) - throw MemoryAllocationError(); + w->out.offsets = new unsigned[w->out.num_channels]; + if (!w->out.offsets) + throw MemoryAllocationError(); - w->domain_regs = new ec_pdo_entry_reg_t[w->in.num_channels + w->out.num_channels + 1]; - if (!w->domain_regs) - throw MemoryAllocationError(); + w->domain_regs = + new ec_pdo_entry_reg_t[w->in.num_channels + w->out.num_channels + 1]; + if (!w->domain_regs) + throw MemoryAllocationError(); - memset(w->domain_regs, 0, (w->in.num_channels + w->out.num_channels + 1) * sizeof(ec_pdo_entry_reg_t)); + memset(w->domain_regs, 0, + (w->in.num_channels + w->out.num_channels + 1) * + sizeof(ec_pdo_entry_reg_t)); - // Prepare list of domain registers - int o = 0; - for (unsigned i = 0; i < w->out.num_channels; i++) { - w->out.offsets[i] = 0; + // Prepare list of domain registers + int o = 0; + for (unsigned i = 0; i < w->out.num_channels; i++) { + w->out.offsets[i] = 0; - w->domain_regs[o].alias = alias; - w->domain_regs[o].position = w->out.position; - w->domain_regs[o].vendor_id = w->out.vendor_id; - w->domain_regs[o].product_code = w->out.product_code; - w->domain_regs[o].index = 0x7000 + i * 0x10; - w->domain_regs[o].subindex = 0x1; - w->domain_regs[o].offset = w->out.offsets + i; + w->domain_regs[o].alias = alias; + w->domain_regs[o].position = w->out.position; + w->domain_regs[o].vendor_id = w->out.vendor_id; + w->domain_regs[o].product_code = w->out.product_code; + w->domain_regs[o].index = 0x7000 + i * 0x10; + w->domain_regs[o].subindex = 0x1; + w->domain_regs[o].offset = w->out.offsets + i; - o++; - }; + o++; + }; - // Prepare list of domain registers - for (unsigned i = 0; i < w->in.num_channels; i++) { - w->in.offsets[i] = 0; + // Prepare list of domain registers + for (unsigned i = 0; i < w->in.num_channels; i++) { + w->in.offsets[i] = 0; - w->domain_regs[o].alias = alias; - w->domain_regs[o].position = w->in.position; - w->domain_regs[o].vendor_id = w->in.vendor_id; - w->domain_regs[o].product_code = w->in.product_code; - w->domain_regs[o].index = 0x6000 + i * 0x10; - w->domain_regs[o].subindex = 0x11; - w->domain_regs[o].offset = w->in.offsets + i; + w->domain_regs[o].alias = alias; + w->domain_regs[o].position = w->in.position; + w->domain_regs[o].vendor_id = w->in.vendor_id; + w->domain_regs[o].product_code = w->in.product_code; + w->domain_regs[o].index = 0x6000 + i * 0x10; + w->domain_regs[o].subindex = 0x11; + w->domain_regs[o].offset = w->in.offsets + i; - o++; - }; + o++; + }; - w->domain = ecrt_master_create_domain(master); - if (!w->domain) - return -1; + w->domain = ecrt_master_create_domain(master); + if (!w->domain) + return -1; - return 0; + return 0; } -int villas::node::ethercat_start(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_start(NodeCompat *n) { + int ret; + auto *w = n->getData(); - // Configure analog in - w->in.sc = ecrt_master_slave_config(master, alias, w->in.position, w->in.vendor_id, w->in.product_code); - if (!w->in.sc) - throw RuntimeError("Failed to get slave configuration."); + // Configure analog in + w->in.sc = ecrt_master_slave_config(master, alias, w->in.position, + w->in.vendor_id, w->in.product_code); + if (!w->in.sc) + throw RuntimeError("Failed to get slave configuration."); - ret = ecrt_slave_config_pdos(w->in.sc, EC_END, slave_4_syncs); - if (ret) - throw RuntimeError("Failed to configure PDOs."); + ret = ecrt_slave_config_pdos(w->in.sc, EC_END, slave_4_syncs); + if (ret) + throw RuntimeError("Failed to configure PDOs."); - // Configure analog out - w->out.sc = ecrt_master_slave_config(master, alias, w->out.position, w->out.vendor_id, w->out.product_code); - if (!w->out.sc) - throw RuntimeError("Failed to get slave configuration."); + // Configure analog out + w->out.sc = ecrt_master_slave_config(master, alias, w->out.position, + w->out.vendor_id, w->out.product_code); + if (!w->out.sc) + throw RuntimeError("Failed to get slave configuration."); - ret = ecrt_slave_config_pdos(w->out.sc, EC_END, slave_3_syncs); - if (ret) - throw RuntimeError("Failed to configure PDOs."); + ret = ecrt_slave_config_pdos(w->out.sc, EC_END, slave_3_syncs); + if (ret) + throw RuntimeError("Failed to configure PDOs."); - ret = ecrt_domain_reg_pdo_entry_list(w->domain, w->domain_regs); - if (ret) - throw RuntimeError("PDO entry registration failed!"); + ret = ecrt_domain_reg_pdo_entry_list(w->domain, w->domain_regs); + if (ret) + throw RuntimeError("PDO entry registration failed!"); - // TODO: Check that master is not already active... - ret = ecrt_master_activate(master); - if (ret) - return -1; + // TODO: Check that master is not already active... + ret = ecrt_master_activate(master); + if (ret) + return -1; - w->domain_pd = ecrt_domain_data(w->domain); - if (!w->domain_pd) - return -1; + w->domain_pd = ecrt_domain_data(w->domain); + if (!w->domain_pd) + return -1; - // Start cyclic timer - w->task.setRate(w->rate); + // Start cyclic timer + w->task.setRate(w->rate); - // Start cyclic task - w->thread = std::thread(ethercat_cyclic_task, n); + // Start cyclic task + w->thread = std::thread(ethercat_cyclic_task, n); - return 0; + return 0; } -int villas::node::ethercat_stop(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_stop(NodeCompat *n) { + int ret; + auto *w = n->getData(); - w->thread.join(); + w->thread.join(); - ret = queue_signalled_close(&w->queue); - if (ret) - return ret; + ret = queue_signalled_close(&w->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *w = n->getData(); +int villas::node::ethercat_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *w = n->getData(); - int avail; - struct Sample *cpys[cnt]; + int avail; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&w->queue, (void **) cpys, cnt); - if (avail < 0) - n->logger->warn("Pool underrun: avail={}", avail); + avail = queue_signalled_pull_many(&w->queue, (void **)cpys, cnt); + if (avail < 0) + n->logger->warn("Pool underrun: avail={}", avail); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int villas::node::ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *w = n->getData(); +int villas::node::ethercat_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *w = n->getData(); - if (cnt < 1) - return cnt; + if (cnt < 1) + return cnt; - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - sample_incref(smp); + sample_incref(smp); - struct Sample *old = w->send.exchange(smp); - if (old) - sample_decref(old); + struct Sample *old = w->send.exchange(smp); + if (old) + sample_decref(old); - return 1; + return 1; } -int villas::node::ethercat_init(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::ethercat_init(NodeCompat *n) { + auto *w = n->getData(); - // Default values - w->rate = 1000; + // Default values + w->rate = 1000; - w->in.num_channels = 8; - w->in.range = 10.0; - w->in.position = 2; - w->in.product_code = ETHERCAT_PID_EL3008; - w->in.vendor_id = ETHERCAT_VID_BECKHOFF; - w->in.sc = nullptr; - w->in.offsets = nullptr; + w->in.num_channels = 8; + w->in.range = 10.0; + w->in.position = 2; + w->in.product_code = ETHERCAT_PID_EL3008; + w->in.vendor_id = ETHERCAT_VID_BECKHOFF; + w->in.sc = nullptr; + w->in.offsets = nullptr; - w->out.num_channels = 8; - w->out.range = 10.0; - w->out.position = 1; - w->out.product_code = ETHERCAT_PID_EL4038; - w->out.vendor_id = ETHERCAT_VID_BECKHOFF; - w->out.sc = nullptr; - w->out.offsets = nullptr; + w->out.num_channels = 8; + w->out.range = 10.0; + w->out.position = 1; + w->out.product_code = ETHERCAT_PID_EL4038; + w->out.vendor_id = ETHERCAT_VID_BECKHOFF; + w->out.sc = nullptr; + w->out.offsets = nullptr; - w->domain = nullptr; - w->domain_pd = nullptr; - w->domain_regs = nullptr; + w->domain = nullptr; + w->domain_pd = nullptr; + w->domain_regs = nullptr; - // Placement new for C++ objects - new (&w->send) std::atomic(); - new (&w->thread) std::thread(); - new (&w->task) Task(CLOCK_REALTIME); + // Placement new for C++ objects + new (&w->send) std::atomic(); + new (&w->thread) std::thread(); + new (&w->task) Task(CLOCK_REALTIME); - return 0; + return 0; } -int villas::node::ethercat_destroy(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_destroy(NodeCompat *n) { + int ret; + auto *w = n->getData(); - if (w->domain_regs) - delete[] w->domain_regs; + if (w->domain_regs) + delete[] w->domain_regs; - if (w->in.offsets) - delete[] w->in.offsets; + if (w->in.offsets) + delete[] w->in.offsets; - if (w->out.offsets) - delete[] w->out.offsets; + if (w->out.offsets) + delete[] w->out.offsets; - ret = queue_signalled_destroy(&w->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&w->queue); + if (ret) + return ret; - ret = pool_destroy(&w->pool); - if (ret) - return ret; + ret = pool_destroy(&w->pool); + if (ret) + return ret; - w->task.~Task(); + w->task.~Task(); - // TODO: Destroy domain? + // TODO: Destroy domain? - return 0; + return 0; } -int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) -{ - auto *w = n->getData(); +int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) { + auto *w = n->getData(); - fds[0] = queue_signalled_fd(&w->queue); + fds[0] = queue_signalled_fd(&w->queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "ethercat"; - p.description = "Send and receive samples of an ethercat connection"; - p.vectorize = 1; // we only process a single sample per call - p.size = sizeof(struct ethercat); - p.type.start = ethercat_type_start; - p.type.stop = ethercat_type_stop; - p.parse = ethercat_parse; - p.print = ethercat_print; - p.check = ethercat_check; - p.init = ethercat_init; - p.destroy = ethercat_destroy; - p.prepare = ethercat_prepare; - p.start = ethercat_start; - p.stop = ethercat_stop; - p.read = ethercat_read; - p.write = ethercat_write; - p.poll_fds = ethercat_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "ethercat"; + p.description = "Send and receive samples of an ethercat connection"; + p.vectorize = 1; // we only process a single sample per call + p.size = sizeof(struct ethercat); + p.type.start = ethercat_type_start; + p.type.stop = ethercat_type_stop; + p.parse = ethercat_parse; + p.print = ethercat_print; + p.check = ethercat_check; + p.init = ethercat_init; + p.destroy = ethercat_destroy; + p.prepare = ethercat_prepare; + p.start = ethercat_start; + p.stop = ethercat_stop; + p.read = ethercat_read; + p.write = ethercat_write; + p.poll_fds = ethercat_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/example.cpp b/lib/nodes/example.cpp index b71cc0715..1914d3dec 100644 --- a/lib/nodes/example.cpp +++ b/lib/nodes/example.cpp @@ -8,76 +8,64 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include #include -#include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -ExampleNode::ExampleNode(const uuid_t &id, const std::string &name) : - Node(id, name), - setting1(72), - setting2("something"), - state1(0) -{ } +ExampleNode::ExampleNode(const uuid_t &id, const std::string &name) + : Node(id, name), setting1(72), setting2("something"), state1(0) {} -ExampleNode::~ExampleNode() -{ } +ExampleNode::~ExampleNode() {} -int ExampleNode::prepare() -{ - state1 = setting1; +int ExampleNode::prepare() { + state1 = setting1; - if (setting2 == "double") - state1 *= 2; + if (setting2 == "double") + state1 *= 2; - return 0; + return 0; } -int ExampleNode::parse(json_t *json) -{ - // TODO: Add implementation here. The following is just an example +int ExampleNode::parse(json_t *json) { + // TODO: Add implementation here. The following is just an example - const char *setting2_str = nullptr; + const char *setting2_str = nullptr; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", - "setting1", &setting1, - "setting2", &setting2_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-example"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", "setting1", + &setting1, "setting2", &setting2_str); + if (ret) + throw ConfigError(json, err, "node-config-node-example"); - if (setting2_str) - setting2 = setting2_str; + if (setting2_str) + setting2 = setting2_str; - return 0; + return 0; } -int ExampleNode::check() -{ - if (setting1 > 100 || setting1 < 0) - return -1; +int ExampleNode::check() { + if (setting1 > 100 || setting1 < 0) + return -1; - if (setting2.empty() || setting2.size() > 10) - return -1; + if (setting2.empty() || setting2.size() > 10) + return -1; - return 0; + return 0; } -int ExampleNode::start() -{ - // TODO add implementation here +int ExampleNode::start() { + // TODO add implementation here - start_time = time_now(); + start_time = time_now(); - return 0; + return 0; } // int ExampleNode::stop() @@ -127,47 +115,49 @@ int ExampleNode::start() // // TODO add implementation here // } -const std::string & ExampleNode::getDetails() -{ - details = fmt::format("setting1={}, setting2={}", setting1, setting2); - return details; +const std::string &ExampleNode::getDetails() { + details = fmt::format("setting1={}, setting2={}", setting1, setting2); + return details; } -int ExampleNode::_read(struct Sample *smps[], unsigned cnt) -{ - int read; - struct timespec now; +int ExampleNode::_read(struct Sample *smps[], unsigned cnt) { + int read; + struct timespec now; - // TODO: Add implementation here. The following is just an example + // TODO: Add implementation here. The following is just an example - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - now = time_now(); + now = time_now(); - smps[0]->data[0].f = time_delta(&now, &start_time); + smps[0]->data[0].f = time_delta(&now, &start_time); - /* Dont forget to set other flags in struct Sample::flags + /* Dont forget to set other flags in struct Sample::flags * E.g. for sequence no, timestamps... */ - smps[0]->flags = (int) SampleFlags::HAS_DATA; - smps[0]->signals = getInputSignals(false); + smps[0]->flags = (int)SampleFlags::HAS_DATA; + smps[0]->signals = getInputSignals(false); - read = 1; // The number of samples read + read = 1; // The number of samples read - return read; + return read; } -int ExampleNode::_write(struct Sample *smps[], unsigned cnt) -{ - int written; +int ExampleNode::_write(struct Sample *smps[], unsigned cnt) { + int written; - // TODO: Add implementation here. + // TODO: Add implementation here. - written = 0; // The number of samples written + written = 0; // The number of samples written - return written; + return written; } // Register node static char n[] = "example"; static char d[] = "An example for staring new node-type implementations"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index 3bfa36007..0d33a76e7 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -8,205 +8,198 @@ #include #include +#include #include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -ExecNode::~ExecNode() -{ - if (stream_in) - fclose(stream_in); +ExecNode::~ExecNode() { + if (stream_in) + fclose(stream_in); - if (stream_out) - fclose(stream_out); + if (stream_out) + fclose(stream_out); } -int ExecNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int ExecNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_error_t err; - int f = 1, s = -1; + json_error_t err; + int f = 1, s = -1; - json_t *json_exec; - json_t *json_env = nullptr; - json_t *json_format = nullptr; + json_t *json_exec; + json_t *json_env = nullptr; + json_t *json_format = nullptr; - const char *wd = nullptr; + const char *wd = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: o, s?: b, s?: o, s?: b, s?: s }", - "exec", &json_exec, - "format", &json_format, - "flush", &f, - "environment", &json_env, - "shell", &s, - "working_directory", &wd - ); - if (ret) - throw ConfigError(json, err, "node-config-node-exec"); + ret = json_unpack_ex( + json, &err, 0, "{ s: o, s?: o, s?: b, s?: o, s?: b, s?: s }", "exec", + &json_exec, "format", &json_format, "flush", &f, "environment", &json_env, + "shell", &s, "working_directory", &wd); + if (ret) + throw ConfigError(json, err, "node-config-node-exec"); - flush = f != 0; - shell = s < 0 ? json_is_string(json_exec) : s != 0; + flush = f != 0; + shell = s < 0 ? json_is_string(json_exec) : s != 0; - arguments.clear(); - environment.clear(); + arguments.clear(); + environment.clear(); - if (json_is_string(json_exec)) { - if (!shell) - throw ConfigError(json_exec, "node-config-node-exec-shell", "The exec setting must be an array if shell mode is disabled."); + if (json_is_string(json_exec)) { + if (!shell) + throw ConfigError( + json_exec, "node-config-node-exec-shell", + "The exec setting must be an array if shell mode is disabled."); - command = json_string_value(json_exec); - } - else if (json_is_array(json_exec)) { - if (shell) - throw ConfigError(json_exec, "node-config-node-exec-shell", "The exec setting must be a string if shell mode is enabled."); + command = json_string_value(json_exec); + } else if (json_is_array(json_exec)) { + if (shell) + throw ConfigError( + json_exec, "node-config-node-exec-shell", + "The exec setting must be a string if shell mode is enabled."); - if (json_array_size(json_exec) < 1) - throw ConfigError(json_exec, "node-config-node-exec-exec", "At least one argument must be given"); + if (json_array_size(json_exec) < 1) + throw ConfigError(json_exec, "node-config-node-exec-exec", + "At least one argument must be given"); - size_t i; - json_t *json_arg; - json_array_foreach(json_exec, i, json_arg) { - if (!json_is_string(json_arg)) - throw ConfigError(json_arg, "node-config-node-exec-exec", "All arguments must be of string type"); + size_t i; + json_t *json_arg; + json_array_foreach(json_exec, i, json_arg) { + if (!json_is_string(json_arg)) + throw ConfigError(json_arg, "node-config-node-exec-exec", + "All arguments must be of string type"); - if (i == 0) - command = json_string_value(json_arg); + if (i == 0) + command = json_string_value(json_arg); - arguments.push_back(json_string_value(json_arg)); - } - } + arguments.push_back(json_string_value(json_arg)); + } + } - if (json_env) { - // obj is a JSON object - const char *key; - json_t *json_value; + if (json_env) { + // obj is a JSON object + const char *key; + json_t *json_value; - json_object_foreach(json_env, key, json_value) { - if (!json_is_string(json_value)) - throw ConfigError(json_value, "node-config-node-exec-environment", "Environment variables must be of string type"); + json_object_foreach(json_env, key, json_value) { + if (!json_is_string(json_value)) + throw ConfigError(json_value, "node-config-node-exec-environment", + "Environment variables must be of string type"); - environment[key] = json_string_value(json_value); - } - } + environment[key] = json_string_value(json_value); + } + } - // Format - auto *fmt = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); + // Format + auto *fmt = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); - formatter = Format::Ptr(fmt); - if (!formatter) - throw ConfigError(json_format, "node-config-node-exec-format", "Invalid format configuration"); + formatter = Format::Ptr(fmt); + if (!formatter) + throw ConfigError(json_format, "node-config-node-exec-format", + "Invalid format configuration"); - state = State::PARSED; + state = State::PARSED; - return 0; + return 0; } -int ExecNode::prepare() -{ - assert(state == State::CHECKED); +int ExecNode::prepare() { + assert(state == State::CHECKED); - // Initialize IO - formatter->start(getInputSignals(false)); + // Initialize IO + formatter->start(getInputSignals(false)); - return Node::prepare(); + return Node::prepare(); } -int ExecNode::start() -{ - // Start subprocess - proc = std::make_unique(command, arguments, environment, working_dir, shell); - logger->debug("Started sub-process with pid={}", proc->getPid()); +int ExecNode::start() { + // Start subprocess + proc = std::make_unique(command, arguments, environment, working_dir, + shell); + logger->debug("Started sub-process with pid={}", proc->getPid()); - stream_in = fdopen(proc->getFdIn(), "r"); - if (!stream_in) - return -1; + stream_in = fdopen(proc->getFdIn(), "r"); + if (!stream_in) + return -1; - stream_out = fdopen(proc->getFdOut(), "w"); - if (!stream_out) - return -1; + stream_out = fdopen(proc->getFdOut(), "w"); + if (!stream_out) + return -1; - int ret = Node::start(); - if (!ret) - state = State::STARTED; + int ret = Node::start(); + if (!ret) + state = State::STARTED; - return 0; + return 0; } -int ExecNode::stop() -{ - int ret = Node::stop(); - if (ret) - return ret; +int ExecNode::stop() { + int ret = Node::stop(); + if (ret) + return ret; - // Stop subprocess - logger->debug("Killing sub-process with pid={}", proc->getPid()); - proc->kill(SIGINT); + // Stop subprocess + logger->debug("Killing sub-process with pid={}", proc->getPid()); + proc->kill(SIGINT); - logger->debug("Waiting for sub-process with pid={} to terminate", proc->getPid()); - proc->close(); + logger->debug("Waiting for sub-process with pid={} to terminate", + proc->getPid()); + proc->close(); - // TODO: Check exit code of subprocess? - return 0; + // TODO: Check exit code of subprocess? + return 0; } -int ExecNode::_read(struct Sample * smps[], unsigned cnt) -{ - return formatter->scan(stream_in, smps, cnt); +int ExecNode::_read(struct Sample *smps[], unsigned cnt) { + return formatter->scan(stream_in, smps, cnt); } -int ExecNode::_write(struct Sample * smps[], unsigned cnt) -{ - int ret; +int ExecNode::_write(struct Sample *smps[], unsigned cnt) { + int ret; - ret = formatter->print(stream_out, smps, cnt); - if (ret < 0) - return ret; + ret = formatter->print(stream_out, smps, cnt); + if (ret < 0) + return ret; - if (flush) - fflush(stream_out); + if (flush) + fflush(stream_out); - return cnt; + return cnt; } -const std::string & ExecNode::getDetails() -{ - if (details.empty()) { - std::string wd = working_dir; - if (wd.empty()) { - char buf[128]; - wd = getcwd(buf, sizeof(buf)); - } +const std::string &ExecNode::getDetails() { + if (details.empty()) { + std::string wd = working_dir; + if (wd.empty()) { + char buf[128]; + wd = getcwd(buf, sizeof(buf)); + } - details = fmt::format("exec={}, shell={}, flush={}, #environment={}, #arguments={}, working_dir={}", - command, - shell ? "yes" : "no", - flush ? "yes" : "no", - environment.size(), - arguments.size(), - wd - ); - } + details = fmt::format("exec={}, shell={}, flush={}, #environment={}, " + "#arguments={}, working_dir={}", + command, shell ? "yes" : "no", flush ? "yes" : "no", + environment.size(), arguments.size(), wd); + } - return details; + return details; } -std::vector ExecNode::getPollFDs() -{ - return { proc->getFdIn() }; -} +std::vector ExecNode::getPollFDs() { return {proc->getFdIn()}; } // Register node static char n[] = "exec"; static char d[] = "run subprocesses with stdin/stdout communication"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index 5ae0ea762..3fd6692e3 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -5,489 +5,463 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include #include +#include #include #include -#include +#include +#include +#include #include #include -#include -#include #include -#include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -char * file_format_name(const char *format, struct timespec *ts) -{ - struct tm tm; - char *buf = new char[FILE_MAX_PATHLEN]; - if (!buf) - throw MemoryAllocationError(); +static char *file_format_name(const char *format, struct timespec *ts) { + struct tm tm; + char *buf = new char[FILE_MAX_PATHLEN]; + if (!buf) + throw MemoryAllocationError(); - // Convert time - gmtime_r(&ts->tv_sec, &tm); + // Convert time + gmtime_r(&ts->tv_sec, &tm); - strftime(buf, FILE_MAX_PATHLEN, format, &tm); + strftime(buf, FILE_MAX_PATHLEN, format, &tm); - return buf; + return buf; } -static -struct timespec file_calc_offset(const struct timespec *first, const struct timespec *epoch, enum file::EpochMode mode) -{ - // Get current time - struct timespec now = time_now(); - struct timespec offset; +static struct timespec file_calc_offset(const struct timespec *first, + const struct timespec *epoch, + enum file::EpochMode mode) { + // Get current time + struct timespec now = time_now(); + struct timespec offset; - // Set offset depending on epoch - switch (mode) { - case file::EpochMode::DIRECT: // read first value at now + epoch - offset = time_diff(first, &now); - return time_add(&offset, epoch); + // Set offset depending on epoch + switch (mode) { + case file::EpochMode::DIRECT: // read first value at now + epoch + offset = time_diff(first, &now); + return time_add(&offset, epoch); - case file::EpochMode::WAIT: // read first value at now + first + epoch - offset = now; - return time_add(&now, epoch); + case file::EpochMode::WAIT: // read first value at now + first + epoch + offset = now; + return time_add(&now, epoch); - case file::EpochMode::RELATIVE: // read first value at first + epoch - return *epoch; + case file::EpochMode::RELATIVE: // read first value at first + epoch + return *epoch; - case file::EpochMode::ABSOLUTE: // read first value at f->epoch - return time_diff(first, epoch); + case file::EpochMode::ABSOLUTE: // read first value at f->epoch + return time_diff(first, epoch); - default: - return (struct timespec) { 0 }; - } + default: + return (struct timespec){0}; + } } -int villas::node::file_parse(NodeCompat *n, json_t *json) -{ - auto *f = n->getData(); +int villas::node::file_parse(NodeCompat *n, json_t *json) { + auto *f = n->getData(); - int ret; - json_error_t err; - json_t *json_format = nullptr; + int ret; + json_error_t err; + json_t *json_format = nullptr; - const char *uri_tmpl = nullptr; - const char *eof = nullptr; - const char *epoch = nullptr; - double epoch_flt = 0; + const char *uri_tmpl = nullptr; + const char *eof = nullptr; + const char *epoch = nullptr; + double epoch_flt = 0; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: { s?: s, s?: F, s?: s, s?: F, s?: i, s?: i }, s?: { s?: b, s?: i } }", - "uri", &uri_tmpl, - "format", &json_format, - "in", - "eof", &eof, - "rate", &f->rate, - "epoch_mode", &epoch, - "epoch", &epoch_flt, - "buffer_size", &f->buffer_size_in, - "skip", &f->skip_lines, - "out", - "flush", &f->flush, - "buffer_size", &f->buffer_size_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-file"); + ret = json_unpack_ex(json, &err, 0, + "{ s: s, s?: o, s?: { s?: s, s?: F, s?: s, s?: F, s?: " + "i, s?: i }, s?: { s?: b, s?: i } }", + "uri", &uri_tmpl, "format", &json_format, "in", "eof", + &eof, "rate", &f->rate, "epoch_mode", &epoch, "epoch", + &epoch_flt, "buffer_size", &f->buffer_size_in, "skip", + &f->skip_lines, "out", "flush", &f->flush, "buffer_size", + &f->buffer_size_out); + if (ret) + throw ConfigError(json, err, "node-config-node-file"); - f->epoch = time_from_double(epoch_flt); - f->uri_tmpl = uri_tmpl ? strdup(uri_tmpl) : nullptr; + f->epoch = time_from_double(epoch_flt); + f->uri_tmpl = uri_tmpl ? strdup(uri_tmpl) : nullptr; - // Format - if (f->formatter) - delete f->formatter; - f->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); - if (!f->formatter) - throw ConfigError(json_format, "node-config-node-file-format", "Invalid format configuration"); + // Format + if (f->formatter) + delete f->formatter; + f->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); + if (!f->formatter) + throw ConfigError(json_format, "node-config-node-file-format", + "Invalid format configuration"); - if (eof) { - if (!strcmp(eof, "exit") || !strcmp(eof, "stop")) - f->eof_mode = file::EOFBehaviour::STOP; - else if (!strcmp(eof, "rewind")) - f->eof_mode = file::EOFBehaviour::REWIND; - else if (!strcmp(eof, "wait")) - f->eof_mode = file::EOFBehaviour::SUSPEND; - else - throw RuntimeError("Invalid mode '{}' for 'eof' setting", eof); - } + if (eof) { + if (!strcmp(eof, "exit") || !strcmp(eof, "stop")) + f->eof_mode = file::EOFBehaviour::STOP; + else if (!strcmp(eof, "rewind")) + f->eof_mode = file::EOFBehaviour::REWIND; + else if (!strcmp(eof, "wait")) + f->eof_mode = file::EOFBehaviour::SUSPEND; + else + throw RuntimeError("Invalid mode '{}' for 'eof' setting", eof); + } - if (epoch) { - if (!strcmp(epoch, "direct")) - f->epoch_mode = file::EpochMode::DIRECT; - else if (!strcmp(epoch, "wait")) - f->epoch_mode = file::EpochMode::WAIT; - else if (!strcmp(epoch, "relative")) - f->epoch_mode = file::EpochMode::RELATIVE; - else if (!strcmp(epoch, "absolute")) - f->epoch_mode = file::EpochMode::ABSOLUTE; - else if (!strcmp(epoch, "original")) - f->epoch_mode = file::EpochMode::ORIGINAL; - else - throw RuntimeError("Invalid value '{}' for setting 'epoch'", epoch); - } + if (epoch) { + if (!strcmp(epoch, "direct")) + f->epoch_mode = file::EpochMode::DIRECT; + else if (!strcmp(epoch, "wait")) + f->epoch_mode = file::EpochMode::WAIT; + else if (!strcmp(epoch, "relative")) + f->epoch_mode = file::EpochMode::RELATIVE; + else if (!strcmp(epoch, "absolute")) + f->epoch_mode = file::EpochMode::ABSOLUTE; + else if (!strcmp(epoch, "original")) + f->epoch_mode = file::EpochMode::ORIGINAL; + else + throw RuntimeError("Invalid value '{}' for setting 'epoch'", epoch); + } - return 0; + return 0; } -char * villas::node::file_print(NodeCompat *n) -{ - auto *f = n->getData(); - char *buf = nullptr; +char *villas::node::file_print(NodeCompat *n) { + auto *f = n->getData(); + char *buf = nullptr; - const char *epoch_str = nullptr; - const char *eof_str = nullptr; + const char *epoch_str = nullptr; + const char *eof_str = nullptr; - switch (f->epoch_mode) { - case file::EpochMode::DIRECT: - epoch_str = "direct"; - break; + switch (f->epoch_mode) { + case file::EpochMode::DIRECT: + epoch_str = "direct"; + break; - case file::EpochMode::WAIT: - epoch_str = "wait"; - break; + case file::EpochMode::WAIT: + epoch_str = "wait"; + break; - case file::EpochMode::RELATIVE: - epoch_str = "relative"; - break; + case file::EpochMode::RELATIVE: + epoch_str = "relative"; + break; - case file::EpochMode::ABSOLUTE: - epoch_str = "absolute"; - break; + case file::EpochMode::ABSOLUTE: + epoch_str = "absolute"; + break; - case file::EpochMode::ORIGINAL: - epoch_str = "original"; - break; + case file::EpochMode::ORIGINAL: + epoch_str = "original"; + break; - default: - epoch_str = ""; - break; - } + default: + epoch_str = ""; + break; + } - switch (f->eof_mode) { - case file::EOFBehaviour::STOP: - eof_str = "stop"; - break; + switch (f->eof_mode) { + case file::EOFBehaviour::STOP: + eof_str = "stop"; + break; - case file::EOFBehaviour::SUSPEND: - eof_str = "wait"; - break; + case file::EOFBehaviour::SUSPEND: + eof_str = "wait"; + break; - case file::EOFBehaviour::REWIND: - eof_str = "rewind"; - break; + case file::EOFBehaviour::REWIND: + eof_str = "rewind"; + break; - default: - eof_str = ""; - break; - } + default: + eof_str = ""; + break; + } - strcatf(&buf, "uri=%s, out.flush=%s, in.skip=%d, in.eof=%s, in.epoch=%s, in.epoch=%.2f", - f->uri ? f->uri : f->uri_tmpl, - f->flush ? "yes" : "no", - f->skip_lines, - eof_str, - epoch_str, - time_to_double(&f->epoch) - ); + strcatf( + &buf, + "uri=%s, out.flush=%s, in.skip=%d, in.eof=%s, in.epoch=%s, in.epoch=%.2f", + f->uri ? f->uri : f->uri_tmpl, f->flush ? "yes" : "no", f->skip_lines, + eof_str, epoch_str, time_to_double(&f->epoch)); - if (f->rate) - strcatf(&buf, ", in.rate=%.1f", f->rate); + if (f->rate) + strcatf(&buf, ", in.rate=%.1f", f->rate); - if (f->first.tv_sec || f->first.tv_nsec) - strcatf(&buf, ", first=%.2f", time_to_double(&f->first)); + if (f->first.tv_sec || f->first.tv_nsec) + strcatf(&buf, ", first=%.2f", time_to_double(&f->first)); - if (f->offset.tv_sec || f->offset.tv_nsec) - strcatf(&buf, ", offset=%.2f", time_to_double(&f->offset)); + if (f->offset.tv_sec || f->offset.tv_nsec) + strcatf(&buf, ", offset=%.2f", time_to_double(&f->offset)); - if ((f->first.tv_sec || f->first.tv_nsec) && - (f->offset.tv_sec || f->offset.tv_nsec)) { - struct timespec eta, now = time_now(); + if ((f->first.tv_sec || f->first.tv_nsec) && + (f->offset.tv_sec || f->offset.tv_nsec)) { + struct timespec eta, now = time_now(); - eta = time_add(&f->first, &f->offset); - eta = time_diff(&now, &eta); + eta = time_add(&f->first, &f->offset); + eta = time_diff(&now, &eta); - if (eta.tv_sec || eta.tv_nsec) - strcatf(&buf, ", eta=%.2f sec", time_to_double(&eta)); - } + if (eta.tv_sec || eta.tv_nsec) + strcatf(&buf, ", eta=%.2f sec", time_to_double(&eta)); + } - return buf; + return buf; } -int villas::node::file_start(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_start(NodeCompat *n) { + auto *f = n->getData(); - struct timespec now = time_now(); - int ret; + struct timespec now = time_now(); + int ret; - // Prepare file name - if (f->uri) - delete[] f->uri; + // Prepare file name + if (f->uri) + delete[] f->uri; - f->uri = file_format_name(f->uri_tmpl, &now); + f->uri = file_format_name(f->uri_tmpl, &now); - // Check if directory exists - struct stat sb; - char *cpy = strdup(f->uri); - char *dir = dirname(cpy); + // Check if directory exists + struct stat sb; + char *cpy = strdup(f->uri); + char *dir = dirname(cpy); - ret = stat(dir, &sb); - if (ret) { - if (errno == ENOENT || errno == ENOTDIR) { - ret = mkdir(dir, 0644); - if (ret) - throw SystemError("Failed to create directory"); - } - else if (errno != EISDIR) - throw SystemError("Failed to stat"); - } - else if (!S_ISDIR(sb.st_mode)) { - ret = mkdir(dir, 0644); - if (ret) - throw SystemError("Failed to create directory"); - } + ret = stat(dir, &sb); + if (ret) { + if (errno == ENOENT || errno == ENOTDIR) { + ret = mkdir(dir, 0644); + if (ret) + throw SystemError("Failed to create directory"); + } else if (errno != EISDIR) + throw SystemError("Failed to stat"); + } else if (!S_ISDIR(sb.st_mode)) { + ret = mkdir(dir, 0644); + if (ret) + throw SystemError("Failed to create directory"); + } - free(cpy); + free(cpy); - f->formatter->start(n->getInputSignals(false)); + f->formatter->start(n->getInputSignals(false)); - // Open file - f->stream_out = fopen(f->uri, "a+"); - if (!f->stream_out) - return -1; + // Open file + f->stream_out = fopen(f->uri, "a+"); + if (!f->stream_out) + return -1; - f->stream_in = fopen(f->uri, "r"); - if (!f->stream_in) - return -1; + f->stream_in = fopen(f->uri, "r"); + if (!f->stream_in) + return -1; - if (f->buffer_size_in) { - ret = setvbuf(f->stream_in, nullptr, _IOFBF, f->buffer_size_in); - if (ret) - return ret; - } + if (f->buffer_size_in) { + ret = setvbuf(f->stream_in, nullptr, _IOFBF, f->buffer_size_in); + if (ret) + return ret; + } - if (f->buffer_size_out) { - ret = setvbuf(f->stream_out, nullptr, _IOFBF, f->buffer_size_out); - if (ret) - return ret; - } + if (f->buffer_size_out) { + ret = setvbuf(f->stream_out, nullptr, _IOFBF, f->buffer_size_out); + if (ret) + return ret; + } - // Create timer - f->task.setRate(f->rate); + // Create timer + f->task.setRate(f->rate); - // Get timestamp of first line - if (f->epoch_mode != file::EpochMode::ORIGINAL) { - rewind(f->stream_in); + // Get timestamp of first line + if (f->epoch_mode != file::EpochMode::ORIGINAL) { + rewind(f->stream_in); - if (feof(f->stream_in)) { - n->logger->warn("Empty file"); - } - else { - struct Sample smp; + if (feof(f->stream_in)) { + n->logger->warn("Empty file"); + } else { + struct Sample smp; - smp.capacity = 0; + smp.capacity = 0; - ret = f->formatter->scan(f->stream_in, &smp); - if (ret == 1) { - f->first = smp.ts.origin; - f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); - } - else - n->logger->warn("Failed to read first timestamp"); - } - } + ret = f->formatter->scan(f->stream_in, &smp); + if (ret == 1) { + f->first = smp.ts.origin; + f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); + } else + n->logger->warn("Failed to read first timestamp"); + } + } - rewind(f->stream_in); + rewind(f->stream_in); - // Fast-forward - struct Sample *smp = sample_alloc_mem(n->getInputSignals(false)->size()); - for (unsigned i = 0; i < f->skip_lines; i++) - f->formatter->scan(f->stream_in, smp); + // Fast-forward + struct Sample *smp = sample_alloc_mem(n->getInputSignals(false)->size()); + for (unsigned i = 0; i < f->skip_lines; i++) + f->formatter->scan(f->stream_in, smp); - sample_free(smp); + sample_free(smp); - return 0; + return 0; } -int villas::node::file_stop(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_stop(NodeCompat *n) { + auto *f = n->getData(); - f->task.stop(); + f->task.stop(); - fclose(f->stream_in); - fclose(f->stream_out); + fclose(f->stream_in); + fclose(f->stream_out); - return 0; + return 0; } -int villas::node::file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *f = n->getData(); - int ret; - uint64_t steps; +int villas::node::file_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *f = n->getData(); + int ret; + uint64_t steps; - assert(cnt == 1); + assert(cnt == 1); -retry: ret = f->formatter->scan(f->stream_in, smps, cnt); - if (ret <= 0) { - if (feof(f->stream_in)) { - switch (f->eof_mode) { - case file::EOFBehaviour::REWIND: - n->logger->info("Rewind input file"); +retry: + ret = f->formatter->scan(f->stream_in, smps, cnt); + if (ret <= 0) { + if (feof(f->stream_in)) { + switch (f->eof_mode) { + case file::EOFBehaviour::REWIND: + n->logger->info("Rewind input file"); - f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); - rewind(f->stream_in); - goto retry; + f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); + rewind(f->stream_in); + goto retry; - case file::EOFBehaviour::SUSPEND: - // We wait 10ms before fetching again. - usleep(100000); + case file::EOFBehaviour::SUSPEND: + // We wait 10ms before fetching again. + usleep(100000); - // Try to download more data if this is a remote file. - clearerr(f->stream_in); - goto retry; + // Try to download more data if this is a remote file. + clearerr(f->stream_in); + goto retry; - case file::EOFBehaviour::STOP: - n->logger->info("Reached end-of-file."); + case file::EOFBehaviour::STOP: + n->logger->info("Reached end-of-file."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; + return -1; - default: { } - } - } - else - n->logger->warn("Failed to read messages: reason={}", ret); + default: { + } + } + } else + n->logger->warn("Failed to read messages: reason={}", ret); - return 0; - } + return 0; + } - // We dont wait in FILE_EPOCH_ORIGINAL mode - if (f->epoch_mode == file::EpochMode::ORIGINAL) - return cnt; + // We dont wait in FILE_EPOCH_ORIGINAL mode + if (f->epoch_mode == file::EpochMode::ORIGINAL) + return cnt; - if (f->rate) { - steps = f->task.wait(); + if (f->rate) { + steps = f->task.wait(); - smps[0]->ts.origin = time_now(); - } - else { - smps[0]->ts.origin = time_add(&smps[0]->ts.origin, &f->offset); + smps[0]->ts.origin = time_now(); + } else { + smps[0]->ts.origin = time_add(&smps[0]->ts.origin, &f->offset); - f->task.setNext(&smps[0]->ts.origin); - steps = f->task.wait(); - } + f->task.setNext(&smps[0]->ts.origin); + steps = f->task.wait(); + } - // Check for overruns - if (steps == 0) - throw SystemError("Failed to wait for timer"); - else if (steps != 1) - n->logger->warn("Missed steps: {}", steps - 1); + // Check for overruns + if (steps == 0) + throw SystemError("Failed to wait for timer"); + else if (steps != 1) + n->logger->warn("Missed steps: {}", steps - 1); - return cnt; + return cnt; } -int villas::node::file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *f = n->getData(); +int villas::node::file_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *f = n->getData(); - assert(cnt == 1); + assert(cnt == 1); - ret = f->formatter->print(f->stream_out, smps, cnt); - if (ret < 0) - return ret; + ret = f->formatter->print(f->stream_out, smps, cnt); + if (ret < 0) + return ret; - if (f->flush) - fflush(f->stream_out); + if (f->flush) + fflush(f->stream_out); - return cnt; + return cnt; } -int villas::node::file_poll_fds(NodeCompat *n, int fds[]) -{ - auto *f = n->getData(); +int villas::node::file_poll_fds(NodeCompat *n, int fds[]) { + auto *f = n->getData(); - if (f->rate) { - fds[0] = f->task.getFD(); + if (f->rate) { + fds[0] = f->task.getFD(); - return 1; - } - else if (f->epoch_mode == file::EpochMode::ORIGINAL) { - fds[0] = fileno(f->stream_in); + return 1; + } else if (f->epoch_mode == file::EpochMode::ORIGINAL) { + fds[0] = fileno(f->stream_in); - return 1; - } + return 1; + } - return -1; // TODO: not supported yet + return -1; // TODO: not supported yet } -int villas::node::file_init(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_init(NodeCompat *n) { + auto *f = n->getData(); - new (&f->task) Task(CLOCK_REALTIME); + new (&f->task) Task(CLOCK_REALTIME); - // Default values - f->rate = 0; - f->eof_mode = file::EOFBehaviour::STOP; - f->epoch_mode = file::EpochMode::DIRECT; - f->flush = 0; - f->buffer_size_in = 0; - f->buffer_size_out = 0; - f->skip_lines = 0; + // Default values + f->rate = 0; + f->eof_mode = file::EOFBehaviour::STOP; + f->epoch_mode = file::EpochMode::DIRECT; + f->flush = 0; + f->buffer_size_in = 0; + f->buffer_size_out = 0; + f->skip_lines = 0; - f->formatter = nullptr; + f->formatter = nullptr; - return 0; + return 0; } -int villas::node::file_destroy(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_destroy(NodeCompat *n) { + auto *f = n->getData(); - f->task.~Task(); + f->task.~Task(); - if (f->uri) - delete[] f->uri; + if (f->uri) + delete[] f->uri; - if (f->formatter) - delete f->formatter; + if (f->formatter) + delete f->formatter; - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "file"; - p.description = "support for file log / replay node type"; - p.vectorize = 1; - p.size = sizeof(struct file); - p.init = file_init; - p.destroy = file_destroy; - p.parse = file_parse; - p.print = file_print; - p.start = file_start; - p.stop = file_stop; - p.read = file_read; - p.write = file_write; - p.poll_fds = file_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "file"; + p.description = "support for file log / replay node type"; + p.vectorize = 1; + p.size = sizeof(struct file); + p.init = file_init; + p.destroy = file_destroy; + p.parse = file_parse; + p.print = file_print; + p.start = file_start; + p.stop = file_stop; + p.read = file_read; + p.write = file_write; + p.poll_fds = file_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index 461e97e09..7f12d1382 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -5,27 +5,27 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include -#include #include +#include +#include #include +#include +#include #include #include -#include -#include -#include #include #include +#include #include #include -#include #include +#include using namespace villas; using namespace villas::node; @@ -33,217 +33,200 @@ using namespace villas::fpga; using namespace villas::utils; // Global state -static -std::list> cards; -static -std::map dmaMap; +static std::list> cards; +static std::map dmaMap; -static -std::shared_ptr pciDevices; -static -std::shared_ptr vfioContainer; +static std::shared_ptr pciDevices; +static std::shared_ptr vfioContainer; using namespace villas; using namespace villas::node; -FpgaNode::FpgaNode(const uuid_t &id, const std::string &name) : - Node(id, name), - irqFd(-1), - coalesce(0), - polling(true) -{ } +FpgaNode::FpgaNode(const uuid_t &id, const std::string &name) + : Node(id, name), irqFd(-1), coalesce(0), polling(true) {} -FpgaNode::~FpgaNode() -{ } +FpgaNode::~FpgaNode() {} -int FpgaNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int FpgaNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_error_t err; + json_error_t err; - const char *card = nullptr; - const char *intf = nullptr; - const char *dma = nullptr; - int poll = polling; + const char *card = nullptr; + const char *intf = nullptr; + const char *dma = nullptr; + int poll = polling; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", - "card", &card, - "interface", &intf, - "dma", &dma, - "coalesce", &coalesce, - "polling", &polling - ); - if (ret) - throw ConfigError(json, err, "node-config-fpga", "Failed to parse configuration of node {}", this->getName()); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", + "card", &card, "interface", &intf, "dma", &dma, + "coalesce", &coalesce, "polling", &polling); + if (ret) + throw ConfigError(json, err, "node-config-fpga", + "Failed to parse configuration of node {}", + this->getName()); - if (card) - cardName = card; + if (card) + cardName = card; - if (intf) - intfName = intf; + if (intf) + intfName = intf; - if (dma) - dmaName = dma; + if (dma) + dmaName = dma; - polling = poll; // cast int to bool + polling = poll; // cast int to bool - return 0; + return 0; } -const std::string & FpgaNode::getDetails() -{ - if (details.empty()) { - auto &name = card ? card->name : cardName; +const std::string &FpgaNode::getDetails() { + if (details.empty()) { + auto &name = card ? card->name : cardName; - details = fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", - name, - dma->getInstanceName(), - polling ? "yes" : "no", - coalesce - ); - } + details = + fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", name, + dma->getInstanceName(), polling ? "yes" : "no", coalesce); + } - return details; + return details; } -int FpgaNode::check() -{ - return 0; +int FpgaNode::check() { return 0; } + +int FpgaNode::prepare() { + auto it = cardName.empty() + ? cards.begin() + : std::find_if(cards.begin(), cards.end(), + [this](std::shared_ptr c) { + return c->name == cardName; + }); + + if (it == cards.end()) + throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", + "Invalid FPGA card name: {}", cardName); + + card = *it; + + auto intfCore = intfName.empty() + ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) + : card->lookupIp(intfName); + if (!intfCore) + throw ConfigError(config, "node-config-fpga-interface", + "There is no interface IP with the name: {}", intfName); + + intf = std::dynamic_pointer_cast(intfCore); + if (!intf) + throw RuntimeError("The IP {} is not a interface", *intfCore); + + auto dmaCore = dmaName.empty() ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) + : card->lookupIp(dmaName); + if (!dmaCore) + throw ConfigError(config, "node-config-fpga-dma", + "There is no DMA IP with the name: {}", dmaName); + + dma = std::dynamic_pointer_cast(dmaCore); + if (!dma) + throw RuntimeError("The IP {} is not a DMA controller", *dmaCore); + + int ret = intf->connect(*(dma), true); + if (ret) + throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); + + auto &alloc = HostDmaRam::getAllocator(); + + const std::shared_ptr blockRx = + alloc.allocateBlock(0x100 * sizeof(float)); + const std::shared_ptr blockTx = + alloc.allocateBlock(0x100 * sizeof(float)); + villas::MemoryAccessor memRx = *blockRx; + villas::MemoryAccessor memTx = *blockTx; + + dma->makeAccesibleFromVA(blockRx); + dma->makeAccesibleFromVA(blockTx); + + // Show some debugging infos + auto &mm = MemoryManager::get(); + + dma->dump(); + intf->dump(); + mm.getGraph().dump(); + + return Node::prepare(); } -int FpgaNode::prepare() -{ - auto it = cardName.empty() - ? cards.begin() - : std::find_if(cards.begin(), cards.end(), [this](std::shared_ptr c) { - return c->name == cardName; - }); +int FpgaNode::_read(Sample *smps[], unsigned cnt) { + unsigned read; + Sample *smp = smps[0]; - if (it == cards.end()) - throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", "Invalid FPGA card name: {}", cardName); + assert(cnt == 1); - card = *it; + dma->read(*blockRx, blockRx->getSize()); // TODO: calc size + const size_t bytesRead = dma->readComplete().bytes; + read = bytesRead / sizeof(int32_t); - auto intfCore = intfName.empty() - ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) - : card->lookupIp(intfName); - if (!intfCore) - throw ConfigError(config, "node-config-fpga-interface", "There is no interface IP with the name: {}", intfName); + auto mem = MemoryAccessor(*blockRx); - intf = std::dynamic_pointer_cast(intfCore); - if (!intf) - throw RuntimeError("The IP {} is not a interface", *intfCore); + for (unsigned i = 0; i < MIN(read, smp->capacity); i++) + smp->data[i].i = mem[i]; - auto dmaCore = dmaName.empty() - ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) - : card->lookupIp(dmaName); - if (!dmaCore) - throw ConfigError(config, "node-config-fpga-dma", "There is no DMA IP with the name: {}", dmaName); + smp->signals = in.signals; - dma = std::dynamic_pointer_cast(dmaCore); - if (!dma) - throw RuntimeError("The IP {} is not a DMA controller", *dmaCore); - - int ret = intf->connect(*(dma), true); - if (ret) - throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); - - auto &alloc = HostDmaRam::getAllocator(); - - const std::shared_ptr blockRx = alloc.allocateBlock(0x100 * sizeof(float)); - const std::shared_ptr blockTx = alloc.allocateBlock(0x100 * sizeof(float)); - villas::MemoryAccessor memRx = *blockRx; - villas::MemoryAccessor memTx = *blockTx; - - dma->makeAccesibleFromVA(blockRx); - dma->makeAccesibleFromVA(blockTx); - - // Show some debugging infos - auto &mm = MemoryManager::get(); - - dma->dump(); - intf->dump(); - mm.getGraph().dump(); - - return Node::prepare(); + return read; } -int FpgaNode::_read(Sample *smps[], unsigned cnt) -{ - unsigned read; - Sample *smp = smps[0]; +int FpgaNode::_write(Sample *smps[], unsigned cnt) { + int written; + Sample *smp = smps[0]; - assert(cnt == 1); + assert(cnt == 1); - dma->read(*blockRx, blockRx->getSize()); // TODO: calc size - const size_t bytesRead = dma->readComplete().bytes; - read = bytesRead / sizeof(int32_t); + auto mem = MemoryAccessor(*blockTx); - auto mem = MemoryAccessor(*blockRx); + for (unsigned i = 0; i < smps[0]->length; i++) + mem[i] = smps[0]->data[i].i; - for (unsigned i = 0; i < MIN(read, smp->capacity); i++) - smp->data[i].i = mem[i]; + bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); + if (!state) + return -1; - smp->signals = in.signals; + written = 0; // The number of samples written - return read; + return written; } -int FpgaNode::_write(Sample *smps[], unsigned cnt) -{ - int written; - Sample *smp = smps[0]; +std::vector FpgaNode::getPollFDs() { + std::vector fds; - assert(cnt == 1); + if (!polling) + fds.push_back(irqFd); - auto mem = MemoryAccessor(*blockTx); - - for (unsigned i = 0; i < smps[0]->length; i++) - mem[i] = smps[0]->data[i].i; - - bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); - if (!state) - return -1; - - written = 0; // The number of samples written - - return written; + return fds; } -std::vector FpgaNode::getPollFDs() -{ - std::vector fds; +int FpgaNodeFactory::start(SuperNode *sn) { + vfioContainer = std::make_shared(); + pciDevices = std::make_shared(); - if (!polling) - fds.push_back(irqFd); + // Get the FPGA card plugin + auto pcieCardPlugin = plugin::registry->lookup("pcie"); + if (!pcieCardPlugin) + throw RuntimeError("No FPGA PCIe plugin found"); - return fds; -} + json_t *json_cfg = sn->getConfig(); + json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); + if (!json_fpgas) + throw ConfigError(json_cfg, "node-config-fpgas", + "No section 'fpgas' found in config"); -int FpgaNodeFactory::start(SuperNode *sn) -{ - vfioContainer = std::make_shared(); - pciDevices = std::make_shared(); + // Create all FPGA card instances using the corresponding plugin + auto piceCards = + fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); - // Get the FPGA card plugin - auto pcieCardPlugin = plugin::registry->lookup("pcie"); - if (!pcieCardPlugin) - throw RuntimeError("No FPGA PCIe plugin found"); + cards.splice(cards.end(), piceCards); - json_t *json_cfg = sn->getConfig(); - json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); - if (!json_fpgas) - throw ConfigError(json_cfg, "node-config-fpgas", "No section 'fpgas' found in config"); - - // Create all FPGA card instances using the corresponding plugin - auto piceCards = fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); - - cards.splice(cards.end(), piceCards); - - return NodeFactory::start(sn); + return NodeFactory::start(sn); } static FpgaNodeFactory p; diff --git a/lib/nodes/iec60870.cpp b/lib/nodes/iec60870.cpp index e3b213b2a..a05ee4890 100644 --- a/lib/nodes/iec60870.cpp +++ b/lib/nodes/iec60870.cpp @@ -7,12 +7,12 @@ #include +#include #include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; @@ -20,787 +20,793 @@ using namespace villas::utils; using namespace villas::node::iec60870; using namespace std::literals::chrono_literals; -static -CP56Time2a timespec_to_cp56time2a(timespec time) { - time_t time_ms = - static_cast(time.tv_sec) * 1000 - + static_cast(time.tv_nsec) / 1000000; - return CP56Time2a_createFromMsTimestamp(NULL, time_ms); +static CP56Time2a timespec_to_cp56time2a(timespec time) { + time_t time_ms = static_cast(time.tv_sec) * 1000 + + static_cast(time.tv_nsec) / 1000000; + return CP56Time2a_createFromMsTimestamp(NULL, time_ms); } -static -timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { - auto time_ms = CP56Time2a_toMsTimestamp(cp56time2a); - timespec time {}; - time.tv_nsec = time_ms % 1000 * 1000; - time.tv_sec = time_ms / 1000; - return time; +static timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { + auto time_ms = CP56Time2a_toMsTimestamp(cp56time2a); + timespec time{}; + time.tv_nsec = time_ms % 1000 * 1000; + time.tv_sec = time_ms / 1000; + return time; } -ASDUData ASDUData::parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence) { - json_error_t err; - char const *asdu_type_name = nullptr; - int with_timestamp = -1; - char const *asdu_type_id = nullptr; - std::optional ioa_sequence_start = std::nullopt; - int ioa = -1; +ASDUData ASDUData::parse(json_t *json_signal, std::optional last_data, + bool duplicate_ioa_is_sequence) { + json_error_t err; + char const *asdu_type_name = nullptr; + int with_timestamp = -1; + char const *asdu_type_id = nullptr; + std::optional ioa_sequence_start = std::nullopt; + int ioa = -1; - if (json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: b, s?: s, s: i }", - "asdu_type", &asdu_type_name, - "with_timestamp", &with_timestamp, - "asdu_type_id", &asdu_type_id, - "ioa", &ioa - )) - throw ConfigError(json_signal, err, "node-config-node-iec60870-5-104"); + if (json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: b, s?: s, s: i }", + "asdu_type", &asdu_type_name, "with_timestamp", + &with_timestamp, "asdu_type_id", &asdu_type_id, "ioa", + &ioa)) + throw ConfigError(json_signal, err, "node-config-node-iec60870-5-104"); - // Increase the ioa if it is found twice to make it a sequence - if ( duplicate_ioa_is_sequence && - last_data && - ioa == last_data->ioa_sequence_start) { - ioa = last_data->ioa + 1; - ioa_sequence_start = last_data->ioa_sequence_start; - } + // Increase the ioa if it is found twice to make it a sequence + if (duplicate_ioa_is_sequence && last_data && + ioa == last_data->ioa_sequence_start) { + ioa = last_data->ioa + 1; + ioa_sequence_start = last_data->ioa_sequence_start; + } - if ( (asdu_type_name && asdu_type_id) || - (!asdu_type_name && !asdu_type_id)) - throw RuntimeError("Please specify one of asdu_type or asdu_type_id", ioa); + if ((asdu_type_name && asdu_type_id) || (!asdu_type_name && !asdu_type_id)) + throw RuntimeError("Please specify one of asdu_type or asdu_type_id", ioa); - auto asdu_data = asdu_type_name - ? ASDUData::lookupName(asdu_type_name, - with_timestamp != -1 ? with_timestamp != 0 : false, - ioa, ioa_sequence_start.value_or(ioa)) - : ASDUData::lookupTypeId(asdu_type_id, ioa, ioa_sequence_start.value_or(ioa)); + auto asdu_data = + asdu_type_name ? ASDUData::lookupName( + asdu_type_name, + with_timestamp != -1 ? with_timestamp != 0 : false, + ioa, ioa_sequence_start.value_or(ioa)) + : ASDUData::lookupTypeId(asdu_type_id, ioa, + ioa_sequence_start.value_or(ioa)); - if (!asdu_data.has_value()) - throw RuntimeError("Found invalid asdu_type or asdu_type_id"); + if (!asdu_data.has_value()) + throw RuntimeError("Found invalid asdu_type or asdu_type_id"); - if (asdu_type_id && with_timestamp != -1 && asdu_data->hasTimestamp() != with_timestamp) - throw RuntimeError("Found mismatch between asdu_type_id {} and with_timestamp {}", asdu_type_id, with_timestamp != 0); + if (asdu_type_id && with_timestamp != -1 && + asdu_data->hasTimestamp() != with_timestamp) + throw RuntimeError( + "Found mismatch between asdu_type_id {} and with_timestamp {}", + asdu_type_id, with_timestamp != 0); - return *asdu_data; + return *asdu_data; }; -std::optional ASDUData::lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start) -{ - auto check = [type_id] (Descriptor descriptor) { - return !strcmp(descriptor.type_id, type_id); - }; +std::optional ASDUData::lookupTypeId(char const *type_id, int ioa, + int ioa_sequence_start) { + auto check = [type_id](Descriptor descriptor) { + return !strcmp(descriptor.type_id, type_id); + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -std::optional ASDUData::lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start) -{ - auto check = [name, with_timestamp] (Descriptor descriptor) { - return !strcmp(descriptor.name, name) && descriptor.has_timestamp == with_timestamp; - }; +std::optional ASDUData::lookupName(char const *name, + bool with_timestamp, int ioa, + int ioa_sequence_start) { + auto check = [name, with_timestamp](Descriptor descriptor) { + return !strcmp(descriptor.name, name) && + descriptor.has_timestamp == with_timestamp; + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -std::optional ASDUData::lookupType(int type, int ioa, int ioa_sequence_start) -{ - auto check = [type] (Descriptor descriptor) { - return descriptor.type == type; - }; +std::optional ASDUData::lookupType(int type, int ioa, + int ioa_sequence_start) { + auto check = [type](Descriptor descriptor) { + return descriptor.type == type; + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -bool ASDUData::hasTimestamp() const -{ - return descriptor->has_timestamp; +bool ASDUData::hasTimestamp() const { return descriptor->has_timestamp; } + +ASDUData::Type ASDUData::type() const { return descriptor->type; } + +char const *ASDUData::name() const { return descriptor->name; } + +ASDUData::Type ASDUData::typeWithoutTimestamp() const { + return descriptor->type_without_timestamp; } -ASDUData::Type ASDUData::type() const -{ - return descriptor->type; +ASDUData ASDUData::withoutTimestamp() const { + return ASDUData::lookupType(typeWithoutTimestamp(), ioa, ioa_sequence_start) + .value(); } -char const * ASDUData::name() const { - return descriptor->name; +SignalType ASDUData::signalType() const { return descriptor->signal_type; } + +std::optional +ASDUData::checkASDU(CS101_ASDU const &asdu) const { + if (CS101_ASDU_getTypeID(asdu) != static_cast(descriptor->type)) + return std::nullopt; + + for (int i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) { + InformationObject io = CS101_ASDU_getElement(asdu, i); + + if (ioa != InformationObject_getObjectAddress(io)) { + InformationObject_destroy(io); + continue; + } + + SignalData signal_data; + QualityDescriptor quality; + switch (typeWithoutTimestamp()) { + case ASDUData::SCALED_INT: { + auto scaled_int = reinterpret_cast(io); + int scaled_int_value = MeasuredValueScaled_getValue(scaled_int); + signal_data.i = static_cast(scaled_int_value); + quality = MeasuredValueScaled_getQuality(scaled_int); + break; + } + + case ASDUData::NORMALIZED_FLOAT: { + auto normalized_float = reinterpret_cast(io); + float normalized_float_value = + MeasuredValueNormalized_getValue(normalized_float); + signal_data.f = static_cast(normalized_float_value); + quality = MeasuredValueNormalized_getQuality(normalized_float); + break; + } + + case ASDUData::DOUBLE_POINT: { + auto double_point = reinterpret_cast(io); + DoublePointValue double_point_value = + DoublePointInformation_getValue(double_point); + signal_data.i = static_cast(double_point_value); + quality = DoublePointInformation_getQuality(double_point); + break; + } + + case ASDUData::SINGLE_POINT: { + auto single_point = reinterpret_cast(io); + bool single_point_value = SinglePointInformation_getValue(single_point); + signal_data.b = static_cast(single_point_value); + quality = SinglePointInformation_getQuality(single_point); + break; + } + + case ASDUData::SHORT_FLOAT: { + auto short_float = reinterpret_cast(io); + float short_float_value = MeasuredValueShort_getValue(short_float); + signal_data.f = static_cast(short_float_value); + quality = MeasuredValueShort_getQuality(short_float); + break; + } + + default: + throw RuntimeError{"unsupported asdu type"}; + } + + std::optional time_cp56; + switch (type()) { + case ASDUData::SCALED_INT_WITH_TIMESTAMP: { + auto scaled_int = reinterpret_cast(io); + time_cp56 = MeasuredValueScaledWithCP56Time2a_getTimestamp(scaled_int); + break; + } + + case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { + auto normalized_float = + reinterpret_cast(io); + time_cp56 = + MeasuredValueNormalizedWithCP56Time2a_getTimestamp(normalized_float); + break; + } + + case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { + auto double_point = reinterpret_cast(io); + time_cp56 = DoublePointWithCP56Time2a_getTimestamp(double_point); + break; + } + + case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { + auto single_point = reinterpret_cast(io); + time_cp56 = SinglePointWithCP56Time2a_getTimestamp(single_point); + break; + } + + case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { + auto short_float = reinterpret_cast(io); + time_cp56 = MeasuredValueShortWithCP56Time2a_getTimestamp(short_float); + break; + } + + default: + time_cp56 = std::nullopt; + } + + InformationObject_destroy(io); + + std::optional timestamp = + time_cp56.has_value() + ? std::optional{cp56time2a_to_timespec(*time_cp56)} + : std::nullopt; + + return ASDUData::Sample{signal_data, quality, timestamp}; + } + + return std::nullopt; } -ASDUData::Type ASDUData::typeWithoutTimestamp() const -{ - return descriptor->type_without_timestamp; -} - -ASDUData ASDUData::withoutTimestamp() const -{ - return ASDUData::lookupType(typeWithoutTimestamp(), ioa, ioa_sequence_start).value(); -} - -SignalType ASDUData::signalType() const -{ - return descriptor->signal_type; -} - -std::optional ASDUData::checkASDU(CS101_ASDU const &asdu) const -{ - if (CS101_ASDU_getTypeID(asdu) != static_cast(descriptor->type)) - return std::nullopt; - - for (int i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) { - InformationObject io = CS101_ASDU_getElement(asdu, i); - - if (ioa != InformationObject_getObjectAddress(io)) { - InformationObject_destroy(io); - continue; - } - - SignalData signal_data; - QualityDescriptor quality; - switch (typeWithoutTimestamp()) { - case ASDUData::SCALED_INT: { - auto scaled_int = reinterpret_cast(io); - int scaled_int_value = MeasuredValueScaled_getValue(scaled_int); - signal_data.i = static_cast(scaled_int_value); - quality = MeasuredValueScaled_getQuality(scaled_int); - break; - } - - case ASDUData::NORMALIZED_FLOAT: { - auto normalized_float = reinterpret_cast(io); - float normalized_float_value = MeasuredValueNormalized_getValue(normalized_float); - signal_data.f = static_cast(normalized_float_value); - quality = MeasuredValueNormalized_getQuality(normalized_float); - break; - } - - case ASDUData::DOUBLE_POINT: { - auto double_point = reinterpret_cast(io); - DoublePointValue double_point_value = DoublePointInformation_getValue(double_point); - signal_data.i = static_cast(double_point_value); - quality = DoublePointInformation_getQuality(double_point); - break; - } - - case ASDUData::SINGLE_POINT: { - auto single_point = reinterpret_cast(io); - bool single_point_value = SinglePointInformation_getValue(single_point); - signal_data.b = static_cast(single_point_value); - quality = SinglePointInformation_getQuality(single_point); - break; - } - - case ASDUData::SHORT_FLOAT: { - auto short_float = reinterpret_cast(io); - float short_float_value = MeasuredValueShort_getValue(short_float); - signal_data.f = static_cast(short_float_value); - quality = MeasuredValueShort_getQuality(short_float); - break; - } - - default: - throw RuntimeError { "unsupported asdu type" }; - } - - std::optional time_cp56; - switch (type()) { - case ASDUData::SCALED_INT_WITH_TIMESTAMP: { - auto scaled_int = reinterpret_cast(io); - time_cp56 = MeasuredValueScaledWithCP56Time2a_getTimestamp(scaled_int); - break; - } - - case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { - auto normalized_float = reinterpret_cast(io); - time_cp56 = MeasuredValueNormalizedWithCP56Time2a_getTimestamp(normalized_float); - break; - } - - case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { - auto double_point = reinterpret_cast(io); - time_cp56 = DoublePointWithCP56Time2a_getTimestamp(double_point); - break; - } - - case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { - auto single_point = reinterpret_cast(io); - time_cp56 = SinglePointWithCP56Time2a_getTimestamp(single_point); - break; - } - - case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { - auto short_float = reinterpret_cast(io); - time_cp56 = MeasuredValueShortWithCP56Time2a_getTimestamp(short_float); - break; - } - - default: - time_cp56 = std::nullopt; - } - - InformationObject_destroy(io); - - std::optional timestamp = time_cp56.has_value() - ? std::optional { cp56time2a_to_timespec(*time_cp56) } - : std::nullopt; - - return ASDUData::Sample { signal_data, quality, timestamp }; - } - - return std::nullopt; -} - -bool ASDUData::addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const -{ +bool ASDUData::addSampleToASDU(CS101_ASDU &asdu, + ASDUData::Sample sample) const { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" - std::optional timestamp = sample.timestamp.has_value() - ? std::optional { timespec_to_cp56time2a(*sample.timestamp) } - : std::nullopt; + std::optional timestamp = + sample.timestamp.has_value() + ? std::optional{timespec_to_cp56time2a(*sample.timestamp)} + : std::nullopt; - InformationObject io = nullptr; - switch (descriptor->type) { - case ASDUData::SCALED_INT: { - auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); - auto scaled_int = MeasuredValueScaled_create(NULL, ioa, scaled_int_value, sample.quality); - io = reinterpret_cast(scaled_int); - break; - } + InformationObject io = nullptr; + switch (descriptor->type) { + case ASDUData::SCALED_INT: { + auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); + auto scaled_int = + MeasuredValueScaled_create(NULL, ioa, scaled_int_value, sample.quality); + io = reinterpret_cast(scaled_int); + break; + } - case ASDUData::NORMALIZED_FLOAT: { - auto normalized_float_value = static_cast(sample.signal_data.f); - auto normalized_float = MeasuredValueNormalized_create(NULL, ioa, normalized_float_value, sample.quality); - io = reinterpret_cast(normalized_float); - break; - } + case ASDUData::NORMALIZED_FLOAT: { + auto normalized_float_value = static_cast(sample.signal_data.f); + auto normalized_float = MeasuredValueNormalized_create( + NULL, ioa, normalized_float_value, sample.quality); + io = reinterpret_cast(normalized_float); + break; + } - case ASDUData::DOUBLE_POINT: { - auto double_point_value = static_cast(sample.signal_data.i & 0x3); - auto double_point = DoublePointInformation_create(NULL, ioa, double_point_value, sample.quality); - io = reinterpret_cast(double_point); - break; - } + case ASDUData::DOUBLE_POINT: { + auto double_point_value = + static_cast(sample.signal_data.i & 0x3); + auto double_point = DoublePointInformation_create( + NULL, ioa, double_point_value, sample.quality); + io = reinterpret_cast(double_point); + break; + } - case ASDUData::SINGLE_POINT: { - auto single_point_value = sample.signal_data.b; - auto single_point = SinglePointInformation_create(NULL, ioa, single_point_value, sample.quality); - io = reinterpret_cast(single_point); - break; - } + case ASDUData::SINGLE_POINT: { + auto single_point_value = sample.signal_data.b; + auto single_point = SinglePointInformation_create( + NULL, ioa, single_point_value, sample.quality); + io = reinterpret_cast(single_point); + break; + } - case ASDUData::SHORT_FLOAT: { - auto short_float_value = static_cast(sample.signal_data.f); - auto short_float = MeasuredValueShort_create(NULL, ioa, short_float_value, sample.quality); - io = reinterpret_cast(short_float); - break; - } + case ASDUData::SHORT_FLOAT: { + auto short_float_value = static_cast(sample.signal_data.f); + auto short_float = + MeasuredValueShort_create(NULL, ioa, short_float_value, sample.quality); + io = reinterpret_cast(short_float); + break; + } - case ASDUData::SCALED_INT_WITH_TIMESTAMP: { - auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); - auto scaled_int = MeasuredValueScaledWithCP56Time2a_create(NULL, ioa, scaled_int_value, sample.quality, timestamp.value()); - io = reinterpret_cast(scaled_int); - break; - } + case ASDUData::SCALED_INT_WITH_TIMESTAMP: { + auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); + auto scaled_int = MeasuredValueScaledWithCP56Time2a_create( + NULL, ioa, scaled_int_value, sample.quality, timestamp.value()); + io = reinterpret_cast(scaled_int); + break; + } - case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { - auto normalized_float_value = static_cast(sample.signal_data.f); - auto normalized_float = MeasuredValueNormalizedWithCP56Time2a_create(NULL, ioa, normalized_float_value, sample.quality, timestamp.value()); - io = reinterpret_cast(normalized_float); - break; - } + case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { + auto normalized_float_value = static_cast(sample.signal_data.f); + auto normalized_float = MeasuredValueNormalizedWithCP56Time2a_create( + NULL, ioa, normalized_float_value, sample.quality, timestamp.value()); + io = reinterpret_cast(normalized_float); + break; + } - case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { - auto double_point_value = static_cast(sample.signal_data.i & 0x3); - auto double_point = DoublePointWithCP56Time2a_create(NULL, ioa, double_point_value, sample.quality, timestamp.value()); - io = reinterpret_cast(double_point); - break; - } + case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { + auto double_point_value = + static_cast(sample.signal_data.i & 0x3); + auto double_point = DoublePointWithCP56Time2a_create( + NULL, ioa, double_point_value, sample.quality, timestamp.value()); + io = reinterpret_cast(double_point); + break; + } - case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { - auto single_point_value = sample.signal_data.b; - auto single_point = SinglePointWithCP56Time2a_create(NULL, ioa, single_point_value, sample.quality, timestamp.value()); - io = reinterpret_cast(single_point); - break; - } + case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { + auto single_point_value = sample.signal_data.b; + auto single_point = SinglePointWithCP56Time2a_create( + NULL, ioa, single_point_value, sample.quality, timestamp.value()); + io = reinterpret_cast(single_point); + break; + } - case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { - auto short_float_value = static_cast(sample.signal_data.f); - auto short_float = MeasuredValueShortWithCP56Time2a_create(NULL, ioa, short_float_value, sample.quality, timestamp.value()); - io = reinterpret_cast(short_float); - break; - } + case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { + auto short_float_value = static_cast(sample.signal_data.f); + auto short_float = MeasuredValueShortWithCP56Time2a_create( + NULL, ioa, short_float_value, sample.quality, timestamp.value()); + io = reinterpret_cast(short_float); + break; + } - default: - throw RuntimeError { "invalid asdu data type" }; - } + default: + throw RuntimeError{"invalid asdu data type"}; + } - bool successfully_added = CS101_ASDU_addInformationObject(asdu, io); + bool successfully_added = CS101_ASDU_addInformationObject(asdu, io); - InformationObject_destroy(io); + InformationObject_destroy(io); - return successfully_added; + return successfully_added; #pragma GCC diagnostic pop } -ASDUData::ASDUData(ASDUData::Descriptor const *descriptor, int ioa, int ioa_sequence_start) : ioa(ioa), ioa_sequence_start(ioa_sequence_start), descriptor(descriptor) -{ +ASDUData::ASDUData(ASDUData::Descriptor const *descriptor, int ioa, + int ioa_sequence_start) + : ioa(ioa), ioa_sequence_start(ioa_sequence_start), descriptor(descriptor) { } -void SlaveNode::createSlave() noexcept -{ - // Destroy slave id it was already created - destroySlave(); +void SlaveNode::createSlave() noexcept { + // Destroy slave id it was already created + destroySlave(); - // Create the slave object - server.slave = CS104_Slave_create(server.low_priority_queue, server.high_priority_queue); - CS104_Slave_setServerMode(server.slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP); - CS104_Slave_setMaxOpenConnections(server.slave, 1); + // Create the slave object + server.slave = + CS104_Slave_create(server.low_priority_queue, server.high_priority_queue); + CS104_Slave_setServerMode(server.slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP); + CS104_Slave_setMaxOpenConnections(server.slave, 1); - // Configure the slave according to config - server.asdu_app_layer_parameters = CS104_Slave_getAppLayerParameters(server.slave); - CS104_APCIParameters apci_parameters = CS104_Slave_getConnectionParameters(server.slave); + // Configure the slave according to config + server.asdu_app_layer_parameters = + CS104_Slave_getAppLayerParameters(server.slave); + CS104_APCIParameters apci_parameters = + CS104_Slave_getConnectionParameters(server.slave); - if (server.apci_t0) - apci_parameters->t0 = *server.apci_t0; + if (server.apci_t0) + apci_parameters->t0 = *server.apci_t0; - if (server.apci_t1) - apci_parameters->t1 = *server.apci_t1; + if (server.apci_t1) + apci_parameters->t1 = *server.apci_t1; - if (server.apci_t2) - apci_parameters->t2 = *server.apci_t2; + if (server.apci_t2) + apci_parameters->t2 = *server.apci_t2; - if (server.apci_t3) - apci_parameters->t3 = *server.apci_t3; + if (server.apci_t3) + apci_parameters->t3 = *server.apci_t3; - if (server.apci_k) - apci_parameters->k = *server.apci_k; + if (server.apci_k) + apci_parameters->k = *server.apci_k; - if (server.apci_w) - apci_parameters->w = *server.apci_w; + if (server.apci_w) + apci_parameters->w = *server.apci_w; - CS104_Slave_setLocalAddress(server.slave, server.local_address.c_str()); - CS104_Slave_setLocalPort(server.slave, server.local_port); + CS104_Slave_setLocalAddress(server.slave, server.local_address.c_str()); + CS104_Slave_setLocalPort(server.slave, server.local_port); - // Setup callbacks into the class - CS104_Slave_setClockSyncHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) { - auto self = static_cast(tcp_node); - return self->onClockSync(connection, asdu, new_time); - }, this); + // Setup callbacks into the class + CS104_Slave_setClockSyncHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) { + auto self = static_cast(tcp_node); + return self->onClockSync(connection, asdu, new_time); + }, + this); - CS104_Slave_setInterrogationHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, QualifierOfInterrogation qoi) { - auto self = static_cast(tcp_node); - return self->onInterrogation(connection, asdu, qoi); - }, this); + CS104_Slave_setInterrogationHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, + QualifierOfInterrogation qoi) { + auto self = static_cast(tcp_node); + return self->onInterrogation(connection, asdu, qoi); + }, + this); - CS104_Slave_setASDUHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu) { - auto self = static_cast(tcp_node); - return self->onASDU(connection, asdu); - }, this); + CS104_Slave_setASDUHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu) { + auto self = static_cast(tcp_node); + return self->onASDU(connection, asdu); + }, + this); - CS104_Slave_setConnectionEventHandler(server.slave, [](void *tcp_node, IMasterConnection connection, CS104_PeerConnectionEvent event){ - auto self = static_cast(tcp_node); - self->debugPrintConnection(connection, event); - }, this); + CS104_Slave_setConnectionEventHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, + CS104_PeerConnectionEvent event) { + auto self = static_cast(tcp_node); + self->debugPrintConnection(connection, event); + }, + this); - CS104_Slave_setRawMessageHandler(server.slave, [](void *tcp_node, IMasterConnection connection, uint8_t *message, int message_size, bool sent){ - auto self = static_cast(tcp_node); - self->debugPrintMessage(connection, message, message_size, sent); - }, this); + CS104_Slave_setRawMessageHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, uint8_t *message, + int message_size, bool sent) { + auto self = static_cast(tcp_node); + self->debugPrintMessage(connection, message, message_size, sent); + }, + this); - server.state = SlaveNode::Server::READY; + server.state = SlaveNode::Server::READY; } -void SlaveNode::destroySlave() noexcept -{ - if (server.state == SlaveNode::Server::NONE) - return; +void SlaveNode::destroySlave() noexcept { + if (server.state == SlaveNode::Server::NONE) + return; - stopSlave(); + stopSlave(); - CS104_Slave_destroy(server.slave); - server.state = SlaveNode::Server::NONE; + CS104_Slave_destroy(server.slave); + server.state = SlaveNode::Server::NONE; } -void SlaveNode::startSlave() noexcept(false) -{ - if (server.state == SlaveNode::Server::NONE) - createSlave(); - else - stopSlave(); +void SlaveNode::startSlave() noexcept(false) { + if (server.state == SlaveNode::Server::NONE) + createSlave(); + else + stopSlave(); - server.state = SlaveNode::Server::READY; + server.state = SlaveNode::Server::READY; - CS104_Slave_start(server.slave); + CS104_Slave_start(server.slave); - if (!CS104_Slave_isRunning(server.slave)) - throw std::runtime_error{"iec60870-5-104 server could not be started"}; + if (!CS104_Slave_isRunning(server.slave)) + throw std::runtime_error{"iec60870-5-104 server could not be started"}; } -void SlaveNode::stopSlave() noexcept -{ - if (server.state != SlaveNode::Server::READY || !CS104_Slave_isRunning(server.slave)) - return; +void SlaveNode::stopSlave() noexcept { + if (server.state != SlaveNode::Server::READY || + !CS104_Slave_isRunning(server.slave)) + return; - server.state = SlaveNode::Server::STOPPED; + server.state = SlaveNode::Server::STOPPED; - if (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) - logger->info("Waiting for last messages in queue"); + if (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) + logger->info("Waiting for last messages in queue"); - // Wait for all messages to be send before really stopping - while ( (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) && - (CS104_Slave_getOpenConnections(server.slave) != 0)) - std::this_thread::sleep_for(100ms); + // Wait for all messages to be send before really stopping + while ((CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) && + (CS104_Slave_getOpenConnections(server.slave) != 0)) + std::this_thread::sleep_for(100ms); - CS104_Slave_stop(server.slave); + CS104_Slave_stop(server.slave); } -void SlaveNode::debugPrintMessage(IMasterConnection connection, uint8_t* message, int message_size, bool sent) const noexcept -{ - /// TODO: debug print the message bytes as trace +void SlaveNode::debugPrintMessage(IMasterConnection connection, + uint8_t *message, int message_size, + bool sent) const noexcept { + /// TODO: debug print the message bytes as trace } -void SlaveNode::debugPrintConnection(IMasterConnection connection, CS104_PeerConnectionEvent event) const noexcept -{ - switch (event) { - case CS104_CON_EVENT_CONNECTION_OPENED: - logger->info("Client connected"); - break; +void SlaveNode::debugPrintConnection( + IMasterConnection connection, + CS104_PeerConnectionEvent event) const noexcept { + switch (event) { + case CS104_CON_EVENT_CONNECTION_OPENED: + logger->info("Client connected"); + break; - case CS104_CON_EVENT_CONNECTION_CLOSED: - logger->info("Client disconnected"); - break; + case CS104_CON_EVENT_CONNECTION_CLOSED: + logger->info("Client disconnected"); + break; - case CS104_CON_EVENT_ACTIVATED: - logger->info("Connection activated"); - break; + case CS104_CON_EVENT_ACTIVATED: + logger->info("Connection activated"); + break; - case CS104_CON_EVENT_DEACTIVATED: - logger->info("Connection closed"); - break; - } + case CS104_CON_EVENT_DEACTIVATED: + logger->info("Connection closed"); + break; + } } -bool SlaveNode::onClockSync(IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) const noexcept -{ - logger->warn("Received clock sync command (unimplemented)"); - return true; +bool SlaveNode::onClockSync(IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) const noexcept { + logger->warn("Received clock sync command (unimplemented)"); + return true; } -bool SlaveNode::onInterrogation(IMasterConnection connection, CS101_ASDU asdu, QualifierOfInterrogation qoi) const noexcept -{ - switch (qoi) { - // Send last values without timestamps - case IEC60870_QOI_STATION: { - IMasterConnection_sendACT_CON(connection, asdu, false); +bool SlaveNode::onInterrogation(IMasterConnection connection, CS101_ASDU asdu, + QualifierOfInterrogation qoi) const noexcept { + switch (qoi) { + // Send last values without timestamps + case IEC60870_QOI_STATION: { + IMasterConnection_sendACT_CON(connection, asdu, false); - logger->debug("Received general interrogation"); + logger->debug("Received general interrogation"); - auto guard = std::lock_guard { output.last_values_mutex }; + auto guard = std::lock_guard{output.last_values_mutex}; - for (auto const &asdu_type : output.asdu_types) { - for (unsigned i = 0; i < output.mapping.size();) { - auto signal_asdu = CS101_ASDU_create( - IMasterConnection_getApplicationLayerParameters(connection), - false, - CS101_COT_INTERROGATED_BY_STATION, - 0, - server.common_address, - false, - false - ); + for (auto const &asdu_type : output.asdu_types) { + for (unsigned i = 0; i < output.mapping.size();) { + auto signal_asdu = CS101_ASDU_create( + IMasterConnection_getApplicationLayerParameters(connection), false, + CS101_COT_INTERROGATED_BY_STATION, 0, server.common_address, false, + false); - do { - auto asdu_data = output.mapping[i]; - auto last_value = output.last_values[i]; + do { + auto asdu_data = output.mapping[i]; + auto last_value = output.last_values[i]; - if (asdu_data.type() != asdu_type) - continue; + if (asdu_data.type() != asdu_type) + continue; - if (!asdu_data.withoutTimestamp().addSampleToASDU(signal_asdu, - ASDUData::Sample { - last_value, - IEC60870_QUALITY_GOOD, - std::nullopt - })) - break; - } while (++i < output.mapping.size()); + if (!asdu_data.withoutTimestamp().addSampleToASDU( + signal_asdu, + ASDUData::Sample{last_value, IEC60870_QUALITY_GOOD, + std::nullopt})) + break; + } while (++i < output.mapping.size()); - if (CS101_ASDU_getNumberOfElements(asdu) != 0) - IMasterConnection_sendASDU(connection, signal_asdu); + if (CS101_ASDU_getNumberOfElements(asdu) != 0) + IMasterConnection_sendASDU(connection, signal_asdu); - CS101_ASDU_destroy(signal_asdu); - } - } + CS101_ASDU_destroy(signal_asdu); + } + } - IMasterConnection_sendACT_TERM(connection, asdu); - break; - } + IMasterConnection_sendACT_TERM(connection, asdu); + break; + } - // Negative acknowledgement - default: - IMasterConnection_sendACT_CON(connection, asdu, true); - logger->warn("Ignoring interrogation type {}", qoi); - } + // Negative acknowledgement + default: + IMasterConnection_sendACT_CON(connection, asdu, true); + logger->warn("Ignoring interrogation type {}", qoi); + } - return true; + return true; } -bool SlaveNode::onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept -{ - logger->warn("Ignoring ASDU type {}", CS101_ASDU_getTypeID(asdu)); - return true; +bool SlaveNode::onASDU(IMasterConnection connection, + CS101_ASDU asdu) const noexcept { + logger->warn("Ignoring ASDU type {}", CS101_ASDU_getTypeID(asdu)); + return true; } -void SlaveNode::sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false) -{ - // ASDUs may only carry one type of ASDU - for (auto const &type : output.asdu_types) { - // Search all occurrences of this ASDU type - for (unsigned signal = 0; signal < MIN(sample->length, output.mapping.size());) { - // Create an ASDU for periodic transmission - CS101_ASDU asdu = CS101_ASDU_create( - server.asdu_app_layer_parameters, - 0, - CS101_COT_PERIODIC, - 0, - server.common_address, - false, - false - ); +void SlaveNode::sendPeriodicASDUsForSample(Sample const *sample) const + noexcept(false) { + // ASDUs may only carry one type of ASDU + for (auto const &type : output.asdu_types) { + // Search all occurrences of this ASDU type + for (unsigned signal = 0; + signal < MIN(sample->length, output.mapping.size());) { + // Create an ASDU for periodic transmission + CS101_ASDU asdu = CS101_ASDU_create(server.asdu_app_layer_parameters, 0, + CS101_COT_PERIODIC, 0, + server.common_address, false, false); - do { - auto &asdu_data = output.mapping[signal]; + do { + auto &asdu_data = output.mapping[signal]; - // This signal_data does not belong in this ASDU - if (asdu_data.type() != type) - continue; + // This signal_data does not belong in this ASDU + if (asdu_data.type() != type) + continue; - auto timestamp = (sample->flags & (int) SampleFlags::HAS_TS_ORIGIN) - ? std::optional{ sample->ts.origin } - : std::nullopt; + auto timestamp = (sample->flags & (int)SampleFlags::HAS_TS_ORIGIN) + ? std::optional{sample->ts.origin} + : std::nullopt; - if (asdu_data.hasTimestamp() && !timestamp.has_value()) - throw RuntimeError("Received sample without timestamp for ASDU type with mandatory timestamp"); + if (asdu_data.hasTimestamp() && !timestamp.has_value()) + throw RuntimeError("Received sample without timestamp for ASDU type " + "with mandatory timestamp"); - if (asdu_data.signalType() != sample_format(sample, signal)) - throw RuntimeError("Expected signal type {}, but received {}", - signalTypeToString(asdu_data.signalType()), - signalTypeToString(sample_format(sample, signal)) - ); + if (asdu_data.signalType() != sample_format(sample, signal)) + throw RuntimeError("Expected signal type {}, but received {}", + signalTypeToString(asdu_data.signalType()), + signalTypeToString(sample_format(sample, signal))); - if (asdu_data.addSampleToASDU(asdu, ASDUData::Sample { - sample->data[signal], - IEC60870_QUALITY_GOOD, - timestamp - }) == false) - // ASDU is full -> dispatch -> create a new one - break; - } while (++signal < MIN(sample->length, output.mapping.size())); + if (asdu_data.addSampleToASDU(asdu, + ASDUData::Sample{sample->data[signal], + IEC60870_QUALITY_GOOD, + timestamp}) == false) + // ASDU is full -> dispatch -> create a new one + break; + } while (++signal < MIN(sample->length, output.mapping.size())); - if (CS101_ASDU_getNumberOfElements(asdu) != 0) - CS104_Slave_enqueueASDU(server.slave, asdu); + if (CS101_ASDU_getNumberOfElements(asdu) != 0) + CS104_Slave_enqueueASDU(server.slave, asdu); - CS101_ASDU_destroy(asdu); - } - } + CS101_ASDU_destroy(asdu); + } + } } -int SlaveNode::_write(Sample *samples[], unsigned sample_count) -{ - if (server.state != SlaveNode::Server::READY) - return -1; +int SlaveNode::_write(Sample *samples[], unsigned sample_count) { + if (server.state != SlaveNode::Server::READY) + return -1; - for (unsigned sample_index = 0; sample_index < sample_count; sample_index++) { - Sample const *sample = samples[sample_index]; + for (unsigned sample_index = 0; sample_index < sample_count; sample_index++) { + Sample const *sample = samples[sample_index]; - // Update last_values - output.last_values_mutex.lock(); - for (unsigned i = 0; i < MIN(sample->length, output.last_values.size()); i++) - output.last_values[i] = sample->data[i]; + // Update last_values + output.last_values_mutex.lock(); + for (unsigned i = 0; i < MIN(sample->length, output.last_values.size()); + i++) + output.last_values[i] = sample->data[i]; - output.last_values_mutex.unlock(); - sendPeriodicASDUsForSample(sample); - } + output.last_values_mutex.unlock(); + sendPeriodicASDUsForSample(sample); + } - return sample_count; + return sample_count; } -SlaveNode::SlaveNode(const uuid_t &id, const std::string &name) : - Node(id, name) -{ - server.state = SlaveNode::Server::NONE; +SlaveNode::SlaveNode(const uuid_t &id, const std::string &name) + : Node(id, name) { + server.state = SlaveNode::Server::NONE; - // Server config (use explicit defaults) - server.local_address = "0.0.0.0"; - server.local_port = 2404; - server.common_address = 1; - server.low_priority_queue = 100; - server.high_priority_queue = 100; + // Server config (use explicit defaults) + server.local_address = "0.0.0.0"; + server.local_port = 2404; + server.common_address = 1; + server.low_priority_queue = 100; + server.high_priority_queue = 100; - // Config (use lib60870 defaults if std::nullopt) - server.apci_t0 = std::nullopt; - server.apci_t1 = std::nullopt; - server.apci_t2 = std::nullopt; - server.apci_t3 = std::nullopt; - server.apci_k = std::nullopt; - server.apci_w = std::nullopt; + // Config (use lib60870 defaults if std::nullopt) + server.apci_t0 = std::nullopt; + server.apci_t1 = std::nullopt; + server.apci_t2 = std::nullopt; + server.apci_t3 = std::nullopt; + server.apci_k = std::nullopt; + server.apci_w = std::nullopt; - // Output config - output.enabled = false; - output.mapping = {}; - output.asdu_types = {}; - output.last_values = {}; + // Output config + output.enabled = false; + output.mapping = {}; + output.asdu_types = {}; + output.last_values = {}; } -SlaveNode::~SlaveNode() -{ - destroySlave(); +SlaveNode::~SlaveNode() { destroySlave(); } + +int SlaveNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; + + json_error_t err; + auto signals = getOutputSignals(); + + json_t *json_out = nullptr; + char const *address = nullptr; + int apci_t0 = -1; + int apci_t1 = -1; + int apci_t2 = -1; + int apci_t3 = -1; + int apci_k = -1; + int apci_w = -1; + + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: s, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, " + "s?: i, s?: i }", + "out", &json_out, "address", &address, "port", &server.local_port, "ca", + &server.common_address, "low_priority_queue", &server.low_priority_queue, + "high_priority_queue", &server.high_priority_queue, "apci_t0", &apci_t0, + "apci_t1", &apci_t1, "apci_t2", &apci_t2, "apci_t3", &apci_t3, "apci_k", + &apci_k, "apci_w", &apci_w); + if (ret) + throw ConfigError(json, err, "node-config-node-iec60870-5-104"); + + if (apci_t0 != -1) + server.apci_t0 = apci_t0; + + if (apci_t1 != -1) + server.apci_t1 = apci_t1; + + if (apci_t2 != -1) + server.apci_t2 = apci_t2; + + if (apci_t3 != -1) + server.apci_t3 = apci_t3; + + if (apci_k != -1) + server.apci_k = apci_k; + + if (apci_w != -1) + server.apci_w = apci_w; + + if (address) + server.local_address = address; + + json_t *json_signals = nullptr; + int duplicate_ioa_is_sequence = false; + + if (json_out) { + output.enabled = true; + + ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s?: b }", "signals", + &json_signals, "duplicate_ioa_is_sequence", + &duplicate_ioa_is_sequence); + if (ret) + throw ConfigError(json_out, err, "node-config-node-iec60870-5-104"); + } + + if (json_signals) { + json_t *json_signal; + size_t i; + std::optional last_data = std::nullopt; + + json_array_foreach(json_signals, i, json_signal) { + auto signal = signals ? signals->getByIndex(i) : Signal::Ptr{}; + auto asdu_data = + ASDUData::parse(json_signal, last_data, duplicate_ioa_is_sequence); + last_data = asdu_data; + SignalData initial_value; + + if (signal) { + if (signal->type != asdu_data.signalType()) { + throw RuntimeError( + "Type mismatch! Expected type {} for signal {}, but found {}", + signalTypeToString(asdu_data.signalType()), signal->name, + signalTypeToString(signal->type)); + } + + switch (signal->type) { + case SignalType::BOOLEAN: + initial_value.b = false; + break; + + case SignalType::INTEGER: + initial_value.i = 0; + break; + + case SignalType::FLOAT: + initial_value.f = 0; + break; + + default: + throw RuntimeError{"unsupported signal type"}; + } + } else + initial_value.f = 0.0; + + output.mapping.push_back(asdu_data); + output.last_values.push_back(initial_value); + } + } + + for (auto const &asdu_data : output.mapping) { + if (std::find(begin(output.asdu_types), end(output.asdu_types), + asdu_data.type()) == end(output.asdu_types)) + output.asdu_types.push_back(asdu_data.type()); + } + + return 0; } -int SlaveNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int SlaveNode::start() { + startSlave(); - json_error_t err; - auto signals = getOutputSignals(); - - json_t *json_out = nullptr; - char const *address = nullptr; - int apci_t0 = -1; - int apci_t1 = -1; - int apci_t2 = -1; - int apci_t3 = -1; - int apci_k = -1; - int apci_w = -1; - - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: s, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i }", - "out", &json_out, - "address", &address, - "port", &server.local_port, - "ca", &server.common_address, - "low_priority_queue", &server.low_priority_queue, - "high_priority_queue", &server.high_priority_queue, - "apci_t0", &apci_t0, - "apci_t1", &apci_t1, - "apci_t2", &apci_t2, - "apci_t3", &apci_t3, - "apci_k", &apci_k, - "apci_w", &apci_w - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec60870-5-104"); - - if (apci_t0 != -1) - server.apci_t0 = apci_t0; - - if (apci_t1 != -1) - server.apci_t1 = apci_t1; - - if (apci_t2 != -1) - server.apci_t2 = apci_t2; - - if (apci_t3 != -1) - server.apci_t3 = apci_t3; - - if (apci_k != -1) - server.apci_k = apci_k; - - if (apci_w != -1) - server.apci_w = apci_w; - - if (address) - server.local_address = address; - - json_t *json_signals = nullptr; - int duplicate_ioa_is_sequence = false; - - if (json_out) { - output.enabled = true; - - ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s?: b }", - "signals", &json_signals, - "duplicate_ioa_is_sequence", &duplicate_ioa_is_sequence - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-iec60870-5-104"); - } - - if (json_signals) { - json_t *json_signal; - size_t i; - std::optional last_data = std::nullopt; - - json_array_foreach(json_signals, i, json_signal) { - auto signal = signals ? signals->getByIndex(i) : Signal::Ptr{}; - auto asdu_data = ASDUData::parse(json_signal, last_data, duplicate_ioa_is_sequence); - last_data = asdu_data; - SignalData initial_value; - - if (signal) { - if (signal->type != asdu_data.signalType()) { - throw RuntimeError("Type mismatch! Expected type {} for signal {}, but found {}", - signalTypeToString(asdu_data.signalType()), - signal->name, - signalTypeToString(signal->type) - ); - } - - switch (signal->type) { - case SignalType::BOOLEAN: - initial_value.b = false; - break; - - case SignalType::INTEGER: - initial_value.i = 0; - break; - - case SignalType::FLOAT: - initial_value.f = 0; - break; - - default: - throw RuntimeError { "unsupported signal type" }; - } - } else - initial_value.f = 0.0; - - output.mapping.push_back(asdu_data); - output.last_values.push_back(initial_value); - } - } - - for (auto const &asdu_data : output.mapping) { - if (std::find(begin(output.asdu_types), end(output.asdu_types), asdu_data.type()) == end(output.asdu_types)) - output.asdu_types.push_back(asdu_data.type()); - } - - return 0; + return Node::start(); } -int SlaveNode::start() -{ - startSlave(); +int SlaveNode::stop() { + stopSlave(); - return Node::start(); -} - -int SlaveNode::stop() -{ - stopSlave(); - - return Node::stop(); + return Node::stop(); } // Register node static char name[] = "iec60870-5-104"; static char description[] = "Provide values as protocol slave"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/iec61850.cpp b/lib/nodes/iec61850.cpp index 33771ad48..2ac58e9b3 100644 --- a/lib/nodes/iec61850.cpp +++ b/lib/nodes/iec61850.cpp @@ -9,11 +9,11 @@ #include #include +#include #include #include #include #include -#include #define CONFIG_SV_DEFAULT_APPID 0x4000 #define CONFIG_SV_DEFAULT_DST_ADDRESS CONFIG_GOOSE_DEFAULT_DST_ADDRESS @@ -25,290 +25,295 @@ using namespace villas::node; using namespace villas::utils; const struct iec61850_type_descriptor type_descriptors[] = { - // name, iec_type, type, size, supported - { "boolean", IEC61850Type::BOOLEAN, SignalType::BOOLEAN, 1, false, false }, - { "int8", IEC61850Type::INT8, SignalType::INTEGER, 1, false, false }, - { "int16", IEC61850Type::INT16, SignalType::INTEGER, 2, false, false }, - { "int32", IEC61850Type::INT32, SignalType::INTEGER, 4, false, false }, - { "int64", IEC61850Type::INT64, SignalType::INTEGER, 8, false, false }, - { "int8u", IEC61850Type::INT8U, SignalType::INTEGER, 1, false, false }, - { "int16u", IEC61850Type::INT16U, SignalType::INTEGER, 2, false, false }, - { "int32u", IEC61850Type::INT32U, SignalType::INTEGER, 4, false, false }, - { "int64u", IEC61850Type::INT64U, SignalType::INTEGER, 8, false, false }, - { "float32", IEC61850Type::FLOAT32, SignalType::FLOAT, 4, false, false }, - { "float64", IEC61850Type::FLOAT64, SignalType::FLOAT, 8, false, false }, - { "enumerated", IEC61850Type::ENUMERATED, SignalType::INVALID, 4, false, false }, - { "coded_enum", IEC61850Type::CODED_ENUM, SignalType::INVALID, 4, false, false }, - { "octet_string", IEC61850Type::OCTET_STRING, SignalType::INVALID, 20, false, false }, - { "visible_string", IEC61850Type::VISIBLE_STRING, SignalType::INVALID, 35, false, false }, - { "objectname", IEC61850Type::OBJECTNAME, SignalType::INVALID, 20, false, false }, - { "objectreference", IEC61850Type::OBJECTREFERENCE, SignalType::INVALID, 20, false, false }, - { "timestamp", IEC61850Type::TIMESTAMP, SignalType::INVALID, 8, false, false }, - { "entrytime", IEC61850Type::ENTRYTIME, SignalType::INVALID, 6, false, false }, - { "bitstring", IEC61850Type::BITSTRING, SignalType::INVALID, 4, false, false } -}; + // name, iec_type, type, size, supported + {"boolean", IEC61850Type::BOOLEAN, SignalType::BOOLEAN, 1, false, false}, + {"int8", IEC61850Type::INT8, SignalType::INTEGER, 1, false, false}, + {"int16", IEC61850Type::INT16, SignalType::INTEGER, 2, false, false}, + {"int32", IEC61850Type::INT32, SignalType::INTEGER, 4, false, false}, + {"int64", IEC61850Type::INT64, SignalType::INTEGER, 8, false, false}, + {"int8u", IEC61850Type::INT8U, SignalType::INTEGER, 1, false, false}, + {"int16u", IEC61850Type::INT16U, SignalType::INTEGER, 2, false, false}, + {"int32u", IEC61850Type::INT32U, SignalType::INTEGER, 4, false, false}, + {"int64u", IEC61850Type::INT64U, SignalType::INTEGER, 8, false, false}, + {"float32", IEC61850Type::FLOAT32, SignalType::FLOAT, 4, false, false}, + {"float64", IEC61850Type::FLOAT64, SignalType::FLOAT, 8, false, false}, + {"enumerated", IEC61850Type::ENUMERATED, SignalType::INVALID, 4, false, + false}, + {"coded_enum", IEC61850Type::CODED_ENUM, SignalType::INVALID, 4, false, + false}, + {"octet_string", IEC61850Type::OCTET_STRING, SignalType::INVALID, 20, false, + false}, + {"visible_string", IEC61850Type::VISIBLE_STRING, SignalType::INVALID, 35, + false, false}, + {"objectname", IEC61850Type::OBJECTNAME, SignalType::INVALID, 20, false, + false}, + {"objectreference", IEC61850Type::OBJECTREFERENCE, SignalType::INVALID, 20, + false, false}, + {"timestamp", IEC61850Type::TIMESTAMP, SignalType::INVALID, 8, false, + false}, + {"entrytime", IEC61850Type::ENTRYTIME, SignalType::INVALID, 6, false, + false}, + {"bitstring", IEC61850Type::BITSTRING, SignalType::INVALID, 4, false, + false}}; // Each network interface needs a separate receiver -static -struct List receivers; -static -pthread_t thread; -static -EthernetHandleSet hset; -static -int users = 0; +static struct List receivers; +static pthread_t thread; +static EthernetHandleSet hset; +static int users = 0; -static -void * iec61850_thread(void *ctx) -{ - int ret; +static void *iec61850_thread(void *ctx) { + int ret; - while (1) { - ret = EthernetHandleSet_waitReady(hset, 1000); - if (ret < 0) - continue; + while (1) { + ret = EthernetHandleSet_waitReady(hset, 1000); + if (ret < 0) + continue; - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - switch (r->type) { - case iec61850_receiver::Type::GOOSE: GooseReceiver_tick(r->goose); break; - case iec61850_receiver::Type::SAMPLED_VALUES: SVReceiver_tick(r->sv); break; - } - } - } + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_tick(r->goose); + break; + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_tick(r->sv); + break; + } + } + } - return nullptr; + return nullptr; } -const struct iec61850_type_descriptor * villas::node::iec61850_lookup_type(const char *name) -{ - for (unsigned i = 0; i < ARRAY_LEN(type_descriptors); i++) { - if (!strcmp(name, type_descriptors[i].name)) - return &type_descriptors[i]; - } +const struct iec61850_type_descriptor * +villas::node::iec61850_lookup_type(const char *name) { + for (unsigned i = 0; i < ARRAY_LEN(type_descriptors); i++) { + if (!strcmp(name, type_descriptors[i].name)) + return &type_descriptors[i]; + } - return nullptr; + return nullptr; } -int villas::node::iec61850_parse_signals(json_t *json_signals, struct List *signals, SignalList::Ptr node_signals) -{ - int ret, total_size = 0; - const char *iec_type; - const struct iec61850_type_descriptor *td; - json_error_t err; +int villas::node::iec61850_parse_signals(json_t *json_signals, + struct List *signals, + SignalList::Ptr node_signals) { + int ret, total_size = 0; + const char *iec_type; + const struct iec61850_type_descriptor *td; + json_error_t err; - ret = list_init(signals); - if (ret) - return ret; + ret = list_init(signals); + if (ret) + return ret; - if (json_is_array(json_signals)) { - json_t *json_signal; - size_t i; - json_array_foreach(json_signals, i, json_signal) { - json_unpack_ex(json_signal, &err, 0, "{ s?: s }", - "iec_type", &iec_type - ); + if (json_is_array(json_signals)) { + json_t *json_signal; + size_t i; + json_array_foreach(json_signals, i, json_signal) { + json_unpack_ex(json_signal, &err, 0, "{ s?: s }", "iec_type", &iec_type); - // Try to deduct the IEC 61850 data type from VILLAS signal format - if (!iec_type) { - if (!node_signals) - return -1; + // Try to deduct the IEC 61850 data type from VILLAS signal format + if (!iec_type) { + if (!node_signals) + return -1; - auto sig = node_signals->getByIndex(i); - if (!sig) - return -1; + auto sig = node_signals->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::BOOLEAN: - iec_type = "boolean"; - break; + switch (sig->type) { + case SignalType::BOOLEAN: + iec_type = "boolean"; + break; - case SignalType::FLOAT: - iec_type = "float64"; - break; + case SignalType::FLOAT: + iec_type = "float64"; + break; - case SignalType::INTEGER: - iec_type = "int64"; - break; + case SignalType::INTEGER: + iec_type = "int64"; + break; - default: - return -1; - } - } + default: + return -1; + } + } - td = iec61850_lookup_type(iec_type); - if (!td) - return -1; + td = iec61850_lookup_type(iec_type); + if (!td) + return -1; - list_push(signals, (void *) td); + list_push(signals, (void *)td); - total_size += td->size; - } - } - else { - ret = json_unpack_ex(json_signals, &err, 0, "{ s: s }", "iec_type", &iec_type); - if (ret) - return ret; + total_size += td->size; + } + } else { + ret = json_unpack_ex(json_signals, &err, 0, "{ s: s }", "iec_type", + &iec_type); + if (ret) + return ret; - td = iec61850_lookup_type(iec_type); - if (!td) - return -1; + td = iec61850_lookup_type(iec_type); + if (!td) + return -1; - for (unsigned i = 0; i < node_signals->size(); i++) { - list_push(signals, (void *) td); + for (unsigned i = 0; i < node_signals->size(); i++) { + list_push(signals, (void *)td); - total_size += td->size; - } - } + total_size += td->size; + } + } - return total_size; + return total_size; } -int villas::node::iec61850_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::iec61850_type_start(villas::node::SuperNode *sn) { + int ret; - // Check if already initialized - if (users > 0) - return 0; + // Check if already initialized + if (users > 0) + return 0; - ret = list_init(&receivers); - if (ret) - return ret; + ret = list_init(&receivers); + if (ret) + return ret; - hset = EthernetHandleSet_new(); + hset = EthernetHandleSet_new(); - ret = pthread_create(&thread, nullptr, iec61850_thread, nullptr); - if (ret) - return ret; + ret = pthread_create(&thread, nullptr, iec61850_thread, nullptr); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_type_stop() -{ - int ret; +int villas::node::iec61850_type_stop() { + int ret; - if (--users > 0) - return 0; + if (--users > 0) + return 0; - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - iec61850_receiver_stop(r); - } + iec61850_receiver_stop(r); + } - ret = pthread_cancel(thread); - if (ret) - return ret; + ret = pthread_cancel(thread); + if (ret) + return ret; - ret = pthread_join(thread, nullptr); - if (ret) - return ret; + ret = pthread_join(thread, nullptr); + if (ret) + return ret; - EthernetHandleSet_destroy(hset); + EthernetHandleSet_destroy(hset); - ret = list_destroy(&receivers, (dtor_cb_t) iec61850_receiver_destroy, true); - if (ret) - return ret; + ret = list_destroy(&receivers, (dtor_cb_t)iec61850_receiver_destroy, true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_receiver_start(struct iec61850_receiver *r) -{ - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - r->socket = GooseReceiver_startThreadless(r->goose); - break; +int villas::node::iec61850_receiver_start(struct iec61850_receiver *r) { + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + r->socket = GooseReceiver_startThreadless(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - r->socket = SVReceiver_startThreadless(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + r->socket = SVReceiver_startThreadless(r->sv); + break; + } - EthernetHandleSet_addSocket(hset, r->socket); + EthernetHandleSet_addSocket(hset, r->socket); - return 0; + return 0; } -int villas::node::iec61850_receiver_stop(struct iec61850_receiver *r) -{ - EthernetHandleSet_removeSocket(hset, r->socket); +int villas::node::iec61850_receiver_stop(struct iec61850_receiver *r) { + EthernetHandleSet_removeSocket(hset, r->socket); - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - GooseReceiver_stopThreadless(r->goose); - break; + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_stopThreadless(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - SVReceiver_stopThreadless(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_stopThreadless(r->sv); + break; + } - return 0; + return 0; } -int villas::node::iec61850_receiver_destroy(struct iec61850_receiver *r) -{ - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - GooseReceiver_destroy(r->goose); - break; +int villas::node::iec61850_receiver_destroy(struct iec61850_receiver *r) { + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_destroy(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - SVReceiver_destroy(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_destroy(r->sv); + break; + } - free(r->interface); + free(r->interface); - return 0; + return 0; } -struct iec61850_receiver * villas::node::iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf) -{ - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); +struct iec61850_receiver * +villas::node::iec61850_receiver_lookup(enum iec61850_receiver::Type t, + const char *intf) { + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - if (r->type == t && strcmp(r->interface, intf) == 0) - return r; - } + if (r->type == t && strcmp(r->interface, intf) == 0) + return r; + } - return nullptr; + return nullptr; } -struct iec61850_receiver * villas::node::iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf) -{ - struct iec61850_receiver *r; +struct iec61850_receiver * +villas::node::iec61850_receiver_create(enum iec61850_receiver::Type t, + const char *intf) { + struct iec61850_receiver *r; - // Check if there is already a SVReceiver for this interface - r = iec61850_receiver_lookup(t, intf); - if (!r) { - r = new struct iec61850_receiver; - if (!r) - throw MemoryAllocationError(); + // Check if there is already a SVReceiver for this interface + r = iec61850_receiver_lookup(t, intf); + if (!r) { + r = new struct iec61850_receiver; + if (!r) + throw MemoryAllocationError(); - r->interface = strdup(intf); - r->type = t; + r->interface = strdup(intf); + r->type = t; - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - r->goose = GooseReceiver_create(); - GooseReceiver_setInterfaceId(r->goose, r->interface); - break; + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + r->goose = GooseReceiver_create(); + GooseReceiver_setInterfaceId(r->goose, r->interface); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - r->sv = SVReceiver_create(); - SVReceiver_setInterfaceId(r->sv, r->interface); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + r->sv = SVReceiver_create(); + SVReceiver_setInterfaceId(r->sv, r->interface); + break; + } - iec61850_receiver_start(r); + iec61850_receiver_start(r); - list_push(&receivers, r); - } + list_push(&receivers, r); + } - return r; + return r; } diff --git a/lib/nodes/iec61850_goose.cpp b/lib/nodes/iec61850_goose.cpp index 0bed4b5da..c7477c237 100644 --- a/lib/nodes/iec61850_goose.cpp +++ b/lib/nodes/iec61850_goose.cpp @@ -8,12 +8,12 @@ #include #include +#include #include #include -#include #include #include -#include +#include using namespace std::literals::chrono_literals; using namespace std::literals::string_literals; @@ -23,893 +23,853 @@ using namespace villas::node; using namespace villas::utils; using namespace villas::node::iec61850; -static -std::optional> stringToMac(char *mac_string) -{ - std::array mac; - char *save; - char *token = strtok_r(mac_string, ":", &save); +static std::optional> stringToMac(char *mac_string) { + std::array mac; + char *save; + char *token = strtok_r(mac_string, ":", &save); - for (auto &i : mac) { - if (!token) return std::nullopt; + for (auto &i : mac) { + if (!token) + return std::nullopt; - i = static_cast(strtol(token, NULL, 16)); + i = static_cast(strtol(token, NULL, 16)); - token = strtok_r(NULL, ":", &save); - } + token = strtok_r(NULL, ":", &save); + } - return std::optional { mac }; + return std::optional{mac}; } -MmsType GooseSignal::mmsType() const -{ - return descriptor->mms_type; +MmsType GooseSignal::mmsType() const { return descriptor->mms_type; } + +std::string const &GooseSignal::name() const { return descriptor->name; } + +SignalType GooseSignal::signalType() const { return descriptor->signal_type; } + +std::optional GooseSignal::fromMmsValue(MmsValue *mms_value) { + auto mms_type = MmsValue_getType(mms_value); + auto descriptor = lookupMmsType(mms_type); + SignalData data; + + if (!descriptor) + return std::nullopt; + + switch (mms_type) { + case MmsType::MMS_BOOLEAN: + data.b = MmsValue_getBoolean(mms_value); + break; + case MmsType::MMS_INTEGER: + data.i = MmsValue_toInt64(mms_value); + break; + case MmsType::MMS_UNSIGNED: + data.i = static_cast(MmsValue_toUint32(mms_value)); + break; + case MmsType::MMS_BIT_STRING: + data.i = static_cast(MmsValue_getBitStringAsInteger(mms_value)); + break; + case MmsType::MMS_FLOAT: + data.f = MmsValue_toDouble(mms_value); + break; + default: + return std::nullopt; + } + + return GooseSignal{descriptor.value(), data}; } -std::string const & GooseSignal::name() const -{ - return descriptor->name; +std::optional +GooseSignal::fromNameAndValue(char const *name, SignalData value, + std::optional meta) { + auto descriptor = lookupMmsTypeName(name); + + if (!descriptor) + return std::nullopt; + + return GooseSignal{descriptor.value(), value, meta}; } -SignalType GooseSignal::signalType() const -{ - return descriptor->signal_type; +MmsValue *GooseSignal::toMmsValue() const { + switch (descriptor->mms_type) { + case MmsType::MMS_BOOLEAN: + return MmsValue_newBoolean(signal_data.b); + case MmsType::MMS_INTEGER: + return newMmsInteger(signal_data.i, meta.size); + case MmsType::MMS_UNSIGNED: + return newMmsUnsigned(static_cast(signal_data.i), meta.size); + case MmsType::MMS_BIT_STRING: + return newMmsBitString(static_cast(signal_data.i), meta.size); + case MmsType::MMS_FLOAT: + return newMmsFloat(signal_data.f, meta.size); + default: + throw RuntimeError{"invalid mms type"}; + } } -std::optional GooseSignal::fromMmsValue(MmsValue *mms_value) -{ - auto mms_type = MmsValue_getType(mms_value); - auto descriptor = lookupMmsType(mms_type); - SignalData data; +MmsValue *GooseSignal::newMmsBitString(uint32_t i, int size) { + auto mms_bitstring = MmsValue_newBitString(size); - if (!descriptor) return std::nullopt; + MmsValue_setBitStringFromInteger(mms_bitstring, i); - switch (mms_type) { - case MmsType::MMS_BOOLEAN: - data.b = MmsValue_getBoolean(mms_value); - break; - case MmsType::MMS_INTEGER: - data.i = MmsValue_toInt64(mms_value); - break; - case MmsType::MMS_UNSIGNED: - data.i = static_cast(MmsValue_toUint32(mms_value)); - break; - case MmsType::MMS_BIT_STRING: - data.i = static_cast(MmsValue_getBitStringAsInteger(mms_value)); - break; - case MmsType::MMS_FLOAT: - data.f = MmsValue_toDouble(mms_value); - break; - default: - return std::nullopt; - } - - return GooseSignal { descriptor.value(), data }; + return mms_bitstring; } -std::optional GooseSignal::fromNameAndValue(char const *name, SignalData value, std::optional meta) -{ - auto descriptor = lookupMmsTypeName(name); +MmsValue *GooseSignal::newMmsInteger(int64_t i, int size) { + auto mms_integer = MmsValue_newInteger(size); - if (!descriptor) return std::nullopt; - - return GooseSignal { descriptor.value(), value, meta }; + switch (size) { + case 8: + MmsValue_setInt8(mms_integer, static_cast(i)); + return mms_integer; + case 16: + MmsValue_setInt16(mms_integer, static_cast(i)); + return mms_integer; + case 32: + MmsValue_setInt32(mms_integer, static_cast(i)); + return mms_integer; + case 64: + MmsValue_setInt64(mms_integer, static_cast(i)); + return mms_integer; + default: + throw RuntimeError{"invalid mms integer size"}; + } } -MmsValue * GooseSignal::toMmsValue() const -{ - switch (descriptor->mms_type) { - case MmsType::MMS_BOOLEAN: - return MmsValue_newBoolean(signal_data.b); - case MmsType::MMS_INTEGER: - return newMmsInteger(signal_data.i, meta.size); - case MmsType::MMS_UNSIGNED: - return newMmsUnsigned(static_cast(signal_data.i), meta.size); - case MmsType::MMS_BIT_STRING: - return newMmsBitString(static_cast(signal_data.i), meta.size); - case MmsType::MMS_FLOAT: - return newMmsFloat(signal_data.f, meta.size); - default: - throw RuntimeError { "invalid mms type" }; - } +MmsValue *GooseSignal::newMmsUnsigned(uint64_t u, int size) { + auto mms_unsigned = MmsValue_newUnsigned(size); + + switch (size) { + case 8: + MmsValue_setUint8(mms_unsigned, static_cast(u)); + return mms_unsigned; + case 16: + MmsValue_setUint16(mms_unsigned, static_cast(u)); + return mms_unsigned; + case 32: + MmsValue_setUint32(mms_unsigned, static_cast(u)); + return mms_unsigned; + default: + throw RuntimeError{"invalid mms integer size"}; + } } -MmsValue * GooseSignal::newMmsBitString(uint32_t i, int size) -{ - auto mms_bitstring = MmsValue_newBitString(size); - - MmsValue_setBitStringFromInteger(mms_bitstring, i); - - return mms_bitstring; +MmsValue *GooseSignal::newMmsFloat(double d, int size) { + switch (size) { + case 32: + return MmsValue_newFloat(static_cast(d)); + case 64: + return MmsValue_newDouble(d); + default: + throw RuntimeError{"invalid mms float size"}; + } } -MmsValue * GooseSignal::newMmsInteger(int64_t i, int size) -{ - auto mms_integer = MmsValue_newInteger(size); +std::optional GooseSignal::lookupMmsType(int mms_type) { + auto check = [mms_type](Descriptor descriptor) { + return descriptor.mms_type == mms_type; + }; - switch (size) { - case 8: - MmsValue_setInt8(mms_integer, static_cast(i)); - return mms_integer; - case 16: - MmsValue_setInt16(mms_integer, static_cast(i)); - return mms_integer; - case 32: - MmsValue_setInt32(mms_integer, static_cast(i)); - return mms_integer; - case 64: - MmsValue_setInt64(mms_integer, static_cast(i)); - return mms_integer; - default: - throw RuntimeError { "invalid mms integer size" }; - } + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return &*descriptor; + else + return std::nullopt; } -MmsValue * GooseSignal::newMmsUnsigned(uint64_t u, int size) -{ - auto mms_unsigned = MmsValue_newUnsigned(size); +std::optional +GooseSignal::lookupMmsTypeName(char const *name) { + auto check = [name](Descriptor descriptor) { + return descriptor.name == name; + }; - switch (size) { - case 8: - MmsValue_setUint8(mms_unsigned, static_cast(u)); - return mms_unsigned; - case 16: - MmsValue_setUint16(mms_unsigned, static_cast(u)); - return mms_unsigned; - case 32: - MmsValue_setUint32(mms_unsigned, static_cast(u)); - return mms_unsigned; - default: - throw RuntimeError { "invalid mms integer size" }; - } + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return &*descriptor; + else + return std::nullopt; } -MmsValue * GooseSignal::newMmsFloat(double d, int size) -{ - switch (size) { - case 32: - return MmsValue_newFloat(static_cast(d)); - case 64: - return MmsValue_newDouble(d); - default: - throw RuntimeError { "invalid mms float size" }; - } -} - -std::optional GooseSignal::lookupMmsType(int mms_type) -{ - auto check = [mms_type] (Descriptor descriptor) { - return descriptor.mms_type == mms_type; - }; - - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return &*descriptor; - else - return std::nullopt; -} - -std::optional GooseSignal::lookupMmsTypeName(char const *name) -{ - auto check = [name] (Descriptor descriptor) { - return descriptor.name == name; - }; - - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return &*descriptor; - else - return std::nullopt; -} - -GooseSignal::GooseSignal(GooseSignal::Descriptor const *descriptor, SignalData data, std::optional meta) : - signal_data(data), - meta(meta.value_or(descriptor->default_meta)), - descriptor(descriptor) -{ -} +GooseSignal::GooseSignal(GooseSignal::Descriptor const *descriptor, + SignalData data, std::optional meta) + : signal_data(data), meta(meta.value_or(descriptor->default_meta)), + descriptor(descriptor) {} bool iec61850::operator==(GooseSignal &lhs, GooseSignal &rhs) { - if (lhs.mmsType() != rhs.mmsType()) - return false; + if (lhs.mmsType() != rhs.mmsType()) + return false; - switch (lhs.mmsType()) { - case MmsType::MMS_INTEGER: - case MmsType::MMS_UNSIGNED: - case MmsType::MMS_BIT_STRING: - case MmsType::MMS_FLOAT: - if (lhs.meta.size != rhs.meta.size) - return false; - break; - default: break; - } + switch (lhs.mmsType()) { + case MmsType::MMS_INTEGER: + case MmsType::MMS_UNSIGNED: + case MmsType::MMS_BIT_STRING: + case MmsType::MMS_FLOAT: + if (lhs.meta.size != rhs.meta.size) + return false; + break; + default: + break; + } - switch (lhs.signalType()) { - case SignalType::BOOLEAN: - return lhs.signal_data.b == rhs.signal_data.b; - case SignalType::INTEGER: - return lhs.signal_data.i == rhs.signal_data.i; - case SignalType::FLOAT: - return lhs.signal_data.f == rhs.signal_data.f; - default: - return false; - } + switch (lhs.signalType()) { + case SignalType::BOOLEAN: + return lhs.signal_data.b == rhs.signal_data.b; + case SignalType::INTEGER: + return lhs.signal_data.i == rhs.signal_data.i; + case SignalType::FLOAT: + return lhs.signal_data.f == rhs.signal_data.f; + default: + return false; + } } bool iec61850::operator!=(GooseSignal &lhs, GooseSignal &rhs) { - return !(lhs == rhs); + return !(lhs == rhs); } -void GooseNode::onEvent(GooseSubscriber subscriber, GooseNode::InputEventContext &ctx) noexcept -{ - if (!GooseSubscriber_isValid(subscriber) || GooseSubscriber_needsCommission(subscriber)) - return; +void GooseNode::onEvent(GooseSubscriber subscriber, + GooseNode::InputEventContext &ctx) noexcept { + if (!GooseSubscriber_isValid(subscriber) || + GooseSubscriber_needsCommission(subscriber)) + return; - int last_state_num = ctx.last_state_num; - int state_num = GooseSubscriber_getStNum(subscriber); - ctx.last_state_num = state_num; + int last_state_num = ctx.last_state_num; + int state_num = GooseSubscriber_getStNum(subscriber); + ctx.last_state_num = state_num; - if (ctx.subscriber_config.trigger == InputTrigger::CHANGE - && !ctx.values.empty() - && state_num == last_state_num) - return; + if (ctx.subscriber_config.trigger == InputTrigger::CHANGE && + !ctx.values.empty() && state_num == last_state_num) + return; - auto mms_values = GooseSubscriber_getDataSetValues(subscriber); + auto mms_values = GooseSubscriber_getDataSetValues(subscriber); - if (MmsValue_getType(mms_values) != MmsType::MMS_ARRAY) { - ctx.node->logger->warn("DataSet is not an array"); - return; - } + if (MmsValue_getType(mms_values) != MmsType::MMS_ARRAY) { + ctx.node->logger->warn("DataSet is not an array"); + return; + } - ctx.values.clear(); + ctx.values.clear(); - for (unsigned int i = 0; i < MmsValue_getArraySize(mms_values); i++) { - auto mms_value = MmsValue_getElement(mms_values, i); - auto goose_value = GooseSignal::fromMmsValue(mms_value); - ctx.values.push_back(goose_value); - } + for (unsigned int i = 0; i < MmsValue_getArraySize(mms_values); i++) { + auto mms_value = MmsValue_getElement(mms_values, i); + auto goose_value = GooseSignal::fromMmsValue(mms_value); + ctx.values.push_back(goose_value); + } - uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber); + uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber); - ctx.node->pushSample(timestamp); + ctx.node->pushSample(timestamp); } -void GooseNode::pushSample(uint64_t timestamp) noexcept -{ - Sample *sample = sample_alloc(&input.pool); - if (!sample) { - logger->warn("Pool underrun"); - return; - } +void GooseNode::pushSample(uint64_t timestamp) noexcept { + Sample *sample = sample_alloc(&input.pool); + if (!sample) { + logger->warn("Pool underrun"); + return; + } - sample->length = input.mappings.size(); - sample->flags = (int) SampleFlags::HAS_DATA; - sample->signals = getInputSignals(false); + sample->length = input.mappings.size(); + sample->flags = (int)SampleFlags::HAS_DATA; + sample->signals = getInputSignals(false); - if (input.with_timestamp) { - sample->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - sample->ts.origin.tv_sec = timestamp / 1000; - sample->ts.origin.tv_nsec = 1000 * (timestamp % 1000); - } + if (input.with_timestamp) { + sample->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + sample->ts.origin.tv_sec = timestamp / 1000; + sample->ts.origin.tv_nsec = 1000 * (timestamp % 1000); + } - for (unsigned int signal = 0; signal < sample->length; signal++) { - auto& mapping = input.mappings[signal]; - auto& values = input.contexts[mapping.subscriber].values; + for (unsigned int signal = 0; signal < sample->length; signal++) { + auto &mapping = input.mappings[signal]; + auto &values = input.contexts[mapping.subscriber].values; - if (mapping.index >= values.size() || !values[mapping.index]) { - auto signal_str = sample->signals->getByIndex(signal)->toString(); - logger->error("tried to access unavailable goose value for signal {}", signal_str); - continue; - } + if (mapping.index >= values.size() || !values[mapping.index]) { + auto signal_str = sample->signals->getByIndex(signal)->toString(); + logger->error("tried to access unavailable goose value for signal {}", + signal_str); + continue; + } - if (mapping.type->mms_type != values[mapping.index]->mmsType()) { - auto signal_str = sample->signals->getByIndex(signal)->toString(); - logger->error("received unexpected mms_type for signal {}", signal_str); - continue; - } + if (mapping.type->mms_type != values[mapping.index]->mmsType()) { + auto signal_str = sample->signals->getByIndex(signal)->toString(); + logger->error("received unexpected mms_type for signal {}", signal_str); + continue; + } - sample->data[signal] = values[mapping.index]->signal_data; - } + sample->data[signal] = values[mapping.index]->signal_data; + } - if (queue_signalled_push(&input.queue, sample) != 1) - logger->warn("Failed to enqueue samples"); + if (queue_signalled_push(&input.queue, sample) != 1) + logger->warn("Failed to enqueue samples"); } -void GooseNode::addSubscriber(GooseNode::InputEventContext &ctx) noexcept -{ - GooseSubscriber subscriber; - SubscriberConfig &sc = ctx.subscriber_config; +void GooseNode::addSubscriber(GooseNode::InputEventContext &ctx) noexcept { + GooseSubscriber subscriber; + SubscriberConfig &sc = ctx.subscriber_config; - ctx.node = this; + ctx.node = this; - subscriber = GooseSubscriber_create(sc.go_cb_ref.data(), NULL); + subscriber = GooseSubscriber_create(sc.go_cb_ref.data(), NULL); - if (sc.dst_address) - GooseSubscriber_setDstMac(subscriber, sc.dst_address->data()); + if (sc.dst_address) + GooseSubscriber_setDstMac(subscriber, sc.dst_address->data()); - if (sc.app_id) - GooseSubscriber_setAppId(subscriber, *sc.app_id); + if (sc.app_id) + GooseSubscriber_setAppId(subscriber, *sc.app_id); - GooseSubscriber_setListener(subscriber, [] (GooseSubscriber goose_subscriber, void* event_context) { - auto context = static_cast (event_context); - onEvent(goose_subscriber, *context); - }, &ctx); + GooseSubscriber_setListener( + subscriber, + [](GooseSubscriber goose_subscriber, void *event_context) { + auto context = static_cast(event_context); + onEvent(goose_subscriber, *context); + }, + &ctx); - GooseReceiver_addSubscriber(input.receiver, subscriber); + GooseReceiver_addSubscriber(input.receiver, subscriber); } -void GooseNode::createReceiver() noexcept -{ - destroyReceiver(); +void GooseNode::createReceiver() noexcept { + destroyReceiver(); - input.receiver = GooseReceiver_create(); + input.receiver = GooseReceiver_create(); - GooseReceiver_setInterfaceId(input.receiver, input.interface_id.c_str()); + GooseReceiver_setInterfaceId(input.receiver, input.interface_id.c_str()); - for (auto& pair_key_context : input.contexts) - addSubscriber(pair_key_context.second); + for (auto &pair_key_context : input.contexts) + addSubscriber(pair_key_context.second); - input.state = Input::READY; + input.state = Input::READY; } -void GooseNode::destroyReceiver() noexcept -{ - int err __attribute__((unused)); +void GooseNode::destroyReceiver() noexcept { + int err __attribute__((unused)); - if (input.state == Input::NONE) - return; + if (input.state == Input::NONE) + return; - stopReceiver(); + stopReceiver(); - GooseReceiver_destroy(input.receiver); + GooseReceiver_destroy(input.receiver); - err = queue_signalled_destroy(&input.queue); + err = queue_signalled_destroy(&input.queue); - input.state = Input::NONE; + input.state = Input::NONE; } -void GooseNode::startReceiver() noexcept(false) -{ - if (input.state == Input::NONE) - createReceiver(); - else - stopReceiver(); +void GooseNode::startReceiver() noexcept(false) { + if (input.state == Input::NONE) + createReceiver(); + else + stopReceiver(); - GooseReceiver_start(input.receiver); + GooseReceiver_start(input.receiver); - if (!GooseReceiver_isRunning(input.receiver)) - throw RuntimeError{"iec61850-GOOSE receiver could not be started"}; + if (!GooseReceiver_isRunning(input.receiver)) + throw RuntimeError{"iec61850-GOOSE receiver could not be started"}; - input.state = Input::READY; + input.state = Input::READY; } -void GooseNode::stopReceiver() noexcept -{ - if (input.state == Input::NONE) - return; +void GooseNode::stopReceiver() noexcept { + if (input.state == Input::NONE) + return; - input.state = Input::STOPPED; + input.state = Input::STOPPED; - if (!GooseReceiver_isRunning(input.receiver)) - return; + if (!GooseReceiver_isRunning(input.receiver)) + return; - GooseReceiver_stop(input.receiver); + GooseReceiver_stop(input.receiver); } -void GooseNode::createPublishers() noexcept -{ - destroyPublishers(); +void GooseNode::createPublishers() noexcept { + destroyPublishers(); - for (auto &ctx : output.contexts) { - auto dst_address = ctx.config.dst_address; - auto comm = CommParameters { - /* vlanPriority */ 0, - /* vlanId */ 0, - ctx.config.app_id, - {} - }; + for (auto &ctx : output.contexts) { + auto dst_address = ctx.config.dst_address; + auto comm = CommParameters{/* vlanPriority */ 0, + /* vlanId */ 0, + ctx.config.app_id, + {}}; - memcpy(comm.dstAddress, dst_address.data(), dst_address.size()); + memcpy(comm.dstAddress, dst_address.data(), dst_address.size()); - ctx.publisher = GoosePublisher_createEx(&comm, output.interface_id.c_str(), false); + ctx.publisher = + GoosePublisher_createEx(&comm, output.interface_id.c_str(), false); - GoosePublisher_setGoID(ctx.publisher, ctx.config.go_id.data()); - GoosePublisher_setGoCbRef(ctx.publisher, ctx.config.go_cb_ref.data()); - GoosePublisher_setDataSetRef(ctx.publisher, ctx.config.data_set_ref.data()); - GoosePublisher_setConfRev(ctx.publisher, ctx.config.conf_rev); - GoosePublisher_setTimeAllowedToLive(ctx.publisher, ctx.config.time_allowed_to_live); - } + GoosePublisher_setGoID(ctx.publisher, ctx.config.go_id.data()); + GoosePublisher_setGoCbRef(ctx.publisher, ctx.config.go_cb_ref.data()); + GoosePublisher_setDataSetRef(ctx.publisher, ctx.config.data_set_ref.data()); + GoosePublisher_setConfRev(ctx.publisher, ctx.config.conf_rev); + GoosePublisher_setTimeAllowedToLive(ctx.publisher, + ctx.config.time_allowed_to_live); + } - output.state = Output::READY; + output.state = Output::READY; } -void GooseNode::destroyPublishers() noexcept -{ - int err __attribute__((unused)); +void GooseNode::destroyPublishers() noexcept { + int err __attribute__((unused)); - if (output.state == Output::NONE) - return; + if (output.state == Output::NONE) + return; - stopPublishers(); + stopPublishers(); - for (auto &ctx : output.contexts) - GoosePublisher_destroy(ctx.publisher); + for (auto &ctx : output.contexts) + GoosePublisher_destroy(ctx.publisher); - output.state = Output::NONE; + output.state = Output::NONE; } -void GooseNode::startPublishers() noexcept(false) -{ - if (output.state == Output::NONE) - createPublishers(); - else - stopPublishers(); +void GooseNode::startPublishers() noexcept(false) { + if (output.state == Output::NONE) + createPublishers(); + else + stopPublishers(); - output.resend_thread_stop = false; - output.resend_thread = std::thread(resend_thread, &output); + output.resend_thread_stop = false; + output.resend_thread = std::thread(resend_thread, &output); - output.state = Output::READY; + output.state = Output::READY; } -void GooseNode::stopPublishers() noexcept -{ - if (output.state == Output::NONE) - return; +void GooseNode::stopPublishers() noexcept { + if (output.state == Output::NONE) + return; - if (output.resend_thread) { - auto lock = std::unique_lock { output.send_mutex }; - output.resend_thread_stop = true; - lock.unlock(); + if (output.resend_thread) { + auto lock = std::unique_lock{output.send_mutex}; + output.resend_thread_stop = true; + lock.unlock(); - output.resend_thread_cv.notify_all(); - output.resend_thread->join(); - output.resend_thread = std::nullopt; - } + output.resend_thread_cv.notify_all(); + output.resend_thread->join(); + output.resend_thread = std::nullopt; + } - output.state = Output::STOPPED; + output.state = Output::STOPPED; } -int GooseNode::_read(Sample *samples[], unsigned sample_count) -{ - int available_samples; - struct Sample *copies[sample_count]; +int GooseNode::_read(Sample *samples[], unsigned sample_count) { + int available_samples; + struct Sample *copies[sample_count]; - if (input.state != Input::READY) - return 0; + if (input.state != Input::READY) + return 0; - available_samples = queue_signalled_pull_many(&input.queue, (void **) copies, sample_count); - sample_copy_many(samples, copies, available_samples); - sample_decref_many(copies, available_samples); + available_samples = + queue_signalled_pull_many(&input.queue, (void **)copies, sample_count); + sample_copy_many(samples, copies, available_samples); + sample_decref_many(copies, available_samples); - return available_samples; + return available_samples; } -void GooseNode::publish_values(GoosePublisher publisher, std::vector &values, bool changed, int burst) noexcept -{ - auto data_set = LinkedList_create(); +void GooseNode::publish_values(GoosePublisher publisher, + std::vector &values, bool changed, + int burst) noexcept { + auto data_set = LinkedList_create(); - for (auto &value : values) { - LinkedList_add(data_set, value.toMmsValue()); - } + for (auto &value : values) { + LinkedList_add(data_set, value.toMmsValue()); + } - if (changed) - GoosePublisher_increaseStNum(publisher); + if (changed) + GoosePublisher_increaseStNum(publisher); - do { - GoosePublisher_publish(publisher, data_set); - } while (changed && --burst > 0); + do { + GoosePublisher_publish(publisher, data_set); + } while (changed && --burst > 0); - LinkedList_destroyDeep(data_set, (LinkedListValueDeleteFunction) MmsValue_delete); + LinkedList_destroyDeep(data_set, + (LinkedListValueDeleteFunction)MmsValue_delete); } -void GooseNode::resend_thread(GooseNode::Output *output) noexcept -{ - using namespace std::chrono; +void GooseNode::resend_thread(GooseNode::Output *output) noexcept { + using namespace std::chrono; - auto interval = duration_cast(duration(output->resend_interval)); - auto lock = std::unique_lock { output->send_mutex }; - time_point next_sample_time; + auto interval = duration_cast( + duration(output->resend_interval)); + auto lock = std::unique_lock{output->send_mutex}; + time_point next_sample_time; - // wait for the first GooseNode::_write call - output->resend_thread_cv.wait(lock); + // wait for the first GooseNode::_write call + output->resend_thread_cv.wait(lock); - while (!output->resend_thread_stop) { - if (output->changed) { - output->changed = false; - next_sample_time = steady_clock::now() + interval; - } + while (!output->resend_thread_stop) { + if (output->changed) { + output->changed = false; + next_sample_time = steady_clock::now() + interval; + } - auto status = output->resend_thread_cv.wait_until(lock, next_sample_time); + auto status = output->resend_thread_cv.wait_until(lock, next_sample_time); - if (status == std::cv_status::no_timeout || output->changed) - continue; + if (status == std::cv_status::no_timeout || output->changed) + continue; - for (auto &ctx : output->contexts) - publish_values(ctx.publisher, ctx.values, false); + for (auto &ctx : output->contexts) + publish_values(ctx.publisher, ctx.values, false); - next_sample_time = next_sample_time + interval; - } + next_sample_time = next_sample_time + interval; + } } -int GooseNode::_write(Sample *samples[], unsigned sample_count) -{ - auto lock = std::unique_lock { output.send_mutex }; +int GooseNode::_write(Sample *samples[], unsigned sample_count) { + auto lock = std::unique_lock{output.send_mutex}; - for (unsigned int i = 0; i < sample_count; i++) { - auto sample = samples[i]; + for (unsigned int i = 0; i < sample_count; i++) { + auto sample = samples[i]; - for (auto &ctx : output.contexts) { - bool changed = false; + for (auto &ctx : output.contexts) { + bool changed = false; - for (unsigned int data_index = 0; data_index < ctx.config.data.size(); data_index++) { - auto data = ctx.config.data[data_index]; - auto goose_value = data.default_value; - auto signal = data.signal; - if (signal && *signal < sample->length) - goose_value.signal_data = sample->data[*signal]; + for (unsigned int data_index = 0; data_index < ctx.config.data.size(); + data_index++) { + auto data = ctx.config.data[data_index]; + auto goose_value = data.default_value; + auto signal = data.signal; + if (signal && *signal < sample->length) + goose_value.signal_data = sample->data[*signal]; - if (ctx.values.size() <= data_index) { - changed = true; - ctx.values.push_back(goose_value); - } else if (ctx.values[data_index] != goose_value) { - changed = true; - ctx.values[data_index] = goose_value; - } - } + if (ctx.values.size() <= data_index) { + changed = true; + ctx.values.push_back(goose_value); + } else if (ctx.values[data_index] != goose_value) { + changed = true; + ctx.values[data_index] = goose_value; + } + } - if (changed) { - output.changed = true; - publish_values(ctx.publisher, ctx.values, changed, ctx.config.burst); - } - } - } + if (changed) { + output.changed = true; + publish_values(ctx.publisher, ctx.values, changed, ctx.config.burst); + } + } + } - if (output.changed) { - lock.unlock(); - output.resend_thread_cv.notify_all(); - } + if (output.changed) { + lock.unlock(); + output.resend_thread_cv.notify_all(); + } - return sample_count; + return sample_count; } -GooseNode::GooseNode(const uuid_t &id, const std::string &name) : - Node(id, name) -{ - input.state = Input::NONE; +GooseNode::GooseNode(const uuid_t &id, const std::string &name) + : Node(id, name) { + input.state = Input::NONE; - input.contexts = {}; - input.mappings = {}; - input.interface_id = "lo"; - input.queue_length = 1024; + input.contexts = {}; + input.mappings = {}; + input.interface_id = "lo"; + input.queue_length = 1024; - output.state = Output::NONE; - output.interface_id = "lo"; - output.changed = false; - output.resend_interval = 1.; - output.resend_thread = std::nullopt; + output.state = Output::NONE; + output.interface_id = "lo"; + output.changed = false; + output.resend_interval = 1.; + output.resend_thread = std::nullopt; } -GooseNode::~GooseNode() -{ - int err __attribute__((unused)); +GooseNode::~GooseNode() { + int err __attribute__((unused)); - destroyReceiver(); - destroyPublishers(); + destroyReceiver(); + destroyPublishers(); - err = queue_signalled_destroy(&input.queue); + err = queue_signalled_destroy(&input.queue); - err = pool_destroy(&input.pool); + err = pool_destroy(&input.pool); } -int GooseNode::parse(json_t *json) -{ - int ret; - json_error_t err; +int GooseNode::parse(json_t *json) { + int ret; + json_error_t err; - ret = Node::parse(json); - if (ret) - return ret; + ret = Node::parse(json); + if (ret) + return ret; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o }", - "in", &json_in, - "out", &json_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_in = nullptr; + json_t *json_out = nullptr; + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o }", "in", &json_in, "out", + &json_out); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parseInput(json_in); - parseOutput(json_out); + parseInput(json_in); + parseOutput(json_out); - return 0; + return 0; } -void GooseNode::parseInput(json_t *json) -{ - int ret; - json_error_t err; +void GooseNode::parseInput(json_t *json) { + int ret; + json_error_t err; - json_t *json_subscribers = nullptr; - json_t *json_signals = nullptr; - char const *interface_id = input.interface_id.c_str(); - int with_timestamp = true; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s: b }", - "subscribers", &json_subscribers, - "signals", &json_signals, - "interface", &interface_id, - "with_timestamp", &with_timestamp - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_subscribers = nullptr; + json_t *json_signals = nullptr; + char const *interface_id = input.interface_id.c_str(); + int with_timestamp = true; + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s: b }", + "subscribers", &json_subscribers, "signals", + &json_signals, "interface", &interface_id, + "with_timestamp", &with_timestamp); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parseSubscribers(json_subscribers, input.contexts); - parseInputSignals(json_signals, input.mappings); + parseSubscribers(json_subscribers, input.contexts); + parseInputSignals(json_signals, input.mappings); - input.interface_id = interface_id; - input.with_timestamp = with_timestamp; + input.interface_id = interface_id; + input.with_timestamp = with_timestamp; } -void GooseNode::parseSubscriber(json_t *json, GooseNode::SubscriberConfig &sc) -{ - int ret; - json_error_t err; +void GooseNode::parseSubscriber(json_t *json, GooseNode::SubscriberConfig &sc) { + int ret; + json_error_t err; - char *go_cb_ref = nullptr; - char *dst_address_str = nullptr; - char *trigger = nullptr; - int app_id = 0; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i }", - "go_cb_ref", &go_cb_ref, - "trigger", &trigger, - "dst_address", &dst_address_str, - "app_id", &app_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + char *go_cb_ref = nullptr; + char *dst_address_str = nullptr; + char *trigger = nullptr; + int app_id = 0; + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i }", + "go_cb_ref", &go_cb_ref, "trigger", &trigger, + "dst_address", &dst_address_str, "app_id", &app_id); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - sc.go_cb_ref = std::string { go_cb_ref }; + sc.go_cb_ref = std::string{go_cb_ref}; - if (!trigger || !strcmp(trigger, "always")) - sc.trigger = InputTrigger::ALWAYS; - else if (!strcmp(trigger, "change")) - sc.trigger = InputTrigger::CHANGE; - else - throw RuntimeError("Unknown trigger type"); + if (!trigger || !strcmp(trigger, "always")) + sc.trigger = InputTrigger::ALWAYS; + else if (!strcmp(trigger, "change")) + sc.trigger = InputTrigger::CHANGE; + else + throw RuntimeError("Unknown trigger type"); - if (dst_address_str) { - std::optional dst_address = stringToMac(dst_address_str); - if (!dst_address) - throw RuntimeError("Invalid dst_address"); - sc.dst_address = *dst_address; - } + if (dst_address_str) { + std::optional dst_address = stringToMac(dst_address_str); + if (!dst_address) + throw RuntimeError("Invalid dst_address"); + sc.dst_address = *dst_address; + } - if (app_id != 0) - sc.app_id = static_cast(app_id); + if (app_id != 0) + sc.app_id = static_cast(app_id); } -void GooseNode::parseSubscribers(json_t *json, std::map &ctx) -{ - char const* key; - json_t* json_subscriber; +void GooseNode::parseSubscribers( + json_t *json, std::map &ctx) { + char const *key; + json_t *json_subscriber; - if (!json_is_object(json)) - throw RuntimeError("subscribers is not an object"); + if (!json_is_object(json)) + throw RuntimeError("subscribers is not an object"); - json_object_foreach(json, key, json_subscriber) { - SubscriberConfig sc; + json_object_foreach(json, key, json_subscriber) { + SubscriberConfig sc; - parseSubscriber(json_subscriber, sc); + parseSubscriber(json_subscriber, sc); - ctx[key] = InputEventContext { sc }; - } + ctx[key] = InputEventContext{sc}; + } } -void GooseNode::parseInputSignals(json_t *json, std::vector &mappings) -{ - int ret; - json_error_t err; - int index; - json_t *value; +void GooseNode::parseInputSignals( + json_t *json, std::vector &mappings) { + int ret; + json_error_t err; + int index; + json_t *value; - mappings.clear(); + mappings.clear(); - json_array_foreach(json, index, value) { - char *mapping_subscriber; - unsigned int mapping_index; - char *mapping_type_name; - ret = json_unpack_ex(value, &err, 0, "{ s: s, s: i, s: s }", - "subscriber", &mapping_subscriber, - "index", &mapping_index, - "mms_type", &mapping_type_name - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_array_foreach(json, index, value) { + char *mapping_subscriber; + unsigned int mapping_index; + char *mapping_type_name; + ret = json_unpack_ex(value, &err, 0, "{ s: s, s: i, s: s }", "subscriber", + &mapping_subscriber, "index", &mapping_index, + "mms_type", &mapping_type_name); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - auto mapping_type = GooseSignal::lookupMmsTypeName(mapping_type_name).value(); + auto mapping_type = + GooseSignal::lookupMmsTypeName(mapping_type_name).value(); - mappings.push_back(InputMapping { - mapping_subscriber, - mapping_index, - mapping_type, - }); - } + mappings.push_back(InputMapping{ + mapping_subscriber, + mapping_index, + mapping_type, + }); + } } -void GooseNode::parseOutput(json_t *json) -{ - int ret; - json_error_t err; +void GooseNode::parseOutput(json_t *json) { + int ret; + json_error_t err; - json_t *json_publishers = nullptr; - json_t *json_signals = nullptr; - char const *interface_id = output.interface_id.c_str(); - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s?: f }", - "publishers", &json_publishers, - "signals", &json_signals, - "interface", &interface_id, - "resend_interval", &output.resend_interval - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_publishers = nullptr; + json_t *json_signals = nullptr; + char const *interface_id = output.interface_id.c_str(); + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s?: f }", + "publishers", &json_publishers, "signals", &json_signals, + "interface", &interface_id, "resend_interval", + &output.resend_interval); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parsePublishers(json_publishers, output.contexts); + parsePublishers(json_publishers, output.contexts); - output.interface_id = interface_id; + output.interface_id = interface_id; } -void GooseNode::parsePublisherData(json_t *json, std::vector &data) -{ - int ret; - json_error_t err; - int index; - json_t* json_signal_or_value; +void GooseNode::parsePublisherData(json_t *json, + std::vector &data) { + int ret; + json_error_t err; + int index; + json_t *json_signal_or_value; - if (!json_is_array(json)) - throw RuntimeError("publisher data is not an array"); + if (!json_is_array(json)) + throw RuntimeError("publisher data is not an array"); - json_array_foreach(json, index, json_signal_or_value) { - char const *mms_type = nullptr; - char const *signal_str = nullptr; - json_t *json_value = nullptr; - int bitstring_size = -1; - ret = json_unpack_ex(json_signal_or_value, &err, 0, "{ s: s, s?: s, s?: o, s?: i }", - "mms_type", &mms_type, - "signal", &signal_str, - "value", &json_value, - "mms_bitstring_size", &bitstring_size - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_array_foreach(json, index, json_signal_or_value) { + char const *mms_type = nullptr; + char const *signal_str = nullptr; + json_t *json_value = nullptr; + int bitstring_size = -1; + ret = json_unpack_ex(json_signal_or_value, &err, 0, + "{ s: s, s?: s, s?: o, s?: i }", "mms_type", &mms_type, + "signal", &signal_str, "value", &json_value, + "mms_bitstring_size", &bitstring_size); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - auto goose_type = GooseSignal::lookupMmsTypeName(mms_type).value(); - std::optional meta = std::nullopt; + auto goose_type = GooseSignal::lookupMmsTypeName(mms_type).value(); + std::optional meta = std::nullopt; - if (goose_type->mms_type == MmsType::MMS_BIT_STRING && bitstring_size != -1) - meta = {.size = bitstring_size}; + if (goose_type->mms_type == MmsType::MMS_BIT_STRING && bitstring_size != -1) + meta = {.size = bitstring_size}; - auto signal_data = SignalData {}; + auto signal_data = SignalData{}; - if (json_value) { - ret = signal_data.parseJson(goose_type->signal_type, json_value); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - } + if (json_value) { + ret = signal_data.parseJson(goose_type->signal_type, json_value); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + } - auto signal = std::optional {}; + auto signal = std::optional{}; - if (signal_str) - signal = out.signals->getIndexByName(signal_str); + if (signal_str) + signal = out.signals->getIndexByName(signal_str); - OutputData value = { - .signal = signal, - .default_value = GooseSignal { goose_type, signal_data, meta } - }; + OutputData value = {.signal = signal, + .default_value = + GooseSignal{goose_type, signal_data, meta}}; - data.push_back(value); - }; + data.push_back(value); + }; } -void GooseNode::parsePublisher(json_t *json, PublisherConfig &pc) -{ - int ret; - json_error_t err; +void GooseNode::parsePublisher(json_t *json, PublisherConfig &pc) { + int ret; + json_error_t err; - char *go_id = nullptr; - char *go_cb_ref = nullptr; - char *data_set_ref = nullptr; - char *dst_address_str = nullptr; - int app_id = 0; - int conf_rev = 0; - int time_allowed_to_live = 0; - int burst = 1; - json_t *json_data = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s, s: s, s: i, s: i, s: i, s?: i, s: o }", - "go_id", &go_id, - "go_cb_ref", &go_cb_ref, - "data_set_ref", &data_set_ref, - "dst_address", &dst_address_str, - "app_id", &app_id, - "conf_rev", &conf_rev, - "time_allowed_to_live", &time_allowed_to_live, - "burst", &burst, - "data", &json_data - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + char *go_id = nullptr; + char *go_cb_ref = nullptr; + char *data_set_ref = nullptr; + char *dst_address_str = nullptr; + int app_id = 0; + int conf_rev = 0; + int time_allowed_to_live = 0; + int burst = 1; + json_t *json_data = nullptr; + ret = json_unpack_ex( + json, &err, 0, + "{ s: s, s: s, s: s, s: s, s: i, s: i, s: i, s?: i, s: o }", "go_id", + &go_id, "go_cb_ref", &go_cb_ref, "data_set_ref", &data_set_ref, + "dst_address", &dst_address_str, "app_id", &app_id, "conf_rev", &conf_rev, + "time_allowed_to_live", &time_allowed_to_live, "burst", &burst, "data", + &json_data); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - std::optional dst_address = stringToMac(dst_address_str); - if (!dst_address) - throw RuntimeError("Invalid dst_address"); + std::optional dst_address = stringToMac(dst_address_str); + if (!dst_address) + throw RuntimeError("Invalid dst_address"); - pc.go_id = std::string { go_id }; - pc.go_cb_ref = std::string { go_cb_ref }; - pc.data_set_ref = std::string { data_set_ref }; - pc.dst_address = *dst_address; - pc.app_id = app_id; - pc.conf_rev = conf_rev; - pc.time_allowed_to_live = time_allowed_to_live; - pc.burst = burst; + pc.go_id = std::string{go_id}; + pc.go_cb_ref = std::string{go_cb_ref}; + pc.data_set_ref = std::string{data_set_ref}; + pc.dst_address = *dst_address; + pc.app_id = app_id; + pc.conf_rev = conf_rev; + pc.time_allowed_to_live = time_allowed_to_live; + pc.burst = burst; - parsePublisherData(json_data, pc.data); + parsePublisherData(json_data, pc.data); } -void GooseNode::parsePublishers(json_t *json, std::vector &ctx) -{ - int index; - json_t* json_publisher; +void GooseNode::parsePublishers(json_t *json, std::vector &ctx) { + int index; + json_t *json_publisher; - json_array_foreach(json, index, json_publisher) { - PublisherConfig pc; + json_array_foreach(json, index, json_publisher) { + PublisherConfig pc; - parsePublisher(json_publisher, pc); + parsePublisher(json_publisher, pc); - ctx.push_back(OutputContext { pc }); - } + ctx.push_back(OutputContext{pc}); + } } -std::vector GooseNode::getPollFDs() -{ - return { queue_signalled_fd(&input.queue) }; +std::vector GooseNode::getPollFDs() { + return {queue_signalled_fd(&input.queue)}; } -int GooseNode::prepare() -{ - int ret; +int GooseNode::prepare() { + int ret; - ret = pool_init(&input.pool, input.queue_length, SAMPLE_LENGTH(getInputSignals(false)->size())); - if (ret) return ret; + ret = pool_init(&input.pool, input.queue_length, + SAMPLE_LENGTH(getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&input.queue, input.queue_length); - if (ret) return ret; + ret = queue_signalled_init(&input.queue, input.queue_length); + if (ret) + return ret; - return Node::prepare(); + return Node::prepare(); } -int GooseNode::start() -{ - if (in.enabled) - startReceiver(); +int GooseNode::start() { + if (in.enabled) + startReceiver(); - if (out.enabled) - startPublishers(); + if (out.enabled) + startPublishers(); - return Node::start(); + return Node::start(); } -int GooseNode::stop() -{ - int err __attribute__((unused)); +int GooseNode::stop() { + int err __attribute__((unused)); - stopReceiver(); - stopPublishers(); + stopReceiver(); + stopPublishers(); - err = queue_signalled_close(&input.queue); + err = queue_signalled_close(&input.queue); - return Node::stop(); + return Node::stop(); } // Register node static char name[] = "iec61850-8-1"; static char description[] = "IEC 61850-8-1 (GOOSE)"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/iec61850_sv.cpp b/lib/nodes/iec61850_sv.cpp index 6b531aef4..64a1c8465 100644 --- a/lib/nodes/iec61850_sv.cpp +++ b/lib/nodes/iec61850_sv.cpp @@ -9,10 +9,10 @@ #include #include -#include -#include #include +#include #include +#include #define CONFIG_SV_DEFAULT_APPID 0x4000 #define CONFIG_SV_DEFAULT_DST_ADDRESS CONFIG_GOOSE_DEFAULT_DST_ADDRESS @@ -23,27 +23,28 @@ using namespace villas; using namespace villas::utils; using namespace villas::node; -static -void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU asdu) -{ - auto *n = (NodeCompat *) ctx; - auto *i = n->getData(); - struct Sample *smp; +static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, + SVSubscriber_ASDU asdu) { + auto *n = (NodeCompat *)ctx; + auto *i = n->getData(); + struct Sample *smp; - const char* svid = SVSubscriber_ASDU_getSvId(asdu); - int smpcnt = SVSubscriber_ASDU_getSmpCnt(asdu); - int confrev = SVSubscriber_ASDU_getConfRev(asdu); - int sz; + const char *svid = SVSubscriber_ASDU_getSvId(asdu); + int smpcnt = SVSubscriber_ASDU_getSmpCnt(asdu); + int confrev = SVSubscriber_ASDU_getConfRev(asdu); + int sz; - n->logger->debug("Received SV: svid={}, smpcnt={}, confrev={}", svid, smpcnt, confrev); + n->logger->debug("Received SV: svid={}, smpcnt={}, confrev={}", svid, smpcnt, + confrev); - sz = SVSubscriber_ASDU_getDataSize(asdu); - if (sz < i->in.total_size) { - n->logger->warn("Received truncated ASDU: size={}, expected={}", SVSubscriber_ASDU_getDataSize(asdu), i->in.total_size); - return; - } + sz = SVSubscriber_ASDU_getDataSize(asdu); + if (sz < i->in.total_size) { + n->logger->warn("Received truncated ASDU: size={}, expected={}", + SVSubscriber_ASDU_getDataSize(asdu), i->in.total_size); + return; + } - /* Access to the data requires a priori knowledge of the data set. + /* Access to the data requires a priori knowledge of the data set. * For this example we assume a data set consisting of FLOAT32 values. * A FLOAT32 value is encoded as 4 bytes. You can find the first FLOAT32 * value at byte position 0, the second value at byte position 4, the third @@ -53,434 +54,438 @@ void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU * data block of the SV message before accessing the data. */ - smp = sample_alloc(&i->in.pool); - if (!smp) { - n->logger->warn("Pool underrun in subscriber"); - return; - } + smp = sample_alloc(&i->in.pool); + if (!smp) { + n->logger->warn("Pool underrun in subscriber"); + return; + } - smp->sequence = smpcnt; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->length = 0; - smp->signals = n->getInputSignals(false); + smp->sequence = smpcnt; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->length = 0; + smp->signals = n->getInputSignals(false); - if (SVSubscriber_ASDU_hasRefrTm(asdu)) { - uint64_t refrtm = SVSubscriber_ASDU_getRefrTmAsMs(asdu); + if (SVSubscriber_ASDU_hasRefrTm(asdu)) { + uint64_t refrtm = SVSubscriber_ASDU_getRefrTmAsMs(asdu); - smp->ts.origin.tv_sec = refrtm / 1000; - smp->ts.origin.tv_nsec = (refrtm % 1000) * 1000000; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->ts.origin.tv_sec = refrtm / 1000; + smp->ts.origin.tv_nsec = (refrtm % 1000) * 1000000; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - unsigned offset = 0; - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->in.signals, j); - auto sig = smp->signals->getByIndex(j); - if (!sig) - continue; + unsigned offset = 0; + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->in.signals, j); + auto sig = smp->signals->getByIndex(j); + if (!sig) + continue; - switch (td->iec_type) { - case IEC61850Type::INT8: - smp->data[j].i = SVSubscriber_ASDU_getINT8(asdu, offset); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + smp->data[j].i = SVSubscriber_ASDU_getINT8(asdu, offset); + break; - case IEC61850Type::INT16: - smp->data[j].i = SVSubscriber_ASDU_getINT16(asdu, offset); - break; + case IEC61850Type::INT16: + smp->data[j].i = SVSubscriber_ASDU_getINT16(asdu, offset); + break; - case IEC61850Type::INT32: - smp->data[j].i = SVSubscriber_ASDU_getINT32(asdu, offset); - break; + case IEC61850Type::INT32: + smp->data[j].i = SVSubscriber_ASDU_getINT32(asdu, offset); + break; - case IEC61850Type::INT8U: - smp->data[j].i = SVSubscriber_ASDU_getINT8U(asdu, offset); - break; + case IEC61850Type::INT8U: + smp->data[j].i = SVSubscriber_ASDU_getINT8U(asdu, offset); + break; - case IEC61850Type::INT16U: - smp->data[j].i = SVSubscriber_ASDU_getINT16U(asdu, offset); - break; + case IEC61850Type::INT16U: + smp->data[j].i = SVSubscriber_ASDU_getINT16U(asdu, offset); + break; - case IEC61850Type::INT32U: - smp->data[j].i = SVSubscriber_ASDU_getINT32U(asdu, offset); - break; + case IEC61850Type::INT32U: + smp->data[j].i = SVSubscriber_ASDU_getINT32U(asdu, offset); + break; - case IEC61850Type::FLOAT32: - smp->data[j].f = SVSubscriber_ASDU_getFLOAT32(asdu, offset); - break; + case IEC61850Type::FLOAT32: + smp->data[j].f = SVSubscriber_ASDU_getFLOAT32(asdu, offset); + break; - case IEC61850Type::FLOAT64: - smp->data[j].f = SVSubscriber_ASDU_getFLOAT64(asdu, offset); - break; + case IEC61850Type::FLOAT64: + smp->data[j].f = SVSubscriber_ASDU_getFLOAT64(asdu, offset); + break; - default: { } - } + default: { + } + } - offset += td->size; + offset += td->size; - smp->length++; - } + smp->length++; + } - int pushed __attribute__((unused)); - pushed = queue_signalled_push(&i->in.queue, smp); + int pushed __attribute__((unused)); + pushed = queue_signalled_push(&i->in.queue, smp); } -int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) { + int ret; + auto *i = n->getData(); - const char *dst_address = nullptr; - const char *interface = nullptr; - const char *svid = nullptr; - const char *smpmod = nullptr; + const char *dst_address = nullptr; + const char *interface = nullptr; + const char *svid = nullptr; + const char *smpmod = nullptr; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_t *json_signals = nullptr; - json_error_t err; + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_t *json_signals = nullptr; + json_error_t err; - // Default values - i->out.enabled = false; - i->in.enabled = false; - i->out.smpmod = -1; // do not set smpmod - i->out.smprate = -1; // do not set smpmod - i->out.confrev = 1; - i->out.vlan_priority = CONFIG_SV_DEFAULT_PRIORITY; - i->out.vlan_id = CONFIG_SV_DEFAULT_VLAN_ID; + // Default values + i->out.enabled = false; + i->in.enabled = false; + i->out.smpmod = -1; // do not set smpmod + i->out.smprate = -1; // do not set smpmod + i->out.confrev = 1; + i->out.vlan_priority = CONFIG_SV_DEFAULT_PRIORITY; + i->out.vlan_id = CONFIG_SV_DEFAULT_VLAN_ID; - i->app_id = CONFIG_SV_DEFAULT_APPID; + i->app_id = CONFIG_SV_DEFAULT_APPID; - uint8_t tmp[] = CONFIG_SV_DEFAULT_DST_ADDRESS; - memcpy(i->dst_address.ether_addr_octet, tmp, sizeof(i->dst_address.ether_addr_octet)); + uint8_t tmp[] = CONFIG_SV_DEFAULT_DST_ADDRESS; + memcpy(i->dst_address.ether_addr_octet, tmp, + sizeof(i->dst_address.ether_addr_octet)); - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s: s, s?: i, s?: s }", - "out", &json_out, - "in", &json_in, - "interface", &interface, - "app_id", &i->app_id, - "dst_address", &dst_address - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-sv"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s: s, s?: i, s?: s }", + "out", &json_out, "in", &json_in, "interface", &interface, + "app_id", &i->app_id, "dst_address", &dst_address); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-sv"); - if (interface) - i->interface = strdup(interface); + if (interface) + i->interface = strdup(interface); - if (dst_address) - ether_aton_r(dst_address, &i->dst_address); + if (dst_address) + ether_aton_r(dst_address, &i->dst_address); - if (json_out) { - i->out.enabled = true; + if (json_out) { + i->out.enabled = true; - ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s: s, s?: i, s?: s, s?: i, s?: i, s?: i }", - "signals", &json_signals, - "svid", &svid, - "confrev", &i->out.confrev, - "smpmod", &smpmod, - "smprate", &i->out.smprate, - "vlan_id", &i->out.vlan_id, - "vlan_priority", &i->out.vlan_priority - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-iec61850-sv-out"); + ret = json_unpack_ex( + json_out, &err, 0, "{ s: o, s: s, s?: i, s?: s, s?: i, s?: i, s?: i }", + "signals", &json_signals, "svid", &svid, "confrev", &i->out.confrev, + "smpmod", &smpmod, "smprate", &i->out.smprate, "vlan_id", + &i->out.vlan_id, "vlan_priority", &i->out.vlan_priority); + if (ret) + throw ConfigError(json_out, err, "node-config-node-iec61850-sv-out"); - if (smpmod) { - if (!strcmp(smpmod, "per_nominal_period")) - i->out.smpmod = IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD; - else if (!strcmp(smpmod, "samples_per_second")) - i->out.smpmod = IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND; - else if (!strcmp(smpmod, "seconds_per_sample")) - i->out.smpmod = IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE; - else - throw RuntimeError("Invalid value '{}' for setting 'smpmod'", smpmod); - } + if (smpmod) { + if (!strcmp(smpmod, "per_nominal_period")) + i->out.smpmod = IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD; + else if (!strcmp(smpmod, "samples_per_second")) + i->out.smpmod = IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND; + else if (!strcmp(smpmod, "seconds_per_sample")) + i->out.smpmod = IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE; + else + throw RuntimeError("Invalid value '{}' for setting 'smpmod'", smpmod); + } - i->out.svid = svid ? strdup(svid) : nullptr; + i->out.svid = svid ? strdup(svid) : nullptr; - ret = iec61850_parse_signals(json_signals, &i->out.signals, n->getOutputSignals()); - if (ret <= 0) - throw RuntimeError("Failed to parse setting 'signals'"); + ret = iec61850_parse_signals(json_signals, &i->out.signals, + n->getOutputSignals()); + if (ret <= 0) + throw RuntimeError("Failed to parse setting 'signals'"); - i->out.total_size = ret; - } + i->out.total_size = ret; + } - if (json_in) { - i->in.enabled = true; + if (json_in) { + i->in.enabled = true; - json_signals = nullptr; - ret = json_unpack_ex(json_in, &err, 0, "{ s: o }", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json_in, err, "node-config-node-iec61850-in"); + json_signals = nullptr; + ret = + json_unpack_ex(json_in, &err, 0, "{ s: o }", "signals", &json_signals); + if (ret) + throw ConfigError(json_in, err, "node-config-node-iec61850-in"); - ret = iec61850_parse_signals(json_signals, &i->in.signals, n->getInputSignals(false)); - if (ret <= 0) - throw RuntimeError("Failed to parse setting 'signals'"); + ret = iec61850_parse_signals(json_signals, &i->in.signals, + n->getInputSignals(false)); + if (ret <= 0) + throw RuntimeError("Failed to parse setting 'signals'"); - i->in.total_size = ret; - } + i->in.total_size = ret; + } - return 0; + return 0; } -char * villas::node::iec61850_sv_print(NodeCompat *n) -{ - char *buf; - auto *i = n->getData(); +char *villas::node::iec61850_sv_print(NodeCompat *n) { + char *buf; + auto *i = n->getData(); - buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, i->app_id, ether_ntoa(&i->dst_address)); + buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, + i->app_id, ether_ntoa(&i->dst_address)); - // Publisher part - if (i->out.enabled) { - strcatf(&buf, ", pub.svid=%s, pub.vlan_prio=%d, pub.vlan_id=%#x, pub.confrev=%d, pub.#fields=%zu", - i->out.svid, - i->out.vlan_priority, - i->out.vlan_id, - i->out.confrev, - n->getOutputSignals()->size() - ); - } + // Publisher part + if (i->out.enabled) { + strcatf(&buf, + ", pub.svid=%s, pub.vlan_prio=%d, pub.vlan_id=%#x, pub.confrev=%d, " + "pub.#fields=%zu", + i->out.svid, i->out.vlan_priority, i->out.vlan_id, i->out.confrev, + n->getOutputSignals()->size()); + } - // Subscriber part - if (i->in.enabled) - strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); + // Subscriber part + if (i->in.enabled) + strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); - return buf; + return buf; } -int villas::node::iec61850_sv_start(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_start(NodeCompat *n) { + int ret; + auto *i = n->getData(); - // Initialize publisher - if (i->out.enabled) { - i->out.publisher = SVPublisher_create(nullptr, i->interface); - i->out.asdu = SVPublisher_addASDU(i->out.publisher, i->out.svid, n->getNameShort().c_str(), i->out.confrev); + // Initialize publisher + if (i->out.enabled) { + i->out.publisher = SVPublisher_create(nullptr, i->interface); + i->out.asdu = + SVPublisher_addASDU(i->out.publisher, i->out.svid, + n->getNameShort().c_str(), i->out.confrev); - for (unsigned k = 0; k < list_length(&i->out.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->out.signals, k); + for (unsigned k = 0; k < list_length(&i->out.signals); k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->out.signals, k); - switch (td->iec_type) { - case IEC61850Type::INT8: - SVPublisher_ASDU_addINT8(i->out.asdu); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + SVPublisher_ASDU_addINT8(i->out.asdu); + break; - case IEC61850Type::INT32: - SVPublisher_ASDU_addINT32(i->out.asdu); - break; + case IEC61850Type::INT32: + SVPublisher_ASDU_addINT32(i->out.asdu); + break; - case IEC61850Type::FLOAT32: - SVPublisher_ASDU_addFLOAT(i->out.asdu); - break; + case IEC61850Type::FLOAT32: + SVPublisher_ASDU_addFLOAT(i->out.asdu); + break; - case IEC61850Type::FLOAT64: - SVPublisher_ASDU_addFLOAT64(i->out.asdu); - break; + case IEC61850Type::FLOAT64: + SVPublisher_ASDU_addFLOAT64(i->out.asdu); + break; - default: { } - } - } + default: { + } + } + } - if (i->out.smpmod >= 0) - SVPublisher_ASDU_setSmpMod(i->out.asdu, i->out.smpmod); + if (i->out.smpmod >= 0) + SVPublisher_ASDU_setSmpMod(i->out.asdu, i->out.smpmod); - SVPublisher_ASDU_enableRefrTm(i->out.asdu); + SVPublisher_ASDU_enableRefrTm(i->out.asdu); -// if (s->out.smprate >= 0) -// SV_ASDU_setSmpRate(i->out.asdu, i->out.smprate); + // if (s->out.smprate >= 0) + // SV_ASDU_setSmpRate(i->out.asdu, i->out.smprate); - // Start publisher - SVPublisher_setupComplete(i->out.publisher); - } + // Start publisher + SVPublisher_setupComplete(i->out.publisher); + } - // Start subscriber - if (i->in.enabled) { - struct iec61850_receiver *r = iec61850_receiver_create(iec61850_receiver::Type::SAMPLED_VALUES, i->interface); + // Start subscriber + if (i->in.enabled) { + struct iec61850_receiver *r = iec61850_receiver_create( + iec61850_receiver::Type::SAMPLED_VALUES, i->interface); - i->in.receiver = r->sv; - i->in.subscriber = SVSubscriber_create(i->dst_address.ether_addr_octet, i->app_id); + i->in.receiver = r->sv; + i->in.subscriber = + SVSubscriber_create(i->dst_address.ether_addr_octet, i->app_id); - // Install a callback handler for the subscriber - SVSubscriber_setListener(i->in.subscriber, iec61850_sv_listener, n); + // Install a callback handler for the subscriber + SVSubscriber_setListener(i->in.subscriber, iec61850_sv_listener, n); - // Connect the subscriber to the receiver - SVReceiver_addSubscriber(i->in.receiver, i->in.subscriber); + // Connect the subscriber to the receiver + SVReceiver_addSubscriber(i->in.receiver, i->in.subscriber); - // Initialize pool and queue to pass samples between threads - ret = pool_init(&i->in.pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + // Initialize pool and queue to pass samples between threads + ret = pool_init(&i->in.pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&i->in.queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&i->in.queue, 1024); + if (ret) + return ret; - for (unsigned k = 0; k < list_length(&i->in.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->in.signals, k); - auto sig = n->getInputSignals(false)->getByIndex(k); + for (unsigned k = 0; k < list_length(&i->in.signals); k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->in.signals, k); + auto sig = n->getInputSignals(false)->getByIndex(k); - if (sig->type == SignalType::INVALID) - sig->type = td->type; - else if (sig->type != td->type) - return -1; - } - } + if (sig->type == SignalType::INVALID) + sig->type = td->type; + else if (sig->type != td->type) + return -1; + } + } - return 0; + return 0; } -int villas::node::iec61850_sv_stop(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_stop(NodeCompat *n) { + int ret; + auto *i = n->getData(); - if (i->in.enabled) - SVReceiver_removeSubscriber(i->in.receiver, i->in.subscriber); + if (i->in.enabled) + SVReceiver_removeSubscriber(i->in.receiver, i->in.subscriber); - ret = queue_signalled_close(&i->in.queue); - if (ret) - return ret; + ret = queue_signalled_close(&i->in.queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_sv_destroy(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_destroy(NodeCompat *n) { + int ret; + auto *i = n->getData(); - // Deinitialize publisher - if (i->out.enabled && i->out.publisher) - SVPublisher_destroy(i->out.publisher); + // Deinitialize publisher + if (i->out.enabled && i->out.publisher) + SVPublisher_destroy(i->out.publisher); - // Deinitialise subscriber - if (i->in.enabled) { - ret = queue_signalled_destroy(&i->in.queue); - if (ret) - return ret; + // Deinitialise subscriber + if (i->in.enabled) { + ret = queue_signalled_destroy(&i->in.queue); + if (ret) + return ret; - ret = pool_destroy(&i->in.pool); - if (ret) - return ret; - } + ret = pool_destroy(&i->in.pool); + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *i = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::iec61850_sv_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *i = n->getData(); + struct Sample *smpt[cnt]; - if (!i->in.enabled) - return -1; + if (!i->in.enabled) + return -1; - pulled = queue_signalled_pull_many(&i->in.queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&i->in.queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); +int villas::node::iec61850_sv_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); - if (!i->out.enabled) - return -1; + if (!i->out.enabled) + return -1; - for (unsigned j = 0; j < cnt; j++) { - unsigned offset = 0; - for (unsigned k = 0; k < MIN(smps[j]->length, list_length(&i->out.signals)); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->out.signals, k); + for (unsigned j = 0; j < cnt; j++) { + unsigned offset = 0; + for (unsigned k = 0; k < MIN(smps[j]->length, list_length(&i->out.signals)); + k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->out.signals, k); - int ival = 0; - double fval = 0; + int ival = 0; + double fval = 0; - switch (td->iec_type) { - case IEC61850Type::INT8: - case IEC61850Type::INT32: - ival = sample_format(smps[j], k) == SignalType::FLOAT ? smps[j]->data[k].f : smps[j]->data[k].i; - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + case IEC61850Type::INT32: + ival = sample_format(smps[j], k) == SignalType::FLOAT + ? smps[j]->data[k].f + : smps[j]->data[k].i; + break; - case IEC61850Type::FLOAT32: - case IEC61850Type::FLOAT64: - fval = sample_format(smps[j], k) == SignalType::FLOAT ? smps[j]->data[k].f : smps[j]->data[k].i; - break; + case IEC61850Type::FLOAT32: + case IEC61850Type::FLOAT64: + fval = sample_format(smps[j], k) == SignalType::FLOAT + ? smps[j]->data[k].f + : smps[j]->data[k].i; + break; - default: { } - } + default: { + } + } - switch (td->iec_type) { - case IEC61850Type::INT8: - SVPublisher_ASDU_setINT8(i->out.asdu, offset, ival); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + SVPublisher_ASDU_setINT8(i->out.asdu, offset, ival); + break; - case IEC61850Type::INT32: - SVPublisher_ASDU_setINT32(i->out.asdu, offset, ival); - break; + case IEC61850Type::INT32: + SVPublisher_ASDU_setINT32(i->out.asdu, offset, ival); + break; - case IEC61850Type::FLOAT32: - SVPublisher_ASDU_setFLOAT(i->out.asdu, offset, fval); - break; + case IEC61850Type::FLOAT32: + SVPublisher_ASDU_setFLOAT(i->out.asdu, offset, fval); + break; - case IEC61850Type::FLOAT64: - SVPublisher_ASDU_setFLOAT64(i->out.asdu, offset, fval); - break; + case IEC61850Type::FLOAT64: + SVPublisher_ASDU_setFLOAT64(i->out.asdu, offset, fval); + break; - default: { } - } + default: { + } + } - offset += td->size; - } + offset += td->size; + } - SVPublisher_ASDU_setSmpCnt(i->out.asdu, smps[j]->sequence); + SVPublisher_ASDU_setSmpCnt(i->out.asdu, smps[j]->sequence); - if (smps[j]->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - uint64_t refrtm = smps[j]->ts.origin.tv_sec * 1000 + smps[j]->ts.origin.tv_nsec / 1000000; + if (smps[j]->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + uint64_t refrtm = smps[j]->ts.origin.tv_sec * 1000 + + smps[j]->ts.origin.tv_nsec / 1000000; - SVPublisher_ASDU_setRefrTm(i->out.asdu, refrtm); - } + SVPublisher_ASDU_setRefrTm(i->out.asdu, refrtm); + } - SVPublisher_publish(i->out.publisher); - } + SVPublisher_publish(i->out.publisher); + } - return cnt; + return cnt; } -int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) -{ - auto *i = n->getData(); +int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) { + auto *i = n->getData(); - fds[0] = queue_signalled_fd(&i->in.queue); + fds[0] = queue_signalled_fd(&i->in.queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "iec61850-9-2"; - p.description = "IEC 61850-9-2 (Sampled Values)"; - p.vectorize = 0; - p.size = sizeof(struct iec61850_sv); - p.type.start = iec61850_type_start; - p.type.stop = iec61850_type_stop; - p.destroy = iec61850_sv_destroy; - p.parse = iec61850_sv_parse; - p.print = iec61850_sv_print; - p.start = iec61850_sv_start; - p.stop = iec61850_sv_stop; - p.read = iec61850_sv_read; - p.write = iec61850_sv_write; - p.poll_fds = iec61850_sv_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "iec61850-9-2"; + p.description = "IEC 61850-9-2 (Sampled Values)"; + p.vectorize = 0; + p.size = sizeof(struct iec61850_sv); + p.type.start = iec61850_type_start; + p.type.stop = iec61850_type_stop; + p.destroy = iec61850_sv_destroy; + p.parse = iec61850_sv_parse; + p.print = iec61850_sv_print; + p.start = iec61850_sv_start; + p.stop = iec61850_sv_stop; + p.read = iec61850_sv_read; + p.write = iec61850_sv_write; + p.poll_fds = iec61850_sv_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index 48c161567..032d7f864 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -5,403 +5,386 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include #include +#include +#include #include +#include #include #include -#include -#include -#include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -int ib_disconnect(NodeCompat *n) -{ - auto *ib = n->getData(); - struct ibv_wc wc[MAX(ib->recv_cq_size, ib->send_cq_size)]; - int wcs; +static int ib_disconnect(NodeCompat *n) { + auto *ib = n->getData(); + struct ibv_wc wc[MAX(ib->recv_cq_size, ib->send_cq_size)]; + int wcs; - n->logger->debug("Starting to clean up"); + n->logger->debug("Starting to clean up"); - rdma_disconnect(ib->ctx.id); + rdma_disconnect(ib->ctx.id); - // If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. - while (ib->conn.available_recv_wrs) { - wcs = ibv_poll_cq(ib->ctx.recv_cq, ib->recv_cq_size, wc); + // If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. + while (ib->conn.available_recv_wrs) { + wcs = ibv_poll_cq(ib->ctx.recv_cq, ib->recv_cq_size, wc); - ib->conn.available_recv_wrs -= wcs; + ib->conn.available_recv_wrs -= wcs; - for (int j = 0; j < wcs; j++) - sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); - } + for (int j = 0; j < wcs; j++) + sample_decref((struct Sample *)(intptr_t)(wc[j].wr_id)); + } - // Send Queue - while ((wcs = ibv_poll_cq(ib->ctx.send_cq, ib->send_cq_size, wc))) - for (int j = 0; j < wcs; j++) - if (wc[j].wr_id > 0) - sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); + // Send Queue + while ((wcs = ibv_poll_cq(ib->ctx.send_cq, ib->send_cq_size, wc))) + for (int j = 0; j < wcs; j++) + if (wc[j].wr_id > 0) + sample_decref((struct Sample *)(intptr_t)(wc[j].wr_id)); - // Destroy QP - rdma_destroy_qp(ib->ctx.id); + // Destroy QP + rdma_destroy_qp(ib->ctx.id); - n->logger->debug("Destroyed QP"); + n->logger->debug("Destroyed QP"); - return ib->stopThreads; + return ib->stopThreads; } -static -void ib_build_ibv(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static void ib_build_ibv(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Starting to build IBV components"); + n->logger->debug("Starting to build IBV components"); - // Create completion queues (No completion channel!) - ib->ctx.recv_cq = ibv_create_cq(ib->ctx.id->verbs, ib->recv_cq_size, nullptr, nullptr, 0); - if (!ib->ctx.recv_cq) - throw RuntimeError("Could not create receive completion queue"); + // Create completion queues (No completion channel!) + ib->ctx.recv_cq = + ibv_create_cq(ib->ctx.id->verbs, ib->recv_cq_size, nullptr, nullptr, 0); + if (!ib->ctx.recv_cq) + throw RuntimeError("Could not create receive completion queue"); - n->logger->debug("Created receive Completion Queue"); + n->logger->debug("Created receive Completion Queue"); - ib->ctx.send_cq = ibv_create_cq(ib->ctx.id->verbs, ib->send_cq_size, nullptr, nullptr, 0); - if (!ib->ctx.send_cq) - throw RuntimeError("Could not create send completion queue"); + ib->ctx.send_cq = + ibv_create_cq(ib->ctx.id->verbs, ib->send_cq_size, nullptr, nullptr, 0); + if (!ib->ctx.send_cq) + throw RuntimeError("Could not create send completion queue"); - n->logger->debug("Created send Completion Queue"); + n->logger->debug("Created send Completion Queue"); - // Prepare remaining Queue Pair (QP) attributes - ib->qp_init.send_cq = ib->ctx.send_cq; - ib->qp_init.recv_cq = ib->ctx.recv_cq; + // Prepare remaining Queue Pair (QP) attributes + ib->qp_init.send_cq = ib->ctx.send_cq; + ib->qp_init.recv_cq = ib->ctx.recv_cq; - // Create the actual QP - ret = rdma_create_qp(ib->ctx.id, ib->ctx.pd, &ib->qp_init); - if (ret) - throw RuntimeError("Failed to create Queue Pair"); + // Create the actual QP + ret = rdma_create_qp(ib->ctx.id, ib->ctx.pd, &ib->qp_init); + if (ret) + throw RuntimeError("Failed to create Queue Pair"); - n->logger->debug("Created Queue Pair with {} receive and {} send elements", - ib->qp_init.cap.max_recv_wr, ib->qp_init.cap.max_send_wr); + n->logger->debug("Created Queue Pair with {} receive and {} send elements", + ib->qp_init.cap.max_recv_wr, ib->qp_init.cap.max_send_wr); - if (ib->conn.send_inline) - n->logger->info("Maximum inline size is set to {} byte", ib->qp_init.cap.max_inline_data); + if (ib->conn.send_inline) + n->logger->info("Maximum inline size is set to {} byte", + ib->qp_init.cap.max_inline_data); } -static -int ib_addr_resolved(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static int ib_addr_resolved(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Successfully resolved address"); + n->logger->debug("Successfully resolved address"); - // Build all components from IB Verbs - ib_build_ibv(n); + // Build all components from IB Verbs + ib_build_ibv(n); - // Resolve address - ret = rdma_resolve_route(ib->ctx.id, ib->conn.timeout); - if (ret) - throw RuntimeError("Failed to resolve route"); + // Resolve address + ret = rdma_resolve_route(ib->ctx.id, ib->conn.timeout); + if (ret) + throw RuntimeError("Failed to resolve route"); - return 0; + return 0; } -static -int ib_route_resolved(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static int ib_route_resolved(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - struct rdma_conn_param cm_params; - memset(&cm_params, 0, sizeof(cm_params)); + struct rdma_conn_param cm_params; + memset(&cm_params, 0, sizeof(cm_params)); - // Send connection request - ret = rdma_connect(ib->ctx.id, &cm_params); - if (ret) - throw RuntimeError("Failed to connect"); + // Send connection request + ret = rdma_connect(ib->ctx.id, &cm_params); + if (ret) + throw RuntimeError("Failed to connect"); - n->logger->debug("Called rdma_connect"); + n->logger->debug("Called rdma_connect"); - return 0; + return 0; } -static -int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) -{ - auto *ib = n->getData(); - int ret; +static int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Received a connection request!"); + n->logger->debug("Received a connection request!"); - ib->ctx.id = id; - ib_build_ibv(n); + ib->ctx.id = id; + ib_build_ibv(n); - struct rdma_conn_param cm_params; - memset(&cm_params, 0, sizeof(cm_params)); + struct rdma_conn_param cm_params; + memset(&cm_params, 0, sizeof(cm_params)); - // Accept connection request - ret = rdma_accept(ib->ctx.id, &cm_params); - if (ret) - throw RuntimeError("Failed to connect"); + // Accept connection request + ret = rdma_accept(ib->ctx.id, &cm_params); + if (ret) + throw RuntimeError("Failed to connect"); - n->logger->info("Successfully accepted connection request"); + n->logger->info("Successfully accepted connection request"); - return 0; + return 0; } -int villas::node::ib_reverse(NodeCompat *n) -{ - auto *ib = n->getData(); +int villas::node::ib_reverse(NodeCompat *n) { + auto *ib = n->getData(); - SWAP(ib->conn.src_addr, ib->conn.dst_addr); + SWAP(ib->conn.src_addr, ib->conn.dst_addr); - return 0; + return 0; } -int villas::node::ib_parse(NodeCompat *n, json_t *json) -{ - auto *ib = n->getData(); +int villas::node::ib_parse(NodeCompat *n, json_t *json) { + auto *ib = n->getData(); - throw ConfigError(json, "The infiniband node-type is currently broken!"); + throw ConfigError(json, "The infiniband node-type is currently broken!"); - int ret; - char *local = nullptr, *remote = nullptr, *lasts; - const char *transport_mode = "RC"; - int timeout = 1000; - int recv_cq_size = 128; - int send_cq_size = 128; - int max_send_wr = 128; - int max_recv_wr = 128; - int max_inline_data = 0; - int send_inline = 1; - int vectorize_in = 1; - int vectorize_out = 1; - int buffer_subtraction = 16; - int use_fallback = 1; + int ret; + char *local = nullptr, *remote = nullptr, *lasts; + const char *transport_mode = "RC"; + int timeout = 1000; + int recv_cq_size = 128; + int send_cq_size = 128; + int max_send_wr = 128; + int max_recv_wr = 128; + int max_inline_data = 0; + int send_inline = 1; + int vectorize_in = 1; + int vectorize_out = 1; + int buffer_subtraction = 16; + int use_fallback = 1; - // Parse JSON files and copy to local variables - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_error_t err; + // Parse JSON files and copy to local variables + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: s }", - "in", &json_in, - "out", &json_out, - "rdma_transport_mode", &transport_mode - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ib"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: s }", "in", &json_in, + "out", &json_out, "rdma_transport_mode", &transport_mode); + if (ret) + throw ConfigError(json, err, "node-config-node-ib"); - if (json_in) { - ret = json_unpack_ex(json_in, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i}", - "address", &local, - "cq_size", &recv_cq_size, - "max_wrs", &max_recv_wr, - "vectorize", &vectorize_in, - "buffer_subtraction", &buffer_subtraction - ); - if (ret) - throw ConfigError(json_in, err, "node-config-node-ib-in"); - } + if (json_in) { + ret = json_unpack_ex( + json_in, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i}", "address", + &local, "cq_size", &recv_cq_size, "max_wrs", &max_recv_wr, "vectorize", + &vectorize_in, "buffer_subtraction", &buffer_subtraction); + if (ret) + throw ConfigError(json_in, err, "node-config-node-ib-in"); + } - if (json_out) { - ret = json_unpack_ex(json_out, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i, s?: b, s?: i, s?: b, s?: i}", - "address", &remote, - "resolution_timeout", &timeout, - "cq_size", &send_cq_size, - "max_wrs", &max_send_wr, - "max_inline_data", &max_inline_data, - "send_inline", &send_inline, - "vectorize", &vectorize_out, - "use_fallback", &use_fallback, - "periodic_signaling", &ib->periodic_signaling - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-ib-out"); + if (json_out) { + ret = json_unpack_ex( + json_out, &err, 0, + "{ s?: s, s?: i, s?: i, s?: i, s?: i, s?: b, s?: i, s?: b, s?: i}", + "address", &remote, "resolution_timeout", &timeout, "cq_size", + &send_cq_size, "max_wrs", &max_send_wr, "max_inline_data", + &max_inline_data, "send_inline", &send_inline, "vectorize", + &vectorize_out, "use_fallback", &use_fallback, "periodic_signaling", + &ib->periodic_signaling); + if (ret) + throw ConfigError(json_out, err, "node-config-node-ib-out"); - if (remote) { - ib->is_source = 1; + if (remote) { + ib->is_source = 1; - n->logger->debug("Setup as source and target"); - } - } - else { - ib->is_source = 0; + n->logger->debug("Setup as source and target"); + } + } else { + ib->is_source = 0; - n->logger->debug("Setup as target"); - } + n->logger->debug("Setup as target"); + } - // Set fallback mode - ib->conn.use_fallback = use_fallback; + // Set fallback mode + ib->conn.use_fallback = use_fallback; - // Set vectorize mode. Do not print, since framework will print this information - n->in.vectorize = vectorize_in; - n->out.vectorize = vectorize_out; + // Set vectorize mode. Do not print, since framework will print this information + n->in.vectorize = vectorize_in; + n->out.vectorize = vectorize_out; - // Set buffer subtraction - ib->conn.buffer_subtraction = buffer_subtraction; + // Set buffer subtraction + ib->conn.buffer_subtraction = buffer_subtraction; - n->logger->debug("Set buffer subtraction to {}", buffer_subtraction); + n->logger->debug("Set buffer subtraction to {}", buffer_subtraction); - // Translate IP:PORT to a struct addrinfo - char *ip_adr = strtok_r(local, ":", &lasts); - char *port = strtok_r(nullptr, ":", &lasts); + // Translate IP:PORT to a struct addrinfo + char *ip_adr = strtok_r(local, ":", &lasts); + char *port = strtok_r(nullptr, ":", &lasts); - ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.src_addr); - if (ret) - throw RuntimeError("Failed to resolve local address '{}': {}", local, gai_strerror(ret)); + ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.src_addr); + if (ret) + throw RuntimeError("Failed to resolve local address '{}': {}", local, + gai_strerror(ret)); - n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); + n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); - // Translate port space - if (strcmp(transport_mode, "RC") == 0) { - ib->conn.port_space = RDMA_PS_TCP; - ib->qp_init.qp_type = IBV_QPT_RC; - } - else if (strcmp(transport_mode, "UC") == 0) { + // Translate port space + if (strcmp(transport_mode, "RC") == 0) { + ib->conn.port_space = RDMA_PS_TCP; + ib->qp_init.qp_type = IBV_QPT_RC; + } else if (strcmp(transport_mode, "UC") == 0) { #ifdef RDMA_CMA_H_CUSTOM - ib->conn.port_space = RDMA_PS_IB; - ib->qp_init.qp_type = IBV_QPT_UC; + ib->conn.port_space = RDMA_PS_IB; + ib->qp_init.qp_type = IBV_QPT_UC; #else - throw RuntimeError("Unreliable Connected (UC) mode is only available with an adapted version of librdma. " - "Please read the Infiniband node type Documentation for more information on UC!"); + throw RuntimeError("Unreliable Connected (UC) mode is only available with " + "an adapted version of librdma. " + "Please read the Infiniband node type Documentation for " + "more information on UC!"); #endif - } - else if (strcmp(transport_mode, "UD") == 0) { - ib->conn.port_space = RDMA_PS_UDP; - ib->qp_init.qp_type = IBV_QPT_UD; - } - else - throw RuntimeError("Invalid transport_mode = '{}'!", transport_mode); + } else if (strcmp(transport_mode, "UD") == 0) { + ib->conn.port_space = RDMA_PS_UDP; + ib->qp_init.qp_type = IBV_QPT_UD; + } else + throw RuntimeError("Invalid transport_mode = '{}'!", transport_mode); - n->logger->debug("Set transport mode to {}", transport_mode); + n->logger->debug("Set transport mode to {}", transport_mode); - // Set timeout - ib->conn.timeout = timeout; + // Set timeout + ib->conn.timeout = timeout; - n->logger->debug("Set timeout to {}", timeout); + n->logger->debug("Set timeout to {}", timeout); - // Set completion queue size - ib->recv_cq_size = recv_cq_size; - ib->send_cq_size = send_cq_size; + // Set completion queue size + ib->recv_cq_size = recv_cq_size; + ib->send_cq_size = send_cq_size; - n->logger->debug("Set Completion Queue size to {} & {} (in & out)", - recv_cq_size, send_cq_size); + n->logger->debug("Set Completion Queue size to {} & {} (in & out)", + recv_cq_size, send_cq_size); - // Translate inline mode - ib->conn.send_inline = send_inline; + // Translate inline mode + ib->conn.send_inline = send_inline; - n->logger->debug("Set send_inline to {}", send_inline); + n->logger->debug("Set send_inline to {}", send_inline); - // Set max. send and receive Work Requests - ib->qp_init.cap.max_send_wr = max_send_wr; - ib->qp_init.cap.max_recv_wr = max_recv_wr; + // Set max. send and receive Work Requests + ib->qp_init.cap.max_send_wr = max_send_wr; + ib->qp_init.cap.max_recv_wr = max_recv_wr; - n->logger->debug("Set max_send_wr and max_recv_wr to {} and {}, respectively", - max_send_wr, max_recv_wr); + n->logger->debug("Set max_send_wr and max_recv_wr to {} and {}, respectively", + max_send_wr, max_recv_wr); - // Set available receive Work Requests to 0 - ib->conn.available_recv_wrs = 0; + // Set available receive Work Requests to 0 + ib->conn.available_recv_wrs = 0; - // Set remaining QP attributes - ib->qp_init.cap.max_send_sge = 4; - ib->qp_init.cap.max_recv_sge = (ib->conn.port_space == RDMA_PS_UDP) ? 5 : 4; + // Set remaining QP attributes + ib->qp_init.cap.max_send_sge = 4; + ib->qp_init.cap.max_recv_sge = (ib->conn.port_space == RDMA_PS_UDP) ? 5 : 4; - // Set number of bytes to be send inline - ib->qp_init.cap.max_inline_data = max_inline_data; + // Set number of bytes to be send inline + ib->qp_init.cap.max_inline_data = max_inline_data; - // If node will send data, set remote address - if (ib->is_source) { - // Translate address info - char *ip_adr = strtok_r(remote, ":", &lasts); - char *port = strtok_r(nullptr, ":", &lasts); + // If node will send data, set remote address + if (ib->is_source) { + // Translate address info + char *ip_adr = strtok_r(remote, ":", &lasts); + char *port = strtok_r(nullptr, ":", &lasts); - ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.dst_addr); - if (ret) - throw RuntimeError("Failed to resolve remote address '{}': {}", remote, gai_strerror(ret)); + ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.dst_addr); + if (ret) + throw RuntimeError("Failed to resolve remote address '{}': {}", remote, + gai_strerror(ret)); - n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); - } + n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); + } - return 0; + return 0; } -int villas::node::ib_check(NodeCompat *n) -{ - auto *ib = n->getData(); +int villas::node::ib_check(NodeCompat *n) { + auto *ib = n->getData(); - // Check if read substraction makes sense - if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) - throw RuntimeError("The buffer substraction value must be bigger than 2 * in.vectorize"); + // Check if read substraction makes sense + if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) + throw RuntimeError( + "The buffer substraction value must be bigger than 2 * in.vectorize"); - if (ib->conn.buffer_subtraction >= ib->qp_init.cap.max_recv_wr - n->in.vectorize) - throw RuntimeError("The buffer substraction value cannot be bigger than in.max_wrs - in.vectorize"); + if (ib->conn.buffer_subtraction >= + ib->qp_init.cap.max_recv_wr - n->in.vectorize) + throw RuntimeError("The buffer substraction value cannot be bigger than " + "in.max_wrs - in.vectorize"); - // Check if the set value is a power of 2, and warn the user if this is not the case - unsigned max_send_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_send_wr))); - unsigned max_recv_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_recv_wr))); + // Check if the set value is a power of 2, and warn the user if this is not the case + unsigned max_send_pow = (int)pow(2, ceil(log2(ib->qp_init.cap.max_send_wr))); + unsigned max_recv_pow = (int)pow(2, ceil(log2(ib->qp_init.cap.max_recv_wr))); - if (ib->qp_init.cap.max_send_wr != max_send_pow) { - n->logger->warn("Max nr. of send WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", - ib->qp_init.cap.max_send_wr, max_send_pow); + if (ib->qp_init.cap.max_send_wr != max_send_pow) { + n->logger->warn("Max nr. of send WRs ({}) is not a power of 2! It will be " + "changed to a power of 2: {}", + ib->qp_init.cap.max_send_wr, max_send_pow); - // Change it now, because otherwise errors are possible in ib_start(). - ib->qp_init.cap.max_send_wr = max_send_pow; - } + // Change it now, because otherwise errors are possible in ib_start(). + ib->qp_init.cap.max_send_wr = max_send_pow; + } - if (ib->qp_init.cap.max_recv_wr != max_recv_pow) { - n->logger->warn("Max nr. of recv WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", - ib->qp_init.cap.max_recv_wr, max_recv_pow); + if (ib->qp_init.cap.max_recv_wr != max_recv_pow) { + n->logger->warn("Max nr. of recv WRs ({}) is not a power of 2! It will be " + "changed to a power of 2: {}", + ib->qp_init.cap.max_recv_wr, max_recv_pow); - // Change it now, because otherwise errors are possible in ib_start(). - ib->qp_init.cap.max_recv_wr = max_recv_pow; - } + // Change it now, because otherwise errors are possible in ib_start(). + ib->qp_init.cap.max_recv_wr = max_recv_pow; + } - // Check maximum size of max_recv_wr and max_send_wr - if (ib->qp_init.cap.max_send_wr > 8192) - n->logger->warn("Max number of send WRs ({}) is bigger than send queue!", ib->qp_init.cap.max_send_wr); + // Check maximum size of max_recv_wr and max_send_wr + if (ib->qp_init.cap.max_send_wr > 8192) + n->logger->warn("Max number of send WRs ({}) is bigger than send queue!", + ib->qp_init.cap.max_send_wr); - if (ib->qp_init.cap.max_recv_wr > 8192) - n->logger->warn("Max number of receive WRs ({}) is bigger than send queue!", ib->qp_init.cap.max_recv_wr); + if (ib->qp_init.cap.max_recv_wr > 8192) + n->logger->warn("Max number of receive WRs ({}) is bigger than send queue!", + ib->qp_init.cap.max_recv_wr); - /* Set periodic signaling + /* Set periodic signaling * This is done here, so that it uses the checked max_send_wr value */ - if (ib->periodic_signaling == 0) - ib->periodic_signaling = ib->qp_init.cap.max_send_wr / 2; + if (ib->periodic_signaling == 0) + ib->periodic_signaling = ib->qp_init.cap.max_send_wr / 2; - // Warn user if he changed the default inline value - if (ib->qp_init.cap.max_inline_data != 0) - n->logger->warn("You changed the default value of max_inline_data. This might influence the maximum number " - "of outstanding Work Requests in the Queue Pair and can be a reason for the Queue Pair creation to fail"); + // Warn user if he changed the default inline value + if (ib->qp_init.cap.max_inline_data != 0) + n->logger->warn("You changed the default value of max_inline_data. This " + "might influence the maximum number " + "of outstanding Work Requests in the Queue Pair and can be " + "a reason for the Queue Pair creation to fail"); - return 0; + return 0; } -char * villas::node::ib_print(NodeCompat *n) -{ - return 0; -} +char *villas::node::ib_print(NodeCompat *n) { return 0; } -int villas::node::ib_destroy(NodeCompat *n) -{ - return 0; -} +int villas::node::ib_destroy(NodeCompat *n) { return 0; } -static -void ib_create_bind_id(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static void ib_create_bind_id(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - /* Create rdma_cm_id + /* Create rdma_cm_id * * The unreliable connected mode is officially not supported by the rdma_cm library. Only the Reliable * Connected mode (RDMA_PS_TCP) and the Unreliable Datagram mode (RDMA_PS_UDP). Although it is not officially @@ -433,595 +416,610 @@ void ib_create_bind_id(NodeCompat *n) * */ #ifdef RDMA_CMA_H_CUSTOM - ret = rdma_create_id2(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space, ib->qp_init.qp_type); + ret = rdma_create_id2(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space, + ib->qp_init.qp_type); #else - ret = rdma_create_id(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space); + ret = rdma_create_id(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space); #endif - if (ret) - throw RuntimeError("Failed to create rdma_cm_id: {}", gai_strerror(ret)); + if (ret) + throw RuntimeError("Failed to create rdma_cm_id: {}", gai_strerror(ret)); - n->logger->debug("Created rdma_cm_id"); + n->logger->debug("Created rdma_cm_id"); - // Bind rdma_cm_id to the HCA - ret = rdma_bind_addr(ib->ctx.id, ib->conn.src_addr->ai_addr); - if (ret) - throw RuntimeError("Failed to bind to local device: {}", gai_strerror(ret)); + // Bind rdma_cm_id to the HCA + ret = rdma_bind_addr(ib->ctx.id, ib->conn.src_addr->ai_addr); + if (ret) + throw RuntimeError("Failed to bind to local device: {}", gai_strerror(ret)); - n->logger->debug("Bound rdma_cm_id to Infiniband device"); + n->logger->debug("Bound rdma_cm_id to Infiniband device"); - /* The ID will be overwritten for the target. If the event type is + /* The ID will be overwritten for the target. If the event type is * RDMA_CM_EVENT_CONNECT_REQUEST, >then this references a new id for * that communication. */ - ib->ctx.listen_id = ib->ctx.id; + ib->ctx.listen_id = ib->ctx.id; } -static -void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) -{ - auto *ib = n->getData(); - int ret; +static void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) { + auto *ib = n->getData(); + int ret; - if (ib->conn.use_fallback) - n->logger->warn("Trying to continue as listening node"); - else - throw RuntimeError("Cannot establish a connection with remote host! If you want that {} tries to " - "continue as listening node in such cases, set use_fallback = true in the configuration"); + if (ib->conn.use_fallback) + n->logger->warn("Trying to continue as listening node"); + else + throw RuntimeError("Cannot establish a connection with remote host! If you " + "want that {} tries to " + "continue as listening node in such cases, set " + "use_fallback = true in the configuration"); - n->setState(State::STARTED); + n->setState(State::STARTED); - // Acknowledge event - rdma_ack_cm_event(event); + // Acknowledge event + rdma_ack_cm_event(event); - // Destroy ID - rdma_destroy_id(ib->ctx.listen_id); + // Destroy ID + rdma_destroy_id(ib->ctx.listen_id); - // Create rdma_cm_id and bind to device - ib_create_bind_id(n); + // Create rdma_cm_id and bind to device + ib_create_bind_id(n); - // Listen to id for events - ret = rdma_listen(ib->ctx.listen_id, 10); - if (ret) - throw RuntimeError("Failed to listen to rdma_cm_id"); + // Listen to id for events + ret = rdma_listen(ib->ctx.listen_id, 10); + if (ret) + throw RuntimeError("Failed to listen to rdma_cm_id"); - // Node is not a source (and will not send data - ib->is_source = 0; + // Node is not a source (and will not send data + ib->is_source = 0; - n->logger->info("Use listening mode"); + n->logger->info("Use listening mode"); } -static -void * ib_rdma_cm_event_thread(void *ctx) -{ - auto *n = (NodeCompat *) ctx; - auto *ib = n->getData(); - struct rdma_cm_event *event; - int ret = 0; +static void *ib_rdma_cm_event_thread(void *ctx) { + auto *n = (NodeCompat *)ctx; + auto *ib = n->getData(); + struct rdma_cm_event *event; + int ret = 0; - n->logger->debug("Started rdma_cm_event thread"); + n->logger->debug("Started rdma_cm_event thread"); - // Wait until node is completely started - while (n->getState() != State::STARTED); + // Wait until node is completely started + while (n->getState() != State::STARTED) + ; - // Monitor event channel - while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { - n->logger->debug("Received communication event: {}", rdma_event_str(event->event)); + // Monitor event channel + while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { + n->logger->debug("Received communication event: {}", + rdma_event_str(event->event)); - switch(event->event) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - ret = ib_addr_resolved(n); - break; + switch (event->event) { + case RDMA_CM_EVENT_ADDR_RESOLVED: + ret = ib_addr_resolved(n); + break; - case RDMA_CM_EVENT_ADDR_ERROR: - n->logger->warn("Address resolution (rdma_resolve_addr) failed!"); + case RDMA_CM_EVENT_ADDR_ERROR: + n->logger->warn("Address resolution (rdma_resolve_addr) failed!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_ROUTE_RESOLVED: - ret = ib_route_resolved(n); - break; + case RDMA_CM_EVENT_ROUTE_RESOLVED: + ret = ib_route_resolved(n); + break; - case RDMA_CM_EVENT_ROUTE_ERROR: - n->logger->warn("Route resolution (rdma_resovle_route) failed!"); + case RDMA_CM_EVENT_ROUTE_ERROR: + n->logger->warn("Route resolution (rdma_resovle_route) failed!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_UNREACHABLE: - n->logger->warn("Remote server unreachable!"); + case RDMA_CM_EVENT_UNREACHABLE: + n->logger->warn("Remote server unreachable!"); - ib_continue_as_listen(n, event); - break; + ib_continue_as_listen(n, event); + break; - case RDMA_CM_EVENT_CONNECT_REQUEST: - ret = ib_connect_request(n, event->id); + case RDMA_CM_EVENT_CONNECT_REQUEST: + ret = ib_connect_request(n, event->id); - /* A target UDP node will never really connect. In order to receive data, + /* A target UDP node will never really connect. In order to receive data, * we set it to connected after it answered the connection request * with rdma_connect. */ - if (ib->conn.port_space == RDMA_PS_UDP && !ib->is_source) - n->setState(State::CONNECTED); - else - n->setState(State::PENDING_CONNECT); + if (ib->conn.port_space == RDMA_PS_UDP && !ib->is_source) + n->setState(State::CONNECTED); + else + n->setState(State::PENDING_CONNECT); - break; + break; - case RDMA_CM_EVENT_CONNECT_ERROR: - n->logger->warn("An error has occurred trying to establish a connection!"); + case RDMA_CM_EVENT_CONNECT_ERROR: + n->logger->warn( + "An error has occurred trying to establish a connection!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_REJECTED: - n->logger->warn("Connection request or response was rejected by the remote end point!"); + case RDMA_CM_EVENT_REJECTED: + n->logger->warn("Connection request or response was rejected by the " + "remote end point!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_ESTABLISHED: - // If the connection is unreliable connectionless, set appropriate variables - if (ib->conn.port_space == RDMA_PS_UDP) { - ib->conn.ud.ud = event->param.ud; - ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); - } + case RDMA_CM_EVENT_ESTABLISHED: + // If the connection is unreliable connectionless, set appropriate variables + if (ib->conn.port_space == RDMA_PS_UDP) { + ib->conn.ud.ud = event->param.ud; + ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); + } - n->setState(State::CONNECTED); + n->setState(State::CONNECTED); - n->logger->info("Connection established"); + n->logger->info("Connection established"); - break; + break; - case RDMA_CM_EVENT_DISCONNECTED: - n->setState(State::STARTED); + case RDMA_CM_EVENT_DISCONNECTED: + n->setState(State::STARTED); - ret = ib_disconnect(n); + ret = ib_disconnect(n); - if (!ret) - n->logger->info("Host disconnected. Ready to accept new connections."); + if (!ret) + n->logger->info("Host disconnected. Ready to accept new connections."); - break; + break; - case RDMA_CM_EVENT_TIMEWAIT_EXIT: - break; + case RDMA_CM_EVENT_TIMEWAIT_EXIT: + break; - default: - throw RuntimeError("Unknown event occurred: {}", event->event); - } + default: + throw RuntimeError("Unknown event occurred: {}", event->event); + } - rdma_ack_cm_event(event); + rdma_ack_cm_event(event); - if (ret) - break; - } + if (ret) + break; + } - return nullptr; + return nullptr; } -int villas::node::ib_start(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +int villas::node::ib_start(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Started ib_start"); + n->logger->debug("Started ib_start"); - // Create event channel - ib->ctx.ec = rdma_create_event_channel(); - if (!ib->ctx.ec) - throw RuntimeError("Failed to create event channel!"); + // Create event channel + ib->ctx.ec = rdma_create_event_channel(); + if (!ib->ctx.ec) + throw RuntimeError("Failed to create event channel!"); - n->logger->debug("Created event channel"); + n->logger->debug("Created event channel"); - // Create rdma_cm_id and bind to device - ib_create_bind_id(n); + // Create rdma_cm_id and bind to device + ib_create_bind_id(n); - n->logger->debug("Initialized Work Completion Buffer"); + n->logger->debug("Initialized Work Completion Buffer"); - // Resolve address or listen to rdma_cm_id - if (ib->is_source) { - // Resolve address - ret = rdma_resolve_addr(ib->ctx.id, nullptr, ib->conn.dst_addr->ai_addr, ib->conn.timeout); - if (ret) - throw RuntimeError("Failed to resolve remote address after {}ms: {}", ib->conn.timeout, gai_strerror(ret)); - } - else { - // Listen on rdma_cm_id for events - ret = rdma_listen(ib->ctx.listen_id, 10); - if (ret) - throw RuntimeError("Failed to listen to rdma_cm_id"); + // Resolve address or listen to rdma_cm_id + if (ib->is_source) { + // Resolve address + ret = rdma_resolve_addr(ib->ctx.id, nullptr, ib->conn.dst_addr->ai_addr, + ib->conn.timeout); + if (ret) + throw RuntimeError("Failed to resolve remote address after {}ms: {}", + ib->conn.timeout, gai_strerror(ret)); + } else { + // Listen on rdma_cm_id for events + ret = rdma_listen(ib->ctx.listen_id, 10); + if (ret) + throw RuntimeError("Failed to listen to rdma_cm_id"); - n->logger->debug("Started to listen to rdma_cm_id"); - } + n->logger->debug("Started to listen to rdma_cm_id"); + } - // Allocate protection domain - ib->ctx.pd = ibv_alloc_pd(ib->ctx.id->verbs); - if (!ib->ctx.pd) - throw RuntimeError("Could not allocate protection domain"); + // Allocate protection domain + ib->ctx.pd = ibv_alloc_pd(ib->ctx.id->verbs); + if (!ib->ctx.pd) + throw RuntimeError("Could not allocate protection domain"); - n->logger->debug("Allocated Protection Domain"); + n->logger->debug("Allocated Protection Domain"); - // Allocate space for 40 Byte GHR. We don't use this. - if (ib->conn.port_space == RDMA_PS_UDP) { - ib->conn.ud.grh_ptr = new char[GRH_SIZE]; - if (!ib->conn.ud.grh_ptr) - throw MemoryAllocationError(); + // Allocate space for 40 Byte GHR. We don't use this. + if (ib->conn.port_space == RDMA_PS_UDP) { + ib->conn.ud.grh_ptr = new char[GRH_SIZE]; + if (!ib->conn.ud.grh_ptr) + throw MemoryAllocationError(); - ib->conn.ud.grh_mr = ibv_reg_mr(ib->ctx.pd, ib->conn.ud.grh_ptr, GRH_SIZE, IBV_ACCESS_LOCAL_WRITE); - } + ib->conn.ud.grh_mr = ibv_reg_mr(ib->ctx.pd, ib->conn.ud.grh_ptr, GRH_SIZE, + IBV_ACCESS_LOCAL_WRITE); + } - /* Several events should occur on the event channel, to make + /* Several events should occur on the event channel, to make * sure the nodes are succesfully connected. */ - n->logger->debug("Starting to monitor events on rdma_cm_id"); + n->logger->debug("Starting to monitor events on rdma_cm_id"); - // Create thread to monitor rdma_cm_event channel - ret = pthread_create(&ib->conn.rdma_cm_event_thread, nullptr, ib_rdma_cm_event_thread, n); - if (ret) - throw RuntimeError("Failed to create thread to monitor rdma_cm events: {}", gai_strerror(ret)); + // Create thread to monitor rdma_cm_event channel + ret = pthread_create(&ib->conn.rdma_cm_event_thread, nullptr, + ib_rdma_cm_event_thread, n); + if (ret) + throw RuntimeError("Failed to create thread to monitor rdma_cm events: {}", + gai_strerror(ret)); - return 0; + return 0; } -int villas::node::ib_stop(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +int villas::node::ib_stop(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Called ib_stop"); + n->logger->debug("Called ib_stop"); - ib->stopThreads = 1; + ib->stopThreads = 1; - /* Call RDMA disconnect function + /* Call RDMA disconnect function * Will flush all outstanding WRs to the Completion Queue and * will call RDMA_CM_EVENT_DISCONNECTED if that is done. */ - if (n->getState() == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { - ret = rdma_disconnect(ib->ctx.id); + if (n->getState() == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { + ret = rdma_disconnect(ib->ctx.id); - if (ret) - throw RuntimeError("Error while calling rdma_disconnect: {}", gai_strerror(ret)); + if (ret) + throw RuntimeError("Error while calling rdma_disconnect: {}", + gai_strerror(ret)); - n->logger->debug("Called rdma_disconnect"); - } - else { - pthread_cancel(ib->conn.rdma_cm_event_thread); + n->logger->debug("Called rdma_disconnect"); + } else { + pthread_cancel(ib->conn.rdma_cm_event_thread); - n->logger->debug("Called pthread_cancel() on communication management thread."); - } + n->logger->debug( + "Called pthread_cancel() on communication management thread."); + } - n->logger->info("Disconnecting... Waiting for threads to join."); + n->logger->info("Disconnecting... Waiting for threads to join."); - // Wait for event thread to join - ret = pthread_join(ib->conn.rdma_cm_event_thread, nullptr); - if (ret) - throw RuntimeError("Error while joining rdma_cm_event_thread: {}", ret); + // Wait for event thread to join + ret = pthread_join(ib->conn.rdma_cm_event_thread, nullptr); + if (ret) + throw RuntimeError("Error while joining rdma_cm_event_thread: {}", ret); - n->logger->debug("Joined rdma_cm_event_thread"); + n->logger->debug("Joined rdma_cm_event_thread"); - // Destroy RDMA CM ID - rdma_destroy_id(ib->ctx.id); - n->logger->debug("Destroyed rdma_cm_id"); + // Destroy RDMA CM ID + rdma_destroy_id(ib->ctx.id); + n->logger->debug("Destroyed rdma_cm_id"); - // Dealloc Protection Domain - ibv_dealloc_pd(ib->ctx.pd); - n->logger->debug("Destroyed protection domain"); + // Dealloc Protection Domain + ibv_dealloc_pd(ib->ctx.pd); + n->logger->debug("Destroyed protection domain"); - // Destroy event channel - rdma_destroy_event_channel(ib->ctx.ec); - n->logger->debug("Destroyed event channel"); + // Destroy event channel + rdma_destroy_event_channel(ib->ctx.ec); + n->logger->debug("Destroyed event channel"); - n->logger->info("Successfully stopped node"); + n->logger->info("Successfully stopped node"); - return 0; + return 0; } -int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *ib = n->getData(); - struct ibv_wc wc[cnt]; - struct ibv_recv_wr wr[cnt], *bad_wr = nullptr; - struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; - struct ibv_mr *mr; - struct timespec ts_receive; - int ret = 0, wcs = 0, read_values = 0, max_wr_post; +int villas::node::ib_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *ib = n->getData(); + struct ibv_wc wc[cnt]; + struct ibv_recv_wr wr[cnt], *bad_wr = nullptr; + struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; + struct ibv_mr *mr; + struct timespec ts_receive; + int ret = 0, wcs = 0, read_values = 0, max_wr_post; - n->logger->debug("ib_read is called"); + n->logger->debug("ib_read is called"); - if (n->getState() == State::CONNECTED || n->getState() == State::PENDING_CONNECT) { + if (n->getState() == State::CONNECTED || + n->getState() == State::PENDING_CONNECT) { - max_wr_post = cnt; + max_wr_post = cnt; - /* Poll Completion Queue + /* Poll Completion Queue * If we've already posted enough receive WRs, try to pull cnt */ - if (ib->conn.available_recv_wrs >= (ib->qp_init.cap.max_recv_wr - ib->conn.buffer_subtraction) ) { - for (int i = 0; ; i++) { - if (i % CHK_PER_ITER == CHK_PER_ITER - 1) pthread_testcancel(); + if (ib->conn.available_recv_wrs >= + (ib->qp_init.cap.max_recv_wr - ib->conn.buffer_subtraction)) { + for (int i = 0;; i++) { + if (i % CHK_PER_ITER == CHK_PER_ITER - 1) + pthread_testcancel(); - /* If IB node disconnects or if it is still in State::PENDING_CONNECT, ib_read + /* If IB node disconnects or if it is still in State::PENDING_CONNECT, ib_read * should return immediately if this condition holds */ - if (n->getState() != State::CONNECTED) return 0; + if (n->getState() != State::CONNECTED) + return 0; - wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); - if (wcs) { - // Get time directly after something arrived in Completion Queue - ts_receive = time_now(); + wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); + if (wcs) { + // Get time directly after something arrived in Completion Queue + ts_receive = time_now(); - n->logger->debug("Received {} Work Completions", wcs); + n->logger->debug("Received {} Work Completions", wcs); - read_values = wcs; // Value to return - max_wr_post = wcs; // Make space free in smps[] + read_values = wcs; // Value to return + max_wr_post = wcs; // Make space free in smps[] - break; - } - } + break; + } + } - /* All samples (wcs * received + unposted) should be released. Let + /* All samples (wcs * received + unposted) should be released. Let * *release be equal to allocated. * * This is set in the framework, before this function was called. */ - } - else { - ib->conn.available_recv_wrs += max_wr_post; + } else { + ib->conn.available_recv_wrs += max_wr_post; - // TODO: fix release logic - // *release = 0; // While we fill the receive queue, we always use all samples - } + // TODO: fix release logic + // *release = 0; // While we fill the receive queue, we always use all samples + } - // Get Memory Region - mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); + // Get Memory Region + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); - for (int i = 0; i < max_wr_post; i++) { - int j = 0; + for (int i = 0; i < max_wr_post; i++) { + int j = 0; - // Prepare receive Scatter/Gather element + // Prepare receive Scatter/Gather element - // First 40 byte of UD data are GRH and unused in our case - if (ib->conn.port_space == RDMA_PS_UDP) { - sge[i][j].addr = (uint64_t) ib->conn.ud.grh_ptr; - sge[i][j].length = GRH_SIZE; - sge[i][j].lkey = ib->conn.ud.grh_mr->lkey; + // First 40 byte of UD data are GRH and unused in our case + if (ib->conn.port_space == RDMA_PS_UDP) { + sge[i][j].addr = (uint64_t)ib->conn.ud.grh_ptr; + sge[i][j].length = GRH_SIZE; + sge[i][j].lkey = ib->conn.ud.grh_mr->lkey; - j++; - } + j++; + } - // Sequence - sge[i][j].addr = (uint64_t) &smps[i]->sequence; - sge[i][j].length = sizeof(smps[i]->sequence); - sge[i][j].lkey = mr->lkey; + // Sequence + sge[i][j].addr = (uint64_t)&smps[i]->sequence; + sge[i][j].length = sizeof(smps[i]->sequence); + sge[i][j].lkey = mr->lkey; - j++; + j++; - // Timespec origin - sge[i][j].addr = (uint64_t) &smps[i]->ts.origin; - sge[i][j].length = sizeof(smps[i]->ts.origin); - sge[i][j].lkey = mr->lkey; + // Timespec origin + sge[i][j].addr = (uint64_t)&smps[i]->ts.origin; + sge[i][j].length = sizeof(smps[i]->ts.origin); + sge[i][j].lkey = mr->lkey; - j++; + j++; - sge[i][j].addr = (uint64_t) &smps[i]->data; - sge[i][j].length = SAMPLE_DATA_LENGTH(DEFAULT_SAMPLE_LENGTH); - sge[i][j].lkey = mr->lkey; + sge[i][j].addr = (uint64_t)&smps[i]->data; + sge[i][j].length = SAMPLE_DATA_LENGTH(DEFAULT_SAMPLE_LENGTH); + sge[i][j].lkey = mr->lkey; - j++; + j++; - // Prepare a receive Work Request - wr[i].wr_id = (uintptr_t) smps[i]; - wr[i].next = &wr[i+1]; - wr[i].sg_list = sge[i]; - wr[i].num_sge = j; - } + // Prepare a receive Work Request + wr[i].wr_id = (uintptr_t)smps[i]; + wr[i].next = &wr[i + 1]; + wr[i].sg_list = sge[i]; + wr[i].num_sge = j; + } - wr[max_wr_post-1].next = nullptr; + wr[max_wr_post - 1].next = nullptr; - n->logger->debug("Prepared {} new receive Work Requests", max_wr_post); - n->logger->debug("{} receive Work Requests in Receive Queue", ib->conn.available_recv_wrs); + n->logger->debug("Prepared {} new receive Work Requests", max_wr_post); + n->logger->debug("{} receive Work Requests in Receive Queue", + ib->conn.available_recv_wrs); - // Post list of Work Requests - ret = ibv_post_recv(ib->ctx.id->qp, &wr[0], &bad_wr); - if (ret) - throw RuntimeError("Was unable to post receive WR: {}, bad WR ID: {:#x}", ret, bad_wr->wr_id); + // Post list of Work Requests + ret = ibv_post_recv(ib->ctx.id->qp, &wr[0], &bad_wr); + if (ret) + throw RuntimeError("Was unable to post receive WR: {}, bad WR ID: {:#x}", + ret, bad_wr->wr_id); - n->logger->debug("Succesfully posted receive Work Requests"); + n->logger->debug("Succesfully posted receive Work Requests"); - // Doesn't start if wcs == 0 - for (int j = 0; j < wcs; j++) { - if ( !( (wc[j].opcode & IBV_WC_RECV) && wc[j].status == IBV_WC_SUCCESS) ) { - // Drop all values, we don't know where the error occured - read_values = 0; - } + // Doesn't start if wcs == 0 + for (int j = 0; j < wcs; j++) { + if (!((wc[j].opcode & IBV_WC_RECV) && wc[j].status == IBV_WC_SUCCESS)) { + // Drop all values, we don't know where the error occured + read_values = 0; + } - if (wc[j].status == IBV_WC_WR_FLUSH_ERR) - n->logger->debug("Received IBV_WC_WR_FLUSH_ERR (ib_read). Ignore it."); - else if (wc[j].status != IBV_WC_SUCCESS) - n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[j].status); + if (wc[j].status == IBV_WC_WR_FLUSH_ERR) + n->logger->debug("Received IBV_WC_WR_FLUSH_ERR (ib_read). Ignore it."); + else if (wc[j].status != IBV_WC_SUCCESS) + n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", + wc[j].status); - /* 32 byte of meta data is always transferred. We should substract it. + /* 32 byte of meta data is always transferred. We should substract it. * Furthermore, in case of an unreliable connection, a 40 byte * global routing header is transferred. This should be substracted as well. */ - int correction = (ib->conn.port_space == RDMA_PS_UDP) ? META_GRH_SIZE : META_SIZE; + int correction = + (ib->conn.port_space == RDMA_PS_UDP) ? META_GRH_SIZE : META_SIZE; - // TODO: fix release logic - // smps[j] = (struct Sample *) (wc[j].wr_id); + // TODO: fix release logic + // smps[j] = (struct Sample *) (wc[j].wr_id); - smps[j]->length = SAMPLE_NUMBER_OF_VALUES(wc[j].byte_len - correction); - smps[j]->ts.received = ts_receive; - smps[j]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_TS_RECEIVED | (int) SampleFlags::HAS_SEQUENCE; - smps[j]->signals = n->getInputSignals(false); - } - - } - return read_values; + smps[j]->length = SAMPLE_NUMBER_OF_VALUES(wc[j].byte_len - correction); + smps[j]->ts.received = ts_receive; + smps[j]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_TS_RECEIVED | + (int)SampleFlags::HAS_SEQUENCE; + smps[j]->signals = n->getInputSignals(false); + } + } + return read_values; } -int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *ib = n->getData(); - struct ibv_send_wr wr[cnt], *bad_wr = nullptr; - struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; - struct ibv_wc wc[cnt]; - struct ibv_mr *mr; +int villas::node::ib_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *ib = n->getData(); + struct ibv_send_wr wr[cnt], *bad_wr = nullptr; + struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; + struct ibv_wc wc[cnt]; + struct ibv_mr *mr; - int ret; - unsigned sent = 0; // Used for first loop: prepare work requests to post to send queue + int ret; + unsigned sent = + 0; // Used for first loop: prepare work requests to post to send queue - n->logger->debug("ib_write is called"); + n->logger->debug("ib_write is called"); - if (n->getState() == State::CONNECTED) { - // TODO: fix release logic - // *release = 0; + if (n->getState() == State::CONNECTED) { + // TODO: fix release logic + // *release = 0; - // First, write + // First, write - // Get Memory Region - mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); + // Get Memory Region + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); - for (sent = 0; sent < cnt; sent++) { - int j = 0; + for (sent = 0; sent < cnt; sent++) { + int j = 0; - // Set Scatter/Gather element to data of sample + // Set Scatter/Gather element to data of sample - // Sequence - sge[sent][j].addr = (uint64_t) &smps[sent]->sequence; - sge[sent][j].length = sizeof(smps[sent]->sequence); - sge[sent][j].lkey = mr->lkey; + // Sequence + sge[sent][j].addr = (uint64_t)&smps[sent]->sequence; + sge[sent][j].length = sizeof(smps[sent]->sequence); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Timespec origin - sge[sent][j].addr = (uint64_t) &smps[sent]->ts.origin; - sge[sent][j].length = sizeof(smps[sent]->ts.origin); - sge[sent][j].lkey = mr->lkey; + // Timespec origin + sge[sent][j].addr = (uint64_t)&smps[sent]->ts.origin; + sge[sent][j].length = sizeof(smps[sent]->ts.origin); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Actual Payload - sge[sent][j].addr = (uint64_t) &smps[sent]->data; - sge[sent][j].length = SAMPLE_DATA_LENGTH(smps[sent]->length); - sge[sent][j].lkey = mr->lkey; + // Actual Payload + sge[sent][j].addr = (uint64_t)&smps[sent]->data; + sge[sent][j].length = SAMPLE_DATA_LENGTH(smps[sent]->length); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Check if connection is connected or unconnected and set appropriate values - if (ib->conn.port_space == RDMA_PS_UDP) { - wr[sent].wr.ud.ah = ib->conn.ud.ah; - wr[sent].wr.ud.remote_qkey = ib->conn.ud.ud.qkey; - wr[sent].wr.ud.remote_qpn = ib->conn.ud.ud.qp_num; - } + // Check if connection is connected or unconnected and set appropriate values + if (ib->conn.port_space == RDMA_PS_UDP) { + wr[sent].wr.ud.ah = ib->conn.ud.ah; + wr[sent].wr.ud.remote_qkey = ib->conn.ud.ud.qkey; + wr[sent].wr.ud.remote_qpn = ib->conn.ud.ud.qp_num; + } - /* Check if data can be send inline + /* Check if data can be send inline * 32 byte meta data is always send. * Once every max_send_wr iterations a signal must be generated. Since we would need * an additional buffer if we were sending inlines with IBV_SEND_SIGNALED, we prefer * to send one samples every max_send_wr NOT inline (which thus generates a signal). */ - int send_inline = ((sge[sent][j-1].length + META_SIZE) < ib->qp_init.cap.max_inline_data) - && ((++ib->signaling_counter % ib->periodic_signaling) != 0) ? - ib->conn.send_inline : 0; + int send_inline = + ((sge[sent][j - 1].length + META_SIZE) < + ib->qp_init.cap.max_inline_data) && + ((++ib->signaling_counter % ib->periodic_signaling) != 0) + ? ib->conn.send_inline + : 0; - n->logger->debug("Sample will be send inline [0/1]: {}", send_inline); + n->logger->debug("Sample will be send inline [0/1]: {}", send_inline); - // Set Send Work Request - wr[sent].wr_id = (uintptr_t) smps[sent]; - wr[sent].sg_list = sge[sent]; - wr[sent].num_sge = j; - wr[sent].next = &wr[sent+1]; + // Set Send Work Request + wr[sent].wr_id = (uintptr_t)smps[sent]; + wr[sent].sg_list = sge[sent]; + wr[sent].num_sge = j; + wr[sent].next = &wr[sent + 1]; - wr[sent].send_flags = send_inline ? IBV_SEND_INLINE : IBV_SEND_SIGNALED; - wr[sent].opcode = IBV_WR_SEND; - } + wr[sent].send_flags = send_inline ? IBV_SEND_INLINE : IBV_SEND_SIGNALED; + wr[sent].opcode = IBV_WR_SEND; + } - n->logger->debug("Prepared {} send Work Requests", cnt); - wr[cnt-1].next = nullptr; + n->logger->debug("Prepared {} send Work Requests", cnt); + wr[cnt - 1].next = nullptr; - // Send linked list of Work Requests - ret = ibv_post_send(ib->ctx.id->qp, wr, &bad_wr); - n->logger->debug("Posted send Work Requests"); + // Send linked list of Work Requests + ret = ibv_post_send(ib->ctx.id->qp, wr, &bad_wr); + n->logger->debug("Posted send Work Requests"); - /* Reorder list. Place inline and unposted samples to the top + /* Reorder list. Place inline and unposted samples to the top * m will always be equal or smaller than *release */ - for (unsigned m = 0; m < cnt; m++) { - /* We can't use wr_id as identifier, since it is 0 for inline + for (unsigned m = 0; m < cnt; m++) { + /* We can't use wr_id as identifier, since it is 0 for inline * elements */ - if (ret && (wr[m].sg_list == bad_wr->sg_list)) { - /* The remaining work requests will be bad. Ripple through list + if (ret && (wr[m].sg_list == bad_wr->sg_list)) { + /* The remaining work requests will be bad. Ripple through list * and prepare them to be released */ - n->logger->debug("Bad WR occured with ID: {:#x} and S/G address: {:#x}: {}", - bad_wr->wr_id, (void *) bad_wr->sg_list, ret); + n->logger->debug( + "Bad WR occured with ID: {:#x} and S/G address: {:#x}: {}", + bad_wr->wr_id, (void *)bad_wr->sg_list, ret); - while (1) { - // TODO: fix release logic - // smps[*release] = smps[m]; - // (*release)++; // Increment number of samples to be released - sent--; // Decrement the number of successfully posted elements + while (1) { + // TODO: fix release logic + // smps[*release] = smps[m]; + // (*release)++; // Increment number of samples to be released + sent--; // Decrement the number of successfully posted elements - if (++m == cnt) break; - } - } - else if (wr[m].send_flags & IBV_SEND_INLINE) { - // TODO: fix release logic - // smps[*release] = smps[m]; - // (*release)++; - } - } + if (++m == cnt) + break; + } + } else if (wr[m].send_flags & IBV_SEND_INLINE) { + // TODO: fix release logic + // smps[*release] = smps[m]; + // (*release)++; + } + } - // TODO: fix release logic - // n->logger->debug("{} samples will be released (before WC)", *release); + // TODO: fix release logic + // n->logger->debug("{} samples will be released (before WC)", *release); - // Try to grab as many CQEs from CQ as there is space in *smps[] - // ret = ibv_poll_cq(ib->ctx.send_cq, cnt - *release, wc); + // Try to grab as many CQEs from CQ as there is space in *smps[] + // ret = ibv_poll_cq(ib->ctx.send_cq, cnt - *release, wc); - for (int i = 0; i < ret; i++) { - if (wc[i].status != IBV_WC_SUCCESS && wc[i].status != IBV_WC_WR_FLUSH_ERR) - n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[i].status); + for (int i = 0; i < ret; i++) { + if (wc[i].status != IBV_WC_SUCCESS && wc[i].status != IBV_WC_WR_FLUSH_ERR) + n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", + wc[i].status); - // TODO: fix release logic - // smps[*release] = (struct Sample *) (wc[i].wr_id); - // (*release)++; - } + // TODO: fix release logic + // smps[*release] = (struct Sample *) (wc[i].wr_id); + // (*release)++; + } - // TODO: fix release logic - // n->logger->debug("{} samples will be released (after WC)", *release); - } + // TODO: fix release logic + // n->logger->debug("{} samples will be released (after WC)", *release); + } - return sent; + return sent; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "infiniband"; - p.description = "Infiniband interface (libibverbs, librdmacm)"; - p.vectorize = 0; - p.size = sizeof(struct infiniband); - // TODO: fix - // p.pool_size = 8192; - p.destroy = ib_destroy; - p.parse = ib_parse; - p.check = ib_check; - p.print = ib_print; - p.start = ib_start; - p.stop = ib_stop; - p.read = ib_read; - p.write = ib_write; - p.reverse = ib_reverse; - p.memory_type = memory::ib; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "infiniband"; + p.description = "Infiniband interface (libibverbs, librdmacm)"; + p.vectorize = 0; + p.size = sizeof(struct infiniband); + // TODO: fix + // p.pool_size = 8192; + p.destroy = ib_destroy; + p.parse = ib_parse; + p.check = ib_check; + p.print = ib_print; + p.start = ib_start; + p.stop = ib_stop; + p.read = ib_read; + p.write = ib_write; + p.reverse = ib_reverse; + p.memory_type = memory::ib; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/influxdb.cpp b/lib/nodes/influxdb.cpp index 7080f56bb..8e357df9d 100644 --- a/lib/nodes/influxdb.cpp +++ b/lib/nodes/influxdb.cpp @@ -5,207 +5,193 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include +#include #include +#include +#include -#include -#include +#include #include +#include #include #include -#include +#include +#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::influxdb_parse(NodeCompat *n, json_t *json) -{ - auto *i = n->getData(); +int villas::node::influxdb_parse(NodeCompat *n, json_t *json) { + auto *i = n->getData(); - json_error_t err; - int ret; + json_error_t err; + int ret; - char *tmp, *host, *port, *lasts; - const char *server, *key; + char *tmp, *host, *port, *lasts; + const char *server, *key; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s }", - "server", &server, - "key", &key - ); - if (ret) - throw ConfigError(json, err, "node-config-node-influx"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s }", "server", &server, + "key", &key); + if (ret) + throw ConfigError(json, err, "node-config-node-influx"); - tmp = strdup(server); + tmp = strdup(server); - host = strtok_r(tmp, ":", &lasts); - port = strtok_r(nullptr, "", &lasts); + host = strtok_r(tmp, ":", &lasts); + port = strtok_r(nullptr, "", &lasts); - i->key = strdup(key); - i->host = strdup(host); - i->port = strdup(port ? port : "8089"); + i->key = strdup(key); + i->host = strdup(host); + i->port = strdup(port ? port : "8089"); - free(tmp); + free(tmp); - return 0; + return 0; } -int villas::node::influxdb_open(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::influxdb_open(NodeCompat *n) { + int ret; + auto *i = n->getData(); - struct addrinfo hints, *servinfo, *p; + struct addrinfo hints, *servinfo, *p; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; - ret = getaddrinfo(i->host, i->port, &hints, &servinfo); - if (ret) - throw RuntimeError("Failed to lookup server: {}", gai_strerror(ret)); + ret = getaddrinfo(i->host, i->port, &hints, &servinfo); + if (ret) + throw RuntimeError("Failed to lookup server: {}", gai_strerror(ret)); - // Loop through all the results and connect to the first we can - for (p = servinfo; p != nullptr; p = p->ai_next) { - i->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (i->sd == -1) - throw SystemError("Failed to create socket"); + // Loop through all the results and connect to the first we can + for (p = servinfo; p != nullptr; p = p->ai_next) { + i->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (i->sd == -1) + throw SystemError("Failed to create socket"); - ret = connect(i->sd, p->ai_addr, p->ai_addrlen); - if (ret == -1) { - n->logger->warn("Connect failed: {}", strerror(errno)); - close(i->sd); - continue; - } + ret = connect(i->sd, p->ai_addr, p->ai_addrlen); + if (ret == -1) { + n->logger->warn("Connect failed: {}", strerror(errno)); + close(i->sd); + continue; + } - // If we get here, we must have connected successfully - break; - } + // If we get here, we must have connected successfully + break; + } - return p ? 0 : -1; + return p ? 0 : -1; } -int villas::node::influxdb_close(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::influxdb_close(NodeCompat *n) { + auto *i = n->getData(); - close(i->sd); + close(i->sd); - if (i->host) - free(i->host); - if (i->port) - free(i->port); - if (i->key) - free(i->key); + if (i->host) + free(i->host); + if (i->port) + free(i->port); + if (i->key) + free(i->key); - return 0; + return 0; } -int villas::node::influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); +int villas::node::influxdb_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); - char *buf = strf(""); - ssize_t sentlen, buflen; + char *buf = strf(""); + ssize_t sentlen, buflen; - for (unsigned k = 0; k < cnt; k++) { - const struct Sample *smp = smps[k]; + for (unsigned k = 0; k < cnt; k++) { + const struct Sample *smp = smps[k]; - // Key - strcatf(&buf, "%s", i->key); + // Key + strcatf(&buf, "%s", i->key); - // Fields - for (unsigned j = 0; j < smp->length; j++) { - const auto *data = &smp->data[j]; - auto sig = smp->signals->getByIndex(j); - if (!sig) - return -1; + // Fields + for (unsigned j = 0; j < smp->length; j++) { + const auto *data = &smp->data[j]; + auto sig = smp->signals->getByIndex(j); + if (!sig) + return -1; - if ( - sig->type != SignalType::BOOLEAN && - sig->type != SignalType::FLOAT && - sig->type != SignalType::INTEGER && - sig->type != SignalType::COMPLEX - ) { - n->logger->warn("Unsupported signal format. Skipping"); - continue; - } + if (sig->type != SignalType::BOOLEAN && sig->type != SignalType::FLOAT && + sig->type != SignalType::INTEGER && + sig->type != SignalType::COMPLEX) { + n->logger->warn("Unsupported signal format. Skipping"); + continue; + } - strcatf(&buf, "%c", j == 0 ? ' ' : ','); - if (sig->type == SignalType::COMPLEX) { - strcatf(&buf, "%s_re=%f, %s_im=%f", - sig->name.c_str(), std::real(data->z), - sig->name.c_str(), std::imag(data->z) - ); - } - else { - strcatf(&buf, "%s=", sig->name.c_str()); + strcatf(&buf, "%c", j == 0 ? ' ' : ','); + if (sig->type == SignalType::COMPLEX) { + strcatf(&buf, "%s_re=%f, %s_im=%f", sig->name.c_str(), + std::real(data->z), sig->name.c_str(), std::imag(data->z)); + } else { + strcatf(&buf, "%s=", sig->name.c_str()); - switch (sig->type) { - case SignalType::BOOLEAN: - strcatf(&buf, "%s", data->b ? "true" : "false"); - break; + switch (sig->type) { + case SignalType::BOOLEAN: + strcatf(&buf, "%s", data->b ? "true" : "false"); + break; - case SignalType::FLOAT: - strcatf(&buf, "%f", data->f); - break; + case SignalType::FLOAT: + strcatf(&buf, "%f", data->f); + break; - case SignalType::INTEGER: - strcatf(&buf, "%" PRIi64, data->i); - break; + case SignalType::INTEGER: + strcatf(&buf, "%" PRIi64, data->i); + break; - default: { } - } - } - } + default: { + } + } + } + } - // Timestamp - strcatf(&buf, " %lld%09lld\n", (long long) smp->ts.origin.tv_sec, - (long long) smp->ts.origin.tv_nsec); - } + // Timestamp + strcatf(&buf, " %lld%09lld\n", (long long)smp->ts.origin.tv_sec, + (long long)smp->ts.origin.tv_nsec); + } - buflen = strlen(buf) + 1; - sentlen = send(i->sd, buf, buflen, 0); - if (sentlen < 0) - return -1; - else if (sentlen < buflen) - n->logger->warn("Partial sent"); + buflen = strlen(buf) + 1; + sentlen = send(i->sd, buf, buflen, 0); + if (sentlen < 0) + return -1; + else if (sentlen < buflen) + n->logger->warn("Partial sent"); - free(buf); + free(buf); - return cnt; + return cnt; } -char * villas::node::influxdb_print(NodeCompat *n) -{ - auto *i = n->getData(); - char *buf = nullptr; +char *villas::node::influxdb_print(NodeCompat *n) { + auto *i = n->getData(); + char *buf = nullptr; - strcatf(&buf, "host=%s, port=%s, key=%s", i->host, i->port, i->key); + strcatf(&buf, "host=%s, port=%s, key=%s", i->host, i->port, i->key); - return buf; + return buf; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "influxdb"; - p.description = "Write results to InfluxDB"; - p.vectorize = 0; - p.size = sizeof(struct influxdb); - p.parse = influxdb_parse; - p.print = influxdb_print; - p.start = influxdb_open; - p.stop = influxdb_close; - p.write = influxdb_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "influxdb"; + p.description = "Write results to InfluxDB"; + p.vectorize = 0; + p.size = sizeof(struct influxdb); + p.parse = influxdb_parse; + p.print = influxdb_print; + p.start = influxdb_open; + p.stop = influxdb_close; + p.write = influxdb_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/kafka.cpp b/lib/nodes/kafka.cpp index 710de5fec..5eaccfaab 100644 --- a/lib/nodes/kafka.cpp +++ b/lib/nodes/kafka.cpp @@ -6,599 +6,594 @@ */ #include -#include #include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Each process has a list of clients for which a thread invokes the kafka loop -static -struct List clients; -static -pthread_t thread; -static -Logger logger; +static struct List clients; +static pthread_t thread; +static Logger logger; -static -void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, const char *buf) -{ +static void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, + const char *buf) { - switch (level) { - case LOG_EMERG: - case LOG_CRIT: - case LOG_ERR: - logger->error("{}: {}", fac, buf); - break; + switch (level) { + case LOG_EMERG: + case LOG_CRIT: + case LOG_ERR: + logger->error("{}: {}", fac, buf); + break; - case LOG_ALERT: - case LOG_WARNING: - logger->warn("{}: {}", fac, buf); - break; + case LOG_ALERT: + case LOG_WARNING: + logger->warn("{}: {}", fac, buf); + break; - case LOG_DEBUG: - logger->debug("{}: {}", fac, buf); - break; + case LOG_DEBUG: + logger->debug("{}: {}", fac, buf); + break; - case LOG_NOTICE: - case LOG_INFO: - default: - logger->info("{}: {}", fac, buf); - break; - } + case LOG_NOTICE: + case LOG_INFO: + default: + logger->info("{}: {}", fac, buf); + break; + } } -static -void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) -{ - int ret; - auto *n = (NodeCompat *) ctx; - auto *k = n->getData(); - struct Sample *smps[n->in.vectorize]; +static void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) { + int ret; + auto *n = (NodeCompat *)ctx; + auto *k = n->getData(); + struct Sample *smps[n->in.vectorize]; - n->logger->debug("Received a message of {} bytes from broker {}", msg->len, k->server); + n->logger->debug("Received a message of {} bytes from broker {}", msg->len, + k->server); - ret = sample_alloc_many(&k->pool, smps, n->in.vectorize); - if (ret <= 0) { - n->logger->warn("Pool underrun in consumer"); - return; - } + ret = sample_alloc_many(&k->pool, smps, n->in.vectorize); + if (ret <= 0) { + n->logger->warn("Pool underrun in consumer"); + return; + } - ret = k->formatter->sscan((char *) msg->payload, msg->len, nullptr, smps, n->in.vectorize); - if (ret < 0) { - n->logger->warn("Received an invalid message"); - n->logger->warn(" Payload: {}", (char *) msg->payload); - return; - } + ret = k->formatter->sscan((char *)msg->payload, msg->len, nullptr, smps, + n->in.vectorize); + if (ret < 0) { + n->logger->warn("Received an invalid message"); + n->logger->warn(" Payload: {}", (char *)msg->payload); + return; + } - if (ret == 0) { - n->logger->debug("Skip empty message"); - sample_decref_many(smps, n->in.vectorize); - return; - } + if (ret == 0) { + n->logger->debug("Skip empty message"); + sample_decref_many(smps, n->in.vectorize); + return; + } - ret = queue_signalled_push_many(&k->queue, (void **) smps, n->in.vectorize); - if (ret < (int) n->in.vectorize) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push_many(&k->queue, (void **)smps, n->in.vectorize); + if (ret < (int)n->in.vectorize) + n->logger->warn("Failed to enqueue samples"); } -static -void * kafka_loop_thread(void *ctx) -{ - int ret; +static void *kafka_loop_thread(void *ctx) { + int ret; - // Set the cancel type of this thread to async - ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr); - if (ret != 0) - throw RuntimeError("Unable to set cancel type of Kafka communication thread to asynchronous."); + // Set the cancel type of this thread to async + ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr); + if (ret != 0) + throw RuntimeError("Unable to set cancel type of Kafka communication " + "thread to asynchronous."); - while (true) { - for (unsigned i = 0; i < list_length(&clients); i++) { - auto *n = (NodeCompat *) list_at(&clients, i); - auto *k = n->getData(); + while (true) { + for (unsigned i = 0; i < list_length(&clients); i++) { + auto *n = (NodeCompat *)list_at(&clients, i); + auto *k = n->getData(); - // Execute kafka loop for this client - if (k->consumer.client) { - rd_kafka_message_t *msg = rd_kafka_consumer_poll(k->consumer.client, k->timeout * 1000); - if (msg) { - kafka_message_cb((void *) n, msg); - rd_kafka_message_destroy(msg); - } - } - } - } + // Execute kafka loop for this client + if (k->consumer.client) { + rd_kafka_message_t *msg = + rd_kafka_consumer_poll(k->consumer.client, k->timeout * 1000); + if (msg) { + kafka_message_cb((void *)n, msg); + rd_kafka_message_destroy(msg); + } + } + } + } - return nullptr; + return nullptr; } -int villas::node::kafka_reverse(NodeCompat *n) -{ - auto *k = n->getData(); +int villas::node::kafka_reverse(NodeCompat *n) { + auto *k = n->getData(); - SWAP(k->produce, k->consume); + SWAP(k->produce, k->consume); - return 0; + return 0; } -int villas::node::kafka_init(NodeCompat *n) -{ - auto *k = n->getData(); +int villas::node::kafka_init(NodeCompat *n) { + auto *k = n->getData(); - // Default values - k->server = nullptr; - k->protocol = nullptr; - k->produce = nullptr; - k->consume = nullptr; - k->client_id = nullptr; - k->timeout = 1.0; + // Default values + k->server = nullptr; + k->protocol = nullptr; + k->produce = nullptr; + k->consume = nullptr; + k->client_id = nullptr; + k->timeout = 1.0; - k->consumer.client = nullptr; - k->consumer.group_id = nullptr; - k->producer.client = nullptr; - k->producer.topic = nullptr; + k->consumer.client = nullptr; + k->consumer.group_id = nullptr; + k->producer.client = nullptr; + k->producer.topic = nullptr; - k->sasl.mechanisms = nullptr; - k->sasl.username = nullptr; - k->sasl.password = nullptr; + k->sasl.mechanisms = nullptr; + k->sasl.username = nullptr; + k->sasl.password = nullptr; - k->ssl.ca = nullptr; + k->ssl.ca = nullptr; - k->formatter = nullptr; + k->formatter = nullptr; - return 0; + return 0; } -int villas::node::kafka_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_parse(NodeCompat *n, json_t *json) { + int ret; + auto *k = n->getData(); - const char *server; - const char *produce = nullptr; - const char *consume = nullptr; - const char *protocol; - const char *client_id = "villas-node"; - const char *group_id = nullptr; + const char *server; + const char *produce = nullptr; + const char *consume = nullptr; + const char *protocol; + const char *client_id = "villas-node"; + const char *group_id = nullptr; - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_sasl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_sasl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: s }, s?: { s?: s, s?: s }, s?: o, s: s, s?: F, s: s, s?: s, s?: o, s?: o }", - "out", - "produce", &produce, - "in", - "consume", &consume, - "group_id", &group_id, - "format", &json_format, - "server", &server, - "timeout", &k->timeout, - "protocol", &protocol, - "client_id", &client_id, - "ssl", &json_ssl, - "sasl", &json_sasl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-kafka"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: s }, s?: { s?: s, s?: s }, s?: o, s: s, " + "s?: F, s: s, s?: s, s?: o, s?: o }", + "out", "produce", &produce, "in", "consume", &consume, + "group_id", &group_id, "format", &json_format, "server", + &server, "timeout", &k->timeout, "protocol", &protocol, + "client_id", &client_id, "ssl", &json_ssl, "sasl", + &json_sasl); + if (ret) + throw ConfigError(json, err, "node-config-node-kafka"); - k->server = strdup(server); - k->produce = produce ? strdup(produce) : nullptr; - k->consume = consume ? strdup(consume) : nullptr; - k->protocol = strdup(protocol); - k->client_id = strdup(client_id); - k->consumer.group_id = group_id ? strdup(group_id) : nullptr; + k->server = strdup(server); + k->produce = produce ? strdup(produce) : nullptr; + k->consume = consume ? strdup(consume) : nullptr; + k->protocol = strdup(protocol); + k->client_id = strdup(client_id); + k->consumer.group_id = group_id ? strdup(group_id) : nullptr; - if (strcmp(protocol, "SSL") && - strcmp(protocol, "PLAINTEXT") && - strcmp(protocol, "SASL_SSL") && - strcmp(protocol, "SASL_PLAINTEXT")) - throw ConfigError(json, "node-config-node-kafka-protocol", "Invalid security protocol: {}", protocol); + if (strcmp(protocol, "SSL") && strcmp(protocol, "PLAINTEXT") && + strcmp(protocol, "SASL_SSL") && strcmp(protocol, "SASL_PLAINTEXT")) + throw ConfigError(json, "node-config-node-kafka-protocol", + "Invalid security protocol: {}", protocol); - if (!k->produce && !k->consume) - throw ConfigError(json, "node-config-node-kafka", "At least one topic has to be specified for node {}", n->getName()); + if (!k->produce && !k->consume) + throw ConfigError(json, "node-config-node-kafka", + "At least one topic has to be specified for node {}", + n->getName()); - if (json_ssl) { - const char *ca; + if (json_ssl) { + const char *ca; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s: s }", - "ca", &ca - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-kafka-ssl", "Failed to parse SSL configuration of node {}", n->getName()); + ret = json_unpack_ex(json_ssl, &err, 0, "{ s: s }", "ca", &ca); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-kafka-ssl", + "Failed to parse SSL configuration of node {}", + n->getName()); - k->ssl.ca = strdup(ca); - } + k->ssl.ca = strdup(ca); + } - if (json_sasl) { - const char *mechanisms; - const char *username; - const char *password; + if (json_sasl) { + const char *mechanisms; + const char *username; + const char *password; - ret = json_unpack_ex(json_sasl, &err, 0, "{ s: s, s: s, s: s }", - "mechanisms", &mechanisms, - "username", &username, - "password", &password - ); - if (ret) - throw ConfigError(json_sasl, err, "node-config-node-kafka-sasl", "Failed to parse SASL configuration"); + ret = json_unpack_ex(json_sasl, &err, 0, "{ s: s, s: s, s: s }", + "mechanisms", &mechanisms, "username", &username, + "password", &password); + if (ret) + throw ConfigError(json_sasl, err, "node-config-node-kafka-sasl", + "Failed to parse SASL configuration"); - k->sasl.mechanisms = strdup(mechanisms); - k->sasl.username = strdup(username); - k->sasl.password = strdup(password); - } + k->sasl.mechanisms = strdup(mechanisms); + k->sasl.username = strdup(username); + k->sasl.password = strdup(password); + } - // Format - if (k->formatter) - delete k->formatter; - k->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!k->formatter) - throw ConfigError(json_format, "node-config-node-kafka-format", "Invalid format configuration"); + // Format + if (k->formatter) + delete k->formatter; + k->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!k->formatter) + throw ConfigError(json_format, "node-config-node-kafka-format", + "Invalid format configuration"); - return 0; + return 0; } -int villas::node::kafka_prepare(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_prepare(NodeCompat *n) { + int ret; + auto *k = n->getData(); - k->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + k->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&k->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&k->pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&k->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&k->queue, 1024); + if (ret) + return ret; - return 0; + return 0; } -char * villas::node::kafka_print(NodeCompat *n) -{ - auto *k = n->getData(); +char *villas::node::kafka_print(NodeCompat *n) { + auto *k = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "bootstrap.server=%s, client.id=%s, security.protocol=%s", - k->server, - k->client_id, - k->protocol - ); + strcatf(&buf, "bootstrap.server=%s, client.id=%s, security.protocol=%s", + k->server, k->client_id, k->protocol); - // Only show if not default - if (k->produce) - strcatf(&buf, ", out.produce=%s", k->produce); + // Only show if not default + if (k->produce) + strcatf(&buf, ", out.produce=%s", k->produce); - if (k->consume) - strcatf(&buf, ", in.consume=%s", k->consume); + if (k->consume) + strcatf(&buf, ", in.consume=%s", k->consume); - return buf; + return buf; } -int villas::node::kafka_destroy(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_destroy(NodeCompat *n) { + int ret; + auto *k = n->getData(); - if (k->producer.client) - rd_kafka_destroy(k->producer.client); + if (k->producer.client) + rd_kafka_destroy(k->producer.client); - if (k->consumer.client) - rd_kafka_destroy(k->consumer.client); + if (k->consumer.client) + rd_kafka_destroy(k->consumer.client); - if (k->formatter) - delete k->formatter; + if (k->formatter) + delete k->formatter; - ret = pool_destroy(&k->pool); - if (ret) - return ret; + ret = pool_destroy(&k->pool); + if (ret) + return ret; - ret = queue_signalled_destroy(&k->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&k->queue); + if (ret) + return ret; - if (k->produce) - free(k->produce); + if (k->produce) + free(k->produce); - if (k->consume) - free(k->consume); + if (k->consume) + free(k->consume); - if (k->protocol) - free(k->protocol); + if (k->protocol) + free(k->protocol); - if (k->client_id) - free(k->client_id); + if (k->client_id) + free(k->client_id); - free(k->server); + free(k->server); - return 0; + return 0; } -int villas::node::kafka_start(NodeCompat *n) -{ - int ret; - char errstr[1024]; - auto *k = n->getData(); +int villas::node::kafka_start(NodeCompat *n) { + int ret; + char errstr[1024]; + auto *k = n->getData(); - rd_kafka_conf_t *rdkconf = rd_kafka_conf_new(); - if (!rdkconf) - throw MemoryAllocationError(); + rd_kafka_conf_t *rdkconf = rd_kafka_conf_new(); + if (!rdkconf) + throw MemoryAllocationError(); - rd_kafka_conf_set_log_cb(rdkconf, kafka_logger_cb); + rd_kafka_conf_set_log_cb(rdkconf, kafka_logger_cb); - ret = rd_kafka_conf_set(rdkconf, "client.id", k->client_id, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "client.id", k->client_id, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "bootstrap.servers", k->server, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "bootstrap.servers", k->server, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "security.protocol", k->protocol, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "security.protocol", k->protocol, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - if (!strcmp(k->protocol, "SASL_SSL") || !strcmp(k->protocol, "SSL")) { - ret = rd_kafka_conf_set(rdkconf, "ssl.ca.location", k->ssl.ca, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; - } + if (!strcmp(k->protocol, "SASL_SSL") || !strcmp(k->protocol, "SSL")) { + ret = rd_kafka_conf_set(rdkconf, "ssl.ca.location", k->ssl.ca, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; + } - if (!strcmp(k->protocol, "SASL_PLAINTEXT") || !strcmp(k->protocol, "SASL_SSL")) { - ret = rd_kafka_conf_set(rdkconf, "sasl.mechanisms", k->sasl.mechanisms, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + if (!strcmp(k->protocol, "SASL_PLAINTEXT") || + !strcmp(k->protocol, "SASL_SSL")) { + ret = rd_kafka_conf_set(rdkconf, "sasl.mechanisms", k->sasl.mechanisms, + errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "sasl.username", k->sasl.username, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "sasl.username", k->sasl.username, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "sasl.password", k->sasl.password, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; - } + ret = rd_kafka_conf_set(rdkconf, "sasl.password", k->sasl.password, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; + } - if (k->produce) { - // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, - // so we will need to create a copy first - rd_kafka_conf_t *rdkconf_prod = rd_kafka_conf_dup(rdkconf); - if (!rdkconf_prod) - throw MemoryAllocationError(); + if (k->produce) { + // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, + // so we will need to create a copy first + rd_kafka_conf_t *rdkconf_prod = rd_kafka_conf_dup(rdkconf); + if (!rdkconf_prod) + throw MemoryAllocationError(); - k->producer.client = rd_kafka_new(RD_KAFKA_PRODUCER, rdkconf_prod, errstr, sizeof(errstr)); - if (!k->producer.client) - goto kafka_config_error; + k->producer.client = + rd_kafka_new(RD_KAFKA_PRODUCER, rdkconf_prod, errstr, sizeof(errstr)); + if (!k->producer.client) + goto kafka_config_error; - rd_kafka_topic_conf_t *topic_conf = rd_kafka_topic_conf_new(); - if (!topic_conf) - throw MemoryAllocationError(); + rd_kafka_topic_conf_t *topic_conf = rd_kafka_topic_conf_new(); + if (!topic_conf) + throw MemoryAllocationError(); - ret = rd_kafka_topic_conf_set(topic_conf, "acks", "all", errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_topic_conf_set(topic_conf, "acks", "all", errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - k->producer.topic = rd_kafka_topic_new(k->producer.client, k->produce, topic_conf); - if (!k->producer.topic) - throw MemoryAllocationError(); + k->producer.topic = + rd_kafka_topic_new(k->producer.client, k->produce, topic_conf); + if (!k->producer.topic) + throw MemoryAllocationError(); - n->logger->info("Connected producer to bootstrap server {}", k->server); - } + n->logger->info("Connected producer to bootstrap server {}", k->server); + } - if (k->consume) { - // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, - // so we will need to create a copy first - rd_kafka_conf_t *rdkconf_cons = rd_kafka_conf_dup(rdkconf); - if (!rdkconf_cons) - throw MemoryAllocationError(); + if (k->consume) { + // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, + // so we will need to create a copy first + rd_kafka_conf_t *rdkconf_cons = rd_kafka_conf_dup(rdkconf); + if (!rdkconf_cons) + throw MemoryAllocationError(); - rd_kafka_topic_partition_list_t *partitions = rd_kafka_topic_partition_list_new(1); - if (!partitions) - throw MemoryAllocationError(); + rd_kafka_topic_partition_list_t *partitions = + rd_kafka_topic_partition_list_new(1); + if (!partitions) + throw MemoryAllocationError(); - rd_kafka_topic_partition_t *partition = rd_kafka_topic_partition_list_add(partitions, k->consume, 0); - if (!partition) - throw RuntimeError("Failed to add new partition"); + rd_kafka_topic_partition_t *partition = + rd_kafka_topic_partition_list_add(partitions, k->consume, 0); + if (!partition) + throw RuntimeError("Failed to add new partition"); - ret = rd_kafka_conf_set(rdkconf_cons, "group.id", k->consumer.group_id, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf_cons, "group.id", k->consumer.group_id, + errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - k->consumer.client = rd_kafka_new(RD_KAFKA_CONSUMER, rdkconf_cons, errstr, sizeof(errstr)); - if (!k->consumer.client) - throw MemoryAllocationError(); + k->consumer.client = + rd_kafka_new(RD_KAFKA_CONSUMER, rdkconf_cons, errstr, sizeof(errstr)); + if (!k->consumer.client) + throw MemoryAllocationError(); - ret = rd_kafka_subscribe(k->consumer.client, partitions); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) - throw RuntimeError("Error subscribing to {} at {}: {}", k->consume, k->server, rd_kafka_err2str((rd_kafka_resp_err_t) ret)); + ret = rd_kafka_subscribe(k->consumer.client, partitions); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) + throw RuntimeError("Error subscribing to {} at {}: {}", k->consume, + k->server, rd_kafka_err2str((rd_kafka_resp_err_t)ret)); - n->logger->info("Subscribed consumer from bootstrap server {}", k->server); - } + n->logger->info("Subscribed consumer from bootstrap server {}", k->server); + } - // Add client to global list of kafka clients - // so that thread can call kafka loop for this client - list_push(&clients, n); + // Add client to global list of kafka clients + // so that thread can call kafka loop for this client + list_push(&clients, n); - rd_kafka_conf_destroy(rdkconf); + rd_kafka_conf_destroy(rdkconf); - return 0; + return 0; kafka_config_error: - rd_kafka_conf_destroy(rdkconf); + rd_kafka_conf_destroy(rdkconf); - throw RuntimeError(errstr); + throw RuntimeError(errstr); - return -1; + return -1; } -int villas::node::kafka_stop(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_stop(NodeCompat *n) { + int ret; + auto *k = n->getData(); - if (k->producer.client) { - ret = rd_kafka_flush(k->producer.client, k->timeout * 1000); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) - n->logger->error("Failed to flush messages: {}", rd_kafka_err2str((rd_kafka_resp_err_t) ret)); + if (k->producer.client) { + ret = rd_kafka_flush(k->producer.client, k->timeout * 1000); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) + n->logger->error("Failed to flush messages: {}", + rd_kafka_err2str((rd_kafka_resp_err_t)ret)); - /* If the output queue is still not empty there is an issue + /* If the output queue is still not empty there is an issue * with producing messages to the clusters. */ - if (rd_kafka_outq_len(k->producer.client) > 0) - n->logger->warn("{} message(s) were not delivered", rd_kafka_outq_len(k->producer.client)); - } + if (rd_kafka_outq_len(k->producer.client) > 0) + n->logger->warn("{} message(s) were not delivered", + rd_kafka_outq_len(k->producer.client)); + } - // Unregister client from global kafka client list - // so that kafka loop is no longer invoked for this client - // important to do that before disconnecting from broker, otherwise, kafka thread will attempt to reconnect - list_remove_all(&clients, n); + // Unregister client from global kafka client list + // so that kafka loop is no longer invoked for this client + // important to do that before disconnecting from broker, otherwise, kafka thread will attempt to reconnect + list_remove_all(&clients, n); - ret = queue_signalled_close(&k->queue); - if (ret) - return ret; + ret = queue_signalled_close(&k->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::kafka_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::kafka_type_start(villas::node::SuperNode *sn) { + int ret; - logger = logging.get("node:kafka"); + logger = logging.get("node:kafka"); - ret = list_init(&clients); - if (ret) - goto kafka_error; + ret = list_init(&clients); + if (ret) + goto kafka_error; - // Start thread here to run kafka loop for registered clients - ret = pthread_create(&thread, nullptr, kafka_loop_thread, nullptr); - if (ret) - goto kafka_error; + // Start thread here to run kafka loop for registered clients + ret = pthread_create(&thread, nullptr, kafka_loop_thread, nullptr); + if (ret) + goto kafka_error; - return 0; + return 0; kafka_error: - logger->warn("Error initialazing node type kafka"); + logger->warn("Error initialazing node type kafka"); - return ret; + return ret; } -int villas::node::kafka_type_stop() -{ - int ret; +int villas::node::kafka_type_stop() { + int ret; - // Stop thread here that executes kafka loop - ret = pthread_cancel(thread); - if (ret) - return ret; + // Stop thread here that executes kafka loop + ret = pthread_cancel(thread); + if (ret) + return ret; - logger->debug("Called pthread_cancel() on kafka communication management thread."); + logger->debug( + "Called pthread_cancel() on kafka communication management thread."); - ret = pthread_join(thread, nullptr); - if (ret) - goto kafka_error; + ret = pthread_join(thread, nullptr); + if (ret) + goto kafka_error; - // When this is called the list of clients should be empty - if (list_length(&clients) > 0) - throw RuntimeError("List of kafka clients contains elements at time of destruction. Call node_stop for each kafka node before stopping node type!"); + // When this is called the list of clients should be empty + if (list_length(&clients) > 0) + throw RuntimeError( + "List of kafka clients contains elements at time of destruction. Call " + "node_stop for each kafka node before stopping node type!"); - ret = list_destroy(&clients, nullptr, false); - if (ret) - goto kafka_error; + ret = list_destroy(&clients, nullptr, false); + if (ret) + goto kafka_error; - return 0; + return 0; kafka_error: - logger->warn("Error stoping node type kafka"); + logger->warn("Error stoping node type kafka"); - return ret; + return ret; } -int villas::node::kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *k = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::kafka_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *k = n->getData(); + struct Sample *smpt[cnt]; - pulled = queue_signalled_pull_many(&k->queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&k->queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *k = n->getData(); - size_t wbytes; + size_t wbytes; - char data[DEFAULT_FORMAT_BUFFER_LENGTH]; + char data[DEFAULT_FORMAT_BUFFER_LENGTH]; - ret = k->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = k->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret < 0) + return ret; - if (k->produce) { - ret = rd_kafka_produce(k->producer.topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, - data, wbytes, NULL, 0, NULL); + if (k->produce) { + ret = rd_kafka_produce(k->producer.topic, RD_KAFKA_PARTITION_UA, + RD_KAFKA_MSG_F_COPY, data, wbytes, NULL, 0, NULL); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) { - n->logger->warn("Publish failed"); - return -abs(ret); - } - } - else - n->logger->warn("No produce possible because no produce topic is configured"); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) { + n->logger->warn("Publish failed"); + return -abs(ret); + } + } else + n->logger->warn( + "No produce possible because no produce topic is configured"); - return cnt; + return cnt; } -int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) -{ - auto *k = n->getData(); +int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) { + auto *k = n->getData(); - fds[0] = queue_signalled_fd(&k->queue); + fds[0] = queue_signalled_fd(&k->queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "kafka"; - p.description = "Kafka event message streaming (rdkafka)"; - p.vectorize = 0; - p.size = sizeof(struct kafka); - p.type.start = kafka_type_start; - p.type.stop = kafka_type_stop; - p.destroy = kafka_destroy; - p.prepare = kafka_prepare; - p.parse = kafka_parse; - p.prepare = kafka_prepare; - p.print = kafka_print; - p.init = kafka_init; - p.destroy = kafka_destroy; - p.start = kafka_start; - p.stop = kafka_stop; - p.read = kafka_read; - p.write = kafka_write; - p.reverse = kafka_reverse; - p.poll_fds = kafka_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "kafka"; + p.description = "Kafka event message streaming (rdkafka)"; + p.vectorize = 0; + p.size = sizeof(struct kafka); + p.type.start = kafka_type_start; + p.type.stop = kafka_type_stop; + p.destroy = kafka_destroy; + p.prepare = kafka_prepare; + p.parse = kafka_parse; + p.prepare = kafka_prepare; + p.print = kafka_print; + p.init = kafka_init; + p.destroy = kafka_destroy; + p.start = kafka_start; + p.stop = kafka_stop; + p.read = kafka_read; + p.write = kafka_write; + p.reverse = kafka_reverse; + p.poll_fds = kafka_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/loopback.cpp b/lib/nodes/loopback.cpp index 55cd70d91..a82385342 100644 --- a/lib/nodes/loopback.cpp +++ b/lib/nodes/loopback.cpp @@ -7,136 +7,127 @@ #include +#include #include +#include #include #include -#include -#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -LoopbackNode::LoopbackNode(const uuid_t &id, const std::string &name) : - Node(id, name), - queuelen(DEFAULT_QUEUE_LENGTH), - mode(QueueSignalledMode::AUTO) -{ - queue.queue.state = State::DESTROYED; +LoopbackNode::LoopbackNode(const uuid_t &id, const std::string &name) + : Node(id, name), queuelen(DEFAULT_QUEUE_LENGTH), + mode(QueueSignalledMode::AUTO) { + queue.queue.state = State::DESTROYED; } -LoopbackNode::~LoopbackNode() -{ - int ret __attribute__((unused)); +LoopbackNode::~LoopbackNode() { + int ret __attribute__((unused)); - ret = queue_signalled_destroy(&queue); + ret = queue_signalled_destroy(&queue); } -int LoopbackNode::prepare() -{ - assert(state == State::CHECKED); +int LoopbackNode::prepare() { + assert(state == State::CHECKED); - int ret = queue_signalled_init(&queue, queuelen, &memory::mmap, mode); - if (ret) - throw RuntimeError("Failed to initialize queue"); + int ret = queue_signalled_init(&queue, queuelen, &memory::mmap, mode); + if (ret) + throw RuntimeError("Failed to initialize queue"); - return Node::prepare(); + return Node::prepare(); } -int LoopbackNode::stop() -{ - int ret; +int LoopbackNode::stop() { + int ret; - ret = queue_signalled_close(&queue); - if (ret) - return ret; + ret = queue_signalled_close(&queue); + if (ret) + return ret; - return 0; + return 0; } -int LoopbackNode::_read(struct Sample * smps[], unsigned cnt) -{ - int avail; +int LoopbackNode::_read(struct Sample *smps[], unsigned cnt) { + int avail; - struct Sample *cpys[cnt]; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); + avail = queue_signalled_pull_many(&queue, (void **)cpys, cnt); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int LoopbackNode::_write(struct Sample * smps[], unsigned cnt) -{ - sample_incref_many(smps, cnt); +int LoopbackNode::_write(struct Sample *smps[], unsigned cnt) { + sample_incref_many(smps, cnt); - int pushed = queue_signalled_push_many(&queue, (void **) smps, cnt); - if (pushed < 0) { - sample_decref_many(smps, cnt); - return pushed; - } + int pushed = queue_signalled_push_many(&queue, (void **)smps, cnt); + if (pushed < 0) { + sample_decref_many(smps, cnt); + return pushed; + } - // Released unpushed samples - if ((unsigned) pushed < cnt) { - sample_decref_many(smps + pushed, cnt - pushed); - logger->warn("Queue overrun"); - } + // Released unpushed samples + if ((unsigned)pushed < cnt) { + sample_decref_many(smps + pushed, cnt - pushed); + logger->warn("Queue overrun"); + } - return pushed; + return pushed; } -std::vector LoopbackNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector LoopbackNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } -const std::string & LoopbackNode::getDetails() -{ - if (details.empty()) { - details = fmt::format("queuelen={}", queuelen); - } +const std::string &LoopbackNode::getDetails() { + if (details.empty()) { + details = fmt::format("queuelen={}", queuelen); + } - return details; + return details; } -int LoopbackNode::parse(json_t *json) -{ - const char *mode_str = nullptr; +int LoopbackNode::parse(json_t *json) { + const char *mode_str = nullptr; - json_error_t err; - int ret; + json_error_t err; + int ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", - "queuelen", &queuelen, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-loopback"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", "queuelen", &queuelen, + "mode", &mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-loopback"); - if (mode_str) { - if (!strcmp(mode_str, "auto")) - mode = QueueSignalledMode::AUTO; + if (mode_str) { + if (!strcmp(mode_str, "auto")) + mode = QueueSignalledMode::AUTO; #ifdef HAVE_EVENTFD - else if (!strcmp(mode_str, "eventfd")) - mode = QueueSignalledMode::EVENTFD; + else if (!strcmp(mode_str, "eventfd")) + mode = QueueSignalledMode::EVENTFD; #endif - else if (!strcmp(mode_str, "pthread")) - mode = QueueSignalledMode::PTHREAD; - else if (!strcmp(mode_str, "polling")) - mode = QueueSignalledMode::POLLING; - else - throw ConfigError(json, "node-config-node-loopback-mode", "Unknown mode '{}'", mode_str); - } + else if (!strcmp(mode_str, "pthread")) + mode = QueueSignalledMode::PTHREAD; + else if (!strcmp(mode_str, "polling")) + mode = QueueSignalledMode::POLLING; + else + throw ConfigError(json, "node-config-node-loopback-mode", + "Unknown mode '{}'", mode_str); + } - return Node::parse(json); + return Node::parse(json); } // Register node static char n[] = "loopback"; static char d[] = "loopback node-type"; -static NodePlugin nf; +static NodePlugin + nf; diff --git a/lib/nodes/loopback_internal.cpp b/lib/nodes/loopback_internal.cpp index e2f87d547..ed18875ba 100644 --- a/lib/nodes/loopback_internal.cpp +++ b/lib/nodes/loopback_internal.cpp @@ -7,100 +7,94 @@ #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -static -InternalLoopbackNodeFactory nf; +static InternalLoopbackNodeFactory nf; -InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) : - queuelen(ql), - source(src) -{ - auto name = fmt::format("{}.lo{}", src->getNameShort(), id); +InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) + : queuelen(ql), source(src) { + auto name = fmt::format("{}.lo{}", src->getNameShort(), id); - uuid_t uuid; - int ret = uuid::generateFromString(uuid, fmt::format("lo{}", id), src->getUuid()); - if (ret) - throw RuntimeError("Failed to initialize UUID"); + uuid_t uuid; + int ret = + uuid::generateFromString(uuid, fmt::format("lo{}", id), src->getUuid()); + if (ret) + throw RuntimeError("Failed to initialize UUID"); - Node(uuid, name); + Node(uuid, name); - factory = &nf; - name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_short, nf.getName()); + factory = &nf; + name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_short, + nf.getName()); - auto logger_name = fmt::format("node:{}", getNameShort()); + auto logger_name = fmt::format("node:{}", getNameShort()); - logger = logging.get(logger_name); + logger = logging.get(logger_name); - in.signals = source->getInputSignals(false); + in.signals = source->getInputSignals(false); - ret = queue_signalled_init(&queue, queuelen); - if (ret) - throw RuntimeError("Failed to initialize queue"); + ret = queue_signalled_init(&queue, queuelen); + if (ret) + throw RuntimeError("Failed to initialize queue"); - state = State::PREPARED; + state = State::PREPARED; } -InternalLoopbackNode::~InternalLoopbackNode() -{ - int ret __attribute__((unused)); +InternalLoopbackNode::~InternalLoopbackNode() { + int ret __attribute__((unused)); - ret = queue_signalled_destroy(&queue); + ret = queue_signalled_destroy(&queue); } -int InternalLoopbackNode::stop() -{ - int ret; +int InternalLoopbackNode::stop() { + int ret; - ret = queue_signalled_close(&queue); - if (ret) - return ret; + ret = queue_signalled_close(&queue); + if (ret) + return ret; - return 0; + return 0; } -int InternalLoopbackNode::_read(struct Sample * smps[], unsigned cnt) -{ - int avail; +int InternalLoopbackNode::_read(struct Sample *smps[], unsigned cnt) { + int avail; - struct Sample *cpys[cnt]; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); + avail = queue_signalled_pull_many(&queue, (void **)cpys, cnt); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int InternalLoopbackNode::_write(struct Sample * smps[], unsigned cnt) -{ - sample_incref_many(smps, cnt); +int InternalLoopbackNode::_write(struct Sample *smps[], unsigned cnt) { + sample_incref_many(smps, cnt); - int pushed = queue_signalled_push_many(&queue, (void **) smps, cnt); - if (pushed < 0) { - sample_decref_many(smps, cnt); - return pushed; - } + int pushed = queue_signalled_push_many(&queue, (void **)smps, cnt); + if (pushed < 0) { + sample_decref_many(smps, cnt); + return pushed; + } - // Released unpushed samples - if ((unsigned) pushed < cnt) { - sample_decref_many(smps + pushed, cnt - pushed); - logger->warn("Queue overrun"); - } + // Released unpushed samples + if ((unsigned)pushed < cnt) { + sample_decref_many(smps + pushed, cnt - pushed); + logger->warn("Queue overrun"); + } - return pushed; + return pushed; } -std::vector InternalLoopbackNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector InternalLoopbackNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 13bd07beb..ee751a1c2 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -40,908 +40,875 @@ #include +#include #include #include -#include #include -#include #include -#include - +#include using namespace villas; using namespace villas::node; using namespace villas::node::modbus; using namespace villas::utils; -int64_t RegisterMappingSingle::IntegerToInteger::read(uint16_t const *registers) const -{ - int64_t integer = 0; - auto ptr = word_endianess == Endianess::Big ? registers + num_registers - 1 : registers; +int64_t +RegisterMappingSingle::IntegerToInteger::read(uint16_t const *registers) const { + int64_t integer = 0; + auto ptr = word_endianess == Endianess::Big ? registers + num_registers - 1 + : registers; - for (size_t i = 0; i < num_registers; ++i) { - integer <<= sizeof(uint16_t) * 8; + for (size_t i = 0; i < num_registers; ++i) { + integer <<= sizeof(uint16_t) * 8; - if (byte_endianess == Endianess::Big) - integer |= (int64_t) *ptr; - else - integer |= (int64_t) byteswap(*ptr); + if (byte_endianess == Endianess::Big) + integer |= (int64_t)*ptr; + else + integer |= (int64_t)byteswap(*ptr); - if (word_endianess == Endianess::Big) - --ptr; - else - ++ptr; - } + if (word_endianess == Endianess::Big) + --ptr; + else + ++ptr; + } - return integer; + return integer; } -void RegisterMappingSingle::IntegerToInteger::write(int64_t integer, uint16_t *registers) const -{ - auto ptr = word_endianess == Endianess::Big ? registers : registers + num_registers - 1; +void RegisterMappingSingle::IntegerToInteger::write(int64_t integer, + uint16_t *registers) const { + auto ptr = word_endianess == Endianess::Big ? registers + : registers + num_registers - 1; - for (size_t i = 0; i < num_registers; ++i) { - if (byte_endianess == Endianess::Big) - *ptr = (uint16_t) integer; - else - *ptr = byteswap((uint16_t) integer); + for (size_t i = 0; i < num_registers; ++i) { + if (byte_endianess == Endianess::Big) + *ptr = (uint16_t)integer; + else + *ptr = byteswap((uint16_t)integer); - if (word_endianess == Endianess::Big) - ++ptr; - else - --ptr; + if (word_endianess == Endianess::Big) + ++ptr; + else + --ptr; - integer >>= sizeof(uint16_t) * 8; - } + integer >>= sizeof(uint16_t) * 8; + } } -double RegisterMappingSingle::IntegerToFloat::read(uint16_t const *registers) const -{ - int64_t integer = integer_conversion.read(registers); +double +RegisterMappingSingle::IntegerToFloat::read(uint16_t const *registers) const { + int64_t integer = integer_conversion.read(registers); - return integer * scale + offset; + return integer * scale + offset; } -void RegisterMappingSingle::IntegerToFloat::write(double d, uint16_t *registers) const -{ - int64_t integer = (d - offset) / scale; +void RegisterMappingSingle::IntegerToFloat::write(double d, + uint16_t *registers) const { + int64_t integer = (d - offset) / scale; - integer_conversion.write(integer, registers); + integer_conversion.write(integer, registers); } -double RegisterMappingSingle::FloatToFloat::read(uint16_t const *registers) const -{ - static_assert(sizeof(float) == sizeof(uint32_t)); +double +RegisterMappingSingle::FloatToFloat::read(uint16_t const *registers) const { + static_assert(sizeof(float) == sizeof(uint32_t)); - auto const conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = 2, - }; + auto const conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; - union { - uint32_t i; - float f; - } value; + union { + uint32_t i; + float f; + } value; - value.i = (uint32_t) conversion.read(registers); + value.i = (uint32_t)conversion.read(registers); - return value.f * scale + offset; + return value.f * scale + offset; } -void RegisterMappingSingle::FloatToFloat::write(double d, uint16_t *registers) const -{ - static_assert(sizeof(float) == sizeof(uint32_t)); +void RegisterMappingSingle::FloatToFloat::write(double d, + uint16_t *registers) const { + static_assert(sizeof(float) == sizeof(uint32_t)); - auto const conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = 2, - }; + auto const conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; - union { - uint32_t i; - float f; - } value; + union { + uint32_t i; + float f; + } value; - value.f = (d - offset) / scale; + value.f = (d - offset) / scale; - conversion.write((int64_t) value.i, registers); + conversion.write((int64_t)value.i, registers); } -bool RegisterMappingSingle::BitToBool::read(uint16_t reg) const -{ - return (reg >> bit) & 1; +bool RegisterMappingSingle::BitToBool::read(uint16_t reg) const { + return (reg >> bit) & 1; } -RegisterMappingSingle::RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address) : - conversion(IntegerToInteger { - .word_endianess = Endianess::Big, - .byte_endianess = Endianess::Big, - .num_registers = 1, - }), - signal_index(signal_index), - address(address) -{ } +RegisterMappingSingle::RegisterMappingSingle(unsigned int signal_index, + modbus_addr_t address) + : conversion(IntegerToInteger{ + .word_endianess = Endianess::Big, + .byte_endianess = Endianess::Big, + .num_registers = 1, + }), + signal_index(signal_index), address(address) {} -SignalData RegisterMappingSingle::read(uint16_t const *registers, modbus_addr_t length) const -{ - SignalData data; +SignalData RegisterMappingSingle::read(uint16_t const *registers, + modbus_addr_t length) const { + SignalData data; - if (num_registers() != length) - throw RuntimeError { "reading from invalid register range" }; + if (num_registers() != length) + throw RuntimeError{"reading from invalid register range"}; - if (auto i2i = std::get_if(&conversion)) - data.i = i2i->read(registers); - else if (auto i2f = std::get_if(&conversion)) - data.f = i2f->read(registers); - else if (auto f2f = std::get_if(&conversion)) - data.f = f2f->read(registers); - else if (auto b2b = std::get_if(&conversion)) - data.b = b2b->read(*registers); - else - throw RuntimeError { "read unsupported" }; + if (auto i2i = std::get_if(&conversion)) + data.i = i2i->read(registers); + else if (auto i2f = std::get_if(&conversion)) + data.f = i2f->read(registers); + else if (auto f2f = std::get_if(&conversion)) + data.f = f2f->read(registers); + else if (auto b2b = std::get_if(&conversion)) + data.b = b2b->read(*registers); + else + throw RuntimeError{"read unsupported"}; - return data; + return data; } -void RegisterMappingSingle::write(SignalData data, uint16_t *registers, modbus_addr_t length) const -{ - if (num_registers() != length) - throw RuntimeError { "writing to invalid register range" }; +void RegisterMappingSingle::write(SignalData data, uint16_t *registers, + modbus_addr_t length) const { + if (num_registers() != length) + throw RuntimeError{"writing to invalid register range"}; - if (auto i2i = std::get_if(&conversion)) - i2i->write(data.i, registers); - else if (auto i2f = std::get_if(&conversion)) - i2f->write(data.f, registers); - else if (auto f2f = std::get_if(&conversion)) - f2f->write(data.f, registers); - else - throw RuntimeError { "write unsupported" }; + if (auto i2i = std::get_if(&conversion)) + i2i->write(data.i, registers); + else if (auto i2f = std::get_if(&conversion)) + i2f->write(data.f, registers); + else if (auto f2f = std::get_if(&conversion)) + f2f->write(data.f, registers); + else + throw RuntimeError{"write unsupported"}; } -modbus_addr_t RegisterMappingSingle::num_registers() const -{ - if (auto i2i = std::get_if(&conversion)) - return i2i->num_registers; +modbus_addr_t RegisterMappingSingle::num_registers() const { + if (auto i2i = std::get_if(&conversion)) + return i2i->num_registers; - if (auto i2f = std::get_if(&conversion)) - return i2f->integer_conversion.num_registers; + if (auto i2f = std::get_if(&conversion)) + return i2f->integer_conversion.num_registers; - if (std::holds_alternative(conversion)) - return 2; + if (std::holds_alternative(conversion)) + return 2; - if (std::holds_alternative(conversion)) - return 1; + if (std::holds_alternative(conversion)) + return 1; - throw RuntimeError { "unreachable" }; + throw RuntimeError{"unreachable"}; } -uint16_t modbus::byteswap(uint16_t i) -{ - uint8_t low = (i & 0x00FF); - uint8_t high = (i & 0xFF00) >> 8; - return (low << 8) | high; +uint16_t modbus::byteswap(uint16_t i) { + uint8_t low = (i & 0x00FF); + uint8_t high = (i & 0xFF00) >> 8; + return (low << 8) | high; } -modbus_addr_t modbus::blockBegin(RegisterMappingSingle const &single) -{ - return single.address; +modbus_addr_t modbus::blockBegin(RegisterMappingSingle const &single) { + return single.address; } -modbus_addr_t modbus::blockBegin(RegisterMappingBlock const &block) -{ - assert(!block.empty()); - return blockBegin(block.front()); +modbus_addr_t modbus::blockBegin(RegisterMappingBlock const &block) { + assert(!block.empty()); + return blockBegin(block.front()); } -modbus_addr_t modbus::blockBegin(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return blockBegin(v); - }, mapping); +modbus_addr_t modbus::blockBegin(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return blockBegin(v); }, mapping); } -modbus_addr_t modbus::blockEnd(RegisterMappingSingle const &single) -{ - return single.address + single.num_registers(); +modbus_addr_t modbus::blockEnd(RegisterMappingSingle const &single) { + return single.address + single.num_registers(); } -modbus_addr_t modbus::blockEnd(RegisterMappingBlock const &block) -{ - assert(!block.empty()); - return blockEnd(block.back()); +modbus_addr_t modbus::blockEnd(RegisterMappingBlock const &block) { + assert(!block.empty()); + return blockEnd(block.back()); } -modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return blockEnd(v); - }, mapping); +modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return blockEnd(v); }, mapping); } -modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) -{ - return single.num_registers(); +modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) { + return single.num_registers(); } -modbus_addr_t modbus::mappedRegisters(RegisterMappingBlock const &block) -{ - auto mapped = 0; +modbus_addr_t modbus::mappedRegisters(RegisterMappingBlock const &block) { + auto mapped = 0; - modbus_addr_t last_address = -1; - for (auto &single : block) { - if (single.address != last_address) - mapped += single.num_registers(); + modbus_addr_t last_address = -1; + for (auto &single : block) { + if (single.address != last_address) + mapped += single.num_registers(); - last_address = single.address; - } + last_address = single.address; + } - return mapped; + return mapped; } -modbus_addr_t modbus::mappedRegisters(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return mappedRegisters(v); - }, mapping); +modbus_addr_t modbus::mappedRegisters(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return mappedRegisters(v); }, mapping); } -modbus_addrdiff_t modbus::blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - if (blockBegin(rhs) >= blockEnd(lhs)) - return (modbus_addrdiff_t) blockBegin(rhs) - blockEnd(lhs); +modbus_addrdiff_t modbus::blockDistance(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + if (blockBegin(rhs) >= blockEnd(lhs)) + return (modbus_addrdiff_t)blockBegin(rhs) - blockEnd(lhs); - if (blockBegin(lhs) >= blockEnd(rhs)) - return (modbus_addrdiff_t) blockBegin(lhs) - blockEnd(rhs); + if (blockBegin(lhs) >= blockEnd(rhs)) + return (modbus_addrdiff_t)blockBegin(lhs) - blockEnd(rhs); - if (hasOverlappingBitMapping(lhs, rhs)) - return -1; + if (hasOverlappingBitMapping(lhs, rhs)) + return -1; - throw RuntimeError { "overlapping mappings" }; + throw RuntimeError{"overlapping mappings"}; } -bool modbus::hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - // Only check if there is exactly 1 register of overlap. - if (blockEnd(lhs) - blockBegin(rhs) != 1 && blockEnd(rhs) - blockBegin(lhs) != 1) - return false; +bool modbus::hasOverlappingBitMapping(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + // Only check if there is exactly 1 register of overlap. + if (blockEnd(lhs) - blockBegin(rhs) != 1 && + blockEnd(rhs) - blockBegin(lhs) != 1) + return false; - // Assume that lhs is at a lower address than rhs. - if (blockBegin(rhs) < blockBegin(lhs) || blockEnd(rhs) < blockEnd(lhs)) - return hasOverlappingBitMapping(rhs, lhs); + // Assume that lhs is at a lower address than rhs. + if (blockBegin(rhs) < blockBegin(lhs) || blockEnd(rhs) < blockEnd(lhs)) + return hasOverlappingBitMapping(rhs, lhs); - // Get the last mapping from the lhs block. - RegisterMappingSingle const *lhs_back = nullptr; - if (auto single = std::get_if(&lhs)) - lhs_back = single; - else if (auto block = std::get_if(&lhs)) - lhs_back = &block->back(); - else - return false; + // Get the last mapping from the lhs block. + RegisterMappingSingle const *lhs_back = nullptr; + if (auto single = std::get_if(&lhs)) + lhs_back = single; + else if (auto block = std::get_if(&lhs)) + lhs_back = &block->back(); + else + return false; - // We are only interested in bit mappings. - if (!std::holds_alternative(lhs_back->conversion)) - return false; + // We are only interested in bit mappings. + if (!std::holds_alternative( + lhs_back->conversion)) + return false; - // Get the first mapping from the rhs block. - RegisterMappingSingle const *rhs_front = nullptr; - if (auto single = std::get_if(&rhs)) - rhs_front = single; - else if (auto block = std::get_if(&rhs)) - rhs_front = &block->front(); - else - return false; + // Get the first mapping from the rhs block. + RegisterMappingSingle const *rhs_front = nullptr; + if (auto single = std::get_if(&rhs)) + rhs_front = single; + else if (auto block = std::get_if(&rhs)) + rhs_front = &block->front(); + else + return false; - // We are only interested in bit mappings. - if (!std::holds_alternative(rhs_front->conversion)) - return false; + // We are only interested in bit mappings. + if (!std::holds_alternative( + rhs_front->conversion)) + return false; - // The last register of lhs and the first register of rhs overlap and are both bit mappings. - return true; + // The last register of lhs and the first register of rhs overlap and are both bit mappings. + return true; } -bool modbus::compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - if (blockBegin(rhs) >= blockEnd(lhs)) - return true; +bool modbus::compareBlockAddress(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + if (blockBegin(rhs) >= blockEnd(lhs)) + return true; - if (blockBegin(lhs) >= blockEnd(rhs)) - return false; + if (blockBegin(lhs) >= blockEnd(rhs)) + return false; - if (hasOverlappingBitMapping(lhs, rhs)) - return false; + if (hasOverlappingBitMapping(lhs, rhs)) + return false; - throw RuntimeError { "overlapping mappings" }; + throw RuntimeError{"overlapping mappings"}; } -bool ModbusNode::isReconnecting() -{ - return reconnecting.load(); +bool ModbusNode::isReconnecting() { return reconnecting.load(); } + +void ModbusNode::reconnect() { + if (reconnecting.exchange(true)) + return; + + logger->error("No connection to the Modbus server. Reconnecting..."); + + std::thread([this]() { + auto start = std::chrono::steady_clock::now(); + + if (modbus_connect(modbus_context) == -1) { + logger->error("reconnect failure: ", modbus_strerror(errno)); + std::this_thread::sleep_until( + start + std::chrono::duration(reconnect_interval)); + } + + reconnecting.store(false); + }).detach(); } -void ModbusNode::reconnect() -{ - if (reconnecting.exchange(true)) - return; +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingBlock const &rhs) { + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock{*lhs_single}; - logger->error("No connection to the Modbus server. Reconnecting..."); - - std::thread([this](){ - auto start = std::chrono::steady_clock::now(); - - if (modbus_connect(modbus_context) == -1) { - logger->error("reconnect failure: ", modbus_strerror(errno)); - std::this_thread::sleep_until(start + std::chrono::duration(reconnect_interval)); - } - - reconnecting.store(false); - }).detach(); + auto &block = std::get(lhs); + block.reserve(blockEnd(rhs) - blockBegin(lhs)); + std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(block)); } -void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs) -{ - if (auto lhs_single = std::get_if(&lhs)) - lhs = RegisterMappingBlock { *lhs_single }; +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingSingle const &rhs) { + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock{*lhs_single}; - auto &block = std::get(lhs); - block.reserve(blockEnd(rhs) - blockBegin(lhs)); - std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(block)); + auto &block = std::get(lhs); + block.push_back(rhs); } -void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs) -{ - if (auto lhs_single = std::get_if(&lhs)) - lhs = RegisterMappingBlock { *lhs_single }; +bool ModbusNode::tryMergeMappingInplace(RegisterMapping &lhs, + RegisterMapping const &rhs) { + auto block_size = blockEnd(rhs) - blockBegin(lhs); - auto &block = std::get(lhs); - block.push_back(rhs); + if (block_size >= max_block_size) + return false; + + auto block_usage = + (mappedRegisters(lhs) + mappedRegisters(rhs)) / (float)block_size; + + if (block_usage < min_block_usage) + return false; + + std::visit([&lhs](auto const &rhs) { mergeMappingInplace(lhs, rhs); }, rhs); + + return true; } -bool ModbusNode::tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs) -{ - auto block_size = blockEnd(rhs) - blockBegin(lhs); +void ModbusNode::mergeMappings(std::vector &mappings, + modbus_addrdiff_t max_block_distance) { + if (std::size(mappings) < 2) + return; - if (block_size >= max_block_size) - return false; + // Sort all mappings by their block address. + std::sort(std::begin(mappings), std::end(mappings), compareBlockAddress); - auto block_usage = (mappedRegisters(lhs) + mappedRegisters(rhs)) / (float) block_size; + // Calculate the distances. (number of unused registers inbetween mappings) + auto distances = std::vector(); + distances.reserve(std::size(mappings)); + for (size_t i = 1; i < std::size(mappings); i++) + distances.push_back(blockDistance(mappings[i - 1], mappings[i])); - if (block_usage < min_block_usage) - return false; + for (;;) { + // Try to group the mappings closest to each other first. + auto min_distance = + std::min_element(std::begin(distances), std::end(distances)); - std::visit([&lhs](auto const &rhs){ - mergeMappingInplace(lhs, rhs); - }, rhs); + // The closest distance is too far to merge, abort the merging process. + if (min_distance == std::end(distances) || + *min_distance >= max_block_distance) + break; - return true; + // Find the mappings to the left and right of the minimum distance. + auto i = std::distance(std::begin(distances), min_distance); + auto left_mapping = std::next(std::begin(mappings), i); + auto right_mapping = std::next(std::begin(mappings), i + 1); + + if (tryMergeMappingInplace(*left_mapping, *right_mapping)) { + // Remove the right mapping and the distance + // if it could be merged into the left mapping. + mappings.erase(right_mapping); + distances.erase(min_distance); + } else { + // Set the distance to a value, so that it won't be retried. + *min_distance = max_block_distance; + } + } } -void ModbusNode::mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance) -{ - if (std::size(mappings) < 2) - return; +int ModbusNode::readBlock(RegisterMapping const &mapping, SignalData *data, + size_t size) { + if (isReconnecting()) + return -1; - // Sort all mappings by their block address. - std::sort(std::begin(mappings), std::end(mappings), compareBlockAddress); + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; - // Calculate the distances. (number of unused registers inbetween mappings) - auto distances = std::vector(); - distances.reserve(std::size(mappings)); - for (size_t i = 1; i < std::size(mappings); i++) - distances.push_back(blockDistance(mappings[i-1], mappings[i])); + read_buffer.resize(block_size); - for (;;) { - // Try to group the mappings closest to each other first. - auto min_distance = std::min_element(std::begin(distances), std::end(distances)); + if (modbus_read_registers(modbus_context, address, block_size, + read_buffer.data()) == -1) { + logger->error("read registers failure: ", modbus_strerror(errno)); - // The closest distance is too far to merge, abort the merging process. - if (min_distance == std::end(distances) || *min_distance >= max_block_distance) - break; + reconnect(); - // Find the mappings to the left and right of the minimum distance. - auto i = std::distance(std::begin(distances), min_distance); - auto left_mapping = std::next(std::begin(mappings), i); - auto right_mapping = std::next(std::begin(mappings), i+1); + return -1; + } - if (tryMergeMappingInplace(*left_mapping, *right_mapping)) { - // Remove the right mapping and the distance - // if it could be merged into the left mapping. - mappings.erase(right_mapping); - distances.erase(min_distance); - } else { - // Set the distance to a value, so that it won't be retried. - *min_distance = max_block_distance; - } - } + return readMapping(mapping, read_buffer.data(), read_buffer.size(), data, + size); } -int ModbusNode::readBlock(RegisterMapping const &mapping, SignalData *data, size_t size) -{ - if (isReconnecting()) - return -1; - - auto address = blockBegin(mapping); - auto block_size = blockEnd(mapping) - address; - - read_buffer.resize(block_size); - - if (modbus_read_registers(modbus_context, address, block_size, read_buffer.data()) == -1) { - logger->error("read registers failure: ", modbus_strerror(errno)); - - reconnect(); - - return -1; - } - - return readMapping(mapping, read_buffer.data(), read_buffer.size(), data, size); +int ModbusNode::readMapping(RegisterMapping const &mapping, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + return std::visit( + [this, registers, num_registers, signals, num_signals](auto mapping) { + return readMapping(mapping, registers, num_registers, signals, + num_signals); + }, + mapping); } -int ModbusNode::readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ - return readMapping(mapping, registers, num_registers, signals, num_signals); - }, mapping); +int ModbusNode::readMapping(RegisterMappingSingle const &single, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + auto signal_data = single.read(registers, num_registers); + + assert(single.signal_index < num_signals); + signals[single.signal_index] = signal_data; + + return 0; } -int ModbusNode::readMapping(RegisterMappingSingle const &single, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - auto signal_data = single.read(registers, num_registers); +int ModbusNode::readMapping(RegisterMappingBlock const &block, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + auto begin_block = blockBegin(block); - assert(single.signal_index < num_signals); - signals[single.signal_index] = signal_data; + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); - return 0; + assert(end_single - begin_block <= num_registers); + if (auto ret = readMapping(single, ®isters[begin_single - begin_block], + end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; } -int ModbusNode::readMapping(RegisterMappingBlock const &block, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - auto begin_block = blockBegin(block); +int ModbusNode::_read(struct Sample *smps[], unsigned cnt) { + read_task.wait(); - for (auto &single : block) { - auto begin_single = blockBegin(single); - auto end_single = blockEnd(single); + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; + smp->length = num_in_signals; + smp->flags |= (int)SampleFlags::HAS_DATA; - assert(end_single - begin_block <= num_registers); - if (auto ret = readMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) - return ret; - } + assert(smp->length <= smp->capacity); - return 0; + for (auto &mapping : in_mappings) { + if (auto ret = readBlock(mapping, smp->data, smp->length)) + return ret; + } + } + + return cnt; } -int ModbusNode::_read(struct Sample *smps[], unsigned cnt) -{ - read_task.wait(); +int ModbusNode::writeBlock(RegisterMapping const &mapping, + SignalData const *data, size_t size) { + if (isReconnecting()) + return -1; - for (unsigned int i = 0; i < cnt; ++i) { - auto smp = smps[i]; - smp->length = num_in_signals; - smp->flags |= (int) SampleFlags::HAS_DATA; + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; - assert(smp->length <= smp->capacity); + write_buffer.resize(block_size); - for (auto &mapping : in_mappings) { - if (auto ret = readBlock(mapping, smp->data, smp->length)) - return ret; - } - } + if (auto ret = writeMapping(mapping, write_buffer.data(), write_buffer.size(), + data, size)) + return ret; - return cnt; + if (modbus_write_registers(modbus_context, address, block_size, + write_buffer.data()) == -1) { + logger->error("write registers failure: ", modbus_strerror(errno)); + + reconnect(); + + return -1; + } + + return 0; } -int ModbusNode::writeBlock(RegisterMapping const &mapping, SignalData const *data, size_t size) -{ - if (isReconnecting()) - return -1; - - auto address = blockBegin(mapping); - auto block_size = blockEnd(mapping) - address; - - write_buffer.resize(block_size); - - if (auto ret = writeMapping(mapping, write_buffer.data(), write_buffer.size(), data, size)) - return ret; - - if (modbus_write_registers(modbus_context, address, block_size, write_buffer.data()) == -1) { - logger->error("write registers failure: ", modbus_strerror(errno)); - - reconnect(); - - return -1; - } - - return 0; +int ModbusNode::writeMapping(RegisterMapping const &mapping, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + return std::visit( + [this, registers, num_registers, signals, num_signals](auto mapping) { + return writeMapping(mapping, registers, num_registers, signals, + num_signals); + }, + mapping); } -int ModbusNode::writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ - return writeMapping(mapping, registers, num_registers, signals, num_signals); - }, mapping); +int ModbusNode::writeMapping(RegisterMappingSingle const &single, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + assert(single.signal_index < num_signals); + single.write(signals[single.signal_index], registers, num_registers); + + return 0; } -int ModbusNode::writeMapping(RegisterMappingSingle const &single, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - assert(single.signal_index < num_signals); - single.write(signals[single.signal_index], registers, num_registers); +int ModbusNode::writeMapping(RegisterMappingBlock const &block, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + auto begin_block = blockBegin(block); - return 0; + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); + + assert(end_single - begin_block <= num_registers); + if (auto ret = + writeMapping(single, ®isters[begin_single - begin_block], + end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; } -int ModbusNode::writeMapping(RegisterMappingBlock const &block, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - auto begin_block = blockBegin(block); +int ModbusNode::_write(struct Sample *smps[], unsigned cnt) { + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; - for (auto &single : block) { - auto begin_single = blockBegin(single); - auto end_single = blockEnd(single); + assert(smp->length == num_out_signals); - assert(end_single - begin_block <= num_registers); - if (auto ret = writeMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) - return ret; - } + for (auto &mapping : out_mappings) { + if (auto ret = writeBlock(mapping, smp->data, smp->length)) + return ret; + } + } - return 0; + return cnt; } -int ModbusNode::_write(struct Sample *smps[], unsigned cnt) -{ - for (unsigned int i = 0; i < cnt; ++i) { - auto smp = smps[i]; +ModbusNode::ModbusNode(const uuid_t &id, const std::string &name) + : Node(id, name), max_block_size(32), min_block_usage(0.25), + connection_settings(), rate(-1), response_timeout(1), in_mappings{}, + num_in_signals(0), out_mappings{}, num_out_signals(0), + reconnect_interval(10), read_buffer{}, write_buffer{}, + modbus_context(nullptr), read_task(), reconnecting(false) {} - assert(smp->length == num_out_signals); - - for (auto &mapping : out_mappings) { - if (auto ret = writeBlock(mapping, smp->data, smp->length)) - return ret; - } - } - - return cnt; +ModbusNode::~ModbusNode() { + if (modbus_context) + modbus_free(modbus_context); } -ModbusNode::ModbusNode(const uuid_t &id, const std::string &name) : - Node(id, name), - max_block_size(32), - min_block_usage(0.25), - connection_settings(), - rate(-1), - response_timeout(1), - in_mappings{}, - num_in_signals(0), - out_mappings{}, - num_out_signals(0), - reconnect_interval(10), - read_buffer{}, - write_buffer{}, - modbus_context(nullptr), - read_task(), - reconnecting(false) -{ } +int ModbusNode::prepare() { + mergeMappings(in_mappings, max_block_size - 2); + mergeMappings(out_mappings, 0); -ModbusNode::~ModbusNode() -{ - if (modbus_context) - modbus_free(modbus_context); + if (in.enabled) { + read_task.setRate(rate); + + logger->info("Making {} Modbus calls for each read", in_mappings.size()); + } + + if (out.enabled) + logger->info("Making {} Modbus calls for each write", out_mappings.size()); + + assert(!std::holds_alternative(connection_settings)); + + if (auto tcp = std::get_if(&connection_settings)) { + modbus_context = modbus_new_tcp(tcp->remote.c_str(), tcp->port); + + if (tcp->unit) + modbus_set_slave(modbus_context, *tcp->unit); + } + + if (auto rtu = std::get_if(&connection_settings)) { + modbus_context = modbus_new_rtu(rtu->device.c_str(), rtu->baudrate, + static_cast(rtu->parity), + rtu->data_bits, rtu->stop_bits); + + modbus_set_slave(modbus_context, rtu->unit); + } + + auto response_timeout_secs = (uint32_t)response_timeout; + auto response_timeout_usecs = + (uint32_t)(response_timeout - (double)response_timeout_secs); + modbus_set_response_timeout(modbus_context, response_timeout_secs, + response_timeout_usecs); + + return Node::prepare(); } -int ModbusNode::prepare() -{ - mergeMappings(in_mappings, max_block_size - 2); - mergeMappings(out_mappings, 0); +Endianess modbus::parseEndianess(char const *str) { + if (!strcmp(str, "little")) + return Endianess::Little; - if (in.enabled) { - read_task.setRate(rate); + if (!strcmp(str, "big")) + return Endianess::Big; - logger->info("Making {} Modbus calls for each read", in_mappings.size()); - } - - if (out.enabled) - logger->info("Making {} Modbus calls for each write", out_mappings.size()); - - assert(!std::holds_alternative(connection_settings)); - - if (auto tcp = std::get_if(&connection_settings)) { - modbus_context = modbus_new_tcp(tcp->remote.c_str(), tcp->port); - - if (tcp->unit) - modbus_set_slave(modbus_context, *tcp->unit); - } - - if (auto rtu = std::get_if(&connection_settings)) { - modbus_context = modbus_new_rtu( - rtu->device.c_str(), - rtu->baudrate, - static_cast(rtu->parity), - rtu->data_bits, - rtu->stop_bits); - - modbus_set_slave(modbus_context, rtu->unit); - } - - auto response_timeout_secs = (uint32_t) response_timeout; - auto response_timeout_usecs = (uint32_t) (response_timeout - (double) response_timeout_secs); - modbus_set_response_timeout(modbus_context, response_timeout_secs, response_timeout_usecs); - - return Node::prepare(); + throw RuntimeError{"invalid endianess"}; } -Endianess modbus::parseEndianess(char const *str) -{ - if (!strcmp(str, "little")) - return Endianess::Little; +Parity modbus::parseParity(char const *str) { + if (!strcmp(str, "none")) + return Parity::None; - if (!strcmp(str, "big")) - return Endianess::Big; + if (!strcmp(str, "even")) + return Parity::Even; - throw RuntimeError { "invalid endianess" }; + if (!strcmp(str, "odd")) + return Parity::Odd; + + throw RuntimeError{"invalid parity"}; } -Parity modbus::parseParity(char const *str) -{ - if (!strcmp(str, "none")) - return Parity::None; +Rtu Rtu::parse(json_t *json) { + char const *device = nullptr; + char const *parity_str = nullptr; + int baudrate = -1; + int data_bits = -1; + int stop_bits = -1; - if (!strcmp(str, "even")) - return Parity::Even; + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: i, s: i, s: i }", + "device", &device, "parity", &parity_str, "baudrate", + &baudrate, "data_bits", &data_bits, "stop_bits", + &stop_bits); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-rtu"); - if (!strcmp(str, "odd")) - return Parity::Odd; + Parity parity = parseParity(parity_str); - throw RuntimeError { "invalid parity" }; + return Rtu{device, parity, baudrate, data_bits, stop_bits}; } -Rtu Rtu::parse(json_t* json) -{ - char const *device = nullptr; - char const *parity_str = nullptr; - int baudrate = -1; - int data_bits = -1; - int stop_bits = -1; +Tcp Tcp::parse(json_t *json) { + char const *remote = nullptr; + int port = 502; + int unit_int = -1; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: i, s: i, s: i }", - "device", &device, - "parity", &parity_str, - "baudrate", &baudrate, - "data_bits", &data_bits, - "stop_bits", &stop_bits - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-rtu"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: i, s?: i }", "remote", + &remote, "port", &port, "unit", &unit_int); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-tcp"); - Parity parity = parseParity(parity_str); + std::optional unit = unit_int >= 0 ? std::optional(unit_int) : std::nullopt; - return Rtu { device, parity, baudrate, data_bits, stop_bits }; + return Tcp{ + .remote = remote, + .port = (uint16_t)port, + .unit = unit, + }; } -Tcp Tcp::parse(json_t* json) -{ - char const *remote = nullptr; - int port = 502; - int unit_int = -1; +RegisterMappingSingle RegisterMappingSingle::parse(unsigned int index, + Signal::Ptr signal, + json_t *json) { + int address = -1; + int bit = -1; + int integer_registers = -1; + char const *word_endianess_str = nullptr; + char const *byte_endianess_str = nullptr; + double offset = 0.0; + double scale = 1.0; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: i, s?: i }", - "remote", &remote, - "port", &port, - "unit", &unit_int - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-tcp"); + json_error_t err; + int ret = json_unpack_ex( + json, &err, 0, "{ s: i, s?: i, s?: i, s?: s, s?: s, s?: F, s?: F }", + "address", &address, "bit", &bit, "integer_registers", &integer_registers, + "word_endianess", &word_endianess_str, "byte_endianess", + &byte_endianess_str, "offset", &offset, "scale", &scale); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-signal"); - std::optional unit = unit_int >= 0 ? std::optional(unit_int) : std::nullopt; + if (integer_registers != -1 && + (integer_registers <= 0 || (size_t)integer_registers > MAX_REGISTERS)) + throw RuntimeError{"unsupported register block size"}; - return Tcp { - .remote = remote, - .port = (uint16_t) port, - .unit = unit, - }; + Endianess word_endianess = Endianess::Big; + if (word_endianess_str) + word_endianess = parseEndianess(word_endianess_str); + + Endianess byte_endianess = Endianess::Big; + if (byte_endianess_str) + byte_endianess = parseEndianess(byte_endianess_str); + + auto mapping = RegisterMappingSingle{index, (modbus_addr_t)address}; + if (signal->type == SignalType::FLOAT) { + if (integer_registers == -1) { + mapping.conversion = FloatToFloat{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .offset = offset, + .scale = scale, + }; + } else { + auto integer_conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t)integer_registers, + }; + + mapping.conversion = IntegerToFloat{ + .integer_conversion = integer_conversion, + .offset = offset, + .scale = scale, + }; + } + + return mapping; + } else if (signal->type == SignalType::INTEGER) { + if (integer_registers == -1) + integer_registers = 1; + + mapping.conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t)integer_registers, + }; + } else if (signal->type == SignalType::BOOLEAN) { + if (bit < 0 || bit > 15) + throw RuntimeError{ + "mappings from bit to bool must be in the range 0 to 16"}; + + mapping.conversion = BitToBool{ + .bit = (uint8_t)bit, + }; + } else { + throw RuntimeError{"unsupported signal type"}; + } + + return mapping; } -RegisterMappingSingle RegisterMappingSingle::parse(unsigned int index, Signal::Ptr signal, json_t *json) -{ - int address = -1; - int bit = -1; - int integer_registers = -1; - char const *word_endianess_str = nullptr; - char const *byte_endianess_str = nullptr; - double offset = 0.0; - double scale = 1.0; +unsigned int ModbusNode::parseMappings(std::vector &mappings, + json_t *json) { + assert(json_is_array(json)); - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: i, s?: i, s?: s, s?: s, s?: F, s?: F }", - "address", &address, - "bit", &bit, - "integer_registers", &integer_registers, - "word_endianess", &word_endianess_str, - "byte_endianess", &byte_endianess_str, - "offset", &offset, - "scale", &scale - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-signal"); + size_t i; + json_t *signal_json; + auto signals = getInputSignals(false); - if (integer_registers != -1 && (integer_registers <= 0 || (size_t) integer_registers > MAX_REGISTERS)) - throw RuntimeError { "unsupported register block size" }; + json_array_foreach(json, i, signal_json) { + auto signal = signals->getByIndex(i); - Endianess word_endianess = Endianess::Big; - if (word_endianess_str) - word_endianess = parseEndianess(word_endianess_str); + mappings.push_back(RegisterMappingSingle::parse(i, signal, signal_json)); + } - Endianess byte_endianess = Endianess::Big; - if (byte_endianess_str) - byte_endianess = parseEndianess(byte_endianess_str); - - auto mapping = RegisterMappingSingle { index, (modbus_addr_t) address }; - if (signal->type == SignalType::FLOAT) { - if (integer_registers == -1) { - mapping.conversion = FloatToFloat { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .offset = offset, - .scale = scale, - }; - } else { - auto integer_conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = (modbus_addr_t) integer_registers, - }; - - mapping.conversion = IntegerToFloat { - .integer_conversion = integer_conversion, - .offset = offset, - .scale = scale, - }; - } - - return mapping; - } else if (signal->type == SignalType::INTEGER) { - if (integer_registers == -1) - integer_registers = 1; - - mapping.conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = (modbus_addr_t) integer_registers, - }; - } else if (signal->type == SignalType::BOOLEAN) { - if (bit < 0 || bit > 15) - throw RuntimeError { "mappings from bit to bool must be in the range 0 to 16" }; - - mapping.conversion = BitToBool { - .bit = (uint8_t) bit, - }; - } else { - throw RuntimeError { "unsupported signal type" }; - } - - return mapping; + return json_array_size(json); } -unsigned int ModbusNode::parseMappings(std::vector &mappings, json_t *json) -{ - assert(json_is_array(json)); +int ModbusNode::parse(json_t *json) { + if (auto ret = Node::parse(json)) + return ret; - size_t i; - json_t *signal_json; - auto signals = getInputSignals(false); + json_error_t err; + char const *transport = nullptr; + json_t *in_json = nullptr; + json_t *out_json = nullptr; - json_array_foreach (json, i, signal_json) { - auto signal = signals->getByIndex(i); + if (json_unpack_ex( + json, &err, 0, + "{ s: s, s?: F, s?: F, s?: i, s?: i, s?: F, s?: o, s?: o }", + "transport", &transport, "response_timeout", &response_timeout, + "reconnect_interval", &reconnect_interval, "min_block_usage", + &min_block_usage, "max_block_size", &max_block_size, "rate", &rate, + "in", &in_json, "out", &out_json)) + throw ConfigError(json, err, "node-config-node-modbus"); - mappings.push_back(RegisterMappingSingle::parse(i, signal, signal_json)); - } + if (in.enabled && rate < 0) + throw RuntimeError{"missing polling rate for Modbus reads"}; - return json_array_size(json); + if (!strcmp(transport, "rtu")) + connection_settings = Rtu::parse(json); + else if (!strcmp(transport, "tcp")) + connection_settings = Tcp::parse(json); + else + throw ConfigError(json, err, "node-config-node-modbus-transport"); + + json_t *signals_json; + + if (in_json && (signals_json = json_object_get(in_json, "signals"))) + num_in_signals = parseMappings(in_mappings, signals_json); + + if (out_json && (signals_json = json_object_get(out_json, "signals"))) + num_out_signals = parseMappings(out_mappings, signals_json); + + return 0; } -int ModbusNode::parse(json_t *json) -{ - if (auto ret = Node::parse(json)) - return ret; +int ModbusNode::check() { return Node::check(); } - json_error_t err; - char const * transport = nullptr; - json_t *in_json = nullptr; - json_t *out_json = nullptr; +int ModbusNode::start() { + if (modbus_connect(modbus_context) == -1) + throw RuntimeError{"connection failure: {}", modbus_strerror(errno)}; - if (json_unpack_ex(json, &err, 0, "{ s: s, s?: F, s?: F, s?: i, s?: i, s?: F, s?: o, s?: o }", - "transport", &transport, - "response_timeout", &response_timeout, - "reconnect_interval", &reconnect_interval, - "min_block_usage", &min_block_usage, - "max_block_size", &max_block_size, - "rate", &rate, - "in", &in_json, - "out", &out_json - )) - throw ConfigError(json, err, "node-config-node-modbus"); - - if (in.enabled && rate < 0) - throw RuntimeError { "missing polling rate for Modbus reads" }; - - if (!strcmp(transport, "rtu")) - connection_settings = Rtu::parse(json); - else if (!strcmp(transport, "tcp")) - connection_settings = Tcp::parse(json); - else - throw ConfigError(json, err, "node-config-node-modbus-transport"); - - json_t *signals_json; - - if (in_json && (signals_json = json_object_get(in_json, "signals"))) - num_in_signals = parseMappings(in_mappings, signals_json); - - if (out_json && (signals_json = json_object_get(out_json, "signals"))) - num_out_signals = parseMappings(out_mappings, signals_json); - - return 0; + return Node::start(); } -int ModbusNode::check() -{ - return Node::check(); +int ModbusNode::stop() { + modbus_close(modbus_context); + + return Node::stop(); } -int ModbusNode::start() -{ - if (modbus_connect(modbus_context) == -1) - throw RuntimeError { "connection failure: {}", modbus_strerror(errno) }; +std::vector ModbusNode::getPollFDs() { return {read_task.getFD()}; } - return Node::start(); +std::vector ModbusNode::getNetemFDs() { + if (modbus_context != nullptr && + std::holds_alternative(connection_settings)) { + return {modbus_get_socket(modbus_context)}; + } + + return {}; } -int ModbusNode::stop() -{ - modbus_close(modbus_context); +const std::string &ModbusNode::getDetails() { + if (details.empty()) { + if (auto tcp = std::get_if(&connection_settings)) { + details = fmt::format("transport=tcp, remote={}, port={}", tcp->remote, + tcp->port); - return Node::stop(); -} + if (tcp->unit) + details.append(fmt::format(", unit={}", *tcp->unit)); + } -std::vector ModbusNode::getPollFDs() -{ - return { read_task.getFD() }; -} + if (auto rtu = std::get_if(&connection_settings)) { + details = fmt::format("transport=rtu, device={}, baudrate={}, parity={}, " + "data_bits={}, stop_bits={}, unit={}", + rtu->device.c_str(), rtu->baudrate, + static_cast(rtu->parity), rtu->data_bits, + rtu->stop_bits, rtu->unit); + } + } -std::vector ModbusNode::getNetemFDs() -{ - if (modbus_context != nullptr && std::holds_alternative(connection_settings)) { - return { - modbus_get_socket(modbus_context) - }; - } - - return { }; -} - -const std::string & ModbusNode::getDetails() -{ - if (details.empty()) { - if (auto tcp = std::get_if(&connection_settings)) { - details = fmt::format("transport=tcp, remote={}, port={}", tcp->remote, tcp->port); - - if (tcp->unit) - details.append(fmt::format(", unit={}", *tcp->unit)); - } - - if (auto rtu = std::get_if(&connection_settings)) { - details = fmt::format("transport=rtu, device={}, baudrate={}, parity={}, data_bits={}, stop_bits={}, unit={}", - rtu->device.c_str(), - rtu->baudrate, - static_cast(rtu->parity), - rtu->data_bits, - rtu->stop_bits, - rtu->unit); - } - } - - return details; + return details; } // Register node static char name[] = "modbus"; static char description[] = "Read and write Modbus registers"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/mqtt.cpp b/lib/nodes/mqtt.cpp index a20e815bf..851b36a66 100644 --- a/lib/nodes/mqtt.cpp +++ b/lib/nodes/mqtt.cpp @@ -5,526 +5,504 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, const char *str) -{ - auto *n = (NodeCompat *) ctx; +static void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, + const char *str) { + auto *n = (NodeCompat *)ctx; - switch (level) { - case MOSQ_LOG_NONE: - case MOSQ_LOG_INFO: - case MOSQ_LOG_NOTICE: - n->logger->info("{}", str); - break; + switch (level) { + case MOSQ_LOG_NONE: + case MOSQ_LOG_INFO: + case MOSQ_LOG_NOTICE: + n->logger->info("{}", str); + break; - case MOSQ_LOG_WARNING: - n->logger->warn("{}", str); - break; + case MOSQ_LOG_WARNING: + n->logger->warn("{}", str); + break; - case MOSQ_LOG_ERR: - n->logger->error("{}", str); - break; + case MOSQ_LOG_ERR: + n->logger->error("{}", str); + break; - case MOSQ_LOG_DEBUG: - n->logger->debug("{}", str); - break; - } + case MOSQ_LOG_DEBUG: + n->logger->debug("{}", str); + break; + } } -static -void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - int ret; + int ret; - n->logger->info("Connected to broker {}", m->host); + n->logger->info("Connected to broker {}", m->host); - if (m->subscribe) { - ret = mosquitto_subscribe(m->client, nullptr, m->subscribe, m->qos); - if (ret) - n->logger->warn("Failed to subscribe to topic '{}': {}", m->subscribe, mosquitto_strerror(ret)); - } - else - n->logger->warn("No subscription as no topic is configured"); + if (m->subscribe) { + ret = mosquitto_subscribe(m->client, nullptr, m->subscribe, m->qos); + if (ret) + n->logger->warn("Failed to subscribe to topic '{}': {}", m->subscribe, + mosquitto_strerror(ret)); + } else + n->logger->warn("No subscription as no topic is configured"); } -static -void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - n->logger->info("Disconnected from broker {}", m->host); + n->logger->info("Disconnected from broker {}", m->host); } -static -void mqtt_message_cb(struct mosquitto *mosq, void *ctx, const struct mosquitto_message *msg) -{ - int ret; - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); - struct Sample *smps[n->in.vectorize]; +static void mqtt_message_cb(struct mosquitto *mosq, void *ctx, + const struct mosquitto_message *msg) { + int ret; + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); + struct Sample *smps[n->in.vectorize]; - n->logger->debug("Received a message of {} bytes from broker {}", msg->payloadlen, m->host); + n->logger->debug("Received a message of {} bytes from broker {}", + msg->payloadlen, m->host); - ret = sample_alloc_many(&m->pool, smps, n->in.vectorize); - if (ret <= 0) { - n->logger->warn("Pool underrun in subscriber"); - return; - } + ret = sample_alloc_many(&m->pool, smps, n->in.vectorize); + if (ret <= 0) { + n->logger->warn("Pool underrun in subscriber"); + return; + } - ret = m->formatter->sscan((char *) msg->payload, msg->payloadlen, nullptr, smps, n->in.vectorize); - if (ret < 0) { - n->logger->warn("Received an invalid message"); - n->logger->warn(" Payload: {}", (char *) msg->payload); - return; - } + ret = m->formatter->sscan((char *)msg->payload, msg->payloadlen, nullptr, + smps, n->in.vectorize); + if (ret < 0) { + n->logger->warn("Received an invalid message"); + n->logger->warn(" Payload: {}", (char *)msg->payload); + return; + } - if (ret == 0) { - n->logger->debug("Skip empty message"); - sample_decref_many(smps, n->in.vectorize); - return; - } + if (ret == 0) { + n->logger->debug("Skip empty message"); + sample_decref_many(smps, n->in.vectorize); + return; + } - ret = queue_signalled_push_many(&m->queue, (void **) smps, n->in.vectorize); - if (ret < (int) n->in.vectorize) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push_many(&m->queue, (void **)smps, n->in.vectorize); + if (ret < (int)n->in.vectorize) + n->logger->warn("Failed to enqueue samples"); } -static -void mqtt_subscribe_cb(struct mosquitto *mosq, void *ctx, int mid, int qos_count, const int *granted_qos) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_subscribe_cb(struct mosquitto *mosq, void *ctx, int mid, + int qos_count, const int *granted_qos) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - n->logger->info("Subscribed to broker {}", m->host); + n->logger->info("Subscribed to broker {}", m->host); } -int villas::node::mqtt_reverse(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::mqtt_reverse(NodeCompat *n) { + auto *m = n->getData(); - SWAP(m->publish, m->subscribe); + SWAP(m->publish, m->subscribe); - return 0; + return 0; } -int villas::node::mqtt_init(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::mqtt_init(NodeCompat *n) { + auto *m = n->getData(); - m->client = mosquitto_new(nullptr, true, (void *) n); - if (!m->client) - return -1; + m->client = mosquitto_new(nullptr, true, (void *)n); + if (!m->client) + return -1; - mosquitto_log_callback_set(m->client, mqtt_log_cb); - mosquitto_connect_callback_set(m->client, mqtt_connect_cb); - mosquitto_disconnect_callback_set(m->client, mqtt_disconnect_cb); - mosquitto_message_callback_set(m->client, mqtt_message_cb); - mosquitto_subscribe_callback_set(m->client, mqtt_subscribe_cb); + mosquitto_log_callback_set(m->client, mqtt_log_cb); + mosquitto_connect_callback_set(m->client, mqtt_connect_cb); + mosquitto_disconnect_callback_set(m->client, mqtt_disconnect_cb); + mosquitto_message_callback_set(m->client, mqtt_message_cb); + mosquitto_subscribe_callback_set(m->client, mqtt_subscribe_cb); - m->formatter = nullptr; + m->formatter = nullptr; - // Default values - m->port = 1883; - m->qos = 0; - m->retain = 0; - m->keepalive = 5; // 5 second, minimum required for libmosquitto + // Default values + m->port = 1883; + m->qos = 0; + m->retain = 0; + m->keepalive = 5; // 5 second, minimum required for libmosquitto - m->host = nullptr; - m->username = nullptr; - m->password = nullptr; - m->publish = nullptr; - m->subscribe = nullptr; + m->host = nullptr; + m->username = nullptr; + m->password = nullptr; + m->publish = nullptr; + m->subscribe = nullptr; - m->ssl.enabled = 0; - m->ssl.insecure = 0; - m->ssl.cafile = nullptr; - m->ssl.capath = nullptr; - m->ssl.certfile = nullptr; - m->ssl.keyfile = nullptr; - m->ssl.cert_reqs = SSL_VERIFY_PEER; - m->ssl.tls_version = nullptr; - m->ssl.ciphers = nullptr; + m->ssl.enabled = 0; + m->ssl.insecure = 0; + m->ssl.cafile = nullptr; + m->ssl.capath = nullptr; + m->ssl.certfile = nullptr; + m->ssl.keyfile = nullptr; + m->ssl.cert_reqs = SSL_VERIFY_PEER; + m->ssl.tls_version = nullptr; + m->ssl.ciphers = nullptr; - return 0; + return 0; } -int villas::node::mqtt_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_parse(NodeCompat *n, json_t *json) { + int ret; + auto *m = n->getData(); - const char *host; - const char *publish = nullptr; - const char *subscribe = nullptr; - const char *username = nullptr; - const char *password = nullptr; + const char *host; + const char *publish = nullptr; + const char *subscribe = nullptr; + const char *username = nullptr; + const char *password = nullptr; - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: s }, s?: { s?: s }, s?: o, s: s, s?: i, s?: i, s?: i, s?: b, s?: s, s?: s, s?: o }", - "out", - "publish", &publish, - "in", - "subscribe", &subscribe, - "format", &json_format, - "host", &host, - "port", &m->port, - "qos", &m->qos, - "keepalive", &m->keepalive, - "retain", &m->retain, - "username", &username, - "password", &password, - "ssl", &json_ssl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-mqtt"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: s }, s?: { s?: s }, s?: o, s: s, s?: i, " + "s?: i, s?: i, s?: b, s?: s, s?: s, s?: o }", + "out", "publish", &publish, "in", "subscribe", + &subscribe, "format", &json_format, "host", &host, + "port", &m->port, "qos", &m->qos, "keepalive", + &m->keepalive, "retain", &m->retain, "username", + &username, "password", &password, "ssl", &json_ssl); + if (ret) + throw ConfigError(json, err, "node-config-node-mqtt"); - m->host = strdup(host); - m->publish = publish ? strdup(publish) : nullptr; - m->subscribe = subscribe ? strdup(subscribe) : nullptr; - m->username = username ? strdup(username) : nullptr; - m->password = password ? strdup(password) : nullptr; + m->host = strdup(host); + m->publish = publish ? strdup(publish) : nullptr; + m->subscribe = subscribe ? strdup(subscribe) : nullptr; + m->username = username ? strdup(username) : nullptr; + m->password = password ? strdup(password) : nullptr; - if (!m->publish && !m->subscribe) - throw ConfigError(json, "node-config-node-mqtt", "At least one topic has to be specified for node {}", n->getName()); + if (!m->publish && !m->subscribe) + throw ConfigError(json, "node-config-node-mqtt", + "At least one topic has to be specified for node {}", + n->getName()); - if (json_ssl) { - m->ssl.enabled = 1; + if (json_ssl) { + m->ssl.enabled = 1; - const char *cafile = nullptr; - const char *capath = nullptr; - const char *certfile = nullptr; - const char *keyfile = nullptr; - const char *tls_version = nullptr; - const char *ciphers = nullptr; + const char *cafile = nullptr; + const char *capath = nullptr; + const char *certfile = nullptr; + const char *keyfile = nullptr; + const char *tls_version = nullptr; + const char *ciphers = nullptr; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s, s?: s, s?: s, s?: b, s?: s }", - "enabled", &m->ssl.enabled, - "insecure", &m->ssl.insecure, - "cafile", &cafile, - "capath", &capath, - "certfile", &certfile, - "keyfile", &keyfile, - "cipher", &ciphers, - "verify", &m->ssl.cert_reqs, - "tls_version", &tls_version - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-mqtt-ssl", "Failed to parse SSL configuration of node {}", n->getName()); + ret = json_unpack_ex( + json_ssl, &err, 0, + "{ s?: b, s?: b, s?: s, s?: s, s?: s, s?: s, s?: s, s?: b, s?: s }", + "enabled", &m->ssl.enabled, "insecure", &m->ssl.insecure, "cafile", + &cafile, "capath", &capath, "certfile", &certfile, "keyfile", &keyfile, + "cipher", &ciphers, "verify", &m->ssl.cert_reqs, "tls_version", + &tls_version); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-mqtt-ssl", + "Failed to parse SSL configuration of node {}", + n->getName()); - if (m->ssl.enabled && !cafile && !capath) - throw ConfigError(json_ssl, "node-config-node-mqtt-ssl", "Either 'ssl.cafile' or 'ssl.capath' settings must be set for node {}.", n->getName()); + if (m->ssl.enabled && !cafile && !capath) + throw ConfigError(json_ssl, "node-config-node-mqtt-ssl", + "Either 'ssl.cafile' or 'ssl.capath' settings must be " + "set for node {}.", + n->getName()); - m->ssl.cafile = cafile ? strdup(cafile) : nullptr; - m->ssl.capath = capath ? strdup(capath) : nullptr; - m->ssl.certfile = certfile ? strdup(certfile) : nullptr; - m->ssl.keyfile = keyfile ? strdup(keyfile) : nullptr; - m->ssl.ciphers = ciphers ? strdup(ciphers) : nullptr; - } + m->ssl.cafile = cafile ? strdup(cafile) : nullptr; + m->ssl.capath = capath ? strdup(capath) : nullptr; + m->ssl.certfile = certfile ? strdup(certfile) : nullptr; + m->ssl.keyfile = keyfile ? strdup(keyfile) : nullptr; + m->ssl.ciphers = ciphers ? strdup(ciphers) : nullptr; + } - // Format - if (m->formatter) - delete m->formatter; - m->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!m->formatter) - throw ConfigError(json_format, "node-config-node-mqtt-format", "Invalid format configuration"); + // Format + if (m->formatter) + delete m->formatter; + m->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!m->formatter) + throw ConfigError(json_format, "node-config-node-mqtt-format", + "Invalid format configuration"); - return 0; + return 0; } -int villas::node::mqtt_check(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_check(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = mosquitto_sub_topic_check(m->subscribe); - if (ret != MOSQ_ERR_SUCCESS) - throw RuntimeError("Invalid subscribe topic: '{}': {}", m->subscribe, mosquitto_strerror(ret)); + ret = mosquitto_sub_topic_check(m->subscribe); + if (ret != MOSQ_ERR_SUCCESS) + throw RuntimeError("Invalid subscribe topic: '{}': {}", m->subscribe, + mosquitto_strerror(ret)); - ret = mosquitto_pub_topic_check(m->publish); - if (ret != MOSQ_ERR_SUCCESS) - throw RuntimeError("Invalid publish topic: '{}': {}", m->publish, mosquitto_strerror(ret)); + ret = mosquitto_pub_topic_check(m->publish); + if (ret != MOSQ_ERR_SUCCESS) + throw RuntimeError("Invalid publish topic: '{}': {}", m->publish, + mosquitto_strerror(ret)); - return 0; + return 0; } -int villas::node::mqtt_prepare(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_prepare(NodeCompat *n) { + int ret; + auto *m = n->getData(); - m->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + m->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&m->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&m->pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&m->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&m->queue, 1024); + if (ret) + return ret; - return 0; + return 0; } -char * villas::node::mqtt_print(NodeCompat *n) -{ - auto *m = n->getData(); +char *villas::node::mqtt_print(NodeCompat *n) { + auto *m = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "host=%s, port=%d, keepalive=%d, ssl=%s", - m->host, - m->port, - m->keepalive, - m->ssl.enabled ? "yes" : "no" - ); + strcatf(&buf, "host=%s, port=%d, keepalive=%d, ssl=%s", m->host, m->port, + m->keepalive, m->ssl.enabled ? "yes" : "no"); - // Only show if not default - if (m->username) - strcatf(&buf, ", username=%s", m->username); + // Only show if not default + if (m->username) + strcatf(&buf, ", username=%s", m->username); - if (m->publish) - strcatf(&buf, ", out.publish=%s", m->publish); + if (m->publish) + strcatf(&buf, ", out.publish=%s", m->publish); - if (m->subscribe) - strcatf(&buf, ", in.subscribe=%s", m->subscribe); + if (m->subscribe) + strcatf(&buf, ", in.subscribe=%s", m->subscribe); - return buf; + return buf; } -int villas::node::mqtt_destroy(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_destroy(NodeCompat *n) { + int ret; + auto *m = n->getData(); - mosquitto_destroy(m->client); + mosquitto_destroy(m->client); - ret = pool_destroy(&m->pool); - if (ret) - return ret; + ret = pool_destroy(&m->pool); + if (ret) + return ret; - ret = queue_signalled_destroy(&m->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&m->queue); + if (ret) + return ret; - if (m->publish) - free(m->publish); + if (m->publish) + free(m->publish); - if (m->subscribe) - free(m->subscribe); + if (m->subscribe) + free(m->subscribe); - if (m->password) - free(m->password); + if (m->password) + free(m->password); - if (m->username) - free(m->username); + if (m->username) + free(m->username); - if (m->host) - free(m->host); + if (m->host) + free(m->host); - if (m->formatter) - delete m->formatter; + if (m->formatter) + delete m->formatter; - return 0; + return 0; } -int villas::node::mqtt_start(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_start(NodeCompat *n) { + int ret; + auto *m = n->getData(); - if (m->username && m->password) { - ret = mosquitto_username_pw_set(m->client, m->username, m->password); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; - } + if (m->username && m->password) { + ret = mosquitto_username_pw_set(m->client, m->username, m->password); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; + } - if (m->ssl.enabled) { - ret = mosquitto_tls_set(m->client, m->ssl.cafile, m->ssl.capath, m->ssl.certfile, m->ssl.keyfile, nullptr); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + if (m->ssl.enabled) { + ret = mosquitto_tls_set(m->client, m->ssl.cafile, m->ssl.capath, + m->ssl.certfile, m->ssl.keyfile, nullptr); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_tls_insecure_set(m->client, m->ssl.insecure); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_tls_insecure_set(m->client, m->ssl.insecure); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_tls_opts_set(m->client, m->ssl.cert_reqs, m->ssl.tls_version, m->ssl.ciphers); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; - } + ret = mosquitto_tls_opts_set(m->client, m->ssl.cert_reqs, + m->ssl.tls_version, m->ssl.ciphers); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; + } - ret = mosquitto_connect(m->client, m->host, m->port, m->keepalive); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_connect(m->client, m->host, m->port, m->keepalive); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_loop_start(m->client); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_loop_start(m->client); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - n->logger->warn("{}", mosquitto_strerror(ret)); + n->logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_stop(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_stop(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = mosquitto_disconnect(m->client); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_disconnect(m->client); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_loop_stop(m->client, false); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_loop_stop(m->client, false); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = queue_signalled_close(&m->queue); - if (ret) - return ret; + ret = queue_signalled_close(&m->queue); + if (ret) + return ret; - return 0; + return 0; mosquitto_error: - n->logger->warn("{}", mosquitto_strerror(ret)); + n->logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::mqtt_type_start(villas::node::SuperNode *sn) { + int ret; - ret = mosquitto_lib_init(); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_lib_init(); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - auto logger = logging.get("node:mqtt"); - logger->warn("{}", mosquitto_strerror(ret)); + auto logger = logging.get("node:mqtt"); + logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_type_stop() -{ - int ret; +int villas::node::mqtt_type_stop() { + int ret; - ret = mosquitto_lib_cleanup(); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_lib_cleanup(); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - auto logger = logging.get("node:mqtt"); - logger->warn("{}", mosquitto_strerror(ret)); + auto logger = logging.get("node:mqtt"); + logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *m = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::mqtt_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *m = n->getData(); + struct Sample *smpt[cnt]; - pulled = queue_signalled_pull_many(&m->queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&m->queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *m = n->getData(); - size_t wbytes; + size_t wbytes; - char data[1500]; + char data[1500]; - ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret < 0) + return ret; - if (m->publish) { - ret = mosquitto_publish(m->client, nullptr /* mid */, m->publish, wbytes, data, m->qos, m->retain); - if (ret != MOSQ_ERR_SUCCESS) { - n->logger->warn("Publish failed: {}", mosquitto_strerror(ret)); - return -abs(ret); - } - } - else - n->logger->warn("No publish possible because no publish topic is configured"); + if (m->publish) { + ret = mosquitto_publish(m->client, nullptr /* mid */, m->publish, wbytes, + data, m->qos, m->retain); + if (ret != MOSQ_ERR_SUCCESS) { + n->logger->warn("Publish failed: {}", mosquitto_strerror(ret)); + return -abs(ret); + } + } else + n->logger->warn( + "No publish possible because no publish topic is configured"); - return cnt; + return cnt; } -int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) -{ - auto *m = n->getData(); +int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) { + auto *m = n->getData(); - fds[0] = queue_signalled_fd(&m->queue); + fds[0] = queue_signalled_fd(&m->queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "mqtt"; - p.description = "Message Queuing Telemetry Transport (libmosquitto)"; - p.vectorize = 0; - p.size = sizeof(struct mqtt); - p.type.start = mqtt_type_start; - p.type.stop = mqtt_type_stop; - p.destroy = mqtt_destroy; - p.prepare = mqtt_prepare; - p.parse = mqtt_parse; - p.check = mqtt_check; - p.prepare = mqtt_prepare; - p.print = mqtt_print; - p.init = mqtt_init; - p.destroy = mqtt_destroy; - p.start = mqtt_start; - p.stop = mqtt_stop; - p.read = mqtt_read; - p.write = mqtt_write; - p.reverse = mqtt_reverse; - p.poll_fds = mqtt_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "mqtt"; + p.description = "Message Queuing Telemetry Transport (libmosquitto)"; + p.vectorize = 0; + p.size = sizeof(struct mqtt); + p.type.start = mqtt_type_start; + p.type.stop = mqtt_type_stop; + p.destroy = mqtt_destroy; + p.prepare = mqtt_prepare; + p.parse = mqtt_parse; + p.check = mqtt_check; + p.prepare = mqtt_prepare; + p.print = mqtt_print; + p.init = mqtt_init; + p.destroy = mqtt_destroy; + p.start = mqtt_start; + p.stop = mqtt_stop; + p.read = mqtt_read; + p.write = mqtt_write; + p.reverse = mqtt_reverse; + p.poll_fds = mqtt_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/nanomsg.cpp b/lib/nodes/nanomsg.cpp index 61acc74a5..55a113b8b 100644 --- a/lib/nodes/nanomsg.cpp +++ b/lib/nodes/nanomsg.cpp @@ -5,312 +5,297 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::nanomsg_init(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_init(NodeCompat *n) { + auto *m = n->getData(); - m->formatter = nullptr; + m->formatter = nullptr; - return 0; + return 0; } -int villas::node::nanomsg_destroy(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_destroy(NodeCompat *n) { + auto *m = n->getData(); - if (m->formatter) - delete m->formatter; + if (m->formatter) + delete m->formatter; - return 0; + return 0; } -int villas::node::nanomsg_reverse(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_reverse(NodeCompat *n) { + auto *m = n->getData(); - if (list_length(&m->out.endpoints) != 1 || - list_length(&m->in.endpoints) != 1) - return -1; + if (list_length(&m->out.endpoints) != 1 || list_length(&m->in.endpoints) != 1) + return -1; - char *subscriber = (char *) list_first(&m->in.endpoints); - char *publisher = (char *) list_first(&m->out.endpoints); + char *subscriber = (char *)list_first(&m->in.endpoints); + char *publisher = (char *)list_first(&m->out.endpoints); - list_set(&m->in.endpoints, 0, publisher); - list_set(&m->out.endpoints, 0, subscriber); + list_set(&m->in.endpoints, 0, publisher); + list_set(&m->out.endpoints, 0, subscriber); - return 0; + return 0; } -static -int nanomsg_parse_endpoints(struct List *l, json_t *json) -{ - const char *ep; +static int nanomsg_parse_endpoints(struct List *l, json_t *json) { + const char *ep; - size_t i; - json_t *json_val; + size_t i; + json_t *json_val; - switch (json_typeof(json)) { - case JSON_ARRAY: - json_array_foreach(json, i, json_val) { - ep = json_string_value(json_val); - if (!ep) - return -1; + switch (json_typeof(json)) { + case JSON_ARRAY: + json_array_foreach(json, i, json_val) { + ep = json_string_value(json_val); + if (!ep) + return -1; - list_push(l, strdup(ep)); - } - break; + list_push(l, strdup(ep)); + } + break; - case JSON_STRING: - ep = json_string_value(json); + case JSON_STRING: + ep = json_string_value(json); - list_push(l, strdup(ep)); - break; + list_push(l, strdup(ep)); + break; - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } -int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) { + int ret; + auto *m = n->getData(); - json_error_t err; - json_t *json_format = nullptr; - json_t *json_out_endpoints = nullptr; - json_t *json_in_endpoints = nullptr; + json_error_t err; + json_t *json_format = nullptr; + json_t *json_out_endpoints = nullptr; + json_t *json_in_endpoints = nullptr; - ret = list_init(&m->out.endpoints); - if (ret) - return ret; + ret = list_init(&m->out.endpoints); + if (ret) + return ret; - ret = list_init(&m->in.endpoints); - if (ret) - return ret; + ret = list_init(&m->in.endpoints); + if (ret) + return ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: { s?: o }, s?: { s?: o } }", - "format", &json_format, - "out", - "endpoints", &json_out_endpoints, - "in", - "endpoints", &json_in_endpoints - ); - if (ret) - throw ConfigError(json, err, "node-config-node-nanomsg"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: { s?: o }, s?: { s?: o } }", + "format", &json_format, "out", "endpoints", + &json_out_endpoints, "in", "endpoints", + &json_in_endpoints); + if (ret) + throw ConfigError(json, err, "node-config-node-nanomsg"); - if (json_out_endpoints) { - ret = nanomsg_parse_endpoints(&m->out.endpoints, json_out_endpoints); - if (ret < 0) - throw RuntimeError("Invalid type for 'publish' setting"); - } + if (json_out_endpoints) { + ret = nanomsg_parse_endpoints(&m->out.endpoints, json_out_endpoints); + if (ret < 0) + throw RuntimeError("Invalid type for 'publish' setting"); + } - if (json_in_endpoints) { - ret = nanomsg_parse_endpoints(&m->in.endpoints, json_in_endpoints); - if (ret < 0) - throw RuntimeError("Invalid type for 'subscribe' setting"); - } + if (json_in_endpoints) { + ret = nanomsg_parse_endpoints(&m->in.endpoints, json_in_endpoints); + if (ret < 0) + throw RuntimeError("Invalid type for 'subscribe' setting"); + } - // Format - if (m->formatter) - delete m->formatter; - m->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!m->formatter) - throw ConfigError(json_format, "node-config-node-nanomsg-format", "Invalid format configuration"); + // Format + if (m->formatter) + delete m->formatter; + m->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!m->formatter) + throw ConfigError(json_format, "node-config-node-nanomsg-format", + "Invalid format configuration"); - return 0; + return 0; } -char * villas::node::nanomsg_print(NodeCompat *n) -{ - auto *m = n->getData(); +char *villas::node::nanomsg_print(NodeCompat *n) { + auto *m = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "in.endpoints=[ "); + strcatf(&buf, "in.endpoints=[ "); - for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { - char *ep = (char *) list_at(&m->in.endpoints, i); + for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { + char *ep = (char *)list_at(&m->in.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "], out.endpoints=[ "); + strcatf(&buf, "], out.endpoints=[ "); - for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { - char *ep = (char *) list_at(&m->out.endpoints, i); + for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { + char *ep = (char *)list_at(&m->out.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "]"); + strcatf(&buf, "]"); - return buf; + return buf; } -int villas::node::nanomsg_start(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_start(NodeCompat *n) { + int ret; + auto *m = n->getData(); - m->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + m->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = m->in.socket = nn_socket(AF_SP, NN_SUB); - if (ret < 0) - throw RuntimeError("Failed to create nanomsg socket: {}", nn_strerror(errno)); + ret = m->in.socket = nn_socket(AF_SP, NN_SUB); + if (ret < 0) + throw RuntimeError("Failed to create nanomsg socket: {}", + nn_strerror(errno)); - ret = m->out.socket = nn_socket(AF_SP, NN_PUB); - if (ret < 0) - throw RuntimeError("Failed to create nanomsg socket: {}", nn_strerror(errno)); + ret = m->out.socket = nn_socket(AF_SP, NN_PUB); + if (ret < 0) + throw RuntimeError("Failed to create nanomsg socket: {}", + nn_strerror(errno)); - // Subscribe to all topics - ret = nn_setsockopt(ret = m->in.socket, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); - if (ret < 0) - return ret; + // Subscribe to all topics + ret = nn_setsockopt(ret = m->in.socket, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); + if (ret < 0) + return ret; - // Bind publisher to socket - for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { - char *ep = (char *) list_at(&m->out.endpoints, i); + // Bind publisher to socket + for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { + char *ep = (char *)list_at(&m->out.endpoints, i); - ret = nn_bind(m->out.socket, ep); - if (ret < 0) - throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", ep, nn_strerror(errno)); - } + ret = nn_bind(m->out.socket, ep); + if (ret < 0) + throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", + ep, nn_strerror(errno)); + } - // Connect subscribers socket - for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { - char *ep = (char *) list_at(&m->in.endpoints, i); + // Connect subscribers socket + for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { + char *ep = (char *)list_at(&m->in.endpoints, i); - ret = nn_connect(m->in.socket, ep); - if (ret < 0) - throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", ep, nn_strerror(errno)); - } + ret = nn_connect(m->in.socket, ep); + if (ret < 0) + throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", + ep, nn_strerror(errno)); + } - return 0; + return 0; } -int villas::node::nanomsg_stop(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_stop(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = nn_close(m->in.socket); - if (ret < 0) - return ret; + ret = nn_close(m->in.socket); + if (ret < 0) + return ret; - ret = nn_close(m->out.socket); - if (ret < 0) - return ret; + ret = nn_close(m->out.socket); + if (ret < 0) + return ret; - return 0; + return 0; } -int villas::node::nanomsg_type_stop() -{ - nn_term(); +int villas::node::nanomsg_type_stop() { + nn_term(); - return 0; + return 0; } -int villas::node::nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *m = n->getData(); - int bytes; - char data[NANOMSG_MAX_PACKET_LEN]; +int villas::node::nanomsg_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *m = n->getData(); + int bytes; + char data[NANOMSG_MAX_PACKET_LEN]; - // Receive payload - bytes = nn_recv(m->in.socket, data, sizeof(data), 0); - if (bytes < 0) - return -1; + // Receive payload + bytes = nn_recv(m->in.socket, data, sizeof(data), 0); + if (bytes < 0) + return -1; - return m->formatter->sscan(data, bytes, nullptr, smps, cnt); + return m->formatter->sscan(data, bytes, nullptr, smps, cnt); } -int villas::node::nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *m = n->getData(); - size_t wbytes; + size_t wbytes; - char data[NANOMSG_MAX_PACKET_LEN]; + char data[NANOMSG_MAX_PACKET_LEN]; - ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - ret = nn_send(m->out.socket, data, wbytes, 0); - if (ret < 0) - return ret; + ret = nn_send(m->out.socket, data, wbytes, 0); + if (ret < 0) + return ret; - return cnt; + return cnt; } -int villas::node::nanomsg_poll_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_poll_fds(NodeCompat *n, int fds[]) { + int ret; + auto *m = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = nn_getsockopt(m->in.socket, NN_SOL_SOCKET, NN_RCVFD, &fd, &len); - if (ret) - return ret; + ret = nn_getsockopt(m->in.socket, NN_SOL_SOCKET, NN_RCVFD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) -{ - auto *m = n->getData(); +int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) { + auto *m = n->getData(); - fds[0] = m->out.socket; + fds[0] = m->out.socket; - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "nanomsg"; - p.description = "scalability protocols library (libnanomsg)"; - p.vectorize = 0; - p.size = sizeof(struct nanomsg); - p.type.stop = nanomsg_type_stop; - p.init = nanomsg_init; - p.destroy = nanomsg_destroy; - p.parse = nanomsg_parse; - p.print = nanomsg_print; - p.start = nanomsg_start; - p.stop = nanomsg_stop; - p.read = nanomsg_read; - p.write = nanomsg_write; - p.reverse = nanomsg_reverse; - p.poll_fds = nanomsg_poll_fds; - p.netem_fds = nanomsg_netem_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "nanomsg"; + p.description = "scalability protocols library (libnanomsg)"; + p.vectorize = 0; + p.size = sizeof(struct nanomsg); + p.type.stop = nanomsg_type_stop; + p.init = nanomsg_init; + p.destroy = nanomsg_destroy; + p.parse = nanomsg_parse; + p.print = nanomsg_print; + p.start = nanomsg_start; + p.stop = nanomsg_stop; + p.read = nanomsg_read; + p.write = nanomsg_write; + p.reverse = nanomsg_reverse; + p.poll_fds = nanomsg_poll_fds; + p.netem_fds = nanomsg_netem_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ngsi.cpp b/lib/nodes/ngsi.cpp index 5088ab86f..aeb00d7f0 100644 --- a/lib/nodes/ngsi.cpp +++ b/lib/nodes/ngsi.cpp @@ -5,24 +5,24 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include #include -#include -#include #include #include -#include +#include +#include +#include +#include +#include #include #include -#include #include -#include #include -#include +#include using namespace villas; using namespace villas::node; @@ -31,843 +31,808 @@ using namespace villas::utils; // Some global settings #if OPENSSL_VERSION_NUMBER < 0x010003000L - // See: https://curl.haxx.se/libcurl/c/opensslthreadlock.html - #define CURL_SSL_REQUIRES_LOCKING +// See: https://curl.haxx.se/libcurl/c/opensslthreadlock.html +#define CURL_SSL_REQUIRES_LOCKING #endif #ifdef CURL_SSL_REQUIRES_LOCKING // This array will store all of the mutexes available to OpenSSL. -static -pthread_mutex_t *mutex_buf = NULL; +static pthread_mutex_t *mutex_buf = NULL; -static -void handle_error(const char *file, int lineno, const char *msg) -{ - auto logger = logging.get("curl"); +static void handle_error(const char *file, int lineno, const char *msg) { + auto logger = logging.get("curl"); - logger->error("** {}:{} {}", file, lineno, msg); + logger->error("** {}:{} {}", file, lineno, msg); - ERR_print_errors_fp(stderr); + ERR_print_errors_fp(stderr); - // exit(-1); + // exit(-1); } -static -void curl_ssl_locking_function(int mode, int n, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&mutex_buf[n]); - else - pthread_mutex_unlock(&mutex_buf[n]); +static void curl_ssl_locking_function(int mode, int n, const char *file, + int line) { + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&mutex_buf[n]); + else + pthread_mutex_unlock(&mutex_buf[n]); } -static -unsigned long curl_ssl_thread_id_function(void) -{ - return ((unsigned long) pthread_self()); +static unsigned long curl_ssl_thread_id_function(void) { + return ((unsigned long)pthread_self()); } #endif // CURL_SSL_REQUIRES_LOCKING enum NgsiFlags { - NGSI_ENTITY_ATTRIBUTES_IN = (1 << 0), - NGSI_ENTITY_ATTRIBUTES_OUT = (1 << 1), - NGSI_ENTITY_ATTRIBUTES = NGSI_ENTITY_ATTRIBUTES_IN | NGSI_ENTITY_ATTRIBUTES_OUT, - NGSI_ENTITY_VALUES = (1 << 2), - NGSI_ENTITY_METADATA = (1 << 3), + NGSI_ENTITY_ATTRIBUTES_IN = (1 << 0), + NGSI_ENTITY_ATTRIBUTES_OUT = (1 << 1), + NGSI_ENTITY_ATTRIBUTES = + NGSI_ENTITY_ATTRIBUTES_IN | NGSI_ENTITY_ATTRIBUTES_OUT, + NGSI_ENTITY_VALUES = (1 << 2), + NGSI_ENTITY_METADATA = (1 << 3), }; class NgsiMetadata { public: - NgsiMetadata(json_t *json) - { - parse(json); - } + NgsiMetadata(json_t *json) { parse(json); } - NgsiMetadata(const std::string &nam, const std::string &typ, const std::string &val) : - name(nam), - type(typ), - value(val) - { } + NgsiMetadata(const std::string &nam, const std::string &typ, + const std::string &val) + : name(nam), type(typ), value(val) {} - void parse(json_t *json) - { - int ret; + void parse(json_t *json) { + int ret; - json_error_t err; - const char *nam, *typ, *val; + json_error_t err; + const char *nam, *typ, *val; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s }", - "name", &nam, - "type", &typ, - "value", &val - ); - if (ret) - throw ConfigError(json, "node-config-node-ngsi-metadata", "Failed to parse NGSI metadata"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s }", "name", &nam, + "type", &typ, "value", &val); + if (ret) + throw ConfigError(json, "node-config-node-ngsi-metadata", + "Failed to parse NGSI metadata"); - name = nam; - type = typ; - value = val; - } + name = nam; + type = typ; + value = val; + } - std::string name; - std::string type; - std::string value; + std::string name; + std::string type; + std::string value; }; class NgsiAttribute { public: - std::string name; - std::string type; + std::string name; + std::string type; - size_t index; - std::list metadata; + size_t index; + std::list metadata; - NgsiAttribute(json_t *json, size_t j, Signal::Ptr s) - { - parse(json, j, s); - } + NgsiAttribute(json_t *json, size_t j, Signal::Ptr s) { parse(json, j, s); } - void parse(json_t *json, size_t j, Signal::Ptr s) - { - int ret; + void parse(json_t *json, size_t j, Signal::Ptr s) { + int ret; - json_error_t err; - json_t *json_metadatas = nullptr; + json_error_t err; + json_t *json_metadatas = nullptr; - const char *nam = nullptr; - const char *typ = nullptr; + const char *nam = nullptr; + const char *typ = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o }", - "ngsi_attribute_name", &nam, - "ngsi_attribute_type", &typ, - "ngsi_metadatas", &json_metadatas - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ngsi", "Failed to parse NGSI attribute"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o }", + "ngsi_attribute_name", &nam, "ngsi_attribute_type", + &typ, "ngsi_metadatas", &json_metadatas); + if (ret) + throw ConfigError(json, err, "node-config-node-ngsi", + "Failed to parse NGSI attribute"); - // Copy values from node signal, if 'ngsi_attribute' settings not provided - if (s && !nam) - nam = !s->name.empty() ? s->name.c_str() : ""; + // Copy values from node signal, if 'ngsi_attribute' settings not provided + if (s && !nam) + nam = !s->name.empty() ? s->name.c_str() : ""; - if (s && !typ) - typ = !s->unit.empty() ? s->unit.c_str() : ""; + if (s && !typ) + typ = !s->unit.empty() ? s->unit.c_str() : ""; - name = nam; - type = typ; - index = j; + name = nam; + type = typ; + index = j; - if (json_metadatas) { - if (!json_is_array(json_metadatas)) - throw ConfigError(json_metadatas, "node-config-node-ngsi-metadata", "ngsi_metadata must be a list of objects"); + if (json_metadatas) { + if (!json_is_array(json_metadatas)) + throw ConfigError(json_metadatas, "node-config-node-ngsi-metadata", + "ngsi_metadata must be a list of objects"); - json_t *json_metadata; + json_t *json_metadata; - // cppcheck-suppress unknownMacro - json_array_foreach(json_metadatas, j, json_metadata) - metadata.emplace_back(json_metadata); - } + // cppcheck-suppress unknownMacro + json_array_foreach(json_metadatas, j, json_metadata) + metadata.emplace_back(json_metadata); + } - // Metadata: index(integer)=j - metadata.emplace_back("index", "integer", fmt::format("{}", j)); - } + // Metadata: index(integer)=j + metadata.emplace_back("index", "integer", fmt::format("{}", j)); + } - json_t * build(const struct Sample * const smps[], unsigned cnt, int flags) - { - json_t *json_attribute = json_pack("{ s: s, s: s }", - "name", name.c_str(), - "type", type.c_str() - ); + json_t *build(const struct Sample *const smps[], unsigned cnt, int flags) { + json_t *json_attribute = + json_pack("{ s: s, s: s }", "name", name.c_str(), "type", type.c_str()); - if (flags & NGSI_ENTITY_VALUES) { + if (flags & NGSI_ENTITY_VALUES) { #if NGSI_VECTORS - // Build value vector - json_t *json_value = json_array(); + // Build value vector + json_t *json_value = json_array(); - for (unsigned k = 0; k < cnt; k++) { - const auto *smp = &smps[k]; - const auto *data = &smp->data[index]; - auto sig = smp->signals->getByIndex(index); + for (unsigned k = 0; k < cnt; k++) { + const auto *smp = &smps[k]; + const auto *data = &smp->data[index]; + auto sig = smp->signals->getByIndex(index); - json_array_append_new(json_value, json_pack("[ f, o, i ]", - time_to_double(smp->ts.origin), - data->toJson(sig->type), - smp->sequence - )); - } + json_array_append_new( + json_value, json_pack("[ f, o, i ]", time_to_double(smp->ts.origin), + data->toJson(sig->type), smp->sequence)); + } #else - const auto *smp = smps[0]; - const auto sig = smp->signals->getByIndex(index); - const auto *data = &smp->data[index]; + const auto *smp = smps[0]; + const auto sig = smp->signals->getByIndex(index); + const auto *data = &smp->data[index]; - json_t *json_value = data->toJson(sig->type); + json_t *json_value = data->toJson(sig->type); #endif - json_object_set(json_attribute, "value", json_value); - } + json_object_set(json_attribute, "value", json_value); + } - if (flags & NGSI_ENTITY_METADATA) { // Create Metadata for attribute - json_t *json_metadatas = json_array(); + if (flags & NGSI_ENTITY_METADATA) { // Create Metadata for attribute + json_t *json_metadatas = json_array(); - for (auto &meta : metadata) { - json_array_append_new(json_metadatas, json_pack("{ s: s, s: s, s: s }", - "name", meta.name.c_str(), - "type", meta.type.c_str(), - "value", meta.value.c_str() - )); - } + for (auto &meta : metadata) { + json_array_append_new( + json_metadatas, + json_pack("{ s: s, s: s, s: s }", "name", meta.name.c_str(), "type", + meta.type.c_str(), "value", meta.value.c_str())); + } - json_object_set(json_attribute, "metadatas", json_metadatas); - } + json_object_set(json_attribute, "metadatas", json_metadatas); + } - return json_attribute; - } + return json_attribute; + } }; struct ngsi_response { - char *data; - size_t len; + char *data; + size_t len; }; -static -json_t* ngsi_build_entity(NodeCompat *n, const struct Sample * const smps[], unsigned cnt, int flags) -{ - auto *i = n->getData(); +static json_t *ngsi_build_entity(NodeCompat *n, + const struct Sample *const smps[], + unsigned cnt, int flags) { + auto *i = n->getData(); - json_t *json_entity = json_pack("{ s: s, s: s, s: b }", - "id", i->entity_id, - "type", i->entity_type, - "isPattern", 0 - ); + json_t *json_entity = json_pack("{ s: s, s: s, s: b }", "id", i->entity_id, + "type", i->entity_type, "isPattern", 0); - if (flags & NGSI_ENTITY_ATTRIBUTES) { - json_t *json_attrs = json_array(); + if (flags & NGSI_ENTITY_ATTRIBUTES) { + json_t *json_attrs = json_array(); - if (flags & NGSI_ENTITY_ATTRIBUTES_IN) { - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->in.signals, j); + if (flags & NGSI_ENTITY_ATTRIBUTES_IN) { + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->in.signals, j); - auto *json_attr = attr->build(smps, cnt, flags); + auto *json_attr = attr->build(smps, cnt, flags); - json_array_append_new(json_attrs, json_attr); - } - } + json_array_append_new(json_attrs, json_attr); + } + } - if (flags & NGSI_ENTITY_ATTRIBUTES_OUT) { - for (size_t j = 0; j < list_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->out.signals, j); + if (flags & NGSI_ENTITY_ATTRIBUTES_OUT) { + for (size_t j = 0; j < list_length(&i->out.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->out.signals, j); - auto *json_attr = attr->build(smps, cnt, flags); + auto *json_attr = attr->build(smps, cnt, flags); - json_array_append_new(json_attrs, json_attr); - } - } + json_array_append_new(json_attrs, json_attr); + } + } - json_object_set(json_entity, "attributes", json_attrs); - } + json_object_set(json_entity, "attributes", json_attrs); + } - return json_entity; + return json_entity; } -static -int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const smps[], unsigned cnt) -{ - int ret, length = 0; - const char *id, *name, *type; +static int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, + struct Sample *const smps[], unsigned cnt) { + int ret, length = 0; + const char *id, *name, *type; - auto *i = n->getData(); + auto *i = n->getData(); - size_t l; - json_error_t err; - json_t *json_attr, *json_attrs; + size_t l; + json_error_t err; + json_t *json_attr, *json_attrs; - ret = json_unpack_ex(json_entity, &err, 0, "{ s: s, s: s, s: o }", - "id", &id, - "type", &type, - "attributes", &json_attrs - ); - if (ret || !json_is_array(json_attrs)) - return -1; + ret = json_unpack_ex(json_entity, &err, 0, "{ s: s, s: s, s: o }", "id", &id, + "type", &type, "attributes", &json_attrs); + if (ret || !json_is_array(json_attrs)) + return -1; - if (strcmp(id, i->entity_id) || strcmp(type, i->entity_type)) - return -2; + if (strcmp(id, i->entity_id) || strcmp(type, i->entity_type)) + return -2; - json_array_foreach(json_attrs, l, json_attr) { - NgsiAttribute *attr; - json_error_t err; - json_t *json_metadata, *json_value; + json_array_foreach(json_attrs, l, json_attr) { + NgsiAttribute *attr; + json_error_t err; + json_t *json_metadata, *json_value; - char *end; - const char *value; + char *end; + const char *value; - // Parse JSON - ret = json_unpack_ex(json_attr, &err, 0, "{ s: s, s: s, s: o, s?: o }", - "name", &name, - "type", &type, - "value", &json_value, - "metadatas", &json_metadata - ); - if (ret) - return -3; + // Parse JSON + ret = json_unpack_ex(json_attr, &err, 0, "{ s: s, s: s, s: o, s?: o }", + "name", &name, "type", &type, "value", &json_value, + "metadatas", &json_metadata); + if (ret) + return -3; - // Check attribute name and type - attr = list_lookup_name(&i->in.signals, name); - if (!attr || attr->type != type) - continue; // skip unknown attributes + // Check attribute name and type + attr = list_lookup_name(&i->in.signals, name); + if (!attr || attr->type != type) + continue; // skip unknown attributes - length++; + length++; - // Check metadata - if (!json_is_array(json_metadata)) - return -5; + // Check metadata + if (!json_is_array(json_metadata)) + return -5; #ifdef NGSI_VECTORS - json_t *json_tuple; - const char *ts, *seq; + json_t *json_tuple; + const char *ts, *seq; - // Check number of values - if (!json_is_array(json_value) || json_array_size(json_value) != cnt) - return -6; + // Check number of values + if (!json_is_array(json_value) || json_array_size(json_value) != cnt) + return -6; - size_t k; - json_array_foreach(json_value, k, json_tuple) { - struct Sample *smp = smps[k]; + size_t k; + json_array_foreach(json_value, k, json_tuple) { + struct Sample *smp = smps[k]; - // Check sample format - if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) - return -7; + // Check sample format + if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) + return -7; - ret = json_unpack_ex(json_tuple, &err, 0, "[ s, s, s ]", &ts, &value, &seq); - if (ret) - return -8; + ret = + json_unpack_ex(json_tuple, &err, 0, "[ s, s, s ]", &ts, &value, &seq); + if (ret) + return -8; - smp->sequence = atoi(seq); + smp->sequence = atoi(seq); - struct timespec tss = time_from_double(strtod(ts, &end)); - if (ts == end) - return -9; + struct timespec tss = time_from_double(strtod(ts, &end)); + if (ts == end) + return -9; - smp->ts.origin = tss; + smp->ts.origin = tss; - auto *sd = &smp->data[attr->index]; - auto sig = n->getInputSignals(false)->getByIndex(attr->index); - if (!sig) - return -11; + auto *sd = &smp->data[attr->index]; + auto sig = n->getInputSignals(false)->getByIndex(attr->index); + if (!sig) + return -11; - if (value[0] == '\0') // No data on Orion CB? -> Use init value - *sd = sig->init; - else { - signal_data_parse_str(sd, sig->type, value, &end); - if (value == end) - return -10; - } - } + if (value[0] == '\0') // No data on Orion CB? -> Use init value + *sd = sig->init; + else { + signal_data_parse_str(sd, sig->type, value, &end); + if (value == end) + return -10; + } + } #else - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - // Check number of values - if (!json_is_string(json_value)) - return -6; + // Check number of values + if (!json_is_string(json_value)) + return -6; - value = json_string_value(json_value); + value = json_string_value(json_value); - auto *data = &smp->data[attr->index]; - auto sig = n->getInputSignals(false)->getByIndex(attr->index); - if (!sig) - return -11; + auto *data = &smp->data[attr->index]; + auto sig = n->getInputSignals(false)->getByIndex(attr->index); + if (!sig) + return -11; - if (value[0] == '\0') // No data on Orion CB? -> Use init value - *data = sig->init; - else { - data->parseString(sig->type, value, &end); - if (value == end) - return -10; - } + if (value[0] == '\0') // No data on Orion CB? -> Use init value + *data = sig->init; + else { + data->parseString(sig->type, value, &end); + if (value == end) + return -10; + } #endif - } + } - for (unsigned k = 0; k < cnt; k++) { - struct Sample *smp = smps[k]; + for (unsigned k = 0; k < cnt; k++) { + struct Sample *smp = smps[k]; - smp->length = length; - smp->signals = n->getInputSignals(false); - smp->flags = (int) SampleFlags::HAS_DATA; + smp->length = length; + smp->signals = n->getInputSignals(false); + smp->flags = (int)SampleFlags::HAS_DATA; #ifdef NGSI_VECTORS - smp->flags |= (int) (SampleFlags::HAS_SEQUENCE | - SampleFlags::HAS_TS_ORIGIN); + smp->flags |= (int)(SampleFlags::HAS_SEQUENCE | SampleFlags::HAS_TS_ORIGIN); #endif - } + } - return cnt; + return cnt; } -static -int ngsi_parse_signals(json_t *json_signals, struct List *ngsi_signals, SignalList::Ptr node_signals) -{ - size_t j; - json_t *json_signal; +static int ngsi_parse_signals(json_t *json_signals, struct List *ngsi_signals, + SignalList::Ptr node_signals) { + size_t j; + json_t *json_signal; - if (!json_is_array(json_signals)) - return -1; + if (!json_is_array(json_signals)) + return -1; - json_array_foreach(json_signals, j, json_signal) { - auto s = node_signals->getByIndex(j); - auto *a = new NgsiAttribute(json_signal, j, s); - if (!a) - throw MemoryAllocationError(); + json_array_foreach(json_signals, j, json_signal) { + auto s = node_signals->getByIndex(j); + auto *a = new NgsiAttribute(json_signal, j, s); + if (!a) + throw MemoryAllocationError(); - list_push(ngsi_signals, a); - } + list_push(ngsi_signals, a); + } - return 0; + return 0; } -static -int ngsi_parse_context_response(json_t *json_response, int *code, char **reason, json_t **json_rentity, Logger logger) { - int ret; - char *codestr; +static int ngsi_parse_context_response(json_t *json_response, int *code, + char **reason, json_t **json_rentity, + Logger logger) { + int ret; + char *codestr; - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json_response, &err, 0, "{ s: [ { s: O, s: { s: s, s: s } } ] }", - "contextResponses", - "contextElement", json_rentity, - "statusCode", - "code", &codestr, - "reasonPhrase", reason - ); - if (ret) { - logger->warn("Failed to find NGSI response code"); - return ret; - } + ret = json_unpack_ex(json_response, &err, 0, + "{ s: [ { s: O, s: { s: s, s: s } } ] }", + "contextResponses", "contextElement", json_rentity, + "statusCode", "code", &codestr, "reasonPhrase", reason); + if (ret) { + logger->warn("Failed to find NGSI response code"); + return ret; + } - *code = atoi(codestr); + *code = atoi(codestr); - if (*code != 200) - logger->warn("NGSI response: {} {}", codestr, *reason); + if (*code != 200) + logger->warn("NGSI response: {} {}", codestr, *reason); - return ret; + return ret; } -static -size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, void *userp) -{ - size_t realsize = size * nmemb; - struct ngsi_response *mem = (struct ngsi_response *) userp; +static size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, + void *userp) { + size_t realsize = size * nmemb; + struct ngsi_response *mem = (struct ngsi_response *)userp; - mem->data = (char *) realloc(mem->data, mem->len + realsize + 1); - if (mem->data == nullptr) // out of memory! - throw MemoryAllocationError(); + mem->data = (char *)realloc(mem->data, mem->len + realsize + 1); + if (mem->data == nullptr) // out of memory! + throw MemoryAllocationError(); - memcpy(&(mem->data[mem->len]), contents, realsize); - mem->len += realsize; - mem->data[mem->len] = 0; + memcpy(&(mem->data[mem->len]), contents, realsize); + mem->len += realsize; + mem->data[mem->len] = 0; - return realsize; + return realsize; } -static -int ngsi_request(CURL *handle, const char *endpoint, const char *operation, json_t *json_request, json_t **json_response, Logger logger) -{ - struct ngsi_response chunk = { 0 }; - char *post = json_dumps(json_request, JSON_INDENT(4)); - int old; - double time; - char url[128]; - json_error_t err; +static int ngsi_request(CURL *handle, const char *endpoint, + const char *operation, json_t *json_request, + json_t **json_response, Logger logger) { + struct ngsi_response chunk = {0}; + char *post = json_dumps(json_request, JSON_INDENT(4)); + int old; + double time; + char url[128]; + json_error_t err; - snprintf(url, sizeof(url), "%s/v1/%s", endpoint, operation); + snprintf(url, sizeof(url), "%s/v1/%s", endpoint, operation); - curl_easy_setopt(handle, CURLOPT_URL, url); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ngsi_request_writer); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *) &chunk); - curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(post)); - curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post); + curl_easy_setopt(handle, CURLOPT_URL, url); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ngsi_request_writer); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(post)); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post); - logger->debug("Request to context broker: {}\n{}", url, post); + logger->debug("Request to context broker: {}\n{}", url, post); - // We don't want to leave the handle in an invalid state - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); - CURLcode ret = curl_easy_perform(handle); - pthread_setcancelstate(old, nullptr); + // We don't want to leave the handle in an invalid state + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); + CURLcode ret = curl_easy_perform(handle); + pthread_setcancelstate(old, nullptr); - if (ret) { - logger->warn("HTTP request failed: {}", curl_easy_strerror(ret)); - goto out; - } + if (ret) { + logger->warn("HTTP request failed: {}", curl_easy_strerror(ret)); + goto out; + } - curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); + curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); - logger->debug("Request to context broker completed in {} seconds", time); - logger->debug("Response from context broker:\n{}", chunk.data); + logger->debug("Request to context broker completed in {} seconds", time); + logger->debug("Response from context broker:\n{}", chunk.data); - *json_response = json_loads(chunk.data, 0, &err); - if (!*json_response) - logger->warn("Received invalid JSON: {} in {}:{}:{}\n{}", err.text, err.source, err.line, err.column, chunk.data); + *json_response = json_loads(chunk.data, 0, &err); + if (!*json_response) + logger->warn("Received invalid JSON: {} in {}:{}:{}\n{}", err.text, + err.source, err.line, err.column, chunk.data); -out: free(post); - free(chunk.data); +out: + free(post); + free(chunk.data); - return ret; + return ret; } -static -int ngsi_request_context_query(CURL *handle, const char *endpoint, json_t *json_entity, json_t **json_rentity, Logger logger) -{ - int ret, code; - char *reason; +static int ngsi_request_context_query(CURL *handle, const char *endpoint, + json_t *json_entity, + json_t **json_rentity, Logger logger) { + int ret, code; + char *reason; - json_t *json_response; - json_t *json_request = json_pack("{ s: [ O ] }", "entities", json_entity); + json_t *json_response; + json_t *json_request = json_pack("{ s: [ O ] }", "entities", json_entity); - ret = ngsi_request(handle, endpoint, "queryContext", json_request, &json_response, logger); - if (ret) { - ret = -1; - goto out; - } + ret = ngsi_request(handle, endpoint, "queryContext", json_request, + &json_response, logger); + if (ret) { + ret = -1; + goto out; + } - ret = ngsi_parse_context_response(json_response, &code, &reason, json_rentity, logger); - if (ret) - goto out2; + ret = ngsi_parse_context_response(json_response, &code, &reason, json_rentity, + logger); + if (ret) + goto out2; -out2: json_decref(json_response); -out: json_decref(json_request); +out2: + json_decref(json_response); +out: + json_decref(json_request); - return ret; + return ret; } -static -int ngsi_request_context_update(CURL *handle, const char *endpoint, const char *action, json_t *json_entity, Logger logger) -{ - int ret, code; - char *reason; +static int ngsi_request_context_update(CURL *handle, const char *endpoint, + const char *action, json_t *json_entity, + Logger logger) { + int ret, code; + char *reason; - json_t *json_response; - json_t *json_request = json_pack("{ s: s, s: [ O ] }", - "updateAction", action, - "contextElements", json_entity - ); + json_t *json_response; + json_t *json_request = json_pack("{ s: s, s: [ O ] }", "updateAction", action, + "contextElements", json_entity); - ret = ngsi_request(handle, endpoint, "updateContext", json_request, &json_response, logger); - if (ret) - goto out; + ret = ngsi_request(handle, endpoint, "updateContext", json_request, + &json_response, logger); + if (ret) + goto out; - json_t *json_rentity; - ret = ngsi_parse_context_response(json_response, &code, &reason, &json_rentity, logger); - if (ret) - goto out2; + json_t *json_rentity; + ret = ngsi_parse_context_response(json_response, &code, &reason, + &json_rentity, logger); + if (ret) + goto out2; - json_decref(json_rentity); -out2: json_decref(json_response); -out: json_decref(json_request); + json_decref(json_rentity); +out2: + json_decref(json_response); +out: + json_decref(json_request); - return ret; + return ret; } -int villas::node::ngsi_type_start(villas::node::SuperNode *sn) -{ +int villas::node::ngsi_type_start(villas::node::SuperNode *sn) { #ifdef CURL_SSL_REQUIRES_LOCKING - mutex_buf = new pthread_mutex_t[CRYPTO_num_locks()]; - if (!mutex_buf) - return -1; + mutex_buf = new pthread_mutex_t[CRYPTO_num_locks()]; + if (!mutex_buf) + return -1; - for (int i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&mutex_buf[i], nullptr); + for (int i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&mutex_buf[i], nullptr); - CRYPTO_set_id_callback(curl_ssl_thread_id_function); - CRYPTO_set_locking_callback(curl_ssl_locking_function); + CRYPTO_set_id_callback(curl_ssl_thread_id_function); + CRYPTO_set_locking_callback(curl_ssl_locking_function); - auto logger = logging.get("curl"); - logger->info("Setup libcurl/openssl locking primitives"); + auto logger = logging.get("curl"); + logger->info("Setup libcurl/openssl locking primitives"); #endif // CURL_SSL_REQUIRES_LOCKING - return curl_global_init(CURL_GLOBAL_ALL); + return curl_global_init(CURL_GLOBAL_ALL); } -int villas::node::ngsi_type_stop() -{ +int villas::node::ngsi_type_stop() { #ifdef CURL_SSL_REQUIRES_LOCKING - if (!mutex_buf) - return -1; + if (!mutex_buf) + return -1; - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); - for (int i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&mutex_buf[i]); + for (int i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&mutex_buf[i]); - delete mutex_buf; + delete mutex_buf; #endif // CURL_SSL_REQUIRES_LOCKING - curl_global_cleanup(); + curl_global_cleanup(); - return 0; + return 0; } -int villas::node::ngsi_parse(NodeCompat *n, json_t *json) -{ - auto *i = n->getData(); +int villas::node::ngsi_parse(NodeCompat *n, json_t *json) { + auto *i = n->getData(); - int ret; - json_error_t err; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; + int ret; + json_error_t err; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - int create = 1; - int remove = 1; + int create = 1; + int remove = 1; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: s, s: s, s: s, s?: b, s?: F, s?: F, s?: b, s?: b, s?: { s?: o }, s?: { s?: o } }", - "access_token", &i->access_token, - "endpoint", &i->endpoint, - "entity_id", &i->entity_id, - "entity_type", &i->entity_type, - "ssl_verify", &i->ssl_verify, - "timeout", &i->timeout, - "rate", &i->rate, - "create", &create, - "delete", &remove, - "in", - "signals", &json_signals_in, - "out", - "signals", &json_signals_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ngsi"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: s, s: s, s: s, s: s, s?: b, s?: F, s?: F, s?: b, " + "s?: b, s?: { s?: o }, s?: { s?: o } }", + "access_token", &i->access_token, "endpoint", + &i->endpoint, "entity_id", &i->entity_id, "entity_type", + &i->entity_type, "ssl_verify", &i->ssl_verify, "timeout", + &i->timeout, "rate", &i->rate, "create", &create, + "delete", &remove, "in", "signals", &json_signals_in, + "out", "signals", &json_signals_out); + if (ret) + throw ConfigError(json, err, "node-config-node-ngsi"); - i->create = create; - i->remove = remove; + i->create = create; + i->remove = remove; - if (json_signals_in) { - ret = ngsi_parse_signals(json_signals_in, &i->in.signals, n->in.signals); - if (ret) - throw ConfigError(json_signals_in, "node-config-node-ngsi-in-signals", "Invalid setting 'in.signals' of node {}", n->getName()); - } + if (json_signals_in) { + ret = ngsi_parse_signals(json_signals_in, &i->in.signals, n->in.signals); + if (ret) + throw ConfigError(json_signals_in, "node-config-node-ngsi-in-signals", + "Invalid setting 'in.signals' of node {}", + n->getName()); + } - if (json_signals_out) { - ret = ngsi_parse_signals(json_signals_out, &i->out.signals, n->out.signals); - if (ret) - throw ConfigError(json_signals_out, "node-config-node-ngsi-out-signals", "Invalid setting 'out.signals' of node {}", n->getName()); - } + if (json_signals_out) { + ret = ngsi_parse_signals(json_signals_out, &i->out.signals, n->out.signals); + if (ret) + throw ConfigError(json_signals_out, "node-config-node-ngsi-out-signals", + "Invalid setting 'out.signals' of node {}", + n->getName()); + } - return 0; + return 0; } -char * villas::node::ngsi_print(NodeCompat *n) -{ - auto *i = n->getData(); +char *villas::node::ngsi_print(NodeCompat *n) { + auto *i = n->getData(); - return strf("endpoint=%s, timeout=%.3f secs", - i->endpoint, i->timeout); + return strf("endpoint=%s, timeout=%.3f secs", i->endpoint, i->timeout); } -int villas::node::ngsi_start(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::ngsi_start(NodeCompat *n) { + auto *i = n->getData(); - i->in.curl = curl_easy_init(); - i->out.curl = curl_easy_init(); - i->headers = nullptr; + i->in.curl = curl_easy_init(); + i->out.curl = curl_easy_init(); + i->headers = nullptr; - if (i->access_token) { - char buf[128]; - snprintf(buf, sizeof(buf), "Auth-Token: %s", i->access_token); - i->headers = curl_slist_append(i->headers, buf); - } + if (i->access_token) { + char buf[128]; + snprintf(buf, sizeof(buf), "Auth-Token: %s", i->access_token); + i->headers = curl_slist_append(i->headers, buf); + } - // Create task - if (i->timeout > 1 / i->rate) - n->logger->warn("Timeout is to large for given rate: {}", i->rate); + // Create task + if (i->timeout > 1 / i->rate) + n->logger->warn("Timeout is to large for given rate: {}", i->rate); - i->task.setRate(i->rate); + i->task.setRate(i->rate); - i->headers = curl_slist_append(i->headers, "Accept: application/json"); - i->headers = curl_slist_append(i->headers, "Content-Type: application/json"); + i->headers = curl_slist_append(i->headers, "Accept: application/json"); + i->headers = curl_slist_append(i->headers, "Content-Type: application/json"); - CURL *handles[] = { i->in.curl, i->out.curl }; + CURL *handles[] = {i->in.curl, i->out.curl}; - for (unsigned p = 0; p < ARRAY_LEN(handles); p++) { - curl_easy_setopt(handles[p], CURLOPT_SSL_VERIFYPEER, i->ssl_verify); - curl_easy_setopt(handles[p], CURLOPT_TIMEOUT_MS, i->timeout * 1e3); - curl_easy_setopt(handles[p], CURLOPT_HTTPHEADER, i->headers); - curl_easy_setopt(handles[p], CURLOPT_USERAGENT, HTTP_USER_AGENT); - } + for (unsigned p = 0; p < ARRAY_LEN(handles); p++) { + curl_easy_setopt(handles[p], CURLOPT_SSL_VERIFYPEER, i->ssl_verify); + curl_easy_setopt(handles[p], CURLOPT_TIMEOUT_MS, i->timeout * 1e3); + curl_easy_setopt(handles[p], CURLOPT_HTTPHEADER, i->headers); + curl_easy_setopt(handles[p], CURLOPT_USERAGENT, HTTP_USER_AGENT); + } - // Create entity and atributes - if (i->create) { - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, NGSI_ENTITY_ATTRIBUTES | NGSI_ENTITY_METADATA); + // Create entity and atributes + if (i->create) { + json_t *json_entity = ngsi_build_entity( + n, nullptr, 0, NGSI_ENTITY_ATTRIBUTES | NGSI_ENTITY_METADATA); - int ret = ngsi_request_context_update(i->out.curl, i->endpoint, "APPEND", json_entity, n->logger); - if (ret) - throw RuntimeError("Failed to create NGSI context for node {}", n->getName()); + int ret = ngsi_request_context_update(i->out.curl, i->endpoint, "APPEND", + json_entity, n->logger); + if (ret) + throw RuntimeError("Failed to create NGSI context for node {}", + n->getName()); - json_decref(json_entity); - } + json_decref(json_entity); + } - return 0; + return 0; } -int villas::node::ngsi_stop(NodeCompat *n) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_stop(NodeCompat *n) { + auto *i = n->getData(); + int ret; - i->task.stop(); + i->task.stop(); - // Delete complete entity (not just attributes) - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); + // Delete complete entity (not just attributes) + json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); - ret = ngsi_request_context_update(i->out.curl, i->endpoint, "DELETE", json_entity, n->logger); + ret = ngsi_request_context_update(i->out.curl, i->endpoint, "DELETE", + json_entity, n->logger); - json_decref(json_entity); + json_decref(json_entity); - curl_easy_cleanup(i->in.curl); - curl_easy_cleanup(i->out.curl); - curl_slist_free_all(i->headers); + curl_easy_cleanup(i->in.curl); + curl_easy_cleanup(i->out.curl); + curl_slist_free_all(i->headers); - return ret; + return ret; } -int villas::node::ngsi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); + int ret; - if (i->task.wait() == 0) - throw SystemError("Failed to wait for task"); + if (i->task.wait() == 0) + throw SystemError("Failed to wait for task"); - json_t *json_rentity; - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); + json_t *json_rentity; + json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); - ret = ngsi_request_context_query(i->in.curl, i->endpoint, json_entity, &json_rentity, n->logger); - if (ret) - goto out; + ret = ngsi_request_context_query(i->in.curl, i->endpoint, json_entity, + &json_rentity, n->logger); + if (ret) + goto out; - ret = ngsi_parse_entity(n, json_rentity, smps, cnt); - if (ret) - goto out2; + ret = ngsi_parse_entity(n, json_rentity, smps, cnt); + if (ret) + goto out2; -out2: json_decref(json_rentity); -out: json_decref(json_entity); +out2: + json_decref(json_rentity); +out: + json_decref(json_entity); - return ret; + return ret; } -int villas::node::ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); + int ret; - json_t *json_entity = ngsi_build_entity(n, smps, cnt, NGSI_ENTITY_ATTRIBUTES_OUT | NGSI_ENTITY_VALUES); + json_t *json_entity = ngsi_build_entity( + n, smps, cnt, NGSI_ENTITY_ATTRIBUTES_OUT | NGSI_ENTITY_VALUES); - ret = ngsi_request_context_update(i->out.curl, i->endpoint, "UPDATE", json_entity, n->logger); + ret = ngsi_request_context_update(i->out.curl, i->endpoint, "UPDATE", + json_entity, n->logger); - json_decref(json_entity); + json_decref(json_entity); - return ret ? 0 : cnt; + return ret ? 0 : cnt; } -int villas::node::ngsi_poll_fds(NodeCompat *n, int fds[]) -{ - auto *i = n->getData(); +int villas::node::ngsi_poll_fds(NodeCompat *n, int fds[]) { + auto *i = n->getData(); - fds[0] = i->task.getFD(); + fds[0] = i->task.getFD(); - return 1; + return 1; } -int villas::node::ngsi_init(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::ngsi_init(NodeCompat *n) { + int ret; + auto *i = n->getData(); - new (&i->task) Task(CLOCK_REALTIME); + new (&i->task) Task(CLOCK_REALTIME); - ret = list_init(&i->in.signals); - if (ret) - return ret; + ret = list_init(&i->in.signals); + if (ret) + return ret; - ret = list_init(&i->out.signals); - if (ret) - return ret; + ret = list_init(&i->out.signals); + if (ret) + return ret; - // Default values - i->access_token = nullptr; // disabled by default - i->ssl_verify = 1; // verify by default - i->timeout = 1; // default value - i->rate = 1; // default value + // Default values + i->access_token = nullptr; // disabled by default + i->ssl_verify = 1; // verify by default + i->timeout = 1; // default value + i->rate = 1; // default value - return 0; + return 0; } -int villas::node::ngsi_destroy(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::ngsi_destroy(NodeCompat *n) { + int ret; + auto *i = n->getData(); - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->in.signals, j); + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->in.signals, j); - delete attr; - } + delete attr; + } - for (size_t j = 0; j < list_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->out.signals, j); + for (size_t j = 0; j < list_length(&i->out.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->out.signals, j); - delete attr; - } + delete attr; + } - ret = list_destroy(&i->in.signals); - if (ret) - return ret; + ret = list_destroy(&i->in.signals); + if (ret) + return ret; - ret = list_destroy(&i->out.signals); - if (ret) - return ret; + ret = list_destroy(&i->out.signals); + if (ret) + return ret; - i->task.~Task(); + i->task.~Task(); - return 0; + return 0; } -int villas::node::ngsi_reverse(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::ngsi_reverse(NodeCompat *n) { + auto *i = n->getData(); - n->swapSignals(); - SWAP(i->in.signals, i->out.signals); + n->swapSignals(); + SWAP(i->in.signals, i->out.signals); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "ngsi"; - p.description = "OMA Next Generation Services Interface 10 (libcurl, libjansson)"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "ngsi"; + p.description = + "OMA Next Generation Services Interface 10 (libcurl, libjansson)"; #ifdef NGSI_VECTORS - p.vectorize = 0, // unlimited + p.vectorize = 0, // unlimited #else - p.vectorize = 1, + p.vectorize = 1, #endif - p.size = sizeof(struct ngsi); - p.type.start = ngsi_type_start; - p.type.stop = ngsi_type_stop; - p.init = ngsi_init; - p.destroy = ngsi_destroy; - p.parse = ngsi_parse; - p.print = ngsi_print; - p.start = ngsi_start; - p.stop = ngsi_stop; - p.read = ngsi_read; - p.write = ngsi_write; - p.poll_fds = ngsi_poll_fds; - p.reverse = ngsi_reverse; + p.size = sizeof(struct ngsi); + p.type.start = ngsi_type_start; + p.type.stop = ngsi_type_stop; + p.init = ngsi_init; + p.destroy = ngsi_destroy; + p.parse = ngsi_parse; + p.print = ngsi_print; + p.start = ngsi_start; + p.stop = ngsi_stop; + p.read = ngsi_read; + p.write = ngsi_write; + p.poll_fds = ngsi_poll_fds; + p.reverse = ngsi_reverse; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 4525ff368..d0d224ce4 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -7,44 +7,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include #include +#include #include +#include #include #include #include -#include extern "C" { - /* Define RTLAB before including OpalPrint.h for messages to be sent +/* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ - #define RTLAB - #include - #include - #include +#define RTLAB +#include +#include +#include } // Private static storage -static -std::string asyncShmemName; // Shared Memory identifiers and size, provided via argv. -static -std::string printShmemName; // Shared Memory identifiers and size, provided via argv. -static -size_t asyncShmemSize; // Shared Memory identifiers and size, provided via argv. +static std::string + asyncShmemName; // Shared Memory identifiers and size, provided via argv. +static std::string + printShmemName; // Shared Memory identifiers and size, provided via argv. +static size_t + asyncShmemSize; // Shared Memory identifiers and size, provided via argv. -static -std::vector sendIDs, recvIDs; // A dynamically allocated array of SendIDs. +static std::vector sendIDs, + recvIDs; // A dynamically allocated array of SendIDs. -static -Opal_GenAsyncParam_Ctrl params; // String and Float parameters, provided by the OPAL AsyncProcess block. +static Opal_GenAsyncParam_Ctrl + params; // String and Float parameters, provided by the OPAL AsyncProcess block. -static -pthread_mutex_t lock; // Big Global Lock for libOpalAsync API +static pthread_mutex_t lock; // Big Global Lock for libOpalAsync API using namespace villas; using namespace villas::utils; @@ -53,321 +52,300 @@ using namespace villas::utils; * and undefined by GCC. We replace them by GCC variants here. */ extern "C" { - int __xstat(int ver, const char * path, struct stat * stat_buf) - { - return stat(path, stat_buf); - } - - int backtrace(void **buffer, int size) - { - return 0; - } - - char **backtrace_symbols(void *const *buffer, int size) - { - return nullptr; - } - - void backtrace_symbols_fd(void *const *buffer, int size, int fd) - { - } - - void * _intel_fast_memset(void *b, int c, size_t len) - { - return memset(b, c, len); - } - - void * _intel_fast_memcpy(void *dst, const void *src, size_t n) - { - return memcpy(dst, src, n); - } - - int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) - { - return memcmp(s1, s2, n); - } - - void * _intel_fast_memmove(void *s1, const void *s2, size_t n) - { - return memmove(s1, s2, n); - } +int __xstat(int ver, const char *path, struct stat *stat_buf) { + return stat(path, stat_buf); } -static -int opal_register_region(int argc, char *argv[]) -{ - if (argc != 4) - return -1; +int backtrace(void **buffer, int size) { return 0; } - asyncShmemName = argv[1]; - asyncShmemSize = atoi(argv[2]); - printShmemName = argv[3]; +char **backtrace_symbols(void *const *buffer, int size) { return nullptr; } - return 0; +void backtrace_symbols_fd(void *const *buffer, int size, int fd) {} + +void *_intel_fast_memset(void *b, int c, size_t len) { + return memset(b, c, len); } -int villas::node::opal_type_start(villas::node::SuperNode *sn) -{ - int err, noRecvIcons, noSendIcons; - - pthread_mutex_init(&lock, nullptr); - - // Enable the OpalPrint function. This prints to the OpalDisplay. - err = OpalSystemCtrl_Register((char *) printShmemName.c_str()); - if (err != EOK) - throw RuntimeError("OpalPrint() access not available ({})", err); - - // Open Share Memory created by the model. - err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Model shared memory not available ({})", err); - - err = OpalGetAsyncCtrlParameters(¶ms, sizeof(Opal_GenAsyncParam_Ctrl)); - if (err != EOK) - throw RuntimeError("Could not get OPAL controller parameters ({})", err); - - // Get list of Send and RecvIDs - err = OpalGetNbAsyncSendIcon(&noSendIcons); - if (err != EOK) - throw RuntimeError("Failed to get number of send blocks ({})", err); - err = OpalGetNbAsyncRecvIcon(&noRecvIcons); - if (err != EOK) - throw RuntimeError("Failed to get number of recv blocks ({})", err); - - sendIDs.resize(noSendIcons); - recvIDs.resize(noRecvIcons); - - err = OpalGetAsyncSendIDList(sendIDs.data(), noSendIcons * sizeof(int)); - if (err != EOK) - throw RuntimeError("Failed to get list of send ids ({})", err); - err = OpalGetAsyncRecvIDList(recvIDs.data(), noRecvIcons * sizeof(int)); - if (err != EOK) - throw RuntimeError("Failed to get list of recv ids ({})", err); - - auto logger = logging.get("node:opal"); - logger->info("Started as OPAL Asynchronous process"); - logger->info("This is VILLASnode %s (built on %s, %s)", - PROJECT_BUILD_ID, __DATE__, __TIME__); - - opal_print_global(); - - return 0; +void *_intel_fast_memcpy(void *dst, const void *src, size_t n) { + return memcpy(dst, src, n); } -int villas::node::opal_type_stop() -{ - int err; - - err = OpalCloseAsyncMem(asyncShmemSize, asyncShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Failed to close shared memory area ({})", err); - - auto logger = logging.get("node:opal"); - logger->debug("Closing OPAL shared memory mapping"); - - err = OpalSystemCtrl_UnRegister((char *) printShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Failed to close shared memory for system control ({})", err); - - pthread_mutex_destroy(&lock); - - return 0; +int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) { + return memcmp(s1, s2, n); } -static -int opal_print_global() -{ - auto logger = logging.get("node:opal"); - logger->debug("Controller ID: {}", params.controllerID); - - std::stringstream sss, rss; - - for (auto i : sendIDs) - sss << i << " "; - for (auto i : recvIDs) - rss << i << " "; - - logger->debug("Send Blocks: {}", sss.str()); - logger->debug("Receive Blocks: {}", rss.str()); - - logger->debug("Control Block Parameters:"); - for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++) - logger->debug("FloatParam[{}] = {}", i, (double) params.FloatParam[i]); - for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++) - logger->debug("StringParam[{}] = {}", i, params.StringParam[i]); - - return 0; +void *_intel_fast_memmove(void *s1, const void *s2, size_t n) { + return memmove(s1, s2, n); +} } -int villas::node::opal_parse(NodeCompat *n, json_t *json) -{ - auto *o = n->getData(); +static int opal_register_region(int argc, char *argv[]) { + if (argc != 4) + return -1; - int ret; - json_error_t err; + asyncShmemName = argv[1]; + asyncShmemSize = atoi(argv[2]); + printShmemName = argv[3]; - ret = json_unpack_ex(json, &err, 0, "{ s: i, s: i, s: b }", - "send_id", &o->sendID, - "recv_id", &o->sendID, - "reply", &o->reply - ); - if (ret) - throw ConfigError(json, err, "node-config-node-opal"); - - return 0; + return 0; } -char * villas::node::opal_print(NodeCompat *n) -{ - auto *o = n->getData(); +int villas::node::opal_type_start(villas::node::SuperNode *sn) { + int err, noRecvIcons, noSendIcons; - // TODO: Print send_params, recv_params + pthread_mutex_init(&lock, nullptr); - return strf("sendID=%u, recvID=%u, reply=%u", - o->sendID, o->recvID, o->reply); + // Enable the OpalPrint function. This prints to the OpalDisplay. + err = OpalSystemCtrl_Register((char *)printShmemName.c_str()); + if (err != EOK) + throw RuntimeError("OpalPrint() access not available ({})", err); + + // Open Share Memory created by the model. + err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Model shared memory not available ({})", err); + + err = OpalGetAsyncCtrlParameters(¶ms, sizeof(Opal_GenAsyncParam_Ctrl)); + if (err != EOK) + throw RuntimeError("Could not get OPAL controller parameters ({})", err); + + // Get list of Send and RecvIDs + err = OpalGetNbAsyncSendIcon(&noSendIcons); + if (err != EOK) + throw RuntimeError("Failed to get number of send blocks ({})", err); + err = OpalGetNbAsyncRecvIcon(&noRecvIcons); + if (err != EOK) + throw RuntimeError("Failed to get number of recv blocks ({})", err); + + sendIDs.resize(noSendIcons); + recvIDs.resize(noRecvIcons); + + err = OpalGetAsyncSendIDList(sendIDs.data(), noSendIcons * sizeof(int)); + if (err != EOK) + throw RuntimeError("Failed to get list of send ids ({})", err); + err = OpalGetAsyncRecvIDList(recvIDs.data(), noRecvIcons * sizeof(int)); + if (err != EOK) + throw RuntimeError("Failed to get list of recv ids ({})", err); + + auto logger = logging.get("node:opal"); + logger->info("Started as OPAL Asynchronous process"); + logger->info("This is VILLASnode %s (built on %s, %s)", PROJECT_BUILD_ID, + __DATE__, __TIME__); + + opal_print_global(); + + return 0; } -int villas::node::opal_start(NodeCompat *n) -{ - auto *o = n->getData(); +int villas::node::opal_type_stop() { + int err; - // Search for valid send and recv ids - int sfound = 0, rfound = 0; - for (auto i : sendIDs) - sfound += i == o->sendID; - for (auto i : recvIDs) - rfound += i == o->sendID; + err = OpalCloseAsyncMem(asyncShmemSize, asyncShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Failed to close shared memory area ({})", err); - if (!sfound) - throw RuntimeError("Invalid send_id '{}'", o->sendID); - if (!rfound) - throw RuntimeError("Invalid recv_id '{}'", o->recvID); + auto logger = logging.get("node:opal"); + logger->debug("Closing OPAL shared memory mapping"); - // Get some more informations and paramters from OPAL-RT - OpalGetAsyncSendIconMode(&o->mode, o->sendID); - OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), o->sendID); - OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), o->recvID); + err = OpalSystemCtrl_UnRegister((char *)printShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Failed to close shared memory for system control ({})", + err); - o->sequenceNo = 0; + pthread_mutex_destroy(&lock); - return 0; + return 0; } -int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *o = n->getData(); +static int opal_print_global() { + auto logger = logging.get("node:opal"); + logger->debug("Controller ID: {}", params.controllerID); - int state, ret, len; - unsigned id; + std::stringstream sss, rss; - struct Sample *s = smps[0]; + for (auto i : sendIDs) + sss << i << " "; + for (auto i : recvIDs) + rss << i << " "; - double data[s->capacity]; + logger->debug("Send Blocks: {}", sss.str()); + logger->debug("Receive Blocks: {}", rss.str()); - if (cnt != 1) - throw RuntimeError("The OPAL-RT node type does not support combining!"); + logger->debug("Control Block Parameters:"); + for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++) + logger->debug("FloatParam[{}] = {}", i, (double)params.FloatParam[i]); + for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++) + logger->debug("StringParam[{}] = {}", i, params.StringParam[i]); - // This call unblocks when the 'Data Ready' line of a send icon is asserted. - do { - ret = OpalWaitForAsyncSendRequest(&id); - if (ret != EOK) { - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + return 0; +} - return -1; // TODO: correct return value - } - } while (id != o->sendID); +int villas::node::opal_parse(NodeCompat *n, json_t *json) { + auto *o = n->getData(); - // No errors encountered yet - OpalSetAsyncSendIconError(0, o->sendID); + int ret; + json_error_t err; - // Get the size of the data being sent by the unblocking SendID - OpalGetAsyncSendIconDataLength(&len, o->sendID); - if ((unsigned) len > s->capacity * sizeof(s->data[0])) { - n->logger->warn("Ignoring the last {} of {} values for OPAL (send_id={}).", - len / sizeof(double) - s->capacity, len / sizeof(double), o->sendID); + ret = json_unpack_ex(json, &err, 0, "{ s: i, s: i, s: b }", "send_id", + &o->sendID, "recv_id", &o->sendID, "reply", &o->reply); + if (ret) + throw ConfigError(json, err, "node-config-node-opal"); - len = sizeof(data); - } + return 0; +} - // Read data from the model - OpalGetAsyncSendIconData(data, len, o->sendID); +char *villas::node::opal_print(NodeCompat *n) { + auto *o = n->getData(); - s->sequence = htons(o->sequenceNo++); - s->length = (unsigned) len / sizeof(double); + // TODO: Print send_params, recv_params - for (unsigned i = 0; i < s->length; i++) - s->data[i].f = (float) data[i]; // OPAL provides double precission + return strf("sendID=%u, recvID=%u, reply=%u", o->sendID, o->recvID, o->reply); +} - /* This next call allows the execution of the "asynchronous" process +int villas::node::opal_start(NodeCompat *n) { + auto *o = n->getData(); + + // Search for valid send and recv ids + int sfound = 0, rfound = 0; + for (auto i : sendIDs) + sfound += i == o->sendID; + for (auto i : recvIDs) + rfound += i == o->sendID; + + if (!sfound) + throw RuntimeError("Invalid send_id '{}'", o->sendID); + if (!rfound) + throw RuntimeError("Invalid recv_id '{}'", o->recvID); + + // Get some more informations and paramters from OPAL-RT + OpalGetAsyncSendIconMode(&o->mode, o->sendID); + OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), + o->sendID); + OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), + o->recvID); + + o->sequenceNo = 0; + + return 0; +} + +int villas::node::opal_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *o = n->getData(); + + int state, ret, len; + unsigned id; + + struct Sample *s = smps[0]; + + double data[s->capacity]; + + if (cnt != 1) + throw RuntimeError("The OPAL-RT node type does not support combining!"); + + // This call unblocks when the 'Data Ready' line of a send icon is asserted. + do { + ret = OpalWaitForAsyncSendRequest(&id); + if (ret != EOK) { + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError( + "OpalGetAsyncModelState(): Model stopped or resetted!"); + + return -1; // TODO: correct return value + } + } while (id != o->sendID); + + // No errors encountered yet + OpalSetAsyncSendIconError(0, o->sendID); + + // Get the size of the data being sent by the unblocking SendID + OpalGetAsyncSendIconDataLength(&len, o->sendID); + if ((unsigned)len > s->capacity * sizeof(s->data[0])) { + n->logger->warn("Ignoring the last {} of {} values for OPAL (send_id={}).", + len / sizeof(double) - s->capacity, len / sizeof(double), + o->sendID); + + len = sizeof(data); + } + + // Read data from the model + OpalGetAsyncSendIconData(data, len, o->sendID); + + s->sequence = htons(o->sequenceNo++); + s->length = (unsigned)len / sizeof(double); + + for (unsigned i = 0; i < s->length; i++) + s->data[i].f = (float)data[i]; // OPAL provides double precission + + /* This next call allows the execution of the "asynchronous" process * to actually be synchronous with the model. To achieve this, you * should set the "Sending Mode" in the Async_Send block to * NEED_REPLY_BEFORE_NEXT_SEND or NEED_REPLY_NOW. This will force * the model to wait for this process to call this * OpalAsyncSendRequestDone function before continuing. */ - if (o->reply) - OpalAsyncSendRequestDone(o->sendID); + if (o->reply) + OpalAsyncSendRequestDone(o->sendID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - return 1; + return 1; } -int villas::node::opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *o = n->getData(); +int villas::node::opal_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *o = n->getData(); - struct Sample *s = smps[0]; + struct Sample *s = smps[0]; - int state; - int len; - double data[s->length]; + int state; + int len; + double data[s->length]; - if (cnt != 1) - throw RuntimeError("The OPAL-RT node type does not support combining!"); + if (cnt != 1) + throw RuntimeError("The OPAL-RT node type does not support combining!"); - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - OpalSetAsyncRecvIconStatus(s->sequence, o->recvID); // Set the Status to the message ID - OpalSetAsyncRecvIconError(0, o->recvID); // Set the Error to 0 + OpalSetAsyncRecvIconStatus(s->sequence, + o->recvID); // Set the Status to the message ID + OpalSetAsyncRecvIconError(0, o->recvID); // Set the Error to 0 - // Get the number of signals to send back to the model - OpalGetAsyncRecvIconDataLength(&len, o->recvID); - if (len > (int) sizeof(data)) - n->logger->warn("Node expecting more signals ({}) than values in message ({})", len / sizeof(double), s->length); + // Get the number of signals to send back to the model + OpalGetAsyncRecvIconDataLength(&len, o->recvID); + if (len > (int)sizeof(data)) + n->logger->warn( + "Node expecting more signals ({}) than values in message ({})", + len / sizeof(double), s->length); - for (unsigned i = 0; i < s->length; i++) - data[i] = (double) s->data[i].f; // OPAL expects double precission + for (unsigned i = 0; i < s->length; i++) + data[i] = (double)s->data[i].f; // OPAL expects double precission - OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID); + OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "opal"; - p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)"; - p.vectorize = 1; - p.size = sizeof(struct opal); - p.type.start = opal_type_start; - p.type.stop = opal_type_stop; - p.parse = opal_parse; - p.print = opal_print; - p.start = opal_start; - p.read = opal_read; - p.write = opal_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "opal"; + p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)"; + p.vectorize = 1; + p.size = sizeof(struct opal); + p.type.start = opal_type_start; + p.type.stop = opal_type_stop; + p.parse = opal_parse; + p.print = opal_print; + p.start = opal_start; + p.read = opal_read; + p.write = opal_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/redis.cpp b/lib/nodes/redis.cpp index 2a07d1dfd..bae08e5e0 100644 --- a/lib/nodes/redis.cpp +++ b/lib/nodes/redis.cpp @@ -5,678 +5,640 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Forward declartions -static -NodeCompatType p; -static -void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg); +static NodeCompatType p; +static void redis_on_message(NodeCompat *n, const std::string &channel, + const std::string &msg); -static -std::unordered_map connections; +static std::unordered_map + connections; -RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) : - context(opts), - subscriber(context.subscriber()), - logger(logging.get("nodes:redis")) -{ - // Enable keyspace notifications - context.command("config", "set", "notify-keyspace-events", "K$h"); +RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) + : context(opts), subscriber(context.subscriber()), + logger(logging.get("nodes:redis")) { + // Enable keyspace notifications + context.command("config", "set", "notify-keyspace-events", "K$h"); - subscriber.on_message([this](const std::string &channel, const std::string &msg) { - onMessage(channel, msg); - }); + subscriber.on_message( + [this](const std::string &channel, const std::string &msg) { + onMessage(channel, msg); + }); - logger->info("New connection: {}", opts); + logger->info("New connection: {}", opts); - state = State::INITIALIZED; + state = State::INITIALIZED; } -RedisConnection * RedisConnection::get(const sw::redis::ConnectionOptions &opts) -{ - RedisConnection *conn; +RedisConnection * +RedisConnection::get(const sw::redis::ConnectionOptions &opts) { + RedisConnection *conn; - auto it = connections.find(opts); - if (it != connections.end()) - conn = it->second; - else { - try { - conn = new RedisConnection(opts); - } catch (sw::redis::IoError &e) { - throw RuntimeError(e.what()); - } + auto it = connections.find(opts); + if (it != connections.end()) + conn = it->second; + else { + try { + conn = new RedisConnection(opts); + } catch (sw::redis::IoError &e) { + throw RuntimeError(e.what()); + } - connections[opts] = conn; - } + connections[opts] = conn; + } - return conn; + return conn; } -void RedisConnection::onMessage(const std::string &channel, const std::string &msg) -{ - auto itp = subscriberMap.equal_range(channel); - for (auto it = itp.first; it != itp.second; ++it) { - NodeCompat *n = it->second; +void RedisConnection::onMessage(const std::string &channel, + const std::string &msg) { + auto itp = subscriberMap.equal_range(channel); + for (auto it = itp.first; it != itp.second; ++it) { + NodeCompat *n = it->second; - redis_on_message(n, channel, msg); - } + redis_on_message(n, channel, msg); + } } -void RedisConnection::subscribe(NodeCompat *n, const std::string &channel) -{ - subscriber.subscribe(channel); +void RedisConnection::subscribe(NodeCompat *n, const std::string &channel) { + subscriber.subscribe(channel); - subscriberMap.emplace(channel, n); + subscriberMap.emplace(channel, n); } -void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) -{ - auto itp = subscriberMap.equal_range(channel); - for (auto it = itp.first; it != itp.second; ++it) { - if (it->second == n) - subscriberMap.erase(it); - } +void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) { + auto itp = subscriberMap.equal_range(channel); + for (auto it = itp.first; it != itp.second; ++it) { + if (it->second == n) + subscriberMap.erase(it); + } - if (subscriberMap.count(channel) == 0) - subscriber.subscribe(channel); + if (subscriberMap.count(channel) == 0) + subscriber.subscribe(channel); } -void RedisConnection::start() -{ - if (state == State::RUNNING) - return; // Already running +void RedisConnection::start() { + if (state == State::RUNNING) + return; // Already running - state = State::RUNNING; + state = State::RUNNING; - thread = std::thread(&RedisConnection::loop, this); + thread = std::thread(&RedisConnection::loop, this); } -void RedisConnection::stop() -{ - state = State::STOPPING; +void RedisConnection::stop() { + state = State::STOPPING; - thread.join(); + thread.join(); - state = State::INITIALIZED; + state = State::INITIALIZED; } -void RedisConnection::loop() -{ - while (state == State::RUNNING) { - try { - subscriber.consume(); - } - catch (const sw::redis::TimeoutError &e) { - logger->debug("Timeout."); - continue; - } - catch (const sw::redis::ReplyError &e) { - logger->error("Error: {}", e.what()); - continue; - } - catch (const sw::redis::Error &e) { - logger->error("Error: {}. Recreating subscriber", e.what()); +void RedisConnection::loop() { + while (state == State::RUNNING) { + try { + subscriber.consume(); + } catch (const sw::redis::TimeoutError &e) { + logger->debug("Timeout."); + continue; + } catch (const sw::redis::ReplyError &e) { + logger->error("Error: {}", e.what()); + continue; + } catch (const sw::redis::Error &e) { + logger->error("Error: {}. Recreating subscriber", e.what()); - // Create a new subscriber - subscriber = context.subscriber(); - } - } + // Create a new subscriber + subscriber = context.subscriber(); + } + } } -static -int redis_get(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +static int redis_get(NodeCompat *n, struct Sample *const smps[], unsigned cnt) { + int ret; + auto *r = n->getData(); - switch (r->mode) { - case RedisMode::KEY: { - auto value = r->conn->context.get(r->key); - if (value) { - size_t rbytes, bytes = value->size(); - ret = r->formatter->sscan(value->c_str(), bytes, &rbytes, smps, cnt); + switch (r->mode) { + case RedisMode::KEY: { + auto value = r->conn->context.get(r->key); + if (value) { + size_t rbytes, bytes = value->size(); + ret = r->formatter->sscan(value->c_str(), bytes, &rbytes, smps, cnt); - if (rbytes != bytes) - return -1; + if (rbytes != bytes) + return -1; - return ret; - } - else - return -1; - } + return ret; + } else + return -1; + } - case RedisMode::HASH: { - struct Sample *smp = smps[0]; + case RedisMode::HASH: { + struct Sample *smp = smps[0]; - unsigned j = 0; - for (auto sig : *n->getInputSignals(false)) { - auto *data = &smp->data[j++]; + unsigned j = 0; + for (auto sig : *n->getInputSignals(false)) { + auto *data = &smp->data[j++]; - *data = sig->init; - } + *data = sig->init; + } - std::unordered_map kvs; - r->conn->context.hgetall(r->key, std::inserter(kvs, kvs.begin())); + std::unordered_map kvs; + r->conn->context.hgetall(r->key, std::inserter(kvs, kvs.begin())); - int max_idx = -1; - for (auto &it : kvs) { - auto &name = it.first; - auto &value = it.second; + int max_idx = -1; + for (auto &it : kvs) { + auto &name = it.first; + auto &value = it.second; - auto sig = n->getInputSignals(false)->getByName(name); - if (!sig) - continue; + auto sig = n->getInputSignals(false)->getByName(name); + if (!sig) + continue; - auto idx = n->getInputSignals(false)->getIndexByName(name); - if (idx > max_idx) - max_idx = idx; + auto idx = n->getInputSignals(false)->getIndexByName(name); + if (idx > max_idx) + max_idx = idx; - char *end; - ret = smp->data[idx].parseString(sig->type, value.c_str(), &end); - if (ret < 0) - continue; - } + char *end; + ret = smp->data[idx].parseString(sig->type, value.c_str(), &end); + if (ret < 0) + continue; + } - smp->flags = 0; - smp->length = max_idx + 1; + smp->flags = 0; + smp->length = max_idx + 1; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 1; - } + return 1; + } - default: - return -1; - } + default: + return -1; + } } -static -void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg) -{ - auto *r = n->getData(); +static void redis_on_message(NodeCompat *n, const std::string &channel, + const std::string &msg) { + auto *r = n->getData(); - n->logger->debug("Message: {}: {}", channel, msg); + n->logger->debug("Message: {}: {}", channel, msg); - int alloc, scanned, pushed = 0; - unsigned cnt = n->in.vectorize; - struct Sample *smps[cnt]; + int alloc, scanned, pushed = 0; + unsigned cnt = n->in.vectorize; + struct Sample *smps[cnt]; - alloc = sample_alloc_many(&r->pool, smps, cnt); - if (alloc < 0) { - n->logger->error("Failed to allocate samples"); - return; - } - else if ((unsigned) alloc < cnt) - n->logger->warn("Pool underrun"); + alloc = sample_alloc_many(&r->pool, smps, cnt); + if (alloc < 0) { + n->logger->error("Failed to allocate samples"); + return; + } else if ((unsigned)alloc < cnt) + n->logger->warn("Pool underrun"); - switch (r->mode) { - case RedisMode::CHANNEL: { - size_t rbytes; - scanned = r->formatter->sscan(msg.c_str(), msg.size(), &rbytes, smps, alloc); - break; - } + switch (r->mode) { + case RedisMode::CHANNEL: { + size_t rbytes; + scanned = + r->formatter->sscan(msg.c_str(), msg.size(), &rbytes, smps, alloc); + break; + } - case RedisMode::HASH: - case RedisMode::KEY: - scanned = redis_get(n, smps, cnt); - break; + case RedisMode::HASH: + case RedisMode::KEY: + scanned = redis_get(n, smps, cnt); + break; - default: - pushed = 0; - goto out; - } + default: + pushed = 0; + goto out; + } - if (scanned < 0) { - n->logger->error("Failed to decode samples"); - goto out; - } + if (scanned < 0) { + n->logger->error("Failed to decode samples"); + goto out; + } - pushed = queue_signalled_push_many(&r->queue, (void **) smps, scanned); - if (pushed < 0) { - n->logger->error("Failed to enqueue"); - pushed = 0; - } - else if (pushed != scanned) - n->logger->warn("Queue underrun"); + pushed = queue_signalled_push_many(&r->queue, (void **)smps, scanned); + if (pushed < 0) { + n->logger->error("Failed to enqueue"); + pushed = 0; + } else if (pushed != scanned) + n->logger->warn("Queue underrun"); -out: sample_decref_many(smps + pushed, alloc - pushed); +out: + sample_decref_many(smps + pushed, alloc - pushed); } -int villas::node::redis_init(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_init(NodeCompat *n) { + auto *r = n->getData(); - r->mode = RedisMode::KEY; - r->formatter = nullptr; - r->notify = true; - r->rate = 1.0; + r->mode = RedisMode::KEY; + r->formatter = nullptr; + r->notify = true; + r->rate = 1.0; - new (&r->options) sw::redis::ConnectionOptions; - new (&r->task) Task(CLOCK_REALTIME); - new (&r->key) std::string(); + new (&r->options) sw::redis::ConnectionOptions; + new (&r->task) Task(CLOCK_REALTIME); + new (&r->key) std::string(); - /* We need a timeout in order for RedisConnection::loop() to properly + /* We need a timeout in order for RedisConnection::loop() to properly * terminate after the node is stopped */ - r->options.socket_timeout = std::chrono::milliseconds(500); + r->options.socket_timeout = std::chrono::milliseconds(500); - return 0; + return 0; } -int villas::node::redis_destroy(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_destroy(NodeCompat *n) { + int ret; + auto *r = n->getData(); - if (r->formatter) - delete r->formatter; + if (r->formatter) + delete r->formatter; - using string = std::string; - using redis_co = sw::redis::ConnectionOptions; + using string = std::string; + using redis_co = sw::redis::ConnectionOptions; - r->options.~redis_co(); - r->key.~string(); - r->task.~Task(); + r->options.~redis_co(); + r->key.~string(); + r->task.~Task(); - ret = queue_signalled_destroy(&r->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&r->queue); + if (ret) + return ret; - ret = pool_destroy(&r->pool); - if (ret) - return ret; + ret = pool_destroy(&r->pool); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::redis_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_parse(NodeCompat *n, json_t *json) { + int ret; + auto *r = n->getData(); - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - const char *host = nullptr; - const char *path = nullptr; - const char *user = nullptr; - const char *password = nullptr; - const char *mode = nullptr; - const char *uri = nullptr; - const char *key = nullptr; - const char *channel = nullptr; - int keepalive = -1; - int db = -1; - int notify = -1; + const char *host = nullptr; + const char *path = nullptr; + const char *user = nullptr; + const char *password = nullptr; + const char *mode = nullptr; + const char *uri = nullptr; + const char *key = nullptr; + const char *channel = nullptr; + int keepalive = -1; + int db = -1; + int notify = -1; - double connect_timeout = -1; - double socket_timeout = -1; + double connect_timeout = -1; + double socket_timeout = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: s, s?: s, s?: i, s?: s, s?: s, s?: s, s?: i, s?: { s?: F, s?: F }, s?: o, s?: b, s?: s, s?: s, s?: s, s?: b, s?: F }", - "format", &json_format, - "uri", &uri, - "host", &host, - "port", &r->options.port, - "path", &path, - "user", &user, - "password", &password, - "db", &db, - "timeout", - "connect", &connect_timeout, - "socket", &socket_timeout, - "ssl", &json_ssl, - "keepalive", &keepalive, - "mode", &mode, - "key", &key, - "channel", &channel, - "notify", ¬ify, - "rate", &r->rate - ); - if (ret) - throw ConfigError(json, err, "node-config-node-redis", "Failed to parse node configuration"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: s, s?: s, s?: i, s?: s, s?: s, s?: s, s?: i, s?: { s?: F, " + "s?: F }, s?: o, s?: b, s?: s, s?: s, s?: s, s?: b, s?: F }", + "format", &json_format, "uri", &uri, "host", &host, "port", + &r->options.port, "path", &path, "user", &user, "password", &password, + "db", &db, "timeout", "connect", &connect_timeout, "socket", + &socket_timeout, "ssl", &json_ssl, "keepalive", &keepalive, "mode", &mode, + "key", &key, "channel", &channel, "notify", ¬ify, "rate", &r->rate); + if (ret) + throw ConfigError(json, err, "node-config-node-redis", + "Failed to parse node configuration"); - if (json_ssl) { + if (json_ssl) { #ifdef REDISPP_WITH_TLS - const char *cacert; - const char *cacertdir; - const char *cert; - const char *key; + const char *cacert; + const char *cacertdir; + const char *cert; + const char *key; - int enabled = 1; + int enabled = 1; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: s, s?: s, s?: s, s?: s }", - "enabled", &enabled, - "cacert", &cacert, - "cacertdir", &cacertdir, - "cert", &cert, - "key", &key - ); - if (ret) - throw ConfigError(json, err, "node-config-node-redis-ssl", "Failed to parse Redis SSL configuration"); + ret = json_unpack_ex(json_ssl, &err, 0, + "{ s?: b, s?: s, s?: s, s?: s, s?: s }", "enabled", + &enabled, "cacert", &cacert, "cacertdir", &cacertdir, + "cert", &cert, "key", &key); + if (ret) + throw ConfigError(json, err, "node-config-node-redis-ssl", + "Failed to parse Redis SSL configuration"); - r->options.tls.enabled = enabled != 0; + r->options.tls.enabled = enabled != 0; - r->options.tls.cacert = cacert; - r->options.tls.cacertdir = cacertdir; - r->options.tls.cert = cert; - r->options.tls.key = key; + r->options.tls.cacert = cacert; + r->options.tls.cacertdir = cacertdir; + r->options.tls.cert = cert; + r->options.tls.key = key; - if (host) - r->options.tls.sni = host; + if (host) + r->options.tls.sni = host; #else - throw ConfigError(json_ssl, "node-config-node-redis-ssl", "This built of the redis++ library does not support SSL"); + throw ConfigError(json_ssl, "node-config-node-redis-ssl", + "This built of the redis++ library does not support SSL"); #endif // REDISPP_WITH_TLS - } + } - // Mode - if (mode) { - if (!strcmp(mode, "key") || !strcmp(mode, "set-get")) - r->mode = RedisMode::KEY; - else if (!strcmp(mode, "hash") || !strcmp(mode, "hset-hget")) - r->mode = RedisMode::HASH; - else if (!strcmp(mode, "channel") || !strcmp(mode, "pub-sub")) - r->mode = RedisMode::CHANNEL; - else - throw ConfigError(json, "node-config-node-redis-mode", "Invalid Redis mode: {}", mode); - } + // Mode + if (mode) { + if (!strcmp(mode, "key") || !strcmp(mode, "set-get")) + r->mode = RedisMode::KEY; + else if (!strcmp(mode, "hash") || !strcmp(mode, "hset-hget")) + r->mode = RedisMode::HASH; + else if (!strcmp(mode, "channel") || !strcmp(mode, "pub-sub")) + r->mode = RedisMode::CHANNEL; + else + throw ConfigError(json, "node-config-node-redis-mode", + "Invalid Redis mode: {}", mode); + } - // Format - if (r->formatter) - delete r->formatter; - r->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!r->formatter) - throw ConfigError(json_format, "node-config-node-redis-format", "Invalid format configuration"); + // Format + if (r->formatter) + delete r->formatter; + r->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!r->formatter) + throw ConfigError(json_format, "node-config-node-redis-format", + "Invalid format configuration"); - if (key && r->mode == RedisMode::KEY) - r->key = key; - if (channel && r->mode == RedisMode::CHANNEL) - r->key = channel; + if (key && r->mode == RedisMode::KEY) + r->key = key; + if (channel && r->mode == RedisMode::CHANNEL) + r->key = channel; - if (notify >= 0) - r->notify = notify != 0; + if (notify >= 0) + r->notify = notify != 0; - // Connection options - if (uri) - r->options = make_redis_connection_options(uri); + // Connection options + if (uri) + r->options = make_redis_connection_options(uri); - if (db >= 0) - r->options.db = db; + if (db >= 0) + r->options.db = db; - if (user) - r->options.user = user; + if (user) + r->options.user = user; - if (password) - r->options.password = password; + if (password) + r->options.password = password; - if (host) - r->options.host = host; + if (host) + r->options.host = host; - if (path) - r->options.path = path; + if (path) + r->options.path = path; - if (keepalive >= 0) - r->options.keep_alive = keepalive != 0; + if (keepalive >= 0) + r->options.keep_alive = keepalive != 0; - if (socket_timeout > 0) - r->options.socket_timeout = std::chrono::milliseconds((int) (1000 * socket_timeout)); + if (socket_timeout > 0) + r->options.socket_timeout = + std::chrono::milliseconds((int)(1000 * socket_timeout)); - if (connect_timeout > 0) - r->options.connect_timeout = std::chrono::milliseconds((int) (1000 * connect_timeout)); + if (connect_timeout > 0) + r->options.connect_timeout = + std::chrono::milliseconds((int)(1000 * connect_timeout)); - return 0; + return 0; } -int villas::node::redis_check(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_check(NodeCompat *n) { + auto *r = n->getData(); - if (!r->options.host.empty() && !r->options.path.empty()) - return -1; + if (!r->options.host.empty() && !r->options.path.empty()) + return -1; - if (r->options.db < 0) - return -1; + if (r->options.db < 0) + return -1; - return 0; + return 0; } -char * villas::node::redis_print(NodeCompat *n) -{ - auto *r = n->getData(); +char *villas::node::redis_print(NodeCompat *n) { + auto *r = n->getData(); - std::stringstream ss; + std::stringstream ss; - ss << "mode=" << r->mode - << ", key=" << r->key - << ", notify=" << (r->notify ? "yes" : "no"); + ss << "mode=" << r->mode << ", key=" << r->key + << ", notify=" << (r->notify ? "yes" : "no"); - if (!r->notify) - ss << ", rate=" << r->rate; + if (!r->notify) + ss << ", rate=" << r->rate; - ss << ", " << r->options; + ss << ", " << r->options; - return strdup(ss.str().c_str()); + return strdup(ss.str().c_str()); } -int villas::node::redis_prepare(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_prepare(NodeCompat *n) { + int ret; + auto *r = n->getData(); - r->options.type = r->options.path.empty() - ? sw::redis::ConnectionType::TCP - : sw::redis::ConnectionType::UNIX; + r->options.type = r->options.path.empty() ? sw::redis::ConnectionType::TCP + : sw::redis::ConnectionType::UNIX; - if (r->key.empty()) - r->key = n->getNameShort(); + if (r->key.empty()) + r->key = n->getNameShort(); - ret = queue_signalled_init(&r->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&r->queue, 1024); + if (ret) + return ret; - ret = pool_init(&r->pool, 1024, SAMPLE_LENGTH(64)); - if (ret) - return ret; + ret = pool_init(&r->pool, 1024, SAMPLE_LENGTH(64)); + if (ret) + return ret; - r->conn = RedisConnection::get(r->options); - if (!r->conn) - return -1; + r->conn = RedisConnection::get(r->options); + if (!r->conn) + return -1; - return 0; + return 0; } -int villas::node::redis_start(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_start(NodeCompat *n) { + auto *r = n->getData(); - r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + r->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - if (!r->notify) - r->task.setRate(r->rate); + if (!r->notify) + r->task.setRate(r->rate); - switch (r->mode) { - case RedisMode::CHANNEL: - r->conn->subscribe(n, r->key); - break; + switch (r->mode) { + case RedisMode::CHANNEL: + r->conn->subscribe(n, r->key); + break; - case RedisMode::HASH: - case RedisMode::KEY: - if (r->notify) { - auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); - r->conn->subscribe(n, pattern); - } - break; - } + case RedisMode::HASH: + case RedisMode::KEY: + if (r->notify) { + auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); + r->conn->subscribe(n, pattern); + } + break; + } - r->conn->start(); + r->conn->start(); - return 0; + return 0; } -int villas::node::redis_stop(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_stop(NodeCompat *n) { + int ret; + auto *r = n->getData(); - r->conn->stop(); + r->conn->stop(); - if (!r->notify) - r->task.stop(); + if (!r->notify) + r->task.stop(); - switch (r->mode) { - case RedisMode::CHANNEL: - r->conn->unsubscribe(n, r->key); - break; + switch (r->mode) { + case RedisMode::CHANNEL: + r->conn->unsubscribe(n, r->key); + break; - case RedisMode::HASH: - case RedisMode::KEY: - if (r->notify) { - auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); - r->conn->unsubscribe(n, pattern); - } - break; - } + case RedisMode::HASH: + case RedisMode::KEY: + if (r->notify) { + auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); + r->conn->unsubscribe(n, pattern); + } + break; + } - ret = queue_signalled_close(&r->queue); - if (ret) - return ret; + ret = queue_signalled_close(&r->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *r = n->getData(); +int villas::node::redis_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *r = n->getData(); - // Wait for new data - if (r->notify || r->mode == RedisMode::CHANNEL) { - int pulled_cnt; - struct Sample *pulled_smps[cnt]; + // Wait for new data + if (r->notify || r->mode == RedisMode::CHANNEL) { + int pulled_cnt; + struct Sample *pulled_smps[cnt]; - pulled_cnt = queue_signalled_pull_many(&r->queue, (void **) pulled_smps, cnt); + pulled_cnt = + queue_signalled_pull_many(&r->queue, (void **)pulled_smps, cnt); - sample_copy_many(smps, pulled_smps, pulled_cnt); - sample_decref_many(pulled_smps, pulled_cnt); + sample_copy_many(smps, pulled_smps, pulled_cnt); + sample_decref_many(pulled_smps, pulled_cnt); - return pulled_cnt; - } - else { - if (r->task.wait() == 0) - throw SystemError("Failed to wait for task"); + return pulled_cnt; + } else { + if (r->task.wait() == 0) + throw SystemError("Failed to wait for task"); - return redis_get(n, smps, cnt); - } + return redis_get(n, smps, cnt); + } } -int villas::node::redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); - switch (r->mode) { - case RedisMode::CHANNEL: - for (unsigned i = 0; i < cnt; i++) { - char buf[1500]; - size_t wbytes; + switch (r->mode) { + case RedisMode::CHANNEL: + for (unsigned i = 0; i < cnt; i++) { + char buf[1500]; + size_t wbytes; - ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, &smps[i], cnt); - if (ret < 0) - return ret; + ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, &smps[i], cnt); + if (ret < 0) + return ret; - auto value = std::string_view(buf, wbytes); + auto value = std::string_view(buf, wbytes); - r->conn->context.publish(r->key, value); - } - break; + r->conn->context.publish(r->key, value); + } + break; - case RedisMode::KEY: { - char buf[1500]; - size_t wbytes; + case RedisMode::KEY: { + char buf[1500]; + size_t wbytes; - ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, smps, cnt); + if (ret < 0) + return ret; - auto value = std::string_view(buf, wbytes); + auto value = std::string_view(buf, wbytes); - r->conn->context.set(r->key, value); - break; - } + r->conn->context.set(r->key, value); + break; + } - case RedisMode::HASH: { - // We only update the signals with their latest value here. - struct Sample *smp = smps[cnt - 1]; + case RedisMode::HASH: { + // We only update the signals with their latest value here. + struct Sample *smp = smps[cnt - 1]; - std::unordered_map kvs; + std::unordered_map kvs; - unsigned len = MIN(smp->signals->size(), smp->length); - for (unsigned j = 0; j < len; j++) { - const auto sig = smp->signals->getByIndex(j); - const auto *data = &smp->data[j]; + unsigned len = MIN(smp->signals->size(), smp->length); + for (unsigned j = 0; j < len; j++) { + const auto sig = smp->signals->getByIndex(j); + const auto *data = &smp->data[j]; - kvs[sig->name] = data->toString(sig->type); - } + kvs[sig->name] = data->toString(sig->type); + } - r->conn->context.hmset(r->key, kvs.begin(), kvs.end()); - break; - } - } + r->conn->context.hmset(r->key, kvs.begin(), kvs.end()); + break; + } + } - return cnt; + return cnt; } -int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) -{ - auto *r = n->getData(); +int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) { + auto *r = n->getData(); - fds[0] = r->notify - ? queue_signalled_fd(&r->queue) - : r->task.getFD(); + fds[0] = r->notify ? queue_signalled_fd(&r->queue) : r->task.getFD(); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "redis"; - p.description = "Redis key-value store"; - p.vectorize = 0; - p.size = sizeof(struct redis); - p.init = redis_init; - p.destroy = redis_destroy; - p.parse = redis_parse; - p.check = redis_check; - p.print = redis_print; - p.prepare = redis_prepare; - p.start = redis_start; - p.stop = redis_stop; - p.read = redis_read; - p.write = redis_write; - p.poll_fds = redis_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "redis"; + p.description = "Redis key-value store"; + p.vectorize = 0; + p.size = sizeof(struct redis); + p.init = redis_init; + p.destroy = redis_destroy; + p.parse = redis_parse; + p.check = redis_check; + p.print = redis_print; + p.prepare = redis_prepare; + p.start = redis_start; + p.stop = redis_stop; + p.read = redis_read; + p.write = redis_write; + p.poll_fds = redis_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index dc68965fb..27de3c0e7 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -7,587 +7,568 @@ */ #include -#include #include #include +#include #include #include extern "C" { - #include - #include - #include - #include - #include - #include - #include - #undef ALIGN_MASK +#include +#include +#include +#include +#include +#include +#include +#undef ALIGN_MASK } +#include #include #include -#include #include -#include #include +#include #ifdef WITH_NETEM - #include +#include #endif // WITH_NETEM -static -pthread_t re_pthread; +static pthread_t re_pthread; using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static -int rtp_aimd(NodeCompat *n, double loss_frac) -{ - auto *r = n->getData(); +static int rtp_aimd(NodeCompat *n, double loss_frac) { + auto *r = n->getData(); - double rate; + double rate; - if (!r->rtcp.enabled) - return -1; + if (!r->rtcp.enabled) + return -1; - if (loss_frac < 0.01) - rate = r->aimd.rate + r->aimd.a; - else - rate = r->aimd.rate * r->aimd.b; + if (loss_frac < 0.01) + rate = r->aimd.rate + r->aimd.a; + else + rate = r->aimd.rate * r->aimd.b; - r->aimd.rate = r->aimd.rate_pid.calculate(rate, r->aimd.rate); + r->aimd.rate = r->aimd.rate_pid.calculate(rate, r->aimd.rate); - if (r->aimd.rate_hook) { - r->aimd.rate_hook->setRate(r->aimd.rate); - n->logger->debug("AIMD: Set rate limit to: {}", r->aimd.rate); - } + if (r->aimd.rate_hook) { + r->aimd.rate_hook->setRate(r->aimd.rate); + n->logger->debug("AIMD: Set rate limit to: {}", r->aimd.rate); + } - if (r->aimd.log) - *(r->aimd.log) << r->rtcp.num_rrs << "\t" << loss_frac << "\t" << r->aimd.rate << std::endl; + if (r->aimd.log) + *(r->aimd.log) << r->rtcp.num_rrs << "\t" << loss_frac << "\t" + << r->aimd.rate << std::endl; - n->logger->debug("AIMD: {}\t{}\t{}", r->rtcp.num_rrs, loss_frac, r->aimd.rate); + n->logger->debug("AIMD: {}\t{}\t{}", r->rtcp.num_rrs, loss_frac, + r->aimd.rate); - return 0; + return 0; } -int villas::node::rtp_init(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_init(NodeCompat *n) { + auto *r = n->getData(); - n->logger = villas::logging.get("node:rtp"); + n->logger = villas::logging.get("node:rtp"); - // Default values - r->aimd.a = 10; - r->aimd.b = 0.5; - r->aimd.Kp = 1; - r->aimd.Ki = 0; - r->aimd.Kd = 0; + // Default values + r->aimd.a = 10; + r->aimd.b = 0.5; + r->aimd.Kp = 1; + r->aimd.Ki = 0; + r->aimd.Kd = 0; - r->aimd.rate = 1; - r->aimd.rate_min = 1; - r->aimd.rate_source = 2000; + r->aimd.rate = 1; + r->aimd.rate_min = 1; + r->aimd.rate_source = 2000; - r->aimd.log_filename = nullptr; - r->aimd.log = nullptr; + r->aimd.log_filename = nullptr; + r->aimd.log = nullptr; - r->rtcp.enabled = false; - r->aimd.rate_hook_type = RTPHookType::DISABLED; + r->rtcp.enabled = false; + r->aimd.rate_hook_type = RTPHookType::DISABLED; - r->formatter = nullptr; + r->formatter = nullptr; - return 0; + return 0; } -int villas::node::rtp_reverse(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_reverse(NodeCompat *n) { + auto *r = n->getData(); - SWAP(r->in.saddr_rtp, r->out.saddr_rtp); - SWAP(r->in.saddr_rtcp, r->out.saddr_rtcp); + SWAP(r->in.saddr_rtp, r->out.saddr_rtp); + SWAP(r->in.saddr_rtcp, r->out.saddr_rtcp); - return 0; + return 0; } -int villas::node::rtp_parse(NodeCompat *n, json_t *json) -{ - int ret = 0; - auto *r = n->getData(); +int villas::node::rtp_parse(NodeCompat *n, json_t *json) { + int ret = 0; + auto *r = n->getData(); - const char *local, *remote; - const char *log = nullptr; - const char *hook_type = nullptr; - uint16_t port; + const char *local, *remote; + const char *log = nullptr; + const char *hook_type = nullptr; + uint16_t port; - json_error_t err; - json_t *json_aimd = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_aimd = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b, s?: o, s: { s: s }, s: { s: s } }", - "format", &json_format, - "rtcp", &r->rtcp.enabled, - "aimd", &json_aimd, - "out", - "address", &remote, - "in", - "address", &local - ); - if (ret) - throw ConfigError(json, err, "node-config-node-rtp"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: o, s?: b, s?: o, s: { s: s }, s: { s: s } }", + "format", &json_format, "rtcp", &r->rtcp.enabled, "aimd", &json_aimd, + "out", "address", &remote, "in", "address", &local); + if (ret) + throw ConfigError(json, err, "node-config-node-rtp"); - // AIMD - if (json_aimd) { - ret = json_unpack_ex(json_aimd, &err, 0, "{ s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: s, s?: s }", - "a", &r->aimd.a, - "b", &r->aimd.b, - "Kp", &r->aimd.Kp, - "Ki", &r->aimd.Ki, - "Kd", &r->aimd.Kd, - "rate_min", &r->aimd.rate_min, - "rate_source", &r->aimd.rate_source, - "rate_init", &r->aimd.rate, - "log", &log, - "hook_type", &hook_type - ); - if (ret) - throw ConfigError(json_aimd, err, "node-config-node-rtp-aimd"); + // AIMD + if (json_aimd) { + ret = json_unpack_ex(json_aimd, &err, 0, + "{ s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, " + "s?: F, s?: s, s?: s }", + "a", &r->aimd.a, "b", &r->aimd.b, "Kp", &r->aimd.Kp, + "Ki", &r->aimd.Ki, "Kd", &r->aimd.Kd, "rate_min", + &r->aimd.rate_min, "rate_source", &r->aimd.rate_source, + "rate_init", &r->aimd.rate, "log", &log, "hook_type", + &hook_type); + if (ret) + throw ConfigError(json_aimd, err, "node-config-node-rtp-aimd"); - // AIMD Hook type - if (!r->rtcp.enabled) - r->aimd.rate_hook_type = RTPHookType::DISABLED; - else if (hook_type) { - if (!strcmp(hook_type, "decimate")) - r->aimd.rate_hook_type = RTPHookType::DECIMATE; - else if (!strcmp(hook_type, "limit_rate")) - r->aimd.rate_hook_type = RTPHookType::LIMIT_RATE; - else if (!strcmp(hook_type, "disabled")) - r->aimd.rate_hook_type = RTPHookType::DISABLED; - else - throw RuntimeError("Unknown RTCP hook_type: {}", hook_type); - } - } + // AIMD Hook type + if (!r->rtcp.enabled) + r->aimd.rate_hook_type = RTPHookType::DISABLED; + else if (hook_type) { + if (!strcmp(hook_type, "decimate")) + r->aimd.rate_hook_type = RTPHookType::DECIMATE; + else if (!strcmp(hook_type, "limit_rate")) + r->aimd.rate_hook_type = RTPHookType::LIMIT_RATE; + else if (!strcmp(hook_type, "disabled")) + r->aimd.rate_hook_type = RTPHookType::DISABLED; + else + throw RuntimeError("Unknown RTCP hook_type: {}", hook_type); + } + } - if (log) - r->aimd.log_filename = strdup(log); + if (log) + r->aimd.log_filename = strdup(log); - // Format - if (r->formatter) - delete r->formatter; - r->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!r->formatter) - throw ConfigError(json_format, "node-config-node-rtp-format", "Invalid format configuration"); + // Format + if (r->formatter) + delete r->formatter; + r->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!r->formatter) + throw ConfigError(json_format, "node-config-node-rtp-format", + "Invalid format configuration"); - // Remote address - ret = sa_decode(&r->out.saddr_rtp, remote, strlen(remote)); - if (ret) - throw RuntimeError("Failed to resolve remote address '{}': {}", remote, strerror(ret)); + // Remote address + ret = sa_decode(&r->out.saddr_rtp, remote, strlen(remote)); + if (ret) + throw RuntimeError("Failed to resolve remote address '{}': {}", remote, + strerror(ret)); - // Assign even port number to RTP socket, next odd number to RTCP socket - port = sa_port(&r->out.saddr_rtp) & ~1; - sa_set_sa(&r->out.saddr_rtcp, &r->out.saddr_rtp.u.sa); - sa_set_port(&r->out.saddr_rtp, port); - sa_set_port(&r->out.saddr_rtcp, port+1); + // Assign even port number to RTP socket, next odd number to RTCP socket + port = sa_port(&r->out.saddr_rtp) & ~1; + sa_set_sa(&r->out.saddr_rtcp, &r->out.saddr_rtp.u.sa); + sa_set_port(&r->out.saddr_rtp, port); + sa_set_port(&r->out.saddr_rtcp, port + 1); - // Local address - ret = sa_decode(&r->in.saddr_rtp, local, strlen(local)); - if (ret) - throw RuntimeError("Failed to resolve local address '{}': {}", local, strerror(ret)); + // Local address + ret = sa_decode(&r->in.saddr_rtp, local, strlen(local)); + if (ret) + throw RuntimeError("Failed to resolve local address '{}': {}", local, + strerror(ret)); - // Assign even port number to RTP socket, next odd number to RTCP socket - port = sa_port(&r->in.saddr_rtp) & ~1; - sa_set_sa(&r->in.saddr_rtcp, &r->in.saddr_rtp.u.sa); - sa_set_port(&r->in.saddr_rtp, port); - sa_set_port(&r->in.saddr_rtcp, port+1); + // Assign even port number to RTP socket, next odd number to RTCP socket + port = sa_port(&r->in.saddr_rtp) & ~1; + sa_set_sa(&r->in.saddr_rtcp, &r->in.saddr_rtp.u.sa); + sa_set_port(&r->in.saddr_rtp, port); + sa_set_port(&r->in.saddr_rtcp, port + 1); - // TODO: parse * in addresses + // TODO: parse * in addresses - return 0; + return 0; } -char * villas::node::rtp_print(NodeCompat *n) -{ - auto *r = n->getData(); - char *buf; +char *villas::node::rtp_print(NodeCompat *n) { + auto *r = n->getData(); + char *buf; - char *local = socket_print_addr((struct sockaddr *) &r->in.saddr_rtp.u); - char *remote = socket_print_addr((struct sockaddr *) &r->out.saddr_rtp.u); + char *local = socket_print_addr((struct sockaddr *)&r->in.saddr_rtp.u); + char *remote = socket_print_addr((struct sockaddr *)&r->out.saddr_rtp.u); - buf = strf("in.address=%s, out.address=%s, rtcp.enabled=%s", - local, remote, - r->rtcp.enabled ? "yes" : "no"); + buf = strf("in.address=%s, out.address=%s, rtcp.enabled=%s", local, remote, + r->rtcp.enabled ? "yes" : "no"); - if (r->rtcp.enabled) { - const char *hook_type; + if (r->rtcp.enabled) { + const char *hook_type; - switch (r->aimd.rate_hook_type) { - case RTPHookType::DECIMATE: - hook_type = "decimate"; - break; + switch (r->aimd.rate_hook_type) { + case RTPHookType::DECIMATE: + hook_type = "decimate"; + break; - case RTPHookType::LIMIT_RATE: - hook_type = "limit_rate"; - break; + case RTPHookType::LIMIT_RATE: + hook_type = "limit_rate"; + break; - case RTPHookType::DISABLED: - hook_type = "disabled"; - break; + case RTPHookType::DISABLED: + hook_type = "disabled"; + break; - default: - hook_type = "unknown"; - } + default: + hook_type = "unknown"; + } - strcatf(&buf, ", aimd.hook_type=%s", hook_type); - strcatf(&buf, ", aimd.a=%f, aimd.b=%f, aimd.start_rate=%f", r->aimd.a, r->aimd.b, r->aimd.rate); - } + strcatf(&buf, ", aimd.hook_type=%s", hook_type); + strcatf(&buf, ", aimd.a=%f, aimd.b=%f, aimd.start_rate=%f", r->aimd.a, + r->aimd.b, r->aimd.rate); + } - free(local); - free(remote); + free(local); + free(remote); - return buf; + return buf; } -static -void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf *mb, void *arg) -{ - int ret; - auto *n = (NodeCompat *) arg; - auto *r = n->getData(); +static void rtp_handler(const struct sa *src, const struct rtp_header *hdr, + struct mbuf *mb, void *arg) { + int ret; + auto *n = (NodeCompat *)arg; + auto *r = n->getData(); - // source, header not used - (void) src; - (void) hdr; + // source, header not used + (void)src; + (void)hdr; - void *d = mem_ref((void *) mb); + void *d = mem_ref((void *)mb); - ret = queue_signalled_push(&r->recv_queue, d); - if (ret != 1) { - n->logger->warn("Failed to push to queue"); - mem_deref(d); - } + ret = queue_signalled_push(&r->recv_queue, d); + if (ret != 1) { + n->logger->warn("Failed to push to queue"); + mem_deref(d); + } } -static -void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) -{ - auto *n = (NodeCompat *) arg; - auto *r = n->getData(); +static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, + void *arg) { + auto *n = (NodeCompat *)arg; + auto *r = n->getData(); - // source not used - (void) src; + // source not used + (void)src; - n->logger->debug("RTCP: recv {}", rtcp_type_name((enum rtcp_type) msg->hdr.pt)); + n->logger->debug("RTCP: recv {}", + rtcp_type_name((enum rtcp_type)msg->hdr.pt)); - if (msg->hdr.pt == RTCP_SR) { - if (msg->hdr.count > 0) { - const struct rtcp_rr *rr = &msg->r.sr.rrv[0]; + if (msg->hdr.pt == RTCP_SR) { + if (msg->hdr.count > 0) { + const struct rtcp_rr *rr = &msg->r.sr.rrv[0]; - double loss_frac = (double) rr->fraction / 256; + double loss_frac = (double)rr->fraction / 256; - rtp_aimd(n, loss_frac); + rtp_aimd(n, loss_frac); - auto stats = n->getStats(); - if (stats) { - stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost); - stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac); - stats->update(Stats::Metric::RTP_JITTER, rr->jitter); - } + auto stats = n->getStats(); + if (stats) { + stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost); + stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac); + stats->update(Stats::Metric::RTP_JITTER, rr->jitter); + } - n->logger->info("RTCP: rr: num_rrs={}, loss_frac={}, pkts_lost={}, jitter={}", r->rtcp.num_rrs, loss_frac, rr->lost, rr->jitter); - } - else - n->logger->debug("RTCP: Received sender report with zero reception reports"); - } + n->logger->info( + "RTCP: rr: num_rrs={}, loss_frac={}, pkts_lost={}, jitter={}", + r->rtcp.num_rrs, loss_frac, rr->lost, rr->jitter); + } else + n->logger->debug( + "RTCP: Received sender report with zero reception reports"); + } - r->rtcp.num_rrs++; + r->rtcp.num_rrs++; } -int villas::node::rtp_start(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_start(NodeCompat *n) { + int ret; + auto *r = n->getData(); - // Initialize queue - ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); - if (ret) - return ret; + // Initialize queue + ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); + if (ret) + return ret; - // Initialize IO - r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + // Initialize IO + r->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Initialize memory buffer for sending - r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); - if (!r->send_mb) - return -1; + // Initialize memory buffer for sending + r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); + if (!r->send_mb) + return -1; - ret = mbuf_fill(r->send_mb, 0, RTP_HEADER_SIZE); - if (ret) - return -1; + ret = mbuf_fill(r->send_mb, 0, RTP_HEADER_SIZE); + if (ret) + return -1; - // Initialize AIMD hook - if (r->aimd.rate_hook_type != RTPHookType::DISABLED) { + // Initialize AIMD hook + if (r->aimd.rate_hook_type != RTPHookType::DISABLED) { #ifdef WITH_HOOKS - switch (r->aimd.rate_hook_type) { - case RTPHookType::DECIMATE: - r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); - break; + switch (r->aimd.rate_hook_type) { + case RTPHookType::DECIMATE: + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); + break; - case RTPHookType::LIMIT_RATE: - r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); - break; + case RTPHookType::LIMIT_RATE: + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); + break; - default: - return -1; - } + default: + return -1; + } - if (!r->aimd.rate_hook) - throw MemoryAllocationError(); + if (!r->aimd.rate_hook) + throw MemoryAllocationError(); - r->aimd.rate_hook->init(); + r->aimd.rate_hook->init(); - n->out.hooks.push_back(r->aimd.rate_hook); + n->out.hooks.push_back(r->aimd.rate_hook); - r->aimd.rate_hook->setRate(r->aimd.rate, r->aimd.rate_source); + r->aimd.rate_hook->setRate(r->aimd.rate, r->aimd.rate_source); #else - throw RuntimeError("Rate limiting is not supported"); + throw RuntimeError("Rate limiting is not supported"); - return -1; + return -1; #endif - } + } - double dt = 5.0; // TODO + double dt = 5.0; // TODO - r->aimd.rate_pid = villas::dsp::PID(dt, r->aimd.rate_source, r->aimd.rate_min, r->aimd.Kp, r->aimd.Ki, r->aimd.Kd); + r->aimd.rate_pid = villas::dsp::PID(dt, r->aimd.rate_source, r->aimd.rate_min, + r->aimd.Kp, r->aimd.Ki, r->aimd.Kd); - // Initialize RTP socket - uint16_t port = sa_port(&r->in.saddr_rtp) & ~1; - ret = rtp_listen(&r->rs, IPPROTO_UDP, &r->in.saddr_rtp, port, port+1, r->rtcp.enabled, rtp_handler, rtcp_handler, n); + // Initialize RTP socket + uint16_t port = sa_port(&r->in.saddr_rtp) & ~1; + ret = rtp_listen(&r->rs, IPPROTO_UDP, &r->in.saddr_rtp, port, port + 1, + r->rtcp.enabled, rtp_handler, rtcp_handler, n); - // Start RTCP session - if (r->rtcp.enabled) { - r->rtcp.num_rrs = 0; + // Start RTCP session + if (r->rtcp.enabled) { + r->rtcp.num_rrs = 0; - rtcp_start(r->rs, n->getNameShort().c_str(), &r->out.saddr_rtcp); + rtcp_start(r->rs, n->getNameShort().c_str(), &r->out.saddr_rtcp); - if (r->aimd.log_filename) { - char fn[128]; + if (r->aimd.log_filename) { + char fn[128]; - time_t ts = time(nullptr); - struct tm tm; + time_t ts = time(nullptr); + struct tm tm; - // Convert time - gmtime_r(&ts, &tm); - strftime(fn, sizeof(fn), r->aimd.log_filename, &tm); + // Convert time + gmtime_r(&ts, &tm); + strftime(fn, sizeof(fn), r->aimd.log_filename, &tm); - r->aimd.log = new std::ofstream(fn, std::ios::out | std::ios::trunc); - if (!r->aimd.log) - throw MemoryAllocationError(); + r->aimd.log = new std::ofstream(fn, std::ios::out | std::ios::trunc); + if (!r->aimd.log) + throw MemoryAllocationError(); - *(r->aimd.log) << "# cnt\tfrac_loss\trate" << std::endl; - } - else - r->aimd.log = nullptr; - } + *(r->aimd.log) << "# cnt\tfrac_loss\trate" << std::endl; + } else + r->aimd.log = nullptr; + } - return ret; + return ret; } -int villas::node::rtp_stop(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_stop(NodeCompat *n) { + int ret; + auto *r = n->getData(); - mem_deref(r->rs); + mem_deref(r->rs); - ret = queue_signalled_close(&r->recv_queue); - if (ret) - throw RuntimeError("Problem closing queue"); + ret = queue_signalled_close(&r->recv_queue); + if (ret) + throw RuntimeError("Problem closing queue"); - ret = queue_signalled_destroy(&r->recv_queue); - if (ret) - throw RuntimeError("Problem destroying queue"); + ret = queue_signalled_destroy(&r->recv_queue); + if (ret) + throw RuntimeError("Problem destroying queue"); - mem_deref(r->send_mb); + mem_deref(r->send_mb); - if (r->aimd.log) - r->aimd.log->close(); + if (r->aimd.log) + r->aimd.log->close(); - return 0; + return 0; } -int villas::node::rtp_destroy(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_destroy(NodeCompat *n) { + auto *r = n->getData(); - if (r->aimd.log) - delete r->aimd.log; + if (r->aimd.log) + delete r->aimd.log; - if (r->aimd.log_filename) - free(r->aimd.log_filename); + if (r->aimd.log_filename) + free(r->aimd.log_filename); - if (r->formatter) - delete r->formatter; + if (r->formatter) + delete r->formatter; - return 0; + return 0; } -static -void stop_handler(int sig, siginfo_t *si, void *ctx) -{ - re_cancel(); -} +static void stop_handler(int sig, siginfo_t *si, void *ctx) { re_cancel(); } typedef void *(*pthread_start_routine)(void *); -int villas::node::rtp_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::rtp_type_start(villas::node::SuperNode *sn) { + int ret; - // Initialize library - ret = libre_init(); - if (ret) - throw RuntimeError("Error initializing libre"); + // Initialize library + ret = libre_init(); + if (ret) + throw RuntimeError("Error initializing libre"); - // Add worker thread - ret = pthread_create(&re_pthread, nullptr, (pthread_start_routine) re_main, nullptr); - if (ret) - throw RuntimeError("Error creating rtp node type pthread"); + // Add worker thread + ret = pthread_create(&re_pthread, nullptr, (pthread_start_routine)re_main, + nullptr); + if (ret) + throw RuntimeError("Error creating rtp node type pthread"); - struct sigaction sa; - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = stop_handler; + struct sigaction sa; + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = stop_handler; - ret = sigaction(SIGUSR1, &sa, nullptr); - if (ret) - return ret; + ret = sigaction(SIGUSR1, &sa, nullptr); + if (ret) + return ret; #ifdef WITH_NETEM - if (sn != nullptr) { - // Gather list of used network interfaces - for (auto *n : ncp.instances) { - auto *nc = dynamic_cast(n); - auto *r = nc->getData(); - Interface *j = Interface::getEgress(&r->out.saddr_rtp.u.sa, sn); + if (sn != nullptr) { + // Gather list of used network interfaces + for (auto *n : ncp.instances) { + auto *nc = dynamic_cast(n); + auto *r = nc->getData(); + Interface *j = Interface::getEgress(&r->out.saddr_rtp.u.sa, sn); - if (!j) - throw RuntimeError("Failed to find egress interface"); + if (!j) + throw RuntimeError("Failed to find egress interface"); - j->addNode(n); - } - } + j->addNode(n); + } + } #endif // WITH_NETEM - return 0; + return 0; } -int villas::node::rtp_type_stop() -{ - int ret; +int villas::node::rtp_type_stop() { + int ret; - // Join worker thread - pthread_kill(re_pthread, SIGUSR1); - ret = pthread_join(re_pthread, nullptr); - if (ret) - throw RuntimeError("Error joining rtp node type pthread"); + // Join worker thread + pthread_kill(re_pthread, SIGUSR1); + ret = pthread_join(re_pthread, nullptr); + if (ret) + throw RuntimeError("Error joining rtp node type pthread"); - libre_close(); + libre_close(); - return 0; + return 0; } -int villas::node::rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); - struct mbuf *mb; +int villas::node::rtp_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); + struct mbuf *mb; - // Get data from queue - ret = queue_signalled_pull(&r->recv_queue, (void **) &mb); - if (ret < 0) - throw RuntimeError("Failed to pull from queue"); + // Get data from queue + ret = queue_signalled_pull(&r->recv_queue, (void **)&mb); + if (ret < 0) + throw RuntimeError("Failed to pull from queue"); - // Unpack data - ret = r->formatter->sscan((char *) mb->buf + mb->pos, mbuf_get_left(mb), nullptr, smps, cnt); + // Unpack data + ret = r->formatter->sscan((char *)mb->buf + mb->pos, mbuf_get_left(mb), + nullptr, smps, cnt); - mem_deref(mb); + mem_deref(mb); - return ret; + return ret; } -int villas::node::rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); - size_t wbytes; - size_t avail; + size_t wbytes; + size_t avail; - uint32_t ts = (uint32_t) time(nullptr); + uint32_t ts = (uint32_t)time(nullptr); -retry: mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); - avail = mbuf_get_space(r->send_mb); - cnt = r->formatter->sprint((char *) r->send_mb->buf + r->send_mb->pos, avail, &wbytes, smps, cnt); - if (cnt < 0) - return -1; +retry: + mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); + avail = mbuf_get_space(r->send_mb); + cnt = r->formatter->sprint((char *)r->send_mb->buf + r->send_mb->pos, avail, + &wbytes, smps, cnt); + if (cnt < 0) + return -1; - if (wbytes > avail) { - ret = mbuf_resize(r->send_mb, wbytes + RTP_HEADER_SIZE); - if (!ret) - return -1; + if (wbytes > avail) { + ret = mbuf_resize(r->send_mb, wbytes + RTP_HEADER_SIZE); + if (!ret) + return -1; - goto retry; - } - else - mbuf_set_end(r->send_mb, r->send_mb->pos + wbytes); + goto retry; + } else + mbuf_set_end(r->send_mb, r->send_mb->pos + wbytes); - mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); + mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); - // Send dataset - ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, r->send_mb); - if (ret) - throw RuntimeError("Error from rtp_send, reason: {}", ret); + // Send dataset + ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, + r->send_mb); + if (ret) + throw RuntimeError("Error from rtp_send, reason: {}", ret); - return cnt; + return cnt; } -int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) -{ - auto *r = n->getData(); +int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) { + auto *r = n->getData(); - fds[0] = queue_signalled_fd(&r->recv_queue); + fds[0] = queue_signalled_fd(&r->recv_queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "rtp"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "rtp"; #ifdef WITH_NETEM - p.description = "real-time transport protocol (libre, libnl3 netem support)"; + p.description = "real-time transport protocol (libre, libnl3 netem support)"; #else - p.description = "real-time transport protocol (libre)"; + p.description = "real-time transport protocol (libre)"; #endif - p.vectorize = 0; - p.size = sizeof(struct rtp); - p.type.start = rtp_type_start; - p.type.stop = rtp_type_stop; - p.init = rtp_init; - p.destroy = rtp_destroy; - p.parse = rtp_parse; - p.print = rtp_print; - p.start = rtp_start; - p.stop = rtp_stop; - p.read = rtp_read; - p.write = rtp_write; - p.reverse = rtp_reverse; - p.poll_fds = rtp_poll_fds; + p.vectorize = 0; + p.size = sizeof(struct rtp); + p.type.start = rtp_type_start; + p.type.stop = rtp_type_stop; + p.init = rtp_init; + p.destroy = rtp_destroy; + p.parse = rtp_parse; + p.print = rtp_print; + p.start = rtp_start; + p.stop = rtp_stop; + p.read = rtp_read; + p.write = rtp_write; + p.reverse = rtp_reverse; + p.poll_fds = rtp_poll_fds; } diff --git a/lib/nodes/shmem.cpp b/lib/nodes/shmem.cpp index 3cbb95270..4f9e363cc 100644 --- a/lib/nodes/shmem.cpp +++ b/lib/nodes/shmem.cpp @@ -5,19 +5,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include #include #include #include +#include #include #include -#include -#include #include #include +#include #include #include @@ -25,210 +25,198 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::shmem_init(NodeCompat *n) -{ - auto *shm = n->getData(); +int villas::node::shmem_init(NodeCompat *n) { + auto *shm = n->getData(); - // Default values - shm->conf.queuelen = -1; - shm->conf.samplelen = -1; - shm->conf.polling = false; - shm->exec = nullptr; + // Default values + shm->conf.queuelen = -1; + shm->conf.samplelen = -1; + shm->conf.polling = false; + shm->exec = nullptr; - return 0; + return 0; } -int villas::node::shmem_parse(NodeCompat *n, json_t *json) -{ - auto *shm = n->getData(); - const char *val, *mode_str = nullptr; +int villas::node::shmem_parse(NodeCompat *n, json_t *json) { + auto *shm = n->getData(); + const char *val, *mode_str = nullptr; - int ret; - json_t *json_exec = nullptr; - json_error_t err; + int ret; + json_t *json_exec = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: { s: s }, s: { s: s }, s?: i, s?: o, s?: s }", - "out", - "name", &shm->out_name, - "in", - "name", &shm->in_name, - "queuelen", &shm->conf.queuelen, - "exec", &json_exec, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-shmem"); + ret = json_unpack_ex( + json, &err, 0, "{ s: { s: s }, s: { s: s }, s?: i, s?: o, s?: s }", "out", + "name", &shm->out_name, "in", "name", &shm->in_name, "queuelen", + &shm->conf.queuelen, "exec", &json_exec, "mode", &mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-shmem"); - if (mode_str) { - if (!strcmp(mode_str, "polling")) - shm->conf.polling = true; - else if (!strcmp(mode_str, "pthread")) - shm->conf.polling = false; - else - throw SystemError("Unknown mode '{}'", mode_str); - } + if (mode_str) { + if (!strcmp(mode_str, "polling")) + shm->conf.polling = true; + else if (!strcmp(mode_str, "pthread")) + shm->conf.polling = false; + else + throw SystemError("Unknown mode '{}'", mode_str); + } - if (json_exec) { - if (!json_is_array(json_exec)) - throw SystemError("Setting 'exec' must be an array of strings"); + if (json_exec) { + if (!json_is_array(json_exec)) + throw SystemError("Setting 'exec' must be an array of strings"); - shm->exec = new char*[json_array_size(json_exec) + 1]; - if (!shm->exec) - throw MemoryAllocationError(); + shm->exec = new char *[json_array_size(json_exec) + 1]; + if (!shm->exec) + throw MemoryAllocationError(); - size_t i; - json_t *json_val; - json_array_foreach(json_exec, i, json_val) { - val = json_string_value(json_val); - if (!val) - throw SystemError("Setting 'exec' must be an array of strings"); + size_t i; + json_t *json_val; + json_array_foreach(json_exec, i, json_val) { + val = json_string_value(json_val); + if (!val) + throw SystemError("Setting 'exec' must be an array of strings"); - shm->exec[i] = strdup(val); - } + shm->exec[i] = strdup(val); + } - shm->exec[i] = nullptr; - } + shm->exec[i] = nullptr; + } - return 0; + return 0; } -int villas::node::shmem_prepare(NodeCompat *n) -{ - auto *shm = n->getData(); +int villas::node::shmem_prepare(NodeCompat *n) { + auto *shm = n->getData(); - if (shm->conf.queuelen < 0) - shm->conf.queuelen = MAX(DEFAULT_SHMEM_QUEUELEN, n->in.vectorize); + if (shm->conf.queuelen < 0) + shm->conf.queuelen = MAX(DEFAULT_SHMEM_QUEUELEN, n->in.vectorize); - if (shm->conf.samplelen < 0) { - auto input_sigs = n->getInputSignals(false)->size(); - auto output_sigs = 0U; + if (shm->conf.samplelen < 0) { + auto input_sigs = n->getInputSignals(false)->size(); + auto output_sigs = 0U; - if (n->getOutputSignals(true)) - output_sigs = n->getOutputSignals(true)->size(); + if (n->getOutputSignals(true)) + output_sigs = n->getOutputSignals(true)->size(); - shm->conf.samplelen = MAX(input_sigs, output_sigs); - } + shm->conf.samplelen = MAX(input_sigs, output_sigs); + } - return 0; + return 0; } -int villas::node::shmem_start(NodeCompat *n) -{ - auto *shm = n->getData(); - int ret; +int villas::node::shmem_start(NodeCompat *n) { + auto *shm = n->getData(); + int ret; - if (shm->exec) { - ret = spawn(shm->exec[0], shm->exec); - if (!ret) - throw SystemError("Failed to spawn external program"); + if (shm->exec) { + ret = spawn(shm->exec[0], shm->exec); + if (!ret) + throw SystemError("Failed to spawn external program"); - sleep(1); - } + sleep(1); + } - ret = shmem_int_open(shm->out_name, shm->in_name, &shm->intf, &shm->conf); - if (ret < 0) - throw SystemError("Opening shared memory interface failed (ret={})", ret); + ret = shmem_int_open(shm->out_name, shm->in_name, &shm->intf, &shm->conf); + if (ret < 0) + throw SystemError("Opening shared memory interface failed (ret={})", ret); - return 0; + return 0; } -int villas::node::shmem_stop(NodeCompat *n) -{ - auto* shm = n->getData(); +int villas::node::shmem_stop(NodeCompat *n) { + auto *shm = n->getData(); - return shmem_int_close(&shm->intf); + return shmem_int_close(&shm->intf); } -int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *shm = n->getData(); - int recv; - struct Sample *shared_smps[cnt]; +int villas::node::shmem_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *shm = n->getData(); + int recv; + struct Sample *shared_smps[cnt]; - do { - recv = shmem_int_read(&shm->intf, shared_smps, cnt); - } while (recv == 0); + do { + recv = shmem_int_read(&shm->intf, shared_smps, cnt); + } while (recv == 0); - if (recv < 0) { - /* This can only really mean that the other process has exited, so close + if (recv < 0) { + /* This can only really mean that the other process has exited, so close * the interface to make sure the shared memory object is unlinked */ - n->logger->info("Shared memory segment has been closed."); + n->logger->info("Shared memory segment has been closed."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return recv; - } + return recv; + } - sample_copy_many(smps, shared_smps, recv); - sample_decref_many(shared_smps, recv); + sample_copy_many(smps, shared_smps, recv); + sample_decref_many(shared_smps, recv); - // TODO: signal descriptions are currently not shared between processes - for (int i = 0; i < recv; i++) - smps[i]->signals = n->getInputSignals(false); + // TODO: signal descriptions are currently not shared between processes + for (int i = 0; i < recv; i++) + smps[i]->signals = n->getInputSignals(false); - return recv; + return recv; } -int villas::node::shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *shm = n->getData(); - struct Sample *shared_smps[cnt]; // Samples need to be copied to the shared pool first - int avail, pushed, copied; +int villas::node::shmem_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *shm = n->getData(); + struct Sample + *shared_smps[cnt]; // Samples need to be copied to the shared pool first + int avail, pushed, copied; - avail = sample_alloc_many(&shm->intf.write.shared->pool, shared_smps, cnt); - if (avail != (int) cnt) - n->logger->warn("Pool underrun for shmem node {}", shm->out_name); + avail = sample_alloc_many(&shm->intf.write.shared->pool, shared_smps, cnt); + if (avail != (int)cnt) + n->logger->warn("Pool underrun for shmem node {}", shm->out_name); - copied = sample_copy_many(shared_smps, smps, avail); - if (copied < avail) - n->logger->warn("Outgoing pool underrun"); + copied = sample_copy_many(shared_smps, smps, avail); + if (copied < avail) + n->logger->warn("Outgoing pool underrun"); - pushed = shmem_int_write(&shm->intf, shared_smps, copied); - if (pushed != avail) - n->logger->warn("Outgoing queue overrun for node"); + pushed = shmem_int_write(&shm->intf, shared_smps, copied); + if (pushed != avail) + n->logger->warn("Outgoing queue overrun for node"); - return pushed; + return pushed; } -char * villas::node::shmem_print(NodeCompat *n) -{ - auto *shm = n->getData(); - char *buf = nullptr; +char *villas::node::shmem_print(NodeCompat *n) { + auto *shm = n->getData(); + char *buf = nullptr; - strcatf(&buf, "out_name=%s, in_name=%s, queuelen=%d, polling=%s", - shm->out_name, shm->in_name, shm->conf.queuelen, shm->conf.polling ? "yes" : "no"); + strcatf(&buf, "out_name=%s, in_name=%s, queuelen=%d, polling=%s", + shm->out_name, shm->in_name, shm->conf.queuelen, + shm->conf.polling ? "yes" : "no"); - if (shm->exec) { - strcatf(&buf, ", exec='"); + if (shm->exec) { + strcatf(&buf, ", exec='"); - for (int i = 0; shm->exec[i]; i++) - strcatf(&buf, shm->exec[i+1] ? "%s " : "%s", shm->exec[i]); + for (int i = 0; shm->exec[i]; i++) + strcatf(&buf, shm->exec[i + 1] ? "%s " : "%s", shm->exec[i]); - strcatf(&buf, "'"); - } + strcatf(&buf, "'"); + } - return buf; + return buf; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "shmem"; - p.description = "POSIX shared memory interface with external processes"; - p.vectorize = 0; - p.size = sizeof(struct shmem); - p.parse = shmem_parse; - p.print = shmem_print; - p.start = shmem_start; - p.stop = shmem_stop; - p.read = shmem_read; - p.write = shmem_write; - p.prepare = shmem_prepare; - p.init = shmem_init; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "shmem"; + p.description = "POSIX shared memory interface with external processes"; + p.vectorize = 0; + p.size = sizeof(struct shmem); + p.parse = shmem_parse; + p.print = shmem_print; + p.start = shmem_start; + p.stop = shmem_stop; + p.read = shmem_read; + p.write = shmem_write; + p.prepare = shmem_prepare; + p.init = shmem_init; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/signal.cpp b/lib/nodes/signal.cpp index 798569229..eba731d35 100644 --- a/lib/nodes/signal.cpp +++ b/lib/nodes/signal.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include #include @@ -18,365 +18,337 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -SignalNodeSignal::SignalNodeSignal(json_t *json) : - type(Type::MIXED), - frequency(1.0), - amplitude(1.0), - stddev(0.2), - offset(0.0), - pulse_width(1.0), - pulse_low(0.0), - pulse_high(1.0), - phase(0.0) -{ - parse(json); +SignalNodeSignal::SignalNodeSignal(json_t *json) + : type(Type::MIXED), frequency(1.0), amplitude(1.0), stddev(0.2), + offset(0.0), pulse_width(1.0), pulse_low(0.0), pulse_high(1.0), + phase(0.0) { + parse(json); - last = offset; + last = offset; } -enum SignalNodeSignal::Type SignalNodeSignal::lookupType(const std::string &type) -{ - if (type == "random") - return Type::RANDOM; - else if (type == "sine") - return Type::SINE; - else if (type == "square") - return Type::SQUARE; - else if (type == "triangle") - return Type::TRIANGLE; - else if (type == "ramp") - return Type::RAMP; - else if (type == "counter") - return Type::COUNTER; - else if (type == "constant") - return Type::CONSTANT; - else if (type == "mixed") - return Type::MIXED; - else if (type == "pulse") - return Type::PULSE; +enum SignalNodeSignal::Type +SignalNodeSignal::lookupType(const std::string &type) { + if (type == "random") + return Type::RANDOM; + else if (type == "sine") + return Type::SINE; + else if (type == "square") + return Type::SQUARE; + else if (type == "triangle") + return Type::TRIANGLE; + else if (type == "ramp") + return Type::RAMP; + else if (type == "counter") + return Type::COUNTER; + else if (type == "constant") + return Type::CONSTANT; + else if (type == "mixed") + return Type::MIXED; + else if (type == "pulse") + return Type::PULSE; - throw std::invalid_argument("Invalid signal type"); + throw std::invalid_argument("Invalid signal type"); } -std::string SignalNodeSignal::typeToString(enum Type type) -{ - switch (type) { - case Type::CONSTANT: - return "constant"; +std::string SignalNodeSignal::typeToString(enum Type type) { + switch (type) { + case Type::CONSTANT: + return "constant"; - case Type::SINE: - return "sine"; + case Type::SINE: + return "sine"; - case Type::TRIANGLE: - return "triangle"; + case Type::TRIANGLE: + return "triangle"; - case Type::SQUARE: - return "square"; + case Type::SQUARE: + return "square"; - case Type::RAMP: - return "ramp"; + case Type::RAMP: + return "ramp"; - case Type::COUNTER: - return "counter"; + case Type::COUNTER: + return "counter"; - case Type::RANDOM: - return "random"; + case Type::RANDOM: + return "random"; - case Type::MIXED: - return "mixed"; + case Type::MIXED: + return "mixed"; - case Type::PULSE: - return "pulse"; + case Type::PULSE: + return "pulse"; - default: - return nullptr; - } + default: + return nullptr; + } } -void SignalNodeSignal::start() -{ - last = offset; +void SignalNodeSignal::start() { last = offset; } +void SignalNodeSignal::read(unsigned c, double t, double r, SignalData *d) { + switch (type) { + case Type::CONSTANT: + d->f = offset + amplitude; + break; + + case Type::SINE: + d->f = offset + amplitude * sin(t * frequency * 2 * M_PI + phase); + break; + + case Type::TRIANGLE: + d->f = + offset + + amplitude * + (fabs(fmod(t * frequency + (phase / (2 * M_PI)), 1) - .5) - 0.25) * + 4; + break; + + case Type::SQUARE: + d->f = offset + + amplitude * + ((fmod(t * frequency + (phase / (2 * M_PI)), 1) < .5) ? -1 : 1); + break; + + case Type::RAMP: + d->f = offset + amplitude * fmod(t, frequency); + break; + + case Type::COUNTER: + d->f = offset + amplitude * c; + break; + + case Type::RANDOM: + last += boxMuller(0, stddev); + d->f = last; + break; + + case Type::MIXED: + break; + + case Type::PULSE: + d->f = + abs(fmod(t * frequency + (phase / (2 * M_PI)), 1)) <= (pulse_width / r) + ? pulse_high + : pulse_low; + d->f += offset; + break; + } } -void SignalNodeSignal::read(unsigned c, double t, double r, SignalData *d) -{ - switch (type) { - case Type::CONSTANT: - d->f = offset + amplitude; - break; +int SignalNodeSignal::parse(json_t *json) { + int ret; + const char *type_str; - case Type::SINE: - d->f = offset + amplitude * sin(t * frequency * 2 * M_PI + phase); - break; + json_error_t err; - case Type::TRIANGLE: - d->f = offset + amplitude * (fabs(fmod(t * frequency + (phase / (2 * M_PI)), 1) - .5) - 0.25) * 4; - break; + ret = json_unpack_ex( + json, &err, 0, + "{ s: s, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F }", + "signal", &type_str, "frequency", &frequency, "amplitude", &litude, + "stddev", &stddev, "offset", &offset, "pulse_width", &pulse_width, + "pulse_low", &pulse_low, "pulse_high", &pulse_high, "phase", &phase); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - case Type::SQUARE: - d->f = offset + amplitude * ( (fmod(t * frequency + (phase / (2 * M_PI)), 1) < .5) ? -1 : 1); - break; + try { + type = lookupType(type_str); + } catch (std::invalid_argument &e) { + throw ConfigError(json, "node-config-node-signal-type", + "Unknown signal type: {}", type_str); + } - case Type::RAMP: - d->f = offset + amplitude * fmod(t, frequency); - break; - - case Type::COUNTER: - d->f = offset + amplitude * c; - break; - - case Type::RANDOM: - last += boxMuller(0, stddev); - d->f = last; - break; - - case Type::MIXED: - break; - - case Type::PULSE: - d->f = abs(fmod(t * frequency + (phase / (2 * M_PI)) , 1)) <= (pulse_width / r) - ? pulse_high - : pulse_low; - d->f += offset; - break; - } + return 0; } -int SignalNodeSignal::parse(json_t *json) -{ - int ret; - const char *type_str; +Signal::Ptr SignalNodeSignal::toSignal(Signal::Ptr tpl) const { + auto isDefaultName = tpl->name.rfind("signal", 0) == 0; - json_error_t err; + auto name = isDefaultName ? typeToString(type) : tpl->name; + auto unit = tpl->unit; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F }", - "signal", &type_str, - "frequency", &frequency, - "amplitude", &litude, - "stddev", &stddev, - "offset", &offset, - "pulse_width", &pulse_width, - "pulse_low", &pulse_low, - "pulse_high", &pulse_high, - "phase", &phase - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + auto sig = std::make_shared(name, unit, SignalType::FLOAT); - try { - type = lookupType(type_str); - } catch (std::invalid_argument &e) { - throw ConfigError(json, "node-config-node-signal-type", "Unknown signal type: {}", type_str); - } + sig->init.f = offset; - return 0; + return sig; } -Signal::Ptr SignalNodeSignal::toSignal(Signal::Ptr tpl) const -{ - auto isDefaultName = tpl->name.rfind("signal", 0) == 0; +SignalNode::SignalNode(const uuid_t &id, const std::string &name) + : Node(id, name), task(CLOCK_MONOTONIC), rt(1), rate(10), + monitor_missed(true), limit(-1), missed_steps(0) {} - auto name = isDefaultName ? typeToString(type) : tpl->name; - auto unit = tpl->unit; +int SignalNode::prepare() { + assert(state == State::CHECKED); - auto sig = std::make_shared(name, unit, SignalType::FLOAT); + for (unsigned i = 0; i < signals.size(); i++) { + auto &sig = (*in.signals)[i]; + auto &ssig = signals[i]; - sig->init.f = offset; + sig = ssig.toSignal(sig); + } - return sig; + if (logger->level() <= spdlog::level::debug) + in.signals->dump(logger); + + return Node::prepare(); } -SignalNode::SignalNode(const uuid_t &id, const std::string &name) : - Node(id, name), - task(CLOCK_MONOTONIC), - rt(1), - rate(10), - monitor_missed(true), - limit(-1), - missed_steps(0) -{ } +int SignalNode::parse(json_t *json) { + int r = -1, m = -1, ret = Node::parse(json); + if (ret) + return ret; -int SignalNode::prepare() -{ - assert(state == State::CHECKED); + json_error_t err; - for (unsigned i = 0; i < signals.size(); i++) { - auto &sig = (*in.signals)[i]; - auto &ssig = signals[i]; + size_t i; + json_t *json_signals, *json_signal; - sig = ssig.toSignal(sig); - } + ret = json_unpack_ex(json, &err, 0, + "{ s?: b, s?: i, s?: F, s?: b, s: { s: o } }", + "realtime", &r, "limit", &limit, "rate", &rate, + "monitor_missed", &m, "in", "signals", &json_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - if (logger->level() <= spdlog::level::debug) - in.signals->dump(logger); + if (r >= 0) + rt = r != 0; - return Node::prepare(); + if (m >= 0) + monitor_missed = m != 0; + + signals.clear(); + unsigned j = 0; + json_array_foreach(json_signals, i, json_signal) { + auto sig = SignalNodeSignal(json_signal); + + if (sig.type == SignalNodeSignal::Type::MIXED) + sig.type = + (SignalNodeSignal::Type)(j++ % (int)SignalNodeSignal::Type::MIXED); + + signals.push_back(sig); + } + + state = State::PARSED; + + return 0; } -int SignalNode::parse(json_t *json) -{ - int r = -1, m = -1, ret = Node::parse(json); - if (ret) - return ret; +int SignalNode::start() { + assert(state == State::PREPARED || state == State::PAUSED); - json_error_t err; + missed_steps = 0; + started = time_now(); - size_t i; - json_t *json_signals, *json_signal; + for (auto sig : signals) + sig.start(); - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i, s?: F, s?: b, s: { s: o } }", - "realtime", &r, - "limit", &limit, - "rate", &rate, - "monitor_missed", &m, - "in", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + // Setup task + if (rt) + task.setRate(rate); - if (r >= 0) - rt = r != 0; + int ret = Node::start(); + if (!ret) + state = State::STARTED; - if (m >= 0) - monitor_missed = m != 0; - - signals.clear(); - unsigned j = 0; - json_array_foreach(json_signals, i, json_signal) { - auto sig = SignalNodeSignal(json_signal); - - if (sig.type == SignalNodeSignal::Type::MIXED) - sig.type = (SignalNodeSignal::Type) (j++ % (int) SignalNodeSignal::Type::MIXED); - - signals.push_back(sig); - } - - state = State::PARSED; - - return 0; + return ret; } -int SignalNode::start() -{ - assert(state == State::PREPARED || - state == State::PAUSED); +int SignalNode::stop() { + assert(state == State::STARTED || state == State::PAUSED || + state == State::STOPPING); - missed_steps = 0; - started = time_now(); + int ret = Node::stop(); + if (ret) + return ret; - for (auto sig : signals) - sig.start(); + if (rt) + task.stop(); - // Setup task - if (rt) - task.setRate(rate); + if (missed_steps > 0 && monitor_missed) + logger->warn("Missed a total of {} steps.", missed_steps); - int ret = Node::start(); - if (!ret) - state = State::STARTED; + state = State::STOPPED; - return ret; + return 0; } -int SignalNode::stop() -{ - assert(state == State::STARTED || - state == State::PAUSED || - state == State::STOPPING); +int SignalNode::_read(struct Sample *smps[], unsigned cnt) { + struct Sample *t = smps[0]; - int ret = Node::stop(); - if (ret) - return ret; + struct timespec ts; + uint64_t steps, counter = sequence - sequence_init; - if (rt) - task.stop(); + assert(cnt == 1); - if (missed_steps > 0 && monitor_missed) - logger->warn("Missed a total of {} steps.", missed_steps); + if (rt) + ts = time_now(); + else { + struct timespec offset = time_from_double(counter * 1.0 / rate); + ts = time_add(&started, &offset); + } - state = State::STOPPED; + double running = time_delta(&started, &ts); - return 0; + t->flags = (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + t->ts.origin = ts; + t->sequence = sequence; + t->length = MIN(signals.size(), t->capacity); + t->signals = in.signals; + + for (unsigned i = 0; i < t->length; i++) { + auto &sig = signals[i]; + + sig.read(counter, running, rate, &t->data[i]); + } + + if (limit > 0 && counter >= (unsigned)limit) { + logger->info("Reached limit."); + + setState(State::STOPPING); + return -1; + } + + // Throttle output if desired + if (rt) { + // Block until 1/p->rate seconds elapsed + steps = task.wait(); + if (steps > 1 && monitor_missed) { + logger->debug("Missed steps: {}", steps - 1); + missed_steps += steps - 1; + } + } else + steps = 1; + + sequence += steps; + + return 1; } -int SignalNode::_read(struct Sample *smps[], unsigned cnt) -{ - struct Sample *t = smps[0]; +const std::string &SignalNode::getDetails() { + if (details.empty()) { + details = fmt::format("rt={}, rate={}", rt ? "yes" : "no", rate); - struct timespec ts; - uint64_t steps, counter = sequence - sequence_init; + if (limit > 0) + details += fmt::format(", limit={}", limit); + } - assert(cnt == 1); - - if (rt) - ts = time_now(); - else { - struct timespec offset = time_from_double(counter * 1.0 / rate); - ts = time_add(&started, &offset); - } - - double running = time_delta(&started, &ts); - - t->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - t->ts.origin = ts; - t->sequence = sequence; - t->length = MIN(signals.size(), t->capacity); - t->signals = in.signals; - - for (unsigned i = 0; i < t->length; i++) { - auto &sig = signals[i]; - - sig.read(counter, running, rate, &t->data[i]); - } - - if (limit > 0 && counter >= (unsigned) limit) { - logger->info("Reached limit."); - - setState(State::STOPPING); - return -1; - } - - // Throttle output if desired - if (rt) { - // Block until 1/p->rate seconds elapsed - steps = task.wait(); - if (steps > 1 && monitor_missed) { - logger->debug("Missed steps: {}", steps-1); - missed_steps += steps-1; - } - } - else - steps = 1; - - sequence += steps; - - return 1; + return details; } -const std::string & SignalNode::getDetails() -{ - if (details.empty()) { - details = fmt::format("rt={}, rate={}", rt ? "yes" : "no", rate); +std::vector SignalNode::getPollFDs() { + if (rt) + return {task.getFD()}; - if (limit > 0) - details += fmt::format(", limit={}", limit); - - } - - return details; -} - -std::vector SignalNode::getPollFDs() -{ - if (rt) - return { task.getFD() }; - - return {}; + return {}; } // Register node static char n[] = "signal.v2"; static char d[] = "Signal generator"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/signal_v1.cpp b/lib/nodes/signal_v1.cpp index f9d17b0e6..8c745cba6 100644 --- a/lib/nodes/signal_v1.cpp +++ b/lib/nodes/signal_v1.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include #include @@ -18,453 +18,458 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static -enum signal_node::SignalType signal_node_lookup_type(const char *type) -{ - if (!strcmp(type, "random")) - return signal_node::SignalType::RANDOM; - else if (!strcmp(type, "sine")) - return signal_node::SignalType::SINE; - else if (!strcmp(type, "square")) - return signal_node::SignalType::SQUARE; - else if (!strcmp(type, "triangle")) - return signal_node::SignalType::TRIANGLE; - else if (!strcmp(type, "ramp")) - return signal_node::SignalType::RAMP; - else if (!strcmp(type, "counter")) - return signal_node::SignalType::COUNTER; - else if (!strcmp(type, "constant")) - return signal_node::SignalType::CONSTANT; - else if (!strcmp(type, "mixed")) - return signal_node::SignalType::MIXED; - else if (!strcmp(type, "pulse")) - return signal_node::SignalType::PULSE; +static enum signal_node::SignalType signal_node_lookup_type(const char *type) { + if (!strcmp(type, "random")) + return signal_node::SignalType::RANDOM; + else if (!strcmp(type, "sine")) + return signal_node::SignalType::SINE; + else if (!strcmp(type, "square")) + return signal_node::SignalType::SQUARE; + else if (!strcmp(type, "triangle")) + return signal_node::SignalType::TRIANGLE; + else if (!strcmp(type, "ramp")) + return signal_node::SignalType::RAMP; + else if (!strcmp(type, "counter")) + return signal_node::SignalType::COUNTER; + else if (!strcmp(type, "constant")) + return signal_node::SignalType::CONSTANT; + else if (!strcmp(type, "mixed")) + return signal_node::SignalType::MIXED; + else if (!strcmp(type, "pulse")) + return signal_node::SignalType::PULSE; - throw std::invalid_argument("Invalid signal type"); + throw std::invalid_argument("Invalid signal type"); } -static -const char * signal_node_type_str(enum signal_node::SignalType type) -{ - switch (type) { - case signal_node::SignalType::CONSTANT: - return "constant"; +static const char *signal_node_type_str(enum signal_node::SignalType type) { + switch (type) { + case signal_node::SignalType::CONSTANT: + return "constant"; - case signal_node::SignalType::SINE: - return "sine"; + case signal_node::SignalType::SINE: + return "sine"; - case signal_node::SignalType::TRIANGLE: - return "triangle"; + case signal_node::SignalType::TRIANGLE: + return "triangle"; - case signal_node::SignalType::SQUARE: - return "square"; + case signal_node::SignalType::SQUARE: + return "square"; - case signal_node::SignalType::RAMP: - return "ramp"; + case signal_node::SignalType::RAMP: + return "ramp"; - case signal_node::SignalType::COUNTER: - return "counter"; + case signal_node::SignalType::COUNTER: + return "counter"; - case signal_node::SignalType::RANDOM: - return "random"; + case signal_node::SignalType::RANDOM: + return "random"; - case signal_node::SignalType::MIXED: - return "mixed"; + case signal_node::SignalType::MIXED: + return "mixed"; - case signal_node::SignalType::PULSE: - return "pulse"; + case signal_node::SignalType::PULSE: + return "pulse"; - default: - return nullptr; - } + default: + return nullptr; + } } -int villas::node::signal_node_init(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_init(NodeCompat *n) { + auto *s = n->getData(); - new (&s->task) Task(CLOCK_MONOTONIC); + new (&s->task) Task(CLOCK_MONOTONIC); - s->rt = 1; - s->limit = -1; - s->values = 1; - s->rate = 10; - s->monitor_missed = 1; + s->rt = 1; + s->limit = -1; + s->values = 1; + s->rate = 10; + s->monitor_missed = 1; - s->type = nullptr; - s->frequency = nullptr; - s->amplitude = nullptr; - s->stddev = nullptr; - s->offset = nullptr; - s->phase = nullptr; - s->pulse_width = nullptr; - s->pulse_low = nullptr; - s->pulse_high = nullptr; + s->type = nullptr; + s->frequency = nullptr; + s->amplitude = nullptr; + s->stddev = nullptr; + s->offset = nullptr; + s->phase = nullptr; + s->pulse_width = nullptr; + s->pulse_low = nullptr; + s->pulse_high = nullptr; - return 0; + return 0; } -int villas::node::signal_node_destroy(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_destroy(NodeCompat *n) { + auto *s = n->getData(); - s->task.~Task(); + s->task.~Task(); - if (s->type) - delete[] s->type; + if (s->type) + delete[] s->type; - if (s->frequency) - delete[] s->frequency; + if (s->frequency) + delete[] s->frequency; - if (s->amplitude) - delete[] s->amplitude; + if (s->amplitude) + delete[] s->amplitude; - if (s->stddev) - delete[] s->stddev; + if (s->stddev) + delete[] s->stddev; - if (s->offset) - delete[] s->offset; + if (s->offset) + delete[] s->offset; - if (s->phase) - delete[] s->phase; + if (s->phase) + delete[] s->phase; - if (s->pulse_width) - delete[] s->pulse_width; + if (s->pulse_width) + delete[] s->pulse_width; - if (s->pulse_low) - delete[] s->pulse_low; + if (s->pulse_low) + delete[] s->pulse_low; - if (s->pulse_high) - delete[] s->pulse_high; + if (s->pulse_high) + delete[] s->pulse_high; - return 0; + return 0; } -int villas::node::signal_node_prepare(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_prepare(NodeCompat *n) { + auto *s = n->getData(); - n->in.signals = std::make_shared(); - for (unsigned i = 0; i < s->values; i++) { - auto name = signal_node_type_str((enum signal_node::SignalType) s->type[i]); - auto sig = std::make_shared(name, "", SignalType::FLOAT); + n->in.signals = std::make_shared(); + for (unsigned i = 0; i < s->values; i++) { + auto name = signal_node_type_str((enum signal_node::SignalType)s->type[i]); + auto sig = std::make_shared(name, "", SignalType::FLOAT); - n->in.signals->push_back(sig); - } + n->in.signals->push_back(sig); + } - return 0; + return 0; } -int villas::node::signal_node_parse(NodeCompat *n, json_t *json) -{ - auto *s = n->getData(); +int villas::node::signal_node_parse(NodeCompat *n, json_t *json) { + auto *s = n->getData(); - int ret; + int ret; - json_error_t err; + json_error_t err; - json_t *json_type = nullptr; - json_t *json_amplitude = nullptr; - json_t *json_offset = nullptr; - json_t *json_frequency = nullptr; - json_t *json_stddev = nullptr; - json_t *json_pulse_width = nullptr; - json_t *json_pulse_high = nullptr; - json_t *json_pulse_low = nullptr; - json_t *json_phase = nullptr; + json_t *json_type = nullptr; + json_t *json_amplitude = nullptr; + json_t *json_offset = nullptr; + json_t *json_frequency = nullptr; + json_t *json_stddev = nullptr; + json_t *json_pulse_width = nullptr; + json_t *json_pulse_high = nullptr; + json_t *json_pulse_low = nullptr; + json_t *json_phase = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: b, s?: i, s?: i, s?: F, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: b }", - "signal", &json_type, - "realtime", &s->rt, - "limit", &s->limit, - "values", &s->values, - "rate", &s->rate, - "frequency", &json_frequency, - "amplitude", &json_amplitude, - "stddev", &json_stddev, - "offset", &json_offset, - "pulse_width", &json_pulse_width, - "pulse_low", &json_pulse_low, - "pulse_high", &json_pulse_high, - "phase", &json_phase, - "monitor_missed", &s->monitor_missed - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + ret = json_unpack_ex( + json, &err, 0, + "{ s: o, s?: b, s?: i, s?: i, s?: F, s?: o, s?: o, s?: o, s?: o, s?: o, " + "s?: o, s?: o, s?: o, s?: b }", + "signal", &json_type, "realtime", &s->rt, "limit", &s->limit, "values", + &s->values, "rate", &s->rate, "frequency", &json_frequency, "amplitude", + &json_amplitude, "stddev", &json_stddev, "offset", &json_offset, + "pulse_width", &json_pulse_width, "pulse_low", &json_pulse_low, + "pulse_high", &json_pulse_high, "phase", &json_phase, "monitor_missed", + &s->monitor_missed); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - struct desc { - json_t *json; - double **array; - double def_value; - const char *name; - }; + struct desc { + json_t *json; + double **array; + double def_value; + const char *name; + }; - std::list arrays = { - { json_frequency, &s->frequency, 1, "frequency" }, - { json_amplitude, &s->amplitude, 1, "amplitude" }, - { json_stddev, &s->stddev, 0.2, "stddev" }, - { json_offset, &s->offset, 0, "offset" }, - { json_pulse_width, &s->pulse_width, 1, "pulse_width" }, - { json_pulse_high, &s->pulse_high, 1, "pulse_high" }, - { json_pulse_low, &s->pulse_low, 0, "pulse_low" }, - { json_phase, &s->phase, 0, "phase" } - }; + std::list arrays = { + {json_frequency, &s->frequency, 1, "frequency"}, + {json_amplitude, &s->amplitude, 1, "amplitude"}, + {json_stddev, &s->stddev, 0.2, "stddev"}, + {json_offset, &s->offset, 0, "offset"}, + {json_pulse_width, &s->pulse_width, 1, "pulse_width"}, + {json_pulse_high, &s->pulse_high, 1, "pulse_high"}, + {json_pulse_low, &s->pulse_low, 0, "pulse_low"}, + {json_phase, &s->phase, 0, "phase"}}; - size_t i; - json_t *json_value; - const char *type_str; - signal_node::SignalType type; + size_t i; + json_t *json_value; + const char *type_str; + signal_node::SignalType type; - s->type = new enum signal_node::SignalType[s->values]; + s->type = new enum signal_node::SignalType[s->values]; - switch (json_typeof(json_type)) { - case JSON_ARRAY: - if (json_array_size(json_type) != s->values) - throw ConfigError(json_type, "node-config-node-signal", "Length of values must match"); + switch (json_typeof(json_type)) { + case JSON_ARRAY: + if (json_array_size(json_type) != s->values) + throw ConfigError(json_type, "node-config-node-signal", + "Length of values must match"); - json_array_foreach(json_type, i, json_value) { - type_str = json_string_value(json_value); - if (!type_str) - throw ConfigError(json_value, "node-config-node-signal", "Signal type must be a string"); + json_array_foreach(json_type, i, json_value) { + type_str = json_string_value(json_value); + if (!type_str) + throw ConfigError(json_value, "node-config-node-signal", + "Signal type must be a string"); - s->type[i] = signal_node_lookup_type(type_str); - } - break; + s->type[i] = signal_node_lookup_type(type_str); + } + break; - case JSON_STRING: - type_str = json_string_value(json_type); - type = signal_node_lookup_type(type_str); + case JSON_STRING: + type_str = json_string_value(json_type); + type = signal_node_lookup_type(type_str); - for (size_t i = 0; i < s->values; i++) { - s->type[i] = (type == signal_node::SignalType::MIXED - ? (signal_node::SignalType) (i % 7) - : type); - } - break; + for (size_t i = 0; i < s->values; i++) { + s->type[i] = (type == signal_node::SignalType::MIXED + ? (signal_node::SignalType)(i % 7) + : type); + } + break; - default: - throw ConfigError(json_type, "node-config-node-signal", "Invalid setting 'signal' for node {}", n->getName()); - } + default: + throw ConfigError(json_type, "node-config-node-signal", + "Invalid setting 'signal' for node {}", n->getName()); + } - for (auto &a : arrays) { - if (*a.array) - delete *a.array; + for (auto &a : arrays) { + if (*a.array) + delete *a.array; - *a.array = new double[s->values]; + *a.array = new double[s->values]; - if (a.json) { - switch (json_typeof(a.json)) { - case JSON_ARRAY: - if (json_array_size(a.json) != s->values) - throw ConfigError(a.json, "node-config-node-signal", "Length of values must match"); + if (a.json) { + switch (json_typeof(a.json)) { + case JSON_ARRAY: + if (json_array_size(a.json) != s->values) + throw ConfigError(a.json, "node-config-node-signal", + "Length of values must match"); - size_t i; - json_t *json_value; - json_array_foreach(a.json, i, json_value) { - if (!json_is_number(json_value)) - throw ConfigError(json_value, "node-config-node-signal", "Values must gives as array of integer or float values!"); + size_t i; + json_t *json_value; + json_array_foreach(a.json, i, json_value) { + if (!json_is_number(json_value)) + throw ConfigError( + json_value, "node-config-node-signal", + "Values must gives as array of integer or float values!"); - (*a.array)[i] = json_number_value(json_value); - } + (*a.array)[i] = json_number_value(json_value); + } - break; + break; - case JSON_INTEGER: - case JSON_REAL: - for (size_t i = 0; i < s->values; i++) - (*a.array)[i] = json_number_value(a.json); + case JSON_INTEGER: + case JSON_REAL: + for (size_t i = 0; i < s->values; i++) + (*a.array)[i] = json_number_value(a.json); - break; + break; - default: - throw ConfigError(a.json, "node-config-node-signal", "Values must given as array or scalar integer or float value!"); - } - } - else { - for (size_t i = 0; i < s->values; i++) - (*a.array)[i] = a.def_value; - } - } + default: + throw ConfigError( + a.json, "node-config-node-signal", + "Values must given as array or scalar integer or float value!"); + } + } else { + for (size_t i = 0; i < s->values; i++) + (*a.array)[i] = a.def_value; + } + } - return 0; + return 0; } -int villas::node::signal_node_start(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_start(NodeCompat *n) { + auto *s = n->getData(); - s->missed_steps = 0; - s->counter = 0; - s->started = time_now(); - s->last = new double[s->values]; - if (!s->last) - throw MemoryAllocationError(); + s->missed_steps = 0; + s->counter = 0; + s->started = time_now(); + s->last = new double[s->values]; + if (!s->last) + throw MemoryAllocationError(); - for (unsigned i = 0; i < s->values; i++) - s->last[i] = s->offset[i]; + for (unsigned i = 0; i < s->values; i++) + s->last[i] = s->offset[i]; - // Setup task - if (s->rt) - s->task.setRate(s->rate); + // Setup task + if (s->rt) + s->task.setRate(s->rate); - return 0; + return 0; } -int villas::node::signal_node_stop(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_stop(NodeCompat *n) { + auto *s = n->getData(); - if (s->rt) - s->task.stop(); + if (s->rt) + s->task.stop(); - if (s->missed_steps > 0 && s->monitor_missed) - n->logger->warn("Missed a total of {} steps.", s->missed_steps); + if (s->missed_steps > 0 && s->monitor_missed) + n->logger->warn("Missed a total of {} steps.", s->missed_steps); - delete[] s->last; + delete[] s->last; - return 0; + return 0; } -int villas::node::signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); - struct Sample *t = smps[0]; +int villas::node::signal_node_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); + struct Sample *t = smps[0]; - struct timespec ts; - int steps; + struct timespec ts; + int steps; - assert(cnt == 1); + assert(cnt == 1); - if (s->rt) - ts = time_now(); - else { - struct timespec offset = time_from_double(s->counter * 1.0 / s->rate); + if (s->rt) + ts = time_now(); + else { + struct timespec offset = time_from_double(s->counter * 1.0 / s->rate); - ts = time_add(&s->started, &offset); + ts = time_add(&s->started, &offset); - steps = 1; - } + steps = 1; + } - double running = time_delta(&s->started, &ts); + double running = time_delta(&s->started, &ts); - t->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - t->ts.origin = ts; - t->sequence = s->counter; - t->length = MIN(s->values, t->capacity); - t->signals = n->getInputSignals(false); + t->flags = (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + t->ts.origin = ts; + t->sequence = s->counter; + t->length = MIN(s->values, t->capacity); + t->signals = n->getInputSignals(false); - for (unsigned i = 0; i < t->length; i++) { - switch (s->type[i]) { - case signal_node::SignalType::CONSTANT: - t->data[i].f = s->offset[i] + s->amplitude[i]; - break; + for (unsigned i = 0; i < t->length; i++) { + switch (s->type[i]) { + case signal_node::SignalType::CONSTANT: + t->data[i].f = s->offset[i] + s->amplitude[i]; + break; - case signal_node::SignalType::SINE: - t->data[i].f = s->offset[i] + s->amplitude[i] * sin(running * s->frequency[i] * 2 * M_PI + s->phase[i]); - break; + case signal_node::SignalType::SINE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + sin(running * s->frequency[i] * 2 * M_PI + s->phase[i]); + break; - case signal_node::SignalType::TRIANGLE: - t->data[i].f = s->offset[i] + s->amplitude[i] * (fabs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), 1) - .5) - 0.25) * 4; - break; + case signal_node::SignalType::TRIANGLE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + (fabs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1) - + .5) - + 0.25) * + 4; + break; - case signal_node::SignalType::SQUARE: - t->data[i].f = s->offset[i] + s->amplitude[i] * ( (fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), 1) < .5) ? -1 : 1); - break; + case signal_node::SignalType::SQUARE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + ((fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1) < .5) + ? -1 + : 1); + break; - case signal_node::SignalType::RAMP: - t->data[i].f = s->offset[i] + s->amplitude[i] * fmod(running, s->frequency[i]); - break; + case signal_node::SignalType::RAMP: + t->data[i].f = + s->offset[i] + s->amplitude[i] * fmod(running, s->frequency[i]); + break; - case signal_node::SignalType::COUNTER: - t->data[i].f = s->offset[i] + s->amplitude[i] * s->counter; - break; + case signal_node::SignalType::COUNTER: + t->data[i].f = s->offset[i] + s->amplitude[i] * s->counter; + break; - case signal_node::SignalType::RANDOM: - s->last[i] += boxMuller(0, s->stddev[i]); - t->data[i].f = s->last[i]; - break; + case signal_node::SignalType::RANDOM: + s->last[i] += boxMuller(0, s->stddev[i]); + t->data[i].f = s->last[i]; + break; - case signal_node::SignalType::MIXED: - break; + case signal_node::SignalType::MIXED: + break; - case signal_node::SignalType::PULSE: - t->data[i].f = abs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)) , 1)) <= (s->pulse_width[i] / s->rate) - ? s->pulse_high[i] - : s->pulse_low[i]; - t->data[i].f += s->offset[i]; - break; - } - } + case signal_node::SignalType::PULSE: + t->data[i].f = + abs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1)) <= (s->pulse_width[i] / s->rate) + ? s->pulse_high[i] + : s->pulse_low[i]; + t->data[i].f += s->offset[i]; + break; + } + } - if (s->limit > 0 && s->counter >= (unsigned) s->limit) { - n->logger->info("Reached limit."); + if (s->limit > 0 && s->counter >= (unsigned)s->limit) { + n->logger->info("Reached limit."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; - } + return -1; + } - // Throttle output if desired - if (s->rt) { - // Block until 1/p->rate seconds elapsed - steps = s->task.wait(); - if (steps > 1 && s->monitor_missed) { - n->logger->debug("Missed steps: {}", steps-1); - s->missed_steps += steps-1; - } - } + // Throttle output if desired + if (s->rt) { + // Block until 1/p->rate seconds elapsed + steps = s->task.wait(); + if (steps > 1 && s->monitor_missed) { + n->logger->debug("Missed steps: {}", steps - 1); + s->missed_steps += steps - 1; + } + } - s->counter += steps; + s->counter += steps; - return 1; + return 1; } -char * villas::node::signal_node_print(NodeCompat *n) -{ - auto *s = n->getData(); - char *buf = nullptr; +char *villas::node::signal_node_print(NodeCompat *n) { + auto *s = n->getData(); + char *buf = nullptr; - strcatf(&buf, "rt=%s, rate=%.2f, values=%d", s->rt ? "yes" : "no", s->rate, s->values); + strcatf(&buf, "rt=%s, rate=%.2f, values=%d", s->rt ? "yes" : "no", s->rate, + s->values); - if (s->limit > 0) - strcatf(&buf, ", limit=%d", s->limit); + if (s->limit > 0) + strcatf(&buf, ", limit=%d", s->limit); - return buf; + return buf; } -int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - if (s->rt) { - fds[0] = s->task.getFD(); + if (s->rt) { + fds[0] = s->task.getFD(); - return 1; - } - else - return 0; + return 1; + } else + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "signal"; - p.description = "Legacy Signal generator"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct signal_node); - p.init = signal_node_init; - p.destroy = signal_node_destroy; - p.parse = signal_node_parse; - p.prepare = signal_node_prepare; - p.print = signal_node_print; - p.start = signal_node_start; - p.stop = signal_node_stop; - p.read = signal_node_read; - p.poll_fds = signal_node_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "signal"; + p.description = "Legacy Signal generator"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct signal_node); + p.init = signal_node_init; + p.destroy = signal_node_destroy; + p.parse = signal_node_parse; + p.prepare = signal_node_prepare; + p.print = signal_node_print; + p.start = signal_node_start; + p.stop = signal_node_stop; + p.read = signal_node_read; + p.poll_fds = signal_node_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/socket.cpp b/lib/nodes/socket.cpp index e6c1b9564..965bb4949 100644 --- a/lib/nodes/socket.cpp +++ b/lib/nodes/socket.cpp @@ -5,27 +5,27 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include +#include +#include #include +#include +#include #include #include -#include -#include #include -#include +#include #include +#include #ifdef WITH_SOCKET_LAYER_ETH - #include +#include #endif // WITH_SOCKET_LAYER_ETH #ifdef WITH_NETEM - #include - #include +#include +#include #endif // WITH_NETEM using namespace villas; @@ -34,554 +34,556 @@ using namespace villas::node; using namespace villas::kernel; // Forward declartions -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -int villas::node::socket_type_start(villas::node::SuperNode *sn) -{ +int villas::node::socket_type_start(villas::node::SuperNode *sn) { #ifdef WITH_NETEM - if (sn != nullptr) { - // Gather list of used network interfaces - for (auto *n : ncp.instances) { - auto *nc = dynamic_cast(n); - auto *s = nc->getData(); + if (sn != nullptr) { + // Gather list of used network interfaces + for (auto *n : ncp.instances) { + auto *nc = dynamic_cast(n); + auto *s = nc->getData(); - if (s->layer == SocketLayer::UNIX) - continue; + if (s->layer == SocketLayer::UNIX) + continue; - // Determine outgoing interface - Interface *j = Interface::getEgress((struct sockaddr *) &s->out.saddr, sn); + // Determine outgoing interface + Interface *j = Interface::getEgress((struct sockaddr *)&s->out.saddr, sn); - j->addNode(n); - } - } + j->addNode(n); + } + } #endif // WITH_NETEM - return 0; + return 0; } -int villas::node::socket_init(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_init(NodeCompat *n) { + auto *s = n->getData(); - s->formatter = nullptr; + s->formatter = nullptr; - return 0; + return 0; } -int villas::node::socket_destroy(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_destroy(NodeCompat *n) { + auto *s = n->getData(); - if (s->formatter) - delete s->formatter; + if (s->formatter) + delete s->formatter; - return 0; + return 0; } -char * villas::node::socket_print(NodeCompat *n) -{ - auto *s = n->getData(); - const char *layer = nullptr; - char *buf; +char *villas::node::socket_print(NodeCompat *n) { + auto *s = n->getData(); + const char *layer = nullptr; + char *buf; - switch (s->layer) { - case SocketLayer::UDP: - layer = "udp"; - break; + switch (s->layer) { + case SocketLayer::UDP: + layer = "udp"; + break; - case SocketLayer::IP: - layer = "ip"; - break; + case SocketLayer::IP: + layer = "ip"; + break; - case SocketLayer::ETH: - layer = "eth"; - break; + case SocketLayer::ETH: + layer = "eth"; + break; - case SocketLayer::UNIX: - layer = "unix"; - break; - } + case SocketLayer::UNIX: + layer = "unix"; + break; + } - char *local = socket_print_addr((struct sockaddr *) &s->in.saddr); - char *remote = socket_print_addr((struct sockaddr *) &s->out.saddr); + char *local = socket_print_addr((struct sockaddr *)&s->in.saddr); + char *remote = socket_print_addr((struct sockaddr *)&s->out.saddr); - buf = strf("layer=%s, in.address=%s, out.address=%s", layer, local, remote); + buf = strf("layer=%s, in.address=%s, out.address=%s", layer, local, remote); - if (s->multicast.enabled) { - char group[INET_ADDRSTRLEN]; - char interface[INET_ADDRSTRLEN]; + if (s->multicast.enabled) { + char group[INET_ADDRSTRLEN]; + char interface[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &s->multicast.mreq.imr_multiaddr, group, sizeof(group)); - inet_ntop(AF_INET, &s->multicast.mreq.imr_interface, interface, sizeof(interface)); + inet_ntop(AF_INET, &s->multicast.mreq.imr_multiaddr, group, sizeof(group)); + inet_ntop(AF_INET, &s->multicast.mreq.imr_interface, interface, + sizeof(interface)); - strcatf(&buf, ", in.multicast.enabled=%s", s->multicast.enabled ? "yes" : "no"); - strcatf(&buf, ", in.multicast.loop=%s", s->multicast.loop ? "yes" : "no"); - strcatf(&buf, ", in.multicast.group=%s", group); - strcatf(&buf, ", in.multicast.interface=%s", s->multicast.mreq.imr_interface.s_addr == INADDR_ANY ? "any" : interface); - strcatf(&buf, ", in.multicast.ttl=%u", s->multicast.ttl); - } + strcatf(&buf, ", in.multicast.enabled=%s", + s->multicast.enabled ? "yes" : "no"); + strcatf(&buf, ", in.multicast.loop=%s", s->multicast.loop ? "yes" : "no"); + strcatf(&buf, ", in.multicast.group=%s", group); + strcatf(&buf, ", in.multicast.interface=%s", + s->multicast.mreq.imr_interface.s_addr == INADDR_ANY ? "any" + : interface); + strcatf(&buf, ", in.multicast.ttl=%u", s->multicast.ttl); + } - free(local); - free(remote); + free(local); + free(remote); - return buf; + return buf; } -int villas::node::socket_check(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_check(NodeCompat *n) { + auto *s = n->getData(); - // Some checks on the addresses - if (s->layer != SocketLayer::UNIX) { - if (s->in.saddr.sa.sa_family != s->out.saddr.sa.sa_family) - throw RuntimeError("Address families of local and remote must match!"); - } + // Some checks on the addresses + if (s->layer != SocketLayer::UNIX) { + if (s->in.saddr.sa.sa_family != s->out.saddr.sa.sa_family) + throw RuntimeError("Address families of local and remote must match!"); + } - if (s->layer == SocketLayer::IP) { - if (ntohs(s->in.saddr.sin.sin_port) != ntohs(s->out.saddr.sin.sin_port)) - throw RuntimeError("IP protocol numbers of local and remote must match!"); - } + if (s->layer == SocketLayer::IP) { + if (ntohs(s->in.saddr.sin.sin_port) != ntohs(s->out.saddr.sin.sin_port)) + throw RuntimeError("IP protocol numbers of local and remote must match!"); + } #ifdef WITH_SOCKET_LAYER_ETH - else if (s->layer == SocketLayer::ETH) { - if (ntohs(s->in.saddr.sll.sll_protocol) != ntohs(s->out.saddr.sll.sll_protocol)) - throw RuntimeError("Ethertypes of local and remote must match!"); + else if (s->layer == SocketLayer::ETH) { + if (ntohs(s->in.saddr.sll.sll_protocol) != + ntohs(s->out.saddr.sll.sll_protocol)) + throw RuntimeError("Ethertypes of local and remote must match!"); - if (ntohs(s->in.saddr.sll.sll_protocol) <= 0x5DC) - throw RuntimeError("Ethertype must be large than {} or it is interpreted as an IEEE802.3 length field!", 0x5DC); - } + if (ntohs(s->in.saddr.sll.sll_protocol) <= 0x5DC) + throw RuntimeError("Ethertype must be large than {} or it is interpreted " + "as an IEEE802.3 length field!", + 0x5DC); + } #endif // WITH_SOCKET_LAYER_ETH - if (s->multicast.enabled) { - if (s->in.saddr.sa.sa_family != AF_INET) - throw RuntimeError("Multicast is only supported by IPv4"); + if (s->multicast.enabled) { + if (s->in.saddr.sa.sa_family != AF_INET) + throw RuntimeError("Multicast is only supported by IPv4"); - uint32_t addr = ntohl(s->multicast.mreq.imr_multiaddr.s_addr); - if ((addr >> 28) != 14) - throw RuntimeError("Multicast group address must be within 224.0.0.0/4"); - } + uint32_t addr = ntohl(s->multicast.mreq.imr_multiaddr.s_addr); + if ((addr >> 28) != 14) + throw RuntimeError("Multicast group address must be within 224.0.0.0/4"); + } - return 0; + return 0; } -int villas::node::socket_start(NodeCompat *n) -{ - auto *s = n->getData(); - int ret; +int villas::node::socket_start(NodeCompat *n) { + auto *s = n->getData(); + int ret; - // Initialize IO - s->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + // Initialize IO + s->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Create socket - switch (s->layer) { - case SocketLayer::UDP: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); - break; + // Create socket + switch (s->layer) { + case SocketLayer::UDP: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + break; - case SocketLayer::IP: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_RAW, ntohs(s->in.saddr.sin.sin_port)); - break; + case SocketLayer::IP: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_RAW, + ntohs(s->in.saddr.sin.sin_port)); + break; #ifdef WITH_SOCKET_LAYER_ETH - case SocketLayer::ETH: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, s->in.saddr.sll.sll_protocol); - break; + case SocketLayer::ETH: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, + s->in.saddr.sll.sll_protocol); + break; #endif // WITH_SOCKET_LAYER_ETH - case SocketLayer::UNIX: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, 0); - break; + case SocketLayer::UNIX: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, 0); + break; - default: - throw RuntimeError("Invalid socket type!"); - } + default: + throw RuntimeError("Invalid socket type!"); + } - if (s->sd < 0) - throw SystemError("Failed to create socket"); + if (s->sd < 0) + throw SystemError("Failed to create socket"); - // Delete Unix domain socket if already existing - if (s->layer == SocketLayer::UNIX) { - ret = unlink(s->in.saddr.sun.sun_path); - if (ret && errno != ENOENT) - return ret; - } + // Delete Unix domain socket if already existing + if (s->layer == SocketLayer::UNIX) { + ret = unlink(s->in.saddr.sun.sun_path); + if (ret && errno != ENOENT) + return ret; + } - // Bind socket for receiving - socklen_t addrlen = 0; - switch(s->in.saddr.ss.ss_family) { - case AF_INET: - addrlen = sizeof(struct sockaddr_in); - break; + // Bind socket for receiving + socklen_t addrlen = 0; + switch (s->in.saddr.ss.ss_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; - case AF_INET6: - addrlen = sizeof(struct sockaddr_in6); - break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; - case AF_UNIX: - addrlen = SUN_LEN(&s->in.saddr.sun); - break; + case AF_UNIX: + addrlen = SUN_LEN(&s->in.saddr.sun); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - addrlen = sizeof(struct sockaddr_ll); - break; + case AF_PACKET: + addrlen = sizeof(struct sockaddr_ll); + break; #endif // WITH_SOCKET_LAYER_ETH - default: - addrlen = sizeof(s->in.saddr); - } + default: + addrlen = sizeof(s->in.saddr); + } - ret = bind(s->sd, (struct sockaddr *) &s->in.saddr, addrlen); - if (ret < 0) - throw SystemError("Failed to bind socket"); + ret = bind(s->sd, (struct sockaddr *)&s->in.saddr, addrlen); + if (ret < 0) + throw SystemError("Failed to bind socket"); - if (s->multicast.enabled) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, &s->multicast.loop, sizeof(s->multicast.loop)); - if (ret) - throw SystemError("Failed to set multicast loop option"); + if (s->multicast.enabled) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, &s->multicast.loop, + sizeof(s->multicast.loop)); + if (ret) + throw SystemError("Failed to set multicast loop option"); - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, &s->multicast.ttl, sizeof(s->multicast.ttl)); - if (ret) - throw SystemError("Failed to set multicast ttl option"); + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, &s->multicast.ttl, + sizeof(s->multicast.ttl)); + if (ret) + throw SystemError("Failed to set multicast ttl option"); - ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &s->multicast.mreq, sizeof(s->multicast.mreq)); - if (ret) - throw SystemError("Failed to join multicast group"); - } + ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &s->multicast.mreq, + sizeof(s->multicast.mreq)); + if (ret) + throw SystemError("Failed to join multicast group"); + } - // Set socket priority, QoS or TOS IP options - int prio; - switch (s->layer) { - case SocketLayer::UDP: - case SocketLayer::IP: - prio = IPTOS_LOWDELAY; - if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio))) - throw SystemError("Failed to set type of service (QoS)"); - else - n->logger->debug("Set QoS/TOS IP option to {:#x}", prio); - break; + // Set socket priority, QoS or TOS IP options + int prio; + switch (s->layer) { + case SocketLayer::UDP: + case SocketLayer::IP: + prio = IPTOS_LOWDELAY; + if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio))) + throw SystemError("Failed to set type of service (QoS)"); + else + n->logger->debug("Set QoS/TOS IP option to {:#x}", prio); + break; - default: + default: #ifdef __linux__ - prio = SOCKET_PRIO; - if (setsockopt(s->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) - throw SystemError("Failed to set socket priority"); - else - n->logger->debug("Set socket priority to {}", prio); - break; + prio = SOCKET_PRIO; + if (setsockopt(s->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) + throw SystemError("Failed to set socket priority"); + else + n->logger->debug("Set socket priority to {}", prio); + break; #else - { } + { + } #endif // __linux__ - } + } - s->out.buflen = SOCKET_INITIAL_BUFFER_LEN; - s->out.buf = new char[s->out.buflen]; - if (!s->out.buf) - throw MemoryAllocationError(); + s->out.buflen = SOCKET_INITIAL_BUFFER_LEN; + s->out.buf = new char[s->out.buflen]; + if (!s->out.buf) + throw MemoryAllocationError(); - s->in.buflen = SOCKET_INITIAL_BUFFER_LEN; - s->in.buf = new char[s->in.buflen]; - if (!s->in.buf) - throw MemoryAllocationError(); + s->in.buflen = SOCKET_INITIAL_BUFFER_LEN; + s->in.buf = new char[s->in.buflen]; + if (!s->in.buf) + throw MemoryAllocationError(); - return 0; + return 0; } -int villas::node::socket_reverse(NodeCompat *n) -{ - auto *s = n->getData(); - union sockaddr_union tmp; +int villas::node::socket_reverse(NodeCompat *n) { + auto *s = n->getData(); + union sockaddr_union tmp; - tmp = s->in.saddr; - s->in.saddr = s->out.saddr; - s->out.saddr = tmp; + tmp = s->in.saddr; + s->in.saddr = s->out.saddr; + s->out.saddr = tmp; - return 0; + return 0; } -int villas::node::socket_stop(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_stop(NodeCompat *n) { + int ret; + auto *s = n->getData(); - if (s->multicast.enabled) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &s->multicast.mreq, sizeof(s->multicast.mreq)); - if (ret) - throw SystemError("Failed to leave multicast group"); - } + if (s->multicast.enabled) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &s->multicast.mreq, + sizeof(s->multicast.mreq)); + if (ret) + throw SystemError("Failed to leave multicast group"); + } - if (s->sd >= 0) { - ret = close(s->sd); - if (ret) - return ret; - } + if (s->sd >= 0) { + ret = close(s->sd); + if (ret) + return ret; + } - delete[] s->in.buf; - delete[] s->out.buf; + delete[] s->in.buf; + delete[] s->out.buf; - return 0; + return 0; } -int villas::node::socket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *s = n->getData(); - char *ptr; - ssize_t bytes; - size_t rbytes; + char *ptr; + ssize_t bytes; + size_t rbytes; - union sockaddr_union src; - socklen_t srclen = sizeof(src); + union sockaddr_union src; + socklen_t srclen = sizeof(src); - // Receive next sample - bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); - if (bytes < 0) { - if (errno == EINTR) - return -1; + // Receive next sample + bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); + if (bytes < 0) { + if (errno == EINTR) + return -1; - throw SystemError("Failed recvfrom()"); - } - else if (bytes == 0) - return 0; + throw SystemError("Failed recvfrom()"); + } else if (bytes == 0) + return 0; - ptr = s->in.buf; + ptr = s->in.buf; - // Strip IP header from packet - if (s->layer == SocketLayer::IP) { - struct ip *iphdr = (struct ip *) ptr; + // Strip IP header from packet + if (s->layer == SocketLayer::IP) { + struct ip *iphdr = (struct ip *)ptr; - bytes -= iphdr->ip_hl * 4; - ptr += iphdr->ip_hl * 4; - } + bytes -= iphdr->ip_hl * 4; + ptr += iphdr->ip_hl * 4; + } - /* SOCK_RAW IP sockets to not provide the IP protocol number via recvmsg() + /* SOCK_RAW IP sockets to not provide the IP protocol number via recvmsg() * So we simply set it ourself. */ - if (s->layer == SocketLayer::IP) { - switch (src.sa.sa_family) { - case AF_INET: - src.sin.sin_port = s->out.saddr.sin.sin_port; - break; + if (s->layer == SocketLayer::IP) { + switch (src.sa.sa_family) { + case AF_INET: + src.sin.sin_port = s->out.saddr.sin.sin_port; + break; - case AF_INET6: - src.sin6.sin6_port = s->out.saddr.sin6.sin6_port; - break; - } - } + case AF_INET6: + src.sin6.sin6_port = s->out.saddr.sin6.sin6_port; + break; + } + } - if (s->verify_source && socket_compare_addr(&src.sa, &s->out.saddr.sa) != 0) { - char *buf = socket_print_addr((struct sockaddr *) &src); - n->logger->warn("Received packet from unauthorized source: {}", buf); - free(buf); + if (s->verify_source && socket_compare_addr(&src.sa, &s->out.saddr.sa) != 0) { + char *buf = socket_print_addr((struct sockaddr *)&src); + n->logger->warn("Received packet from unauthorized source: {}", buf); + free(buf); - return 0; - } + return 0; + } - ret = s->formatter->sscan(ptr, bytes, &rbytes, smps, cnt); - if (ret < 0 || (size_t) bytes != rbytes) - n->logger->warn("Received invalid packet: ret={}, bytes={}, rbytes={}", ret, bytes, rbytes); + ret = s->formatter->sscan(ptr, bytes, &rbytes, smps, cnt); + if (ret < 0 || (size_t)bytes != rbytes) + n->logger->warn("Received invalid packet: ret={}, bytes={}, rbytes={}", ret, + bytes, rbytes); - return ret; + return ret; } -int villas::node::socket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); +int villas::node::socket_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); - int ret; - ssize_t bytes; - size_t wbytes; + int ret; + ssize_t bytes; + size_t wbytes; -retry: ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt); - if (ret < 0) { - n->logger->warn("Failed to format payload: reason={}", ret); - return ret; - } +retry: + ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt); + if (ret < 0) { + n->logger->warn("Failed to format payload: reason={}", ret); + return ret; + } - if (wbytes == 0) { - n->logger->warn("Failed to format payload: wbytes={}", wbytes); - return -1; - } + if (wbytes == 0) { + n->logger->warn("Failed to format payload: wbytes={}", wbytes); + return -1; + } - if (wbytes > s->out.buflen) { - s->out.buflen = wbytes; + if (wbytes > s->out.buflen) { + s->out.buflen = wbytes; - delete[] s->out.buf; - s->out.buf = new char[s->out.buflen]; - if (!s->out.buf) - throw MemoryAllocationError(); + delete[] s->out.buf; + s->out.buf = new char[s->out.buflen]; + if (!s->out.buf) + throw MemoryAllocationError(); - goto retry; - } + goto retry; + } - // Send message - socklen_t addrlen = 0; - switch(s->in.saddr.ss.ss_family) { - case AF_INET: - addrlen = sizeof(struct sockaddr_in); - break; + // Send message + socklen_t addrlen = 0; + switch (s->in.saddr.ss.ss_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; - case AF_INET6: - addrlen = sizeof(struct sockaddr_in6); - break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; - case AF_UNIX: - addrlen = SUN_LEN(&s->out.saddr.sun); - break; + case AF_UNIX: + addrlen = SUN_LEN(&s->out.saddr.sun); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - addrlen = sizeof(struct sockaddr_ll); - break; + case AF_PACKET: + addrlen = sizeof(struct sockaddr_ll); + break; #endif // WITH_SOCKET_LAYER_ETH - default: - addrlen = sizeof(s->in.saddr); - } + default: + addrlen = sizeof(s->in.saddr); + } -retry2: bytes = sendto(s->sd, s->out.buf, wbytes, 0, (struct sockaddr *) &s->out.saddr, addrlen); - if (bytes < 0) { - if ((errno == EPERM) || - (errno == ENOENT && s->layer == SocketLayer::UNIX)) - n->logger->warn("Failed sendto(): {}", strerror(errno)); - else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - n->logger->warn("Blocking sendto()"); - goto retry2; - } - else - n->logger->warn("Failed sendto(): {}", strerror(errno)); - } - else if ((size_t) bytes < wbytes) - n->logger->warn("Partial sendto()"); +retry2: + bytes = sendto(s->sd, s->out.buf, wbytes, 0, (struct sockaddr *)&s->out.saddr, + addrlen); + if (bytes < 0) { + if ((errno == EPERM) || (errno == ENOENT && s->layer == SocketLayer::UNIX)) + n->logger->warn("Failed sendto(): {}", strerror(errno)); + else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + n->logger->warn("Blocking sendto()"); + goto retry2; + } else + n->logger->warn("Failed sendto(): {}", strerror(errno)); + } else if ((size_t)bytes < wbytes) + n->logger->warn("Partial sendto()"); - return cnt; + return cnt; } -int villas::node::socket_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_parse(NodeCompat *n, json_t *json) { + int ret; + auto *s = n->getData(); - const char *local, *remote; - const char *layer = nullptr; + const char *local, *remote; + const char *layer = nullptr; - json_error_t err; - json_t *json_multicast = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_multicast = nullptr; + json_t *json_format = nullptr; - // Default values - s->layer = SocketLayer::UDP; - s->verify_source = 0; + // Default values + s->layer = SocketLayer::UDP; + s->verify_source = 0; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s: { s: s }, s: { s: s, s?: b, s?: o } }", - "layer", &layer, - "format", &json_format, - "out", - "address", &remote, - "in", - "address", &local, - "verify_source", &s->verify_source, - "multicast", &json_multicast - ); - if (ret) - throw ConfigError(json, err, "node-config-node-socket"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: s, s?: o, s: { s: s }, s: { s: s, s?: b, s?: o } }", + "layer", &layer, "format", &json_format, "out", "address", &remote, "in", + "address", &local, "verify_source", &s->verify_source, "multicast", + &json_multicast); + if (ret) + throw ConfigError(json, err, "node-config-node-socket"); - // Format - if (s->formatter) - delete s->formatter; - s->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!s->formatter) - throw ConfigError(json_format, "node-config-node-socket-format", "Invalid format configuration"); + // Format + if (s->formatter) + delete s->formatter; + s->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!s->formatter) + throw ConfigError(json_format, "node-config-node-socket-format", + "Invalid format configuration"); - // IP layer - if (layer) { - if (!strcmp(layer, "ip")) - s->layer = SocketLayer::IP; + // IP layer + if (layer) { + if (!strcmp(layer, "ip")) + s->layer = SocketLayer::IP; #ifdef WITH_SOCKET_LAYER_ETH - else if (!strcmp(layer, "eth")) - s->layer = SocketLayer::ETH; + else if (!strcmp(layer, "eth")) + s->layer = SocketLayer::ETH; #endif // WITH_SOCKET_LAYER_ETH - else if (!strcmp(layer, "udp")) - s->layer = SocketLayer::UDP; - else if (!strcmp(layer, "unix") || !strcmp(layer, "local")) - s->layer = SocketLayer::UNIX; - else - throw SystemError("Invalid layer '{}'", layer); - } + else if (!strcmp(layer, "udp")) + s->layer = SocketLayer::UDP; + else if (!strcmp(layer, "unix") || !strcmp(layer, "local")) + s->layer = SocketLayer::UNIX; + else + throw SystemError("Invalid layer '{}'", layer); + } - ret = socket_parse_address(remote, (struct sockaddr *) &s->out.saddr, s->layer, 0); - if (ret) - throw SystemError("Failed to resolve remote address '{}': {}", remote, gai_strerror(ret)); + ret = socket_parse_address(remote, (struct sockaddr *)&s->out.saddr, s->layer, + 0); + if (ret) + throw SystemError("Failed to resolve remote address '{}': {}", remote, + gai_strerror(ret)); - ret = socket_parse_address(local, (struct sockaddr *) &s->in.saddr, s->layer, AI_PASSIVE); - if (ret) - throw SystemError("Failed to resolve local address '{}': {}", local, gai_strerror(ret)); + ret = socket_parse_address(local, (struct sockaddr *)&s->in.saddr, s->layer, + AI_PASSIVE); + if (ret) + throw SystemError("Failed to resolve local address '{}': {}", local, + gai_strerror(ret)); - if (json_multicast) { - const char *group, *interface = nullptr; + if (json_multicast) { + const char *group, *interface = nullptr; - // Default values - s->multicast.enabled = true; - s->multicast.mreq.imr_interface.s_addr = INADDR_ANY; - s->multicast.loop = 0; - s->multicast.ttl = 255; + // Default values + s->multicast.enabled = true; + s->multicast.mreq.imr_interface.s_addr = INADDR_ANY; + s->multicast.loop = 0; + s->multicast.ttl = 255; - ret = json_unpack_ex(json_multicast, &err, 0, "{ s?: b, s: s, s?: s, s?: b, s?: i }", - "enabled", &s->multicast.enabled, - "group", &group, - "interface", &interface, - "loop", &s->multicast.loop, - "ttl", &s->multicast.ttl - ); - if (ret) - throw ConfigError(json_multicast, err, "node-config-node-socket-multicast", "Failed to parse multicast settings"); + ret = json_unpack_ex( + json_multicast, &err, 0, "{ s?: b, s: s, s?: s, s?: b, s?: i }", + "enabled", &s->multicast.enabled, "group", &group, "interface", + &interface, "loop", &s->multicast.loop, "ttl", &s->multicast.ttl); + if (ret) + throw ConfigError(json_multicast, err, + "node-config-node-socket-multicast", + "Failed to parse multicast settings"); - ret = inet_aton(group, &s->multicast.mreq.imr_multiaddr); - if (!ret) - throw SystemError("Failed to resolve multicast group address '{}'", group); + ret = inet_aton(group, &s->multicast.mreq.imr_multiaddr); + if (!ret) + throw SystemError("Failed to resolve multicast group address '{}'", + group); - if (interface) { - ret = inet_aton(group, &s->multicast.mreq.imr_interface); - if (!ret) - throw SystemError("Failed to resolve multicast interface address '{}'", interface); - } - } + if (interface) { + ret = inet_aton(group, &s->multicast.mreq.imr_interface); + if (!ret) + throw SystemError("Failed to resolve multicast interface address '{}'", + interface); + } + } - return 0; + return 0; } -int villas::node::socket_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::socket_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - fds[0] = s->sd; + fds[0] = s->sd; - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "socket"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "socket"; #ifdef WITH_NETEM - p.description = "BSD network sockets for Ethernet / IP / UDP (libnl3, netem support)"; + p.description = + "BSD network sockets for Ethernet / IP / UDP (libnl3, netem support)"; #else - p.description = "BSD network sockets for Ethernet / IP / UDP"; + p.description = "BSD network sockets for Ethernet / IP / UDP"; #endif - p.vectorize = 0; - p.size = sizeof(struct Socket); - p.type.start = socket_type_start; - p.reverse = socket_reverse; - p.init = socket_init; - p.destroy = socket_destroy; - p.parse = socket_parse; - p.print = socket_print; - p.check = socket_check; - p.start = socket_start; - p.stop = socket_stop; - p.read = socket_read; - p.write = socket_write; - p.poll_fds = socket_fds; - p.netem_fds = socket_fds; + p.vectorize = 0; + p.size = sizeof(struct Socket); + p.type.start = socket_type_start; + p.reverse = socket_reverse; + p.init = socket_init; + p.destroy = socket_destroy; + p.parse = socket_parse; + p.print = socket_print; + p.check = socket_check; + p.start = socket_start; + p.stop = socket_stop; + p.read = socket_read; + p.write = socket_write; + p.poll_fds = socket_fds; + p.netem_fds = socket_fds; } diff --git a/lib/nodes/stats.cpp b/lib/nodes/stats.cpp index 000915f9c..aae148fa2 100644 --- a/lib/nodes/stats.cpp +++ b/lib/nodes/stats.cpp @@ -7,262 +7,250 @@ #include -#include -#include #include #include +#include +#include +#include #include #include -#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -NodeList nodes; // The global list of nodes +static NodeList nodes; // The global list of nodes -int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) -{ - free(s->node_str); +int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) { + free(s->node_str); - return 0; + return 0; } -int villas::node::stats_node_signal_parse(struct stats_node_signal *s, json_t *json) -{ - json_error_t err; +int villas::node::stats_node_signal_parse(struct stats_node_signal *s, + json_t *json) { + json_error_t err; - int ret; - const char *stats; - char *metric, *type, *node, *cpy, *lasts; + int ret; + const char *stats; + char *metric, *type, *node, *cpy, *lasts; - ret = json_unpack_ex(json, &err, 0, "{ s: s }", - "stats", &stats - ); - if (ret) - throw ConfigError(json, err, "node-config-node-stats"); + ret = json_unpack_ex(json, &err, 0, "{ s: s }", "stats", &stats); + if (ret) + throw ConfigError(json, err, "node-config-node-stats"); - cpy = strdup(stats); + cpy = strdup(stats); - node = strtok_r(cpy, ".", &lasts); - if (!node) - goto invalid_format; + node = strtok_r(cpy, ".", &lasts); + if (!node) + goto invalid_format; - metric = strtok_r(nullptr, ".", &lasts); - if (!metric) - goto invalid_format; + metric = strtok_r(nullptr, ".", &lasts); + if (!metric) + goto invalid_format; - type = strtok_r(nullptr, ".", &lasts); - if (!type) - goto invalid_format; + type = strtok_r(nullptr, ".", &lasts); + if (!type) + goto invalid_format; - s->metric = Stats::lookupMetric(metric); - s->type = Stats::lookupType(type); + s->metric = Stats::lookupMetric(metric); + s->type = Stats::lookupType(type); - s->node_str = strdup(node); + s->node_str = strdup(node); - free(cpy); - return 0; + free(cpy); + return 0; invalid_format: - free(cpy); - return -1; + free(cpy); + return -1; } -int villas::node::stats_node_type_start(villas::node::SuperNode *sn) -{ - if (sn == nullptr) - throw RuntimeError("Stats node-type requires super-node"); +int villas::node::stats_node_type_start(villas::node::SuperNode *sn) { + if (sn == nullptr) + throw RuntimeError("Stats node-type requires super-node"); - nodes = sn->getNodes(); + nodes = sn->getNodes(); - return 0; + return 0; } -int villas::node::stats_node_prepare(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_prepare(NodeCompat *n) { + auto *s = n->getData(); - assert(n->getInputSignals(false)->size() == 0); + assert(n->getInputSignals(false)->size() == 0); - // Generate signal list - for (size_t i = 0; i < list_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) list_at(&s->signals, i); + // Generate signal list + for (size_t i = 0; i < list_length(&s->signals); i++) { + struct stats_node_signal *stats_sig = + (struct stats_node_signal *)list_at(&s->signals, i); - const char *metric = Stats::metrics[stats_sig->metric].name; - const char *type = Stats::types[stats_sig->type].name; + const char *metric = Stats::metrics[stats_sig->metric].name; + const char *type = Stats::types[stats_sig->type].name; - auto name = fmt::format("{}.{}.{}", stats_sig->node_str, metric, type); + auto name = fmt::format("{}.{}.{}", stats_sig->node_str, metric, type); - auto sig = std::make_shared(name.c_str(), - Stats::metrics[stats_sig->metric].unit, - Stats::types[stats_sig->type].signal_type); + auto sig = std::make_shared( + name.c_str(), Stats::metrics[stats_sig->metric].unit, + Stats::types[stats_sig->type].signal_type); - n->in.signals->push_back(sig); - } + n->in.signals->push_back(sig); + } - return 0; + return 0; } -int villas::node::stats_node_start(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_start(NodeCompat *n) { + auto *s = n->getData(); - s->task.setRate(s->rate); + s->task.setRate(s->rate); - for (size_t i = 0; i < list_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) list_at(&s->signals, i); + for (size_t i = 0; i < list_length(&s->signals); i++) { + struct stats_node_signal *stats_sig = + (struct stats_node_signal *)list_at(&s->signals, i); - stats_sig->node = nodes.lookup(stats_sig->node_str); - if (!stats_sig->node) - throw ConfigError(n->getConfig(), "node-config-node-stats-node", "Invalid reference node {}", stats_sig->node_str); - } + stats_sig->node = nodes.lookup(stats_sig->node_str); + if (!stats_sig->node) + throw ConfigError(n->getConfig(), "node-config-node-stats-node", + "Invalid reference node {}", stats_sig->node_str); + } - return 0; + return 0; } -int villas::node::stats_node_stop(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_stop(NodeCompat *n) { + auto *s = n->getData(); - s->task.stop(); + s->task.stop(); - return 0; + return 0; } -char * villas::node::stats_node_print(NodeCompat *n) -{ - auto *s = n->getData(); +char *villas::node::stats_node_print(NodeCompat *n) { + auto *s = n->getData(); - return strf("rate=%f", s->rate); + return strf("rate=%f", s->rate); } -int villas::node::stats_node_init(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::stats_node_init(NodeCompat *n) { + int ret; + auto *s = n->getData(); - new (&s->task) Task(CLOCK_MONOTONIC); + new (&s->task) Task(CLOCK_MONOTONIC); - ret = list_init(&s->signals); - if (ret) - return ret; + ret = list_init(&s->signals); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::stats_node_destroy(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::stats_node_destroy(NodeCompat *n) { + int ret; + auto *s = n->getData(); - s->task.~Task(); + s->task.~Task(); - ret = list_destroy(&s->signals, (dtor_cb_t) stats_node_signal_destroy, true); - if (ret) - return ret; + ret = list_destroy(&s->signals, (dtor_cb_t)stats_node_signal_destroy, true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::stats_node_parse(NodeCompat *n, json_t *json) -{ - auto *s = n->getData(); +int villas::node::stats_node_parse(NodeCompat *n, json_t *json) { + auto *s = n->getData(); - int ret; - size_t i; - json_error_t err; - json_t *json_signals, *json_signal; + int ret; + size_t i; + json_error_t err; + json_t *json_signals, *json_signal; - ret = json_unpack_ex(json, &err, 0, "{ s: F, s: { s: o } }", - "rate", &s->rate, - "in", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-stats"); + ret = json_unpack_ex(json, &err, 0, "{ s: F, s: { s: o } }", "rate", &s->rate, + "in", "signals", &json_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-stats"); - if (s->rate <= 0) - throw ConfigError(json, "node-config-node-stats-rate", "Setting 'rate' must be positive"); + if (s->rate <= 0) + throw ConfigError(json, "node-config-node-stats-rate", + "Setting 'rate' must be positive"); - if (!json_is_array(json_signals)) - throw ConfigError(json, "node-config-node-stats-in-signals", "Setting 'in.signals' must be an array"); + if (!json_is_array(json_signals)) + throw ConfigError(json, "node-config-node-stats-in-signals", + "Setting 'in.signals' must be an array"); - json_array_foreach(json_signals, i, json_signal) { - auto *stats_sig = new struct stats_node_signal; - if (!stats_sig) - throw MemoryAllocationError(); + json_array_foreach(json_signals, i, json_signal) { + auto *stats_sig = new struct stats_node_signal; + if (!stats_sig) + throw MemoryAllocationError(); - ret = stats_node_signal_parse(stats_sig, json_signal); - if (ret) - throw ConfigError(json_signal, "node-config-node-stats-signals", "Failed to parse statistics signal definition"); + ret = stats_node_signal_parse(stats_sig, json_signal); + if (ret) + throw ConfigError(json_signal, "node-config-node-stats-signals", + "Failed to parse statistics signal definition"); - list_push(&s->signals, stats_sig); - } + list_push(&s->signals, stats_sig); + } - return 0; + return 0; } -int villas::node::stats_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); +int villas::node::stats_node_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); - if (!cnt) - return 0; + if (!cnt) + return 0; - s->task.wait(); + s->task.wait(); - unsigned len = MIN(list_length(&s->signals), smps[0]->capacity); + unsigned len = MIN(list_length(&s->signals), smps[0]->capacity); - for (size_t i = 0; i < len; i++) { - struct stats_node_signal *sig = (struct stats_node_signal *) list_at(&s->signals, i); + for (size_t i = 0; i < len; i++) { + struct stats_node_signal *sig = + (struct stats_node_signal *)list_at(&s->signals, i); - auto st = sig->node->getStats(); - if (!st) - return -1; + auto st = sig->node->getStats(); + if (!st) + return -1; - smps[0]->data[i] = st->getValue(sig->metric, sig->type); - } + smps[0]->data[i] = st->getValue(sig->metric, sig->type); + } - smps[0]->length = len; - smps[0]->flags = (int) SampleFlags::HAS_DATA; - smps[0]->signals = n->getInputSignals(false); + smps[0]->length = len; + smps[0]->flags = (int)SampleFlags::HAS_DATA; + smps[0]->signals = n->getInputSignals(false); - return 1; + return 1; } -int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - fds[0] = s->task.getFD(); + fds[0] = s->task.getFD(); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "stats"; - p.description = "Send statistics to another node"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct stats_node); - p.type.start = stats_node_type_start; - p.parse = stats_node_parse; - p.init = stats_node_init; - p.destroy = stats_node_destroy; - p.print = stats_node_print; - p.prepare = stats_node_prepare; - p.start = stats_node_start; - p.stop = stats_node_stop; - p.read = stats_node_read; - p.poll_fds = stats_node_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "stats"; + p.description = "Send statistics to another node"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct stats_node); + p.type.start = stats_node_type_start; + p.parse = stats_node_parse; + p.init = stats_node_init; + p.destroy = stats_node_destroy; + p.print = stats_node_print; + p.prepare = stats_node_prepare; + p.start = stats_node_start; + p.stop = stats_node_stop; + p.read = stats_node_read; + p.poll_fds = stats_node_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/temper.cpp b/lib/nodes/temper.cpp index fcf890d0c..da0138908 100644 --- a/lib/nodes/temper.cpp +++ b/lib/nodes/temper.cpp @@ -16,407 +16,390 @@ * https://github.com/shakemid/pcsensor */ +#include #include #include -#include #include using namespace villas; using namespace villas::utils; using namespace villas::node; -static -Logger logger; +static Logger logger; -static -std::list devices; +static std::list devices; -static -struct libusb_context *context; +static struct libusb_context *context; // Forward declartions -static -NodeCompatType p; +static NodeCompatType p; -TEMPerDevice::TEMPerDevice(struct libusb_device *dev) : - usb::Device(dev), - scale(1.0), - offset(0.0), - timeout(5000) -{ - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret != LIBUSB_SUCCESS) - throw RuntimeError("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); +TEMPerDevice::TEMPerDevice(struct libusb_device *dev) + : usb::Device(dev), scale(1.0), offset(0.0), timeout(5000) { + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret != LIBUSB_SUCCESS) + throw RuntimeError("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); } -void TEMPerDevice::open(bool reset) -{ - int ret; +void TEMPerDevice::open(bool reset) { + int ret; - usb::detach(handle, 0x00); - usb::detach(handle, 0x01); + usb::detach(handle, 0x00); + usb::detach(handle, 0x01); - if (reset) - libusb_reset_device(handle); + if (reset) + libusb_reset_device(handle); - ret = libusb_set_configuration(handle, 0x01); - if (ret < 0) - throw RuntimeError("Could not set configuration 1"); + ret = libusb_set_configuration(handle, 0x01); + if (ret < 0) + throw RuntimeError("Could not set configuration 1"); - ret = libusb_claim_interface(handle, 0x00); - if (ret < 0) - throw RuntimeError("Could not claim interface. Error: {}", ret); + ret = libusb_claim_interface(handle, 0x00); + if (ret < 0) + throw RuntimeError("Could not claim interface. Error: {}", ret); - ret = libusb_claim_interface(handle, 0x01); - if (ret < 0) - throw RuntimeError("Could not claim interface. Error: {}", ret); + ret = libusb_claim_interface(handle, 0x01); + if (ret < 0) + throw RuntimeError("Could not claim interface. Error: {}", ret); } -void TEMPerDevice::close() -{ - libusb_release_interface(handle, 0x00); - libusb_release_interface(handle, 0x01); +void TEMPerDevice::close() { + libusb_release_interface(handle, 0x00); + libusb_release_interface(handle, 0x01); - libusb_close(handle); + libusb_close(handle); } -void TEMPerDevice::read(struct Sample *smp) -{ - unsigned char answer[8]; - float temp[2]; - int i = 0, al, ret; +void TEMPerDevice::read(struct Sample *smp) { + unsigned char answer[8]; + float temp[2]; + int i = 0, al, ret; - // Read from device - unsigned char question[sizeof(question_temperature)]; - memcpy(question, question_temperature, sizeof(question_temperature)); + // Read from device + unsigned char question[sizeof(question_temperature)]; + memcpy(question, question_temperature, sizeof(question_temperature)); - ret = libusb_control_transfer(handle, 0x21, 0x09, 0x0200, 0x01, question, 8, timeout); - if (ret < 0) - throw SystemError("USB control write failed: {}", ret); + ret = libusb_control_transfer(handle, 0x21, 0x09, 0x0200, 0x01, question, 8, + timeout); + if (ret < 0) + throw SystemError("USB control write failed: {}", ret); - memset(answer, 0, 8); + memset(answer, 0, 8); - ret = libusb_interrupt_transfer(handle, 0x82, answer, 8, &al, timeout); - if (al != 8) - throw SystemError("USB interrupt read failed: {}", ret); + ret = libusb_interrupt_transfer(handle, 0x82, answer, 8, &al, timeout); + if (al != 8) + throw SystemError("USB interrupt read failed: {}", ret); - decode(answer, temp); + decode(answer, temp); - // Temperature 1 - smp->data[i++].f = temp[0]; + // Temperature 1 + smp->data[i++].f = temp[0]; - // Temperature 2 - if (getNumSensors() == 2) - smp->data[i++].f = temp[1]; + // Temperature 2 + if (getNumSensors() == 2) + smp->data[i++].f = temp[1]; - // Humidity - if (hasHumiditySensor()) - smp->data[i++].f = temp[1]; + // Humidity + if (hasHumiditySensor()) + smp->data[i++].f = temp[1]; - smp->flags = 0; - smp->length = i; - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->flags = 0; + smp->length = i; + smp->flags |= (int)SampleFlags::HAS_DATA; } // Thanks to https://github.com/edorfaus/TEMPered -void TEMPer1Device::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPer1Device::decode(unsigned char *answer, float *temp) { + int buf; - // Temperature Celsius internal - buf = ((signed char) answer[2] << 8) + (answer[3] & 0xFF); - temp[0] = buf * (125.0 / 32000.0); - temp[0] *= scale; - temp[0] += offset; + // Temperature Celsius internal + buf = ((signed char)answer[2] << 8) + (answer[3] & 0xFF); + temp[0] = buf * (125.0 / 32000.0); + temp[0] *= scale; + temp[0] += offset; } -void TEMPer2Device::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPer2Device::decode(unsigned char *answer, float *temp) { + int buf; - TEMPer1Device::decode(answer, temp); + TEMPer1Device::decode(answer, temp); - // Temperature Celsius external - buf = ((signed char) answer[4] << 8) + (answer[5] & 0xFF); - temp[1] = buf * (125.0 / 32000.0); - temp[1] *= scale; - temp[1] += offset; + // Temperature Celsius external + buf = ((signed char)answer[4] << 8) + (answer[5] & 0xFF); + temp[1] = buf * (125.0 / 32000.0); + temp[1] *= scale; + temp[1] += offset; } -void TEMPerHUMDevice::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPerHUMDevice::decode(unsigned char *answer, float *temp) { + int buf; - // Temperature Celsius - buf = ((signed char) answer[2] << 8) + (answer[3] & 0xFF); - temp[0] = -39.7 + 0.01 * buf; - temp[0] *= scale; - temp[0] += offset; + // Temperature Celsius + buf = ((signed char)answer[2] << 8) + (answer[3] & 0xFF); + temp[0] = -39.7 + 0.01 * buf; + temp[0] *= scale; + temp[0] += offset; - // Relative Humidity - buf = ((signed char) answer[4] << 8) + (answer[5] & 0xFF); - temp[1] = -2.0468 + 0.0367 * buf - 1.5955e-6 * buf * buf; - temp[1] = (temp[0] - 25) * (0.01 + 0.00008 * buf) + temp[1]; + // Relative Humidity + buf = ((signed char)answer[4] << 8) + (answer[5] & 0xFF); + temp[1] = -2.0468 + 0.0367 * buf - 1.5955e-6 * buf * buf; + temp[1] = (temp[0] - 25) * (0.01 + 0.00008 * buf) + temp[1]; - if (temp[1] < 0) - temp[1] = 0; + if (temp[1] < 0) + temp[1] = 0; - if (temp[1] > 99) - temp[1] = 100; + if (temp[1] > 99) + temp[1] = 100; } -TEMPerDevice * TEMPerDevice::make(struct libusb_device *dev) -{ - if (TEMPerHUMDevice::match(dev)) - return new TEMPerHUMDevice(dev); - else if (TEMPer2Device::match(dev)) - return new TEMPer2Device(dev); - else if (TEMPer1Device::match(dev)) - return new TEMPer1Device(dev); - else - return nullptr; +TEMPerDevice *TEMPerDevice::make(struct libusb_device *dev) { + if (TEMPerHUMDevice::match(dev)) + return new TEMPerHUMDevice(dev); + else if (TEMPer2Device::match(dev)) + return new TEMPer2Device(dev); + else if (TEMPer1Device::match(dev)) + return new TEMPer1Device(dev); + else + return nullptr; } -bool TEMPer1Device::match(struct libusb_device *dev) -{ - struct libusb_device_descriptor desc; - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } +bool TEMPer1Device::match(struct libusb_device *dev) { + struct libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - return desc.idProduct == 0x7401 && - desc.idVendor == 0x0c45; + return desc.idProduct == 0x7401 && desc.idVendor == 0x0c45; } -bool TEMPer2Device::match(struct libusb_device *dev) -{ - int ret; - struct libusb_device_handle *handle; - unsigned char product[256]; +bool TEMPer2Device::match(struct libusb_device *dev) { + int ret; + struct libusb_device_handle *handle; + unsigned char product[256]; - struct libusb_device_descriptor desc; - ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + struct libusb_device_descriptor desc; + ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - ret = libusb_open(dev, &handle); - if (ret < 0) { - logging.get("node:temper")->warn("Failed to open USB device: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + ret = libusb_open(dev, &handle); + if (ret < 0) { + logging.get("node:temper") + ->warn("Failed to open USB device: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, product, sizeof(product)); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB string descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, product, + sizeof(product)); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB string descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - libusb_close(handle); + libusb_close(handle); - return TEMPer1Device::match(dev) && getName() == (char *) product; + return TEMPer1Device::match(dev) && getName() == (char *)product; } -bool TEMPerHUMDevice::match(struct libusb_device *dev) -{ - struct libusb_device_descriptor desc; - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } +bool TEMPerHUMDevice::match(struct libusb_device *dev) { + struct libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - return desc.idProduct == 0x7401 && - desc.idVendor == 0x7402; + return desc.idProduct == 0x7401 && desc.idVendor == 0x7402; } -int villas::node::temper_type_start(villas::node::SuperNode *sn) -{ - context = usb::get_context(); +int villas::node::temper_type_start(villas::node::SuperNode *sn) { + context = usb::get_context(); - logger = logging.get("node:temper"); + logger = logging.get("node:temper"); - // Enumerate temper devices - devices.clear(); - struct libusb_device **devs; + // Enumerate temper devices + devices.clear(); + struct libusb_device **devs; - int cnt = libusb_get_device_list(context, &devs); - for (int i = 0; i < cnt; i++) { - auto *dev = TEMPerDevice::make(devs[i]); + int cnt = libusb_get_device_list(context, &devs); + for (int i = 0; i < cnt; i++) { + auto *dev = TEMPerDevice::make(devs[i]); - logger->debug("Found Temper device at bus={03d}, port={03d}, vendor_id={04x}, product_id={04x}, manufacturer={}, product={}, serial={}", - dev->getBus(), dev->getPort(), - dev->getDescriptor().idVendor, dev->getDescriptor().idProduct, - dev->getManufacturer(), - dev->getProduct(), - dev->getSerial()); + logger->debug( + "Found Temper device at bus={03d}, port={03d}, vendor_id={04x}, " + "product_id={04x}, manufacturer={}, product={}, serial={}", + dev->getBus(), dev->getPort(), dev->getDescriptor().idVendor, + dev->getDescriptor().idProduct, dev->getManufacturer(), + dev->getProduct(), dev->getSerial()); - devices.push_back(dev); - } + devices.push_back(dev); + } - libusb_free_device_list(devs, 1); + libusb_free_device_list(devs, 1); - return 0; + return 0; } -int villas::node::temper_type_stop() -{ - usb::deinit_context(context); +int villas::node::temper_type_stop() { + usb::deinit_context(context); - return 0; + return 0; } -int villas::node::temper_init(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_init(NodeCompat *n) { + auto *t = n->getData(); - t->calibration.scale = 1.0; - t->calibration.offset = 0.0; + t->calibration.scale = 1.0; + t->calibration.offset = 0.0; - t->filter.bus = -1; - t->filter.port = -1; - t->filter.vendor_id = -1; - t->filter.product_id = -1; + t->filter.bus = -1; + t->filter.port = -1; + t->filter.vendor_id = -1; + t->filter.product_id = -1; - t->device = nullptr; + t->device = nullptr; - return 0; + return 0; } -int villas::node::temper_destroy(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_destroy(NodeCompat *n) { + auto *t = n->getData(); - if (t->device) - delete t->device; + if (t->device) + delete t->device; - return 0; + return 0; } -int villas::node::temper_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *t = n->getData(); +int villas::node::temper_parse(NodeCompat *n, json_t *json) { + int ret; + auto *t = n->getData(); - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: F, s?: F}, s?: i, s?: i }", - "calibration", - "scale", &t->calibration.scale, - "offset", &t->calibration.offset, + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: F, s?: F}, s?: i, s?: i }", + "calibration", "scale", &t->calibration.scale, "offset", + &t->calibration.offset, - "bus", &t->filter.bus, - "port", &t->filter.port - ); - if (ret) - throw ConfigError(json, err, "node-config-node-temper"); + "bus", &t->filter.bus, "port", &t->filter.port); + if (ret) + throw ConfigError(json, err, "node-config-node-temper"); - return 0; + return 0; } -char * villas::node::temper_print(NodeCompat *n) -{ - auto *t = n->getData(); +char *villas::node::temper_print(NodeCompat *n) { + auto *t = n->getData(); - return strf("product=%s, manufacturer=%s, serial=%s humidity=%s, temperature=%d, usb.vendor_id=%#x, usb.product_id=%#x, calibration.scale=%f, calibration.offset=%f", - t->device->getProduct(), t->device->getManufacturer(), t->device->getSerial(), - t->device->hasHumiditySensor() ? "yes" : "no", - t->device->getNumSensors(), - t->device->getDescriptor().idVendor, - t->device->getDescriptor().idProduct, - t->calibration.scale, - t->calibration.offset - ); + return strf("product=%s, manufacturer=%s, serial=%s humidity=%s, " + "temperature=%d, usb.vendor_id=%#x, usb.product_id=%#x, " + "calibration.scale=%f, calibration.offset=%f", + t->device->getProduct(), t->device->getManufacturer(), + t->device->getSerial(), + t->device->hasHumiditySensor() ? "yes" : "no", + t->device->getNumSensors(), t->device->getDescriptor().idVendor, + t->device->getDescriptor().idProduct, t->calibration.scale, + t->calibration.offset); } -int villas::node::temper_prepare(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_prepare(NodeCompat *n) { + auto *t = n->getData(); - // Find matching USB device - t->device = nullptr; - for (auto *dev : devices) { - if (dev->match(&t->filter)) { - t->device = dev; - break; - } - } + // Find matching USB device + t->device = nullptr; + for (auto *dev : devices) { + if (dev->match(&t->filter)) { + t->device = dev; + break; + } + } - if (t->device == nullptr) - throw RuntimeError("No matching TEMPer USB device found!"); + if (t->device == nullptr) + throw RuntimeError("No matching TEMPer USB device found!"); - // Create signal list - assert(n->getInputSignals(false)->size() == 0); + // Create signal list + assert(n->getInputSignals(false)->size() == 0); - // Temperature 1 - auto sig1 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - n->in.signals->push_back(sig1); + // Temperature 1 + auto sig1 = std::make_shared( + t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", + SignalType::FLOAT); + n->in.signals->push_back(sig1); - // Temperature 2 - if (t->device->getNumSensors() == 2) { - auto sig2 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - n->in.signals->push_back(sig2); - } + // Temperature 2 + if (t->device->getNumSensors() == 2) { + auto sig2 = std::make_shared( + t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", + SignalType::FLOAT); + n->in.signals->push_back(sig2); + } - // Humidity - if (t->device->hasHumiditySensor()) { - auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); - n->in.signals->push_back(sig3); - } + // Humidity + if (t->device->hasHumiditySensor()) { + auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); + n->in.signals->push_back(sig3); + } - return 0; + return 0; } -int villas::node::temper_start(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_start(NodeCompat *n) { + auto *t = n->getData(); - t->device->open(); + t->device->open(); - return 0; + return 0; } -int villas::node::temper_stop(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_stop(NodeCompat *n) { + auto *t = n->getData(); - t->device->close(); + t->device->close(); - return 0; + return 0; } -int villas::node::temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *t = n->getData(); +int villas::node::temper_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *t = n->getData(); - assert(cnt == 1); + assert(cnt == 1); - t->device->read(smps[0]); + t->device->read(smps[0]); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "temper"; - p.description = "An temper for staring new node-type implementations"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct temper); - p.type.start = temper_type_start; - p.type.stop = temper_type_stop; - p.init = temper_init; - p.destroy = temper_destroy; - p.prepare = temper_prepare; - p.parse = temper_parse; - p.print = temper_print; - p.start = temper_start; - p.stop = temper_stop; - p.read = temper_read; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "temper"; + p.description = "An temper for staring new node-type implementations"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct temper); + p.type.start = temper_type_start; + p.type.stop = temper_type_stop; + p.init = temper_init; + p.destroy = temper_destroy; + p.prepare = temper_prepare; + p.parse = temper_parse; + p.print = temper_print; + p.start = temper_start; + p.stop = temper_stop; + p.read = temper_read; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/test_rtt.cpp b/lib/nodes/test_rtt.cpp index bb5ea6223..551ed6650 100644 --- a/lib/nodes/test_rtt.cpp +++ b/lib/nodes/test_rtt.cpp @@ -7,433 +7,427 @@ #include #include -#include #include +#include -#include -#include -#include -#include -#include #include +#include #include #include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -NodeCompatType p; +static NodeCompatType p; -static -int test_rtt_case_start(NodeCompat *n, int id) -{ - auto *t = n->getData(); - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, id); +static int test_rtt_case_start(NodeCompat *n, int id) { + auto *t = n->getData(); + struct test_rtt_case *c = (struct test_rtt_case *)list_at(&t->cases, id); - n->logger->info("Starting case #{}: filename={}, rate={}, values={}, limit={}", t->current, c->filename_formatted, c->rate, c->values, c->limit); + n->logger->info( + "Starting case #{}: filename={}, rate={}, values={}, limit={}", + t->current, c->filename_formatted, c->rate, c->values, c->limit); - // Open file - t->stream = fopen(c->filename_formatted, "a+"); - if (!t->stream) - return -1; + // Open file + t->stream = fopen(c->filename_formatted, "a+"); + if (!t->stream) + return -1; - // Start timer - t->task.setRate(c->rate); + // Start timer + t->task.setRate(c->rate); - t->counter = 0; - t->current = id; + t->counter = 0; + t->current = id; - return 0; + return 0; } -static -int test_rtt_case_stop(NodeCompat *n, int id) -{ - int ret; - auto *t = n->getData(); +static int test_rtt_case_stop(NodeCompat *n, int id) { + int ret; + auto *t = n->getData(); - // Stop timer - t->task.stop(); + // Stop timer + t->task.stop(); - ret = fclose(t->stream); - if (ret) - throw SystemError("Failed to close file"); + ret = fclose(t->stream); + if (ret) + throw SystemError("Failed to close file"); - n->logger->info("Stopping case #{}", id); + n->logger->info("Stopping case #{}", id); - return 0; + return 0; } -static -int test_rtt_case_destroy(struct test_rtt_case *c) -{ - if (c->filename) - free(c->filename); +static int test_rtt_case_destroy(struct test_rtt_case *c) { + if (c->filename) + free(c->filename); - if (c->filename_formatted) - free(c->filename_formatted); + if (c->filename_formatted) + free(c->filename_formatted); - return 0; + return 0; } -int villas::node::test_rtt_prepare(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::test_rtt_prepare(NodeCompat *n) { + auto *t = n->getData(); - unsigned max_values = 0; + unsigned max_values = 0; - // Take current for time for test case prefix - time_t ts = time(nullptr); - struct tm tm; - gmtime_r(&ts, &tm); + // Take current for time for test case prefix + time_t ts = time(nullptr); + struct tm tm; + gmtime_r(&ts, &tm); - for (size_t i = 0; i < list_length(&t->cases); i++) { - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, i); + for (size_t i = 0; i < list_length(&t->cases); i++) { + struct test_rtt_case *c = (struct test_rtt_case *)list_at(&t->cases, i); - if (c->values > max_values) - max_values = c->values; + if (c->values > max_values) + max_values = c->values; - c->filename_formatted = new char[NAME_MAX]; - if (!c->filename_formatted) - throw MemoryAllocationError(); + c->filename_formatted = new char[NAME_MAX]; + if (!c->filename_formatted) + throw MemoryAllocationError(); - strftime(c->filename_formatted, NAME_MAX, c->filename, &tm); - } + strftime(c->filename_formatted, NAME_MAX, c->filename, &tm); + } - n->in.signals = std::make_shared(max_values, SignalType::FLOAT); + n->in.signals = std::make_shared(max_values, SignalType::FLOAT); - return 0; + return 0; } -int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) { + int ret; + auto *t = n->getData(); - const char *output = "."; - const char *prefix = nullptr; + const char *output = "."; + const char *prefix = nullptr; - std::vector rates; - std::vector values; + std::vector rates; + std::vector values; - size_t i; - json_t *json_cases, *json_case, *json_val, *json_format = nullptr; - json_t *json_rates = nullptr, *json_values = nullptr; - json_error_t err; + size_t i; + json_t *json_cases, *json_case, *json_val, *json_format = nullptr; + json_t *json_rates = nullptr, *json_values = nullptr; + json_error_t err; - t->cooldown = 0; + t->cooldown = 0; - // Generate list of test cases - ret = list_init(&t->cases); - if (ret) - return ret; + // Generate list of test cases + ret = list_init(&t->cases); + if (ret) + return ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F, s: o }", - "prefix", &prefix, - "output", &output, - "format", &json_format, - "cooldown", &t->cooldown, - "cases", &json_cases - ); - if (ret) - throw ConfigError(json, err, "node-config-node-test-rtt"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F, s: o }", + "prefix", &prefix, "output", &output, "format", + &json_format, "cooldown", &t->cooldown, "cases", + &json_cases); + if (ret) + throw ConfigError(json, err, "node-config-node-test-rtt"); - t->output = strdup(output); - t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); + t->output = strdup(output); + t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); - // Initialize IO module - if (!json_format) - json_format = json_string("villas.binary"); + // Initialize IO module + if (!json_format) + json_format = json_string("villas.binary"); - t->formatter = FormatFactory::make(json_format); - if (!t->formatter) - throw ConfigError(json, "node-config-node-test-rtt-format", "Invalid value for setting 'format'"); + t->formatter = FormatFactory::make(json_format); + if (!t->formatter) + throw ConfigError(json, "node-config-node-test-rtt-format", + "Invalid value for setting 'format'"); - // Construct List of test cases - if (!json_is_array(json_cases)) - throw ConfigError(json_cases, "node-config-node-test-rtt-format", "The 'cases' setting must be an array."); + // Construct List of test cases + if (!json_is_array(json_cases)) + throw ConfigError(json_cases, "node-config-node-test-rtt-format", + "The 'cases' setting must be an array."); - json_array_foreach(json_cases, i, json_case) { - int limit = -1; - double duration = -1; // in secs + json_array_foreach(json_cases, i, json_case) { + int limit = -1; + double duration = -1; // in secs - ret = json_unpack_ex(json_case, &err, 0, "{ s: o, s: o, s?: i, s?: F }", - "rates", &json_rates, - "values", &json_values, - "limit", &limit, - "duration", &duration - ); + ret = json_unpack_ex(json_case, &err, 0, "{ s: o, s: o, s?: i, s?: F }", + "rates", &json_rates, "values", &json_values, "limit", + &limit, "duration", &duration); - if (limit > 0 && duration > 0) - throw ConfigError(json_case, "node-config-node-test-rtt-duration", "The settings 'duration' and 'limit' must be used exclusively"); + if (limit > 0 && duration > 0) + throw ConfigError( + json_case, "node-config-node-test-rtt-duration", + "The settings 'duration' and 'limit' must be used exclusively"); - if (!json_is_array(json_rates) && !json_is_number(json_rates)) - throw ConfigError(json_case, "node-config-node-test-rtt-rates", "The 'rates' setting must be a real or an array of real numbers"); + if (!json_is_array(json_rates) && !json_is_number(json_rates)) + throw ConfigError( + json_case, "node-config-node-test-rtt-rates", + "The 'rates' setting must be a real or an array of real numbers"); - if (!json_is_array(json_values) && !json_is_integer(json_values)) - throw ConfigError(json_case, "node-config-node-test-rtt-values", "The 'values' setting must be an integer or an array of integers"); + if (!json_is_array(json_values) && !json_is_integer(json_values)) + throw ConfigError( + json_case, "node-config-node-test-rtt-values", + "The 'values' setting must be an integer or an array of integers"); - values.clear(); - rates.clear(); + values.clear(); + rates.clear(); - if (json_is_array(json_rates)) { - size_t j; - json_array_foreach(json_rates, j, json_val) { - if (!json_is_number(json_val)) - throw ConfigError(json_val, "node-config-node-test-rtt-rates", "The 'rates' setting must be an array of real numbers"); + if (json_is_array(json_rates)) { + size_t j; + json_array_foreach(json_rates, j, json_val) { + if (!json_is_number(json_val)) + throw ConfigError( + json_val, "node-config-node-test-rtt-rates", + "The 'rates' setting must be an array of real numbers"); - rates.push_back(json_integer_value(json_val)); - } - } - else - rates.push_back(json_number_value(json_rates)); + rates.push_back(json_integer_value(json_val)); + } + } else + rates.push_back(json_number_value(json_rates)); - if (json_is_array(json_values)) { - size_t j; - json_array_foreach(json_values, j, json_val) { - if (!json_is_integer(json_val)) - throw ConfigError(json_val, "node-config-node-test-rtt-values", "The 'values' setting must be an array of integers"); + if (json_is_array(json_values)) { + size_t j; + json_array_foreach(json_values, j, json_val) { + if (!json_is_integer(json_val)) + throw ConfigError( + json_val, "node-config-node-test-rtt-values", + "The 'values' setting must be an array of integers"); - values.push_back(json_integer_value(json_val)); - } - } - else - values.push_back(json_integer_value(json_values)); + values.push_back(json_integer_value(json_val)); + } + } else + values.push_back(json_integer_value(json_values)); - for (int rate : rates) { - for (int value : values) { - auto *c = new struct test_rtt_case; - if (!c) - throw MemoryAllocationError(); + for (int rate : rates) { + for (int value : values) { + auto *c = new struct test_rtt_case; + if (!c) + throw MemoryAllocationError(); - c->filename = nullptr; - c->filename_formatted = nullptr; - c->node = n; + c->filename = nullptr; + c->filename_formatted = nullptr; + c->node = n; - c->rate = rate; - c->values = value; + c->rate = rate; + c->values = value; - if (limit > 0) - c->limit = limit; - else if (duration > 0) - c->limit = duration * c->rate; - else - c->limit = 1000; // default value + if (limit > 0) + c->limit = limit; + else if (duration > 0) + c->limit = duration * c->rate; + else + c->limit = 1000; // default value - c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, c->values, c->rate); + c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, + c->values, c->rate); - list_push(&t->cases, c); - } - } - } + list_push(&t->cases, c); + } + } + } - return 0; + return 0; } -int villas::node::test_rtt_init(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::test_rtt_init(NodeCompat *n) { + auto *t = n->getData(); - new (&t->task) Task(CLOCK_MONOTONIC); + new (&t->task) Task(CLOCK_MONOTONIC); - t->formatter = nullptr; + t->formatter = nullptr; - return 0; + return 0; } -int villas::node::test_rtt_destroy(NodeCompat *n) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_destroy(NodeCompat *n) { + int ret; + auto *t = n->getData(); - ret = list_destroy(&t->cases, (dtor_cb_t) test_rtt_case_destroy, true); - if (ret) - return ret; + ret = list_destroy(&t->cases, (dtor_cb_t)test_rtt_case_destroy, true); + if (ret) + return ret; - t->task.~Task(); + t->task.~Task(); - if (t->output) - free(t->output); + if (t->output) + free(t->output); - if (t->prefix) - free(t->prefix); + if (t->prefix) + free(t->prefix); - if (t->formatter) - delete t->formatter; + if (t->formatter) + delete t->formatter; - return 0; + return 0; } -char * villas::node::test_rtt_print(NodeCompat *n) -{ - auto *t = n->getData(); +char *villas::node::test_rtt_print(NodeCompat *n) { + auto *t = n->getData(); - return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, t->prefix, t->cooldown, list_length(&t->cases)); + return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, + t->prefix, t->cooldown, list_length(&t->cases)); } -int villas::node::test_rtt_start(NodeCompat *n) -{ - int ret; - struct stat st; - auto *t = n->getData(); - struct test_rtt_case *c = (struct test_rtt_case *) list_first(&t->cases); +int villas::node::test_rtt_start(NodeCompat *n) { + int ret; + struct stat st; + auto *t = n->getData(); + struct test_rtt_case *c = (struct test_rtt_case *)list_first(&t->cases); - // Create folder for results if not present - ret = stat(t->output, &st); - if (ret || !S_ISDIR(st.st_mode)) { - ret = mkdir(t->output, 0777); - if (ret) - throw SystemError("Failed to create output directory: {}", t->output); - } + // Create folder for results if not present + ret = stat(t->output, &st); + if (ret || !S_ISDIR(st.st_mode)) { + ret = mkdir(t->output, 0777); + if (ret) + throw SystemError("Failed to create output directory: {}", t->output); + } - t->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_DATA); + t->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_DATA); - t->task.setRate(c->rate); + t->task.setRate(c->rate); - t->current = -1; - t->counter = -1; + t->current = -1; + t->counter = -1; - return 0; + return 0; } -int villas::node::test_rtt_stop(NodeCompat *n) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_stop(NodeCompat *n) { + int ret; + auto *t = n->getData(); - if (t->counter >= 0) { - ret = test_rtt_case_stop(n, t->current); - if (ret) - return ret; - } + if (t->counter >= 0) { + ret = test_rtt_case_stop(n, t->current); + if (ret) + return ret; + } - delete t->formatter; + delete t->formatter; - return 0; + return 0; } -int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - uint64_t steps; +int villas::node::test_rtt_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; + uint64_t steps; - auto *t = n->getData(); + auto *t = n->getData(); - // Handle start/stop of new cases - if (t->counter == -1) { - if (t->current < 0) { - t->current = 0; - } - else { - ret = test_rtt_case_stop(n, t->current); - if (ret) - return ret; + // Handle start/stop of new cases + if (t->counter == -1) { + if (t->current < 0) { + t->current = 0; + } else { + ret = test_rtt_case_stop(n, t->current); + if (ret) + return ret; - t->current++; - } + t->current++; + } - if ((unsigned) t->current >= list_length(&t->cases)) { - n->logger->info("This was the last case."); + if ((unsigned)t->current >= list_length(&t->cases)) { + n->logger->info("This was the last case."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; - } - else { - ret = test_rtt_case_start(n, t->current); - if (ret) - return ret; - } - } + return -1; + } else { + ret = test_rtt_case_start(n, t->current); + if (ret) + return ret; + } + } - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, t->current); + struct test_rtt_case *c = + (struct test_rtt_case *)list_at(&t->cases, t->current); - // Wait - steps = t->task.wait(); - if (steps > 1) - n->logger->warn("Skipped {} steps", steps - 1); + // Wait + steps = t->task.wait(); + if (steps > 1) + n->logger->warn("Skipped {} steps", steps - 1); - if ((unsigned) t->counter >= c->limit) { - n->logger->info("Stopping case #{}", t->current); + if ((unsigned)t->counter >= c->limit) { + n->logger->info("Stopping case #{}", t->current); - t->counter = -1; + t->counter = -1; - if (t->cooldown) { - n->logger->info("Entering cooldown phase. Waiting {} seconds...", t->cooldown); - t->task.setTimeout(t->cooldown); - } + if (t->cooldown) { + n->logger->info("Entering cooldown phase. Waiting {} seconds...", + t->cooldown); + t->task.setTimeout(t->cooldown); + } - return 0; - } - else { - struct timespec now = time_now(); + return 0; + } else { + struct timespec now = time_now(); - // Prepare samples - for (i = 0; i < cnt; i++) { - smps[i]->length = c->values; - smps[i]->sequence = t->counter; - smps[i]->ts.origin = now; - smps[i]->flags = (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - smps[i]->signals = n->getInputSignals(false); + // Prepare samples + for (i = 0; i < cnt; i++) { + smps[i]->length = c->values; + smps[i]->sequence = t->counter; + smps[i]->ts.origin = now; + smps[i]->flags = (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_TS_ORIGIN; + smps[i]->signals = n->getInputSignals(false); - t->counter++; - } + t->counter++; + } - return i; - } + return i; + } } -int villas::node::test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *t = n->getData(); +int villas::node::test_rtt_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *t = n->getData(); - if (t->current < 0) - return 0; + if (t->current < 0) + return 0; - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, t->current); + struct test_rtt_case *c = + (struct test_rtt_case *)list_at(&t->cases, t->current); - unsigned i; - for (i = 0; i < cnt; i++) { - if (smps[i]->length != c->values) { - n->logger->warn("Discarding invalid sample due to mismatching length: expecting={}, has={}", c->values, smps[i]->length); - continue; - } + unsigned i; + for (i = 0; i < cnt; i++) { + if (smps[i]->length != c->values) { + n->logger->warn("Discarding invalid sample due to mismatching length: " + "expecting={}, has={}", + c->values, smps[i]->length); + continue; + } - t->formatter->print(t->stream, smps[i]); - } + t->formatter->print(t->stream, smps[i]); + } - return i; + return i; } -int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) -{ - auto *t = n->getData(); +int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) { + auto *t = n->getData(); - fds[0] = t->task.getFD(); + fds[0] = t->task.getFD(); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "test_rtt"; - p.description = "Test round-trip time with loopback"; - p.vectorize = 0; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct test_rtt); - p.parse = test_rtt_parse; - p.prepare = test_rtt_prepare; - p.init = test_rtt_init; - p.destroy = test_rtt_destroy; - p.print = test_rtt_print; - p.start = test_rtt_start; - p.stop = test_rtt_stop; - p.read = test_rtt_read; - p.write = test_rtt_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "test_rtt"; + p.description = "Test round-trip time with loopback"; + p.vectorize = 0; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct test_rtt); + p.parse = test_rtt_parse; + p.prepare = test_rtt_prepare; + p.init = test_rtt_init; + p.destroy = test_rtt_destroy; + p.print = test_rtt_print; + p.start = test_rtt_start; + p.stop = test_rtt_stop; + p.read = test_rtt_read; + p.write = test_rtt_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/uldaq.cpp b/lib/nodes/uldaq.cpp index f0b9a9916..ad442eecd 100644 --- a/lib/nodes/uldaq.cpp +++ b/lib/nodes/uldaq.cpp @@ -9,637 +9,620 @@ #include #include -#include -#include #include #include +#include +#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -unsigned num_devs = ULDAQ_MAX_DEV_COUNT; -static -DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; +static unsigned num_devs = ULDAQ_MAX_DEV_COUNT; +static DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; -static -const struct { - const char *name; - AiInputMode mode; -} input_modes[] = { - { "differential", AI_DIFFERENTIAL }, - { "single-ended", AI_SINGLE_ENDED }, - { "pseudo-differential", AI_PSEUDO_DIFFERENTIAL } -}; +static const struct { + const char *name; + AiInputMode mode; +} input_modes[] = {{"differential", AI_DIFFERENTIAL}, + {"single-ended", AI_SINGLE_ENDED}, + {"pseudo-differential", AI_PSEUDO_DIFFERENTIAL}}; -static -const struct { - const char *name; - DaqDeviceInterface interface; -} interface_types[] = { - { "usb", USB_IFC }, - { "bluetooth", BLUETOOTH_IFC }, - { "ethernet", ETHERNET_IFC }, - { "any", ANY_IFC } -}; +static const struct { + const char *name; + DaqDeviceInterface interface; +} interface_types[] = {{"usb", USB_IFC}, + {"bluetooth", BLUETOOTH_IFC}, + {"ethernet", ETHERNET_IFC}, + {"any", ANY_IFC}}; -static -const struct { - const char *name; - Range range; - float min, max; -} ranges[] = { - { "bipolar-60", BIP60VOLTS, -60.0, +60.0 }, - { "bipolar-60", BIP60VOLTS, -60.0, +60.0 }, - { "bipolar-30", BIP30VOLTS, -30.0, +30.0 }, - { "bipolar-15", BIP15VOLTS, -15.0, +15.0 }, - { "bipolar-20", BIP20VOLTS, -20.0, +20.0 }, - { "bipolar-10", BIP10VOLTS, -10.0, +10.0 }, - { "bipolar-5", BIP5VOLTS, -5.0, +5.0 }, - { "bipolar-4", BIP4VOLTS, -4.0, +4.0 }, - { "bipolar-2.5", BIP2PT5VOLTS, -2.5, +2.5 }, - { "bipolar-2", BIP2VOLTS, -2.0, +2.0 }, - { "bipolar-1.25", BIP1PT25VOLTS, -1.25, +1.25 }, - { "bipolar-1", BIP1VOLTS, -1.0, +1.0 }, - { "bipolar-0.625", BIPPT625VOLTS, -0.625, +0.625 }, - { "bipolar-0.5", BIPPT5VOLTS, -0.5, +0.5 }, - { "bipolar-0.25", BIPPT25VOLTS, -0.25, +0.25 }, - { "bipolar-0.125", BIPPT125VOLTS, -0.125, +0.125 }, - { "bipolar-0.2", BIPPT2VOLTS, -0.2, +0.2 }, - { "bipolar-0.1", BIPPT1VOLTS, -0.1, +0.1 }, - { "bipolar-0.078", BIPPT078VOLTS, -0.078, +0.078 }, - { "bipolar-0.05", BIPPT05VOLTS, -0.05, +0.05 }, - { "bipolar-0.01", BIPPT01VOLTS, -0.01, +0.01 }, - { "bipolar-0.005", BIPPT005VOLTS, -0.005, +0.005 }, - { "unipolar-60", UNI60VOLTS , 0.0, +60.0 }, - { "unipolar-30", UNI30VOLTS , 0.0, +30.0 }, - { "unipolar-15", UNI15VOLTS , 0.0, +15.0 }, - { "unipolar-20", UNI20VOLTS , 0.0, +20.0 }, - { "unipolar-10", UNI10VOLTS , 0.0, +10.0 }, - { "unipolar-5", UNI5VOLTS , 0.0, +5.0 }, - { "unipolar-4", UNI4VOLTS , 0.0, +4.0 }, - { "unipolar-2.5", UNI2PT5VOLTS, 0.0, +2.5 }, - { "unipolar-2", UNI2VOLTS , 0.0, +2.0 }, - { "unipolar-1.25", UNI1PT25VOLTS, 0.0, +1.25 }, - { "unipolar-1", UNI1VOLTS , 0.0, +1.0 }, - { "unipolar-0.625", UNIPT625VOLTS, 0.0, +0.625 }, - { "unipolar-0.5", UNIPT5VOLTS, 0.0, +0.5 }, - { "unipolar-0.25", UNIPT25VOLTS, 0.0, +0.25 }, - { "unipolar-0.125", UNIPT125VOLTS, 0.0, +0.125 }, - { "unipolar-0.2", UNIPT2VOLTS, 0.0, +0.2 }, - { "unipolar-0.1", UNIPT1VOLTS, 0.0, +0.1 }, - { "unipolar-0.078", UNIPT078VOLTS, 0.0, +0.078 }, - { "unipolar-0.05", UNIPT05VOLTS, 0.0, +0.05 }, - { "unipolar-0.01", UNIPT01VOLTS, 0.0, +0.01 }, - { "unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005 } -}; +static const struct { + const char *name; + Range range; + float min, max; +} ranges[] = {{"bipolar-60", BIP60VOLTS, -60.0, +60.0}, + {"bipolar-60", BIP60VOLTS, -60.0, +60.0}, + {"bipolar-30", BIP30VOLTS, -30.0, +30.0}, + {"bipolar-15", BIP15VOLTS, -15.0, +15.0}, + {"bipolar-20", BIP20VOLTS, -20.0, +20.0}, + {"bipolar-10", BIP10VOLTS, -10.0, +10.0}, + {"bipolar-5", BIP5VOLTS, -5.0, +5.0}, + {"bipolar-4", BIP4VOLTS, -4.0, +4.0}, + {"bipolar-2.5", BIP2PT5VOLTS, -2.5, +2.5}, + {"bipolar-2", BIP2VOLTS, -2.0, +2.0}, + {"bipolar-1.25", BIP1PT25VOLTS, -1.25, +1.25}, + {"bipolar-1", BIP1VOLTS, -1.0, +1.0}, + {"bipolar-0.625", BIPPT625VOLTS, -0.625, +0.625}, + {"bipolar-0.5", BIPPT5VOLTS, -0.5, +0.5}, + {"bipolar-0.25", BIPPT25VOLTS, -0.25, +0.25}, + {"bipolar-0.125", BIPPT125VOLTS, -0.125, +0.125}, + {"bipolar-0.2", BIPPT2VOLTS, -0.2, +0.2}, + {"bipolar-0.1", BIPPT1VOLTS, -0.1, +0.1}, + {"bipolar-0.078", BIPPT078VOLTS, -0.078, +0.078}, + {"bipolar-0.05", BIPPT05VOLTS, -0.05, +0.05}, + {"bipolar-0.01", BIPPT01VOLTS, -0.01, +0.01}, + {"bipolar-0.005", BIPPT005VOLTS, -0.005, +0.005}, + {"unipolar-60", UNI60VOLTS, 0.0, +60.0}, + {"unipolar-30", UNI30VOLTS, 0.0, +30.0}, + {"unipolar-15", UNI15VOLTS, 0.0, +15.0}, + {"unipolar-20", UNI20VOLTS, 0.0, +20.0}, + {"unipolar-10", UNI10VOLTS, 0.0, +10.0}, + {"unipolar-5", UNI5VOLTS, 0.0, +5.0}, + {"unipolar-4", UNI4VOLTS, 0.0, +4.0}, + {"unipolar-2.5", UNI2PT5VOLTS, 0.0, +2.5}, + {"unipolar-2", UNI2VOLTS, 0.0, +2.0}, + {"unipolar-1.25", UNI1PT25VOLTS, 0.0, +1.25}, + {"unipolar-1", UNI1VOLTS, 0.0, +1.0}, + {"unipolar-0.625", UNIPT625VOLTS, 0.0, +0.625}, + {"unipolar-0.5", UNIPT5VOLTS, 0.0, +0.5}, + {"unipolar-0.25", UNIPT25VOLTS, 0.0, +0.25}, + {"unipolar-0.125", UNIPT125VOLTS, 0.0, +0.125}, + {"unipolar-0.2", UNIPT2VOLTS, 0.0, +0.2}, + {"unipolar-0.1", UNIPT1VOLTS, 0.0, +0.1}, + {"unipolar-0.078", UNIPT078VOLTS, 0.0, +0.078}, + {"unipolar-0.05", UNIPT05VOLTS, 0.0, +0.05}, + {"unipolar-0.01", UNIPT01VOLTS, 0.0, +0.01}, + {"unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005}}; -static -AiInputMode uldaq_parse_input_mode(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(input_modes); i++) { - if (!strcmp(input_modes[i].name, str)) - return input_modes[i].mode; - } +static AiInputMode uldaq_parse_input_mode(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(input_modes); i++) { + if (!strcmp(input_modes[i].name, str)) + return input_modes[i].mode; + } - return (AiInputMode) -1; + return (AiInputMode)-1; } -static -DaqDeviceInterface uldaq_parse_interface_type(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { - if (!strcmp(interface_types[i].name, str)) - return interface_types[i].interface; - } +static DaqDeviceInterface uldaq_parse_interface_type(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { + if (!strcmp(interface_types[i].name, str)) + return interface_types[i].interface; + } - return (DaqDeviceInterface) -1; + return (DaqDeviceInterface)-1; } -static -const char * uldaq_print_interface_type(DaqDeviceInterface iftype) -{ - for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { - if (interface_types[i].interface == iftype) - return interface_types[i].name; - } +static const char *uldaq_print_interface_type(DaqDeviceInterface iftype) { + for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { + if (interface_types[i].interface == iftype) + return interface_types[i].name; + } - return nullptr; + return nullptr; } -static -Range uldaq_parse_range(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(ranges); i++) { - if (!strcmp(ranges[i].name, str)) - return ranges[i].range; - } +static Range uldaq_parse_range(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(ranges); i++) { + if (!strcmp(ranges[i].name, str)) + return ranges[i].range; + } - return (Range) -1; + return (Range)-1; } -static -DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) { - DaqDeviceDescriptor *d = nullptr; +static DaqDeviceDescriptor *uldaq_find_device(struct uldaq *u) { + DaqDeviceDescriptor *d = nullptr; - if (num_devs == 0) - return nullptr; + if (num_devs == 0) + return nullptr; - if (u->device_interface_type == ANY_IFC && u->device_id == nullptr) - return &descriptors[0]; + if (u->device_interface_type == ANY_IFC && u->device_id == nullptr) + return &descriptors[0]; - for (unsigned i = 0; i < num_devs; i++) { - d = &descriptors[i]; + for (unsigned i = 0; i < num_devs; i++) { + d = &descriptors[i]; - if (u->device_id) { - if (strcmp(u->device_id, d->uniqueId)) - break; - } + if (u->device_id) { + if (strcmp(u->device_id, d->uniqueId)) + break; + } - if (u->device_interface_type != ANY_IFC) { - if (u->device_interface_type != d->devInterface) - break; - } + if (u->device_interface_type != ANY_IFC) { + if (u->device_interface_type != d->devInterface) + break; + } - return d; - } + return d; + } - return nullptr; + return nullptr; } -static -int uldaq_connect(NodeCompat *n) -{ - auto *u = n->getData(); - UlError err; +static int uldaq_connect(NodeCompat *n) { + auto *u = n->getData(); + UlError err; - // Find Matching device - if (!u->device_descriptor) { - u->device_descriptor = uldaq_find_device(u); - if (!u->device_descriptor) - throw RuntimeError("Unable to find a matching device"); - } + // Find Matching device + if (!u->device_descriptor) { + u->device_descriptor = uldaq_find_device(u); + if (!u->device_descriptor) + throw RuntimeError("Unable to find a matching device"); + } - // Get a handle to the DAQ device associated with the first descriptor - if (!u->device_handle) { - u->device_handle = ulCreateDaqDevice(*u->device_descriptor); - if (!u->device_handle) - throw RuntimeError("Unable to create handle for DAQ device"); - } + // Get a handle to the DAQ device associated with the first descriptor + if (!u->device_handle) { + u->device_handle = ulCreateDaqDevice(*u->device_descriptor); + if (!u->device_handle) + throw RuntimeError("Unable to create handle for DAQ device"); + } - // Check if device is already connected - int connected; - err = ulIsDaqDeviceConnected(u->device_handle, &connected); - if (err != ERR_NO_ERROR) - return -1; + // Check if device is already connected + int connected; + err = ulIsDaqDeviceConnected(u->device_handle, &connected); + if (err != ERR_NO_ERROR) + return -1; - // Connect to device - if (!connected) { - err = ulConnectDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to connect to DAQ device: {}", buf); - } - } + // Connect to device + if (!connected) { + err = ulConnectDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to connect to DAQ device: {}", buf); + } + } - return 0; + return 0; } -int villas::node::uldaq_type_start(villas::node::SuperNode *sn) -{ - UlError err; +int villas::node::uldaq_type_start(villas::node::SuperNode *sn) { + UlError err; - // Get descriptors for all of the available DAQ devices - err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs); - if (err != ERR_NO_ERROR) - throw RuntimeError("Failed to retrieve DAQ device list"); + // Get descriptors for all of the available DAQ devices + err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs); + if (err != ERR_NO_ERROR) + throw RuntimeError("Failed to retrieve DAQ device list"); - auto logger = logging.get("node:uldaq"); - logger->info("Found {} DAQ devices", num_devs); - for (unsigned i = 0; i < num_devs; i++) { - DaqDeviceDescriptor *desc = &descriptors[i]; + auto logger = logging.get("node:uldaq"); + logger->info("Found {} DAQ devices", num_devs); + for (unsigned i = 0; i < num_devs; i++) { + DaqDeviceDescriptor *desc = &descriptors[i]; - logger->info(" {}: {} {} ({})", i, desc->uniqueId, desc->devString, uldaq_print_interface_type(desc->devInterface)); - } + logger->info(" {}: {} {} ({})", i, desc->uniqueId, desc->devString, + uldaq_print_interface_type(desc->devInterface)); + } - return 0; + return 0; } -int villas::node::uldaq_init(NodeCompat *n) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_init(NodeCompat *n) { + int ret; + auto *u = n->getData(); - u->device_id = nullptr; - u->device_interface_type = ANY_IFC; + u->device_id = nullptr; + u->device_interface_type = ANY_IFC; - u->in.queues = nullptr; - u->in.sample_rate = 1000; - u->in.scan_options = (ScanOption) (SO_DEFAULTIO | SO_CONTINUOUS); - u->in.flags = AINSCAN_FF_DEFAULT; + u->in.queues = nullptr; + u->in.sample_rate = 1000; + u->in.scan_options = (ScanOption)(SO_DEFAULTIO | SO_CONTINUOUS); + u->in.flags = AINSCAN_FF_DEFAULT; - ret = pthread_mutex_init(&u->in.mutex, nullptr); - if (ret) - return ret; + ret = pthread_mutex_init(&u->in.mutex, nullptr); + if (ret) + return ret; - ret = pthread_cond_init(&u->in.cv, nullptr); - if (ret) - return ret; + ret = pthread_cond_init(&u->in.cv, nullptr); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::uldaq_destroy(NodeCompat *n) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_destroy(NodeCompat *n) { + int ret; + auto *u = n->getData(); - if (u->in.queues) - delete[] u->in.queues; + if (u->in.queues) + delete[] u->in.queues; - ret = pthread_mutex_destroy(&u->in.mutex); - if (ret) - return ret; + ret = pthread_mutex_destroy(&u->in.mutex); + if (ret) + return ret; - ret = pthread_cond_destroy(&u->in.cv); - if (ret) - return ret; + ret = pthread_cond_destroy(&u->in.cv); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::uldaq_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_parse(NodeCompat *n, json_t *json) { + int ret; + auto *u = n->getData(); - const char *default_range_str = nullptr; - const char *default_input_mode_str = nullptr; - const char *interface_type = nullptr; + const char *default_range_str = nullptr; + const char *default_input_mode_str = nullptr; + const char *interface_type = nullptr; - size_t i; - json_t *json_signals; - json_t *json_signal; - json_error_t err; + size_t i; + json_t *json_signals; + json_t *json_signal; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s: { s: o, s: F, s?: s, s?: s } }", - "interface_type", &interface_type, - "device_id", &u->device_id, - "in", - "signals", &json_signals, - "sample_rate", &u->in.sample_rate, - "range", &default_range_str, - "input_mode", &default_input_mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-uldaq"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: s, s?: s, s: { s: o, s: F, s?: s, s?: s } }", + "interface_type", &interface_type, "device_id", &u->device_id, "in", + "signals", &json_signals, "sample_rate", &u->in.sample_rate, "range", + &default_range_str, "input_mode", &default_input_mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-uldaq"); - if (interface_type) { - int iftype = uldaq_parse_interface_type(interface_type); - if (iftype < 0) - throw ConfigError(json, "node-config-node-uldaq-interface-type", "Invalid interface type: {}", interface_type); + if (interface_type) { + int iftype = uldaq_parse_interface_type(interface_type); + if (iftype < 0) + throw ConfigError(json, "node-config-node-uldaq-interface-type", + "Invalid interface type: {}", interface_type); - u->device_interface_type = (DaqDeviceInterface) iftype; - } + u->device_interface_type = (DaqDeviceInterface)iftype; + } - if (u->in.queues) - delete[] u->in.queues; + if (u->in.queues) + delete[] u->in.queues; - u->in.channel_count = n->getInputSignals(false)->size(); - u->in.queues = new struct AiQueueElement[u->in.channel_count]; - if (!u->in.queues) - throw MemoryAllocationError(); + u->in.channel_count = n->getInputSignals(false)->size(); + u->in.queues = new struct AiQueueElement[u->in.channel_count]; + if (!u->in.queues) + throw MemoryAllocationError(); - json_array_foreach(json_signals, i, json_signal) { - const char *range_str = nullptr, *input_mode_str = nullptr; - int channel = -1, input_mode, range; + json_array_foreach(json_signals, i, json_signal) { + const char *range_str = nullptr, *input_mode_str = nullptr; + int channel = -1, input_mode, range; - ret = json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: s, s?: i }", - "range", &range_str, - "input_mode", &input_mode_str, - "channel", &channel - ); - if (ret) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Failed to parse signal configuration"); + ret = json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: s, s?: i }", + "range", &range_str, "input_mode", &input_mode_str, + "channel", &channel); + if (ret) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Failed to parse signal configuration"); - if (!range_str) - range_str = default_range_str; + if (!range_str) + range_str = default_range_str; - if (!input_mode_str) - input_mode_str = default_input_mode_str; + if (!input_mode_str) + input_mode_str = default_input_mode_str; - if (channel < 0) - channel = i; + if (channel < 0) + channel = i; - if (!range_str) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "No input range specified for signal {}.", i); + if (!range_str) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "No input range specified for signal {}.", i); - if (!input_mode_str) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "No input mode specified for signal {}.", i); + if (!input_mode_str) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "No input mode specified for signal {}.", i); - range = uldaq_parse_range(range_str); - if (range < 0) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Invalid input range specified for signal {}.", i); + range = uldaq_parse_range(range_str); + if (range < 0) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Invalid input range specified for signal {}.", i); - input_mode = uldaq_parse_input_mode(input_mode_str); - if (input_mode < 0) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Invalid input mode specified for signal {}.", i); + input_mode = uldaq_parse_input_mode(input_mode_str); + if (input_mode < 0) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Invalid input mode specified for signal {}.", i); - u->in.queues[i].range = (Range) range; - u->in.queues[i].inputMode = (AiInputMode) input_mode; - u->in.queues[i].channel = channel; - } + u->in.queues[i].range = (Range)range; + u->in.queues[i].inputMode = (AiInputMode)input_mode; + u->in.queues[i].channel = channel; + } - return ret; + return ret; } -char * villas::node::uldaq_print(NodeCompat *n) -{ - auto *u = n->getData(); +char *villas::node::uldaq_print(NodeCompat *n) { + auto *u = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - if (u->device_descriptor) { - char *uid = u->device_descriptor->uniqueId; - char *name = u->device_descriptor->productName; - const char *iftype = uldaq_print_interface_type(u->device_descriptor->devInterface); + if (u->device_descriptor) { + char *uid = u->device_descriptor->uniqueId; + char *name = u->device_descriptor->productName; + const char *iftype = + uldaq_print_interface_type(u->device_descriptor->devInterface); - buf = strcatf(&buf, "device=%s (%s), interface=%s", uid, name, iftype); - } - else { - const char *uid = u->device_id; - const char *iftype = uldaq_print_interface_type(u->device_interface_type); + buf = strcatf(&buf, "device=%s (%s), interface=%s", uid, name, iftype); + } else { + const char *uid = u->device_id; + const char *iftype = uldaq_print_interface_type(u->device_interface_type); - buf = strcatf(&buf, "device=%s, interface=%s", uid, iftype); - } + buf = strcatf(&buf, "device=%s, interface=%s", uid, iftype); + } - buf = strcatf(&buf, ", in.sample_rate=%f", u->in.sample_rate); + buf = strcatf(&buf, ", in.sample_rate=%f", u->in.sample_rate); - return buf; + return buf; } -int villas::node::uldaq_check(NodeCompat *n) -{ - int ret; - long long has_ai, event_types, max_channel, scan_options, num_ranges_se, num_ranges_diff; - auto *u = n->getData(); +int villas::node::uldaq_check(NodeCompat *n) { + int ret; + long long has_ai, event_types, max_channel, scan_options, num_ranges_se, + num_ranges_diff; + auto *u = n->getData(); - UlError err; + UlError err; - if (n->in.vectorize < 100) - throw ConfigError(n->getConfig(), "node-config-node-vectorize", "Setting 'vectorize' must be larger than 100"); + if (n->in.vectorize < 100) + throw ConfigError(n->getConfig(), "node-config-node-vectorize", + "Setting 'vectorize' must be larger than 100"); - ret = uldaq_connect(n); - if (ret) - return ret; + ret = uldaq_connect(n); + if (ret) + return ret; - err = ulDevGetInfo(u->device_handle, DEV_INFO_HAS_AI_DEV, 0, &has_ai); - if (err != ERR_NO_ERROR) - return -1; + err = ulDevGetInfo(u->device_handle, DEV_INFO_HAS_AI_DEV, 0, &has_ai); + if (err != ERR_NO_ERROR) + return -1; - err = ulDevGetInfo(u->device_handle, DEV_INFO_DAQ_EVENT_TYPES, 0, &event_types); - if (err != ERR_NO_ERROR) - return -1; + err = + ulDevGetInfo(u->device_handle, DEV_INFO_DAQ_EVENT_TYPES, 0, &event_types); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_CHANS, 0, &max_channel); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_CHANS, 0, &max_channel); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_SCAN_OPTIONS, 0, &scan_options); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_SCAN_OPTIONS, 0, &scan_options); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_DIFF_RANGES, 0, &num_ranges_diff); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_DIFF_RANGES, 0, + &num_ranges_diff); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges_se); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges_se); + if (err != ERR_NO_ERROR) + return -1; - Range ranges_diff[num_ranges_diff]; - Range ranges_se[num_ranges_se]; + Range ranges_diff[num_ranges_diff]; + Range ranges_se[num_ranges_se]; - for (int i = 0; i < num_ranges_diff; i++) { - err = ulAIGetInfo(u->device_handle, AI_INFO_DIFF_RANGE, i, (long long *) &ranges_diff[i]); - if (err != ERR_NO_ERROR) - return -1; - } + for (int i = 0; i < num_ranges_diff; i++) { + err = ulAIGetInfo(u->device_handle, AI_INFO_DIFF_RANGE, i, + (long long *)&ranges_diff[i]); + if (err != ERR_NO_ERROR) + return -1; + } - for (int i = 0; i < num_ranges_se; i++) { - err = ulAIGetInfo(u->device_handle, AI_INFO_SE_RANGE, i, (long long *) &ranges_se[i]); - if (err != ERR_NO_ERROR) - return -1; - } + for (int i = 0; i < num_ranges_se; i++) { + err = ulAIGetInfo(u->device_handle, AI_INFO_SE_RANGE, i, + (long long *)&ranges_se[i]); + if (err != ERR_NO_ERROR) + return -1; + } - if (!has_ai) - throw RuntimeError("DAQ device has no analog input channels"); + if (!has_ai) + throw RuntimeError("DAQ device has no analog input channels"); - if (!(event_types & DE_ON_DATA_AVAILABLE)) - throw RuntimeError("DAQ device does not support events"); + if (!(event_types & DE_ON_DATA_AVAILABLE)) + throw RuntimeError("DAQ device does not support events"); - if ((scan_options & u->in.scan_options) != u->in.scan_options) - throw RuntimeError("DAQ device does not support required scan options"); + if ((scan_options & u->in.scan_options) != u->in.scan_options) + throw RuntimeError("DAQ device does not support required scan options"); - for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { - auto sig = n->getInputSignals(false)->getByIndex(i); - AiQueueElement *q = &u->in.queues[i]; + for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { + auto sig = n->getInputSignals(false)->getByIndex(i); + AiQueueElement *q = &u->in.queues[i]; - if (sig->type != SignalType::FLOAT) - throw RuntimeError("Node supports only signals of type = float!"); + if (sig->type != SignalType::FLOAT) + throw RuntimeError("Node supports only signals of type = float!"); - switch (q->inputMode) { - case AI_PSEUDO_DIFFERENTIAL: - case AI_DIFFERENTIAL: - for (int j = 0; j < num_ranges_diff; j++) { - if (q->range == ranges_diff[j]) - goto found; - } - break; + switch (q->inputMode) { + case AI_PSEUDO_DIFFERENTIAL: + case AI_DIFFERENTIAL: + for (int j = 0; j < num_ranges_diff; j++) { + if (q->range == ranges_diff[j]) + goto found; + } + break; - case AI_SINGLE_ENDED: - for (int j = 0; j < num_ranges_se; j++) { - if (q->range == ranges_se[j]) - goto found; - } - break; - } + case AI_SINGLE_ENDED: + for (int j = 0; j < num_ranges_se; j++) { + if (q->range == ranges_se[j]) + goto found; + } + break; + } - throw RuntimeError("Unsupported range for signal {}", i); + throw RuntimeError("Unsupported range for signal {}", i); -found: if (q->channel > max_channel) - throw RuntimeError("DAQ device does not support more than {} channels", max_channel); - } + found: + if (q->channel > max_channel) + throw RuntimeError("DAQ device does not support more than {} channels", + max_channel); + } - return 0; + return 0; } -static -void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type, unsigned long long event_data, void *ctx) -{ - auto *n = (NodeCompat *) ctx; - auto *u = n->getData(); +static void uldaq_data_available(DaqDeviceHandle device_handle, + DaqEventType event_type, + unsigned long long event_data, void *ctx) { + auto *n = (NodeCompat *)ctx; + auto *u = n->getData(); - pthread_mutex_lock(&u->in.mutex); + pthread_mutex_lock(&u->in.mutex); - UlError err; - err = ulAInScanStatus(device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) - n->logger->warn("Failed to retrieve scan status in event callback"); + UlError err; + err = ulAInScanStatus(device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) + n->logger->warn("Failed to retrieve scan status in event callback"); - pthread_mutex_unlock(&u->in.mutex); + pthread_mutex_unlock(&u->in.mutex); - // Signal uldaq_read() about new data - pthread_cond_signal(&u->in.cv); + // Signal uldaq_read() about new data + pthread_cond_signal(&u->in.cv); } -int villas::node::uldaq_start(NodeCompat *n) -{ - auto *u = n->getData(); +int villas::node::uldaq_start(NodeCompat *n) { + auto *u = n->getData(); - u->sequence = 0; - u->in.buffer_pos = 0; + u->sequence = 0; + u->in.buffer_pos = 0; - int ret; - UlError err; + int ret; + UlError err; - // Allocate a buffer to receive the data - u->in.buffer_len = u->in.channel_count * n->in.vectorize * 50; - u->in.buffer = new double[u->in.buffer_len]; - if (!u->in.buffer) - throw MemoryAllocationError(); + // Allocate a buffer to receive the data + u->in.buffer_len = u->in.channel_count * n->in.vectorize * 50; + u->in.buffer = new double[u->in.buffer_len]; + if (!u->in.buffer) + throw MemoryAllocationError(); - ret = uldaq_connect(n); - if (ret) - return ret; + ret = uldaq_connect(n); + if (ret) + return ret; - err = ulAInLoadQueue(u->device_handle, u->in.queues, n->getInputSignals(false)->size()); - if (err != ERR_NO_ERROR) - throw RuntimeError("Failed to load input queue to DAQ device"); + err = ulAInLoadQueue(u->device_handle, u->in.queues, + n->getInputSignals(false)->size()); + if (err != ERR_NO_ERROR) + throw RuntimeError("Failed to load input queue to DAQ device"); - // Enable the event to be notified every time samples are available - err = ulEnableEvent(u->device_handle, DE_ON_DATA_AVAILABLE, n->in.vectorize, uldaq_data_available, n); + // Enable the event to be notified every time samples are available + err = ulEnableEvent(u->device_handle, DE_ON_DATA_AVAILABLE, n->in.vectorize, + uldaq_data_available, n); - // Start the acquisition - err = ulAInScan(u->device_handle, 0, 0, (AiInputMode) 0, (Range) 0, u->in.buffer_len / u->in.channel_count, &u->in.sample_rate, u->in.scan_options, u->in.flags, u->in.buffer); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to start acquisition on DAQ device: {}", buf); - } + // Start the acquisition + err = ulAInScan(u->device_handle, 0, 0, (AiInputMode)0, (Range)0, + u->in.buffer_len / u->in.channel_count, &u->in.sample_rate, + u->in.scan_options, u->in.flags, u->in.buffer); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to start acquisition on DAQ device: {}", buf); + } - // Get the initial status of the acquisition - err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to retrieve scan status on DAQ device: {}", buf); - } + // Get the initial status of the acquisition + err = + ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to retrieve scan status on DAQ device: {}", buf); + } - if (u->in.status != SS_RUNNING) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Acquisition did not start on DAQ device: {}", buf); - } + if (u->in.status != SS_RUNNING) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Acquisition did not start on DAQ device: {}", buf); + } - return 0; + return 0; } -int villas::node::uldaq_stop(NodeCompat *n) -{ - auto *u = n->getData(); +int villas::node::uldaq_stop(NodeCompat *n) { + auto *u = n->getData(); - UlError err; + UlError err; - // TODO: Fix deadlock - //pthread_mutex_lock(&u->in.mutex); + // TODO: Fix deadlock + //pthread_mutex_lock(&u->in.mutex); - // Get the current status of the acquisition - err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) - return -1; + // Get the current status of the acquisition + err = + ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) + return -1; - // Stop the acquisition if it is still running - if (u->in.status == SS_RUNNING) { - err = ulAInScanStop(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; - } + // Stop the acquisition if it is still running + if (u->in.status == SS_RUNNING) { + err = ulAInScanStop(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; + } - //pthread_mutex_unlock(&u->in.mutex); + //pthread_mutex_unlock(&u->in.mutex); - err = ulDisconnectDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; + err = ulDisconnectDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; - err = ulReleaseDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; + err = ulReleaseDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; - return 0; + return 0; } -int villas::node::uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *u = n->getData(); +int villas::node::uldaq_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *u = n->getData(); - pthread_mutex_lock(&u->in.mutex); + pthread_mutex_lock(&u->in.mutex); - if (u->in.status != SS_RUNNING) - return -1; + if (u->in.status != SS_RUNNING) + return -1; - size_t start_index = u->in.buffer_pos; + size_t start_index = u->in.buffer_pos; - // Wait for data available condition triggered by event callback - if (start_index + n->in.vectorize * u->in.channel_count > u->in.transfer_status.currentTotalCount) - pthread_cond_wait(&u->in.cv, &u->in.mutex); + // Wait for data available condition triggered by event callback + if (start_index + n->in.vectorize * u->in.channel_count > + u->in.transfer_status.currentTotalCount) + pthread_cond_wait(&u->in.cv, &u->in.mutex); - for (unsigned j = 0; j < cnt; j++) { - struct Sample *smp = smps[j]; + for (unsigned j = 0; j < cnt; j++) { + struct Sample *smp = smps[j]; - long long scan_index = start_index + j * u->in.channel_count; + long long scan_index = start_index + j * u->in.channel_count; - for (unsigned i = 0; i < u->in.channel_count; i++) { - long long channel_index = (scan_index + i) % u->in.buffer_len; + for (unsigned i = 0; i < u->in.channel_count; i++) { + long long channel_index = (scan_index + i) % u->in.buffer_len; - smp->data[i].f = u->in.buffer[channel_index]; - } + smp->data[i].f = u->in.buffer[channel_index]; + } - smp->length = u->in.channel_count; - smp->signals = n->getInputSignals(false); - smp->sequence = u->sequence++; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - } + smp->length = u->in.channel_count; + smp->signals = n->getInputSignals(false); + smp->sequence = u->sequence++; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + } - u->in.buffer_pos += u->in.channel_count * cnt; + u->in.buffer_pos += u->in.channel_count * cnt; - pthread_mutex_unlock(&u->in.mutex); + pthread_mutex_unlock(&u->in.mutex); - return cnt; + return cnt; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "uldaq"; - p.description = "Measurement Computing DAQ devices like UL201 (libuldaq)"; - p.vectorize = 0; - p.flags = 0; - p.size = sizeof(struct uldaq); - p.type.start = uldaq_type_start; - p.init = uldaq_init; - p.destroy = uldaq_destroy; - p.parse = uldaq_parse; - p.print = uldaq_print; - p.start = uldaq_start; - p.stop = uldaq_stop; - p.read = uldaq_read; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "uldaq"; + p.description = "Measurement Computing DAQ devices like UL201 (libuldaq)"; + p.vectorize = 0; + p.flags = 0; + p.size = sizeof(struct uldaq); + p.type.start = uldaq_type_start; + p.init = uldaq_init; + p.destroy = uldaq_destroy; + p.parse = uldaq_parse; + p.print = uldaq_print; + p.start = uldaq_start; + p.stop = uldaq_stop; + p.read = uldaq_read; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/webrtc.cpp b/lib/nodes/webrtc.cpp index 872f365d5..c4e9ad52b 100644 --- a/lib/nodes/webrtc.cpp +++ b/lib/nodes/webrtc.cpp @@ -9,245 +9,227 @@ #include +#include #include #include -#include -#include #include -#include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -villas::node::Web *web; +static villas::node::Web *web; -WebRTCNode::WebRTCNode(const uuid_t &id, const std::string &name) : - Node(id, name), - server("https://villas.k8s.eonerc.rwth-aachen.de/ws/signaling"), - peer(uuid::toString(id)), - wait_seconds(0), - format(nullptr), - queue({}), - pool({}), - dci({}) -{ - dci.reliability.type = rtc::Reliability::Type::Rexmit; +WebRTCNode::WebRTCNode(const uuid_t &id, const std::string &name) + : Node(id, name), + server("https://villas.k8s.eonerc.rwth-aachen.de/ws/signaling"), + peer(uuid::toString(id)), wait_seconds(0), format(nullptr), queue({}), + pool({}), dci({}) { + dci.reliability.type = rtc::Reliability::Type::Rexmit; } -WebRTCNode::~WebRTCNode() -{ - int ret = pool_destroy(&pool); - if (ret) // TODO log - ; +WebRTCNode::~WebRTCNode() { + int ret = pool_destroy(&pool); + if (ret) // TODO log + ; } -int WebRTCNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int WebRTCNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - const char *sess; - const char *svr = nullptr; - const char *pr = nullptr; - int ord = -1; - int &rexmit = dci.reliability.rexmit.emplace(0); - json_t *json_ice = nullptr; - json_t *json_format = nullptr; + const char *sess; + const char *svr = nullptr; + const char *pr = nullptr; + int ord = -1; + int &rexmit = dci.reliability.rexmit.emplace(0); + json_t *json_ice = nullptr; + json_t *json_format = nullptr; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i, s?: i, s?: b, s?: o }", - "session", &sess, - "peer", &pr, - "server", &svr, - "wait_seconds", &wait_seconds, - "max_retransmits", &rexmit, - "ordered", &ord, - "ice", &json_ice, - "format", &json_format - ); - if (ret) - throw ConfigError(json, err, "node-config-node-webrtc"); + json_error_t err; + ret = json_unpack_ex( + json, &err, 0, "{ s: s, s?: s, s?: s, s?: i, s?: i, s?: b, s?: o }", + "session", &sess, "peer", &pr, "server", &svr, "wait_seconds", + &wait_seconds, "max_retransmits", &rexmit, "ordered", &ord, "ice", + &json_ice, "format", &json_format); + if (ret) + throw ConfigError(json, err, "node-config-node-webrtc"); - session = sess; + session = sess; - if (svr) - server = svr; + if (svr) + server = svr; - if (pr) - peer = pr; + if (pr) + peer = pr; - if (ord) - dci.reliability.unordered = !ord; + if (ord) + dci.reliability.unordered = !ord; - if (json_ice) { - json_t *json_servers = nullptr; + if (json_ice) { + json_t *json_servers = nullptr; - ret = json_unpack_ex(json_ice, &err, 0, "{ s?: o }", - "servers", &json_servers - ); - if (ret) - throw ConfigError(json, err, "node-config-node-webrtc-ice"); + ret = json_unpack_ex(json_ice, &err, 0, "{ s?: o }", "servers", + &json_servers); + if (ret) + throw ConfigError(json, err, "node-config-node-webrtc-ice"); - if (json_servers) { - rtcConf.iceServers.clear(); + if (json_servers) { + rtcConf.iceServers.clear(); - if (!json_is_array(json_servers)) - throw ConfigError(json_servers, "node-config-node-webrtc-ice-servers", "ICE Servers must be a an array of server configurations."); + if (!json_is_array(json_servers)) + throw ConfigError( + json_servers, "node-config-node-webrtc-ice-servers", + "ICE Servers must be a an array of server configurations."); - size_t i; - json_t *json_server; - json_array_foreach(json_servers, i, json_server) { - if (!json_is_string(json_server)) - throw ConfigError(json_server, "node-config-node-webrtc-ice-server", "ICE servers must be provided as STUN/TURN url."); + size_t i; + json_t *json_server; + json_array_foreach(json_servers, i, json_server) { + if (!json_is_string(json_server)) + throw ConfigError(json_server, "node-config-node-webrtc-ice-server", + "ICE servers must be provided as STUN/TURN url."); - std::string uri = json_string_value(json_server); + std::string uri = json_string_value(json_server); - rtcConf.iceServers.emplace_back(uri); - } - } - } + rtcConf.iceServers.emplace_back(uri); + } + } + } - format = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); + format = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); - assert(format); + assert(format); - return 0; + return 0; } -int WebRTCNode::prepare() -{ - int ret = Node::prepare(); - if (ret) - return ret; +int WebRTCNode::prepare() { + int ret = Node::prepare(); + if (ret) + return ret; - format->start(getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + format->start(getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // TODO: Determine output signals reliably - auto signals = std::make_shared(); + // TODO: Determine output signals reliably + auto signals = std::make_shared(); - conn = std::make_shared(server, session, peer, signals, rtcConf, web, dci); + conn = std::make_shared(server, session, peer, + signals, rtcConf, web, dci); - ret = pool_init(&pool, 1024, SAMPLE_LENGTH(getInputSignals(false)->size())); - if (ret) // TODO log - return ret; + ret = pool_init(&pool, 1024, SAMPLE_LENGTH(getInputSignals(false)->size())); + if (ret) // TODO log + return ret; - ret = queue_signalled_init(&queue, 1024); - if (ret) // TODO log - return ret; + ret = queue_signalled_init(&queue, 1024); + if (ret) // TODO log + return ret; - // TODO: Move this to a member function - conn->onMessage([this](rtc::binary msg){ - int ret; - std::vector smps; - smps.resize(this->in.vectorize); + // TODO: Move this to a member function + conn->onMessage([this](rtc::binary msg) { + int ret; + std::vector smps; + smps.resize(this->in.vectorize); - ret = sample_alloc_many(&this->pool, smps.data(), smps.size()); - if (ret < 0) // TODO log - return; + ret = sample_alloc_many(&this->pool, smps.data(), smps.size()); + if (ret < 0) // TODO log + return; - ret = format->sscan((const char *)msg.data(), msg.size(), nullptr, smps.data(), ret); - if (ret < 0) // TODO log - return; + ret = format->sscan((const char *)msg.data(), msg.size(), nullptr, + smps.data(), ret); + if (ret < 0) // TODO log + return; - ret = queue_signalled_push_many(&this->queue, (void **) smps.data(), ret); - if (ret < 0) // TODO log - return; + ret = queue_signalled_push_many(&this->queue, (void **)smps.data(), ret); + if (ret < 0) // TODO log + return; - this->logger->trace("onMessage(rtc::binary) callback finished pushing {} samples", ret); - }); + this->logger->trace( + "onMessage(rtc::binary) callback finished pushing {} samples", ret); + }); - return 0; + return 0; } -int WebRTCNode::start() -{ - int ret = Node::start(); - if (!ret) - state = State::STARTED; +int WebRTCNode::start() { + int ret = Node::start(); + if (!ret) + state = State::STARTED; - conn->connect(); + conn->connect(); - if (wait_seconds > 0) { - logger->info("Waiting for datachannel..."); + if (wait_seconds > 0) { + logger->info("Waiting for datachannel..."); - if (!conn->waitForDataChannel(std::chrono::seconds { wait_seconds })) { - throw RuntimeError { "Waiting for datachannel timed out after {} seconds", wait_seconds }; - } - } + if (!conn->waitForDataChannel(std::chrono::seconds{wait_seconds})) { + throw RuntimeError{"Waiting for datachannel timed out after {} seconds", + wait_seconds}; + } + } - return 0; + return 0; } -int WebRTCNode::stop() -{ - conn->disconnect(); - return Node::stop(); +int WebRTCNode::stop() { + conn->disconnect(); + return Node::stop(); } -std::vector WebRTCNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector WebRTCNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } -const std::string & WebRTCNode::getDetails() -{ - // TODO - details = fmt::format(""); - return details; +const std::string &WebRTCNode::getDetails() { + // TODO + details = fmt::format(""); + return details; } -int WebRTCNode::_read(struct Sample *smps[], unsigned cnt) -{ - std::vector smpt; - smpt.resize(cnt); +int WebRTCNode::_read(struct Sample *smps[], unsigned cnt) { + std::vector smpt; + smpt.resize(cnt); - int pulled = queue_signalled_pull_many(&queue, (void **) smpt.data(), smpt.size()); + int pulled = + queue_signalled_pull_many(&queue, (void **)smpt.data(), smpt.size()); - sample_copy_many(smps, smpt.data(), pulled); - sample_decref_many(smpt.data(), pulled); + sample_copy_many(smps, smpt.data(), pulled); + sample_decref_many(smpt.data(), pulled); - return pulled; + return pulled; } -int WebRTCNode::_write(struct Sample *smps[], unsigned cnt) -{ - rtc::binary buf; - size_t wbytes; +int WebRTCNode::_write(struct Sample *smps[], unsigned cnt) { + rtc::binary buf; + size_t wbytes; - buf.resize(4 * 1024); - int ret = format->sprint((char *) buf.data(), buf.size(), &wbytes, smps, cnt); - if (ret < 0) // TODO log - return ret; + buf.resize(4 * 1024); + int ret = format->sprint((char *)buf.data(), buf.size(), &wbytes, smps, cnt); + if (ret < 0) // TODO log + return ret; - buf.resize(wbytes); - conn->sendMessage(buf); + buf.resize(wbytes); + conn->sendMessage(buf); - return ret; + return ret; } -json_t * WebRTCNode::_readStatus() const -{ - if (!conn) - return nullptr; +json_t *WebRTCNode::_readStatus() const { + if (!conn) + return nullptr; - return conn->readStatus(); + return conn->readStatus(); } -int WebRTCNodeFactory::start(SuperNode *sn) -{ - web = sn->getWeb(); - if (!web->isEnabled()) - return -1; +int WebRTCNodeFactory::start(SuperNode *sn) { + web = sn->getWeb(); + if (!web->isEnabled()) + return -1; - return 0; + return 0; } -static -WebRTCNodeFactory p; +static WebRTCNodeFactory p; diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index 944de99d8..e32e58eef 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -10,13 +10,13 @@ #include #include +#include #include #include -#include -#include #include #include +#include using namespace std::placeholders; @@ -37,416 +37,382 @@ using namespace villas::node::webrtc; * the data structures are defined, allows ADL to pick these up in spdlog/fmt. */ namespace rtc { - using ::operator<<; +using ::operator<<; } -PeerConnection::PeerConnection(const std::string &server, const std::string &session, const std::string &peer, std::shared_ptr signals, rtc::Configuration cfg, Web *w, rtc::DataChannelInit d) : - web(w), - extraServers({}), - dataChannelInit(d), - defaultConfig(cfg), - conn(nullptr), - chan(nullptr), - signals(signals), - logger(logging.get("webrtc:pc")), - stopStartup(false), - warnNotConnected(false), - standby(true), - first(false), - firstID(INT_MAX), - secondID(INT_MAX), - onMessageCallback(nullptr) -{ - client = std::make_shared(server, session, peer, web); - client->onConnected([this](){ this->onSignalingConnected(); }); - client->onDisconnected([this](){ this->onSignalingDisconnected(); }); - client->onError([this](auto err){ this->onSignalingError(std::move(err)); }); - client->onMessage([this](auto msg){ this->onSignalingMessage(std::move(msg)); }); +PeerConnection::PeerConnection(const std::string &server, + const std::string &session, + const std::string &peer, + std::shared_ptr signals, + rtc::Configuration cfg, Web *w, + rtc::DataChannelInit d) + : web(w), extraServers({}), dataChannelInit(d), defaultConfig(cfg), + conn(nullptr), chan(nullptr), signals(signals), + logger(logging.get("webrtc:pc")), stopStartup(false), + warnNotConnected(false), standby(true), first(false), firstID(INT_MAX), + secondID(INT_MAX), onMessageCallback(nullptr) { + client = std::make_shared(server, session, peer, web); + client->onConnected([this]() { this->onSignalingConnected(); }); + client->onDisconnected([this]() { this->onSignalingDisconnected(); }); + client->onError([this](auto err) { this->onSignalingError(std::move(err)); }); + client->onMessage( + [this](auto msg) { this->onSignalingMessage(std::move(msg)); }); - auto lock = std::unique_lock { mutex }; - resetConnectionAndStandby(lock); + auto lock = std::unique_lock{mutex}; + resetConnectionAndStandby(lock); } -PeerConnection::~PeerConnection() -{ +PeerConnection::~PeerConnection() {} + +bool PeerConnection::waitForDataChannel(std::chrono::seconds timeout) { + auto lock = std::unique_lock{mutex}; + + auto deadline = std::chrono::steady_clock::now() + timeout; + + return startupCondition.wait_until(lock, deadline, + [this]() { return this->stopStartup; }); } -bool PeerConnection::waitForDataChannel(std::chrono::seconds timeout) -{ - auto lock = std::unique_lock { mutex }; +json_t *PeerConnection::readStatus() const { + auto *json = + json_pack("{ s: I, s: I }", "bytes_received", conn->bytesReceived(), + "bytes_sent", conn->bytesSent()); - auto deadline = std::chrono::steady_clock::now() + timeout; + auto rtt = conn->rtt(); + if (rtt.has_value()) { + auto *json_rtt = json_real(rtt.value().count() / 1e3); + json_object_set_new(json, "rtt", json_rtt); + } - return startupCondition.wait_until(lock, deadline, [this](){ return this->stopStartup; }); + rtc::Candidate local, remote; + if (conn->getSelectedCandidatePair(&local, &remote)) { + auto *json_cp = + json_pack("{ s: s, s: s }", "local", std::string(local).c_str(), + "remote", std::string(remote).c_str()); + json_object_set_new(json, "candidate_pair", json_cp); + } + + return json; } -json_t * PeerConnection::readStatus() const -{ - auto *json = json_pack("{ s: I, s: I }", - "bytes_received", conn->bytesReceived(), - "bytes_sent", conn->bytesSent() - ); - - auto rtt = conn->rtt(); - if (rtt.has_value()) { - auto *json_rtt = json_real(rtt.value().count() / 1e3); - json_object_set_new(json, "rtt", json_rtt); - } - - rtc::Candidate local, remote; - if (conn->getSelectedCandidatePair(&local, &remote)) { - auto *json_cp = json_pack("{ s: s, s: s }", - "local", std::string(local).c_str(), - "remote", std::string(remote).c_str() - ); - json_object_set_new(json, "candidate_pair", json_cp); - } - - return json; +void PeerConnection::notifyStartup() { + stopStartup = true; + startupCondition.notify_all(); } -void PeerConnection::notifyStartup() -{ - stopStartup = true; - startupCondition.notify_all(); +void PeerConnection::onMessage(std::function callback) { + auto lock = std::unique_lock{mutex}; + + onMessageCallback = callback; } -void PeerConnection::onMessage(std::function callback) -{ - auto lock = std::unique_lock { mutex }; +void PeerConnection::sendMessage(rtc::binary msg) { + auto lock = std::unique_lock{mutex}; - onMessageCallback = callback; + if (chan && chan->isOpen()) { + chan->send(msg); + warnNotConnected = true; + } else if (warnNotConnected) { + logger->warn("Dropping messages. No peer connected."); + warnNotConnected = false; + } } -void PeerConnection::sendMessage(rtc::binary msg) -{ - auto lock = std::unique_lock { mutex }; +void PeerConnection::connect() { client->connect(); } - if (chan && chan->isOpen()) { - chan->send(msg); - warnNotConnected = true; - } else if (warnNotConnected) { - logger->warn("Dropping messages. No peer connected."); - warnNotConnected = false; - } +void PeerConnection::disconnect() { client->disconnect(); } + +void PeerConnection::resetConnection( + std::unique_lock &lock) { + lock.unlock(); + chan.reset(); + conn.reset(); + lock.lock(); } -void PeerConnection::connect() -{ - client->connect(); +void PeerConnection::resetConnectionAndStandby( + std::unique_lock &lock) { + if (!standby) + logger->info("Going to standby"); + + standby = true; + first = false; + firstID = INT_MAX; + secondID = INT_MAX; + warnNotConnected = false; + + resetConnection(lock); } -void PeerConnection::disconnect() -{ - client->disconnect(); +void PeerConnection::setupPeerConnection( + std::shared_ptr pc) { + logger->debug("Setup {} peer connection", pc ? "existing" : "new"); + + auto config = defaultConfig; + config.iceServers.insert(std::end(config.iceServers), + std::begin(extraServers), std::end(extraServers)); + + conn = pc ? std::move(pc) : std::make_shared(config); + conn->onLocalDescription( + [this](auto desc) { this->onLocalDescription(std::move(desc)); }); + conn->onLocalCandidate( + [this](auto cand) { this->onLocalCandidate(std::move(cand)); }); + conn->onDataChannel( + [this](auto channel) { this->onDataChannel(std::move(channel)); }); + conn->onGatheringStateChange( + [this](auto state) { this->onGatheringStateChange(std::move(state)); }); + conn->onSignalingStateChange( + [this](auto state) { this->onSignalingStateChange(std::move(state)); }); + conn->onStateChange( + [this](auto state) { this->onConnectionStateChange(std::move(state)); }); } -void PeerConnection::resetConnection(std::unique_lock &lock) -{ - lock.unlock(); - chan.reset(); - conn.reset(); - lock.lock(); +void PeerConnection::setupDataChannel(std::shared_ptr dc) { + logger->debug("Setup {} data channel", dc ? "existing" : "new"); + + assert(conn); + chan = + dc ? std::move(dc) : conn->createDataChannel("villas", dataChannelInit); + chan->onMessage( + [this](rtc::binary msg) { this->onDataChannelMessage(std::move(msg)); }, + [this](rtc::string msg) { this->onDataChannelMessage(std::move(msg)); }); + chan->onOpen([this]() { this->onDataChannelOpen(); }); + chan->onClosed([this]() { this->onDataChannelClosed(); }); + chan->onError([this](auto err) { this->onDataChannelError(std::move(err)); }); + + // If this node has it's data channel set up, don't accept any new ones + conn->onDataChannel(nullptr); } -void PeerConnection::resetConnectionAndStandby(std::unique_lock &lock) -{ - if (!standby) - logger->info("Going to standby"); +void PeerConnection::onLocalDescription(rtc::Description desc) { + logger->debug("New local description: type={} sdp=\n{}", desc.typeString(), + desc.generateSdp()); - standby = true; - first = false; - firstID = INT_MAX; - secondID = INT_MAX; - warnNotConnected = false; + auto lock = std::unique_lock{mutex}; - resetConnection(lock); + client->sendMessage({desc}); } -void PeerConnection::setupPeerConnection(std::shared_ptr pc) -{ - logger->debug("Setup {} peer connection", pc ? "existing" : "new"); +void PeerConnection::onLocalCandidate(rtc::Candidate cand) { + logger->debug("New local candidate: {}", std::string{cand}); - auto config = defaultConfig; - config.iceServers.insert(std::end(config.iceServers), std::begin(extraServers), std::end(extraServers)); + auto lock = std::unique_lock{mutex}; - conn = pc ? std::move(pc) : std::make_shared(config); - conn->onLocalDescription([this](auto desc){ this->onLocalDescription(std::move(desc)); }); - conn->onLocalCandidate([this](auto cand){ this->onLocalCandidate(std::move(cand)); }); - conn->onDataChannel([this](auto channel){ this->onDataChannel(std::move(channel)); }); - conn->onGatheringStateChange([this](auto state){ this->onGatheringStateChange(std::move(state)); }); - conn->onSignalingStateChange([this](auto state){ this->onSignalingStateChange(std::move(state)); }); - conn->onStateChange([this](auto state){ this->onConnectionStateChange(std::move(state)); }); + client->sendMessage({cand}); } -void PeerConnection::setupDataChannel(std::shared_ptr dc) -{ - logger->debug("Setup {} data channel", dc ? "existing" : "new"); +void PeerConnection::onConnectionStateChange(rtc::PeerConnection::State state) { + logger->debug("Connection State changed: {}", state); - assert(conn); - chan = dc ? std::move(dc) : conn->createDataChannel("villas", dataChannelInit); - chan->onMessage( - [this](rtc::binary msg){ this->onDataChannelMessage(std::move(msg)); }, - [this](rtc::string msg){ this->onDataChannelMessage(std::move(msg)); } - ); - chan->onOpen([this](){ this->onDataChannelOpen(); }); - chan->onClosed([this](){ this->onDataChannelClosed(); }); - chan->onError([this](auto err){ this->onDataChannelError(std::move(err)); }); + auto lock = std::unique_lock{mutex}; - // If this node has it's data channel set up, don't accept any new ones - conn->onDataChannel(nullptr); + switch (state) { + case rtc::PeerConnection::State::New: { + logger->debug("New peer connection"); + break; + } + + case rtc::PeerConnection::State::Connecting: { + logger->debug("Peer connection connecting."); + break; + } + + case rtc::PeerConnection::State::Connected: { + rtc::Candidate local, remote; + std::optional rtt = conn->rtt(); + if (conn->getSelectedCandidatePair(&local, &remote)) { + std::stringstream l, r; + l << local, r << remote; + logger->debug("Peer connection connected:\n" + "local: {}\n" + "remote: {}\n" + "bytes sent: {} / bytes received: {} / rtt: {}\n", + l.str(), r.str(), conn->bytesSent(), conn->bytesReceived(), + rtt.value_or(decltype(rtt)::value_type{0})); + } else { + logger->debug("Peer connection connected.\n" + "Could not get candidate pair info.\n"); + } + break; + } + + case rtc::PeerConnection::State::Disconnected: + case rtc::PeerConnection::State::Failed: { + logger->debug("Closing peer connection"); + break; + } + + case rtc::PeerConnection::State::Closed: { + logger->debug("Closed peer connection"); + resetConnectionAndStandby(lock); + break; + } + } } -void PeerConnection::onLocalDescription(rtc::Description desc) -{ - logger->debug("New local description: type={} sdp=\n{}", desc.typeString(), desc.generateSdp()); - - auto lock = std::unique_lock { mutex }; - - client->sendMessage({ desc }); +void PeerConnection::onSignalingStateChange( + rtc::PeerConnection::SignalingState state) { + std::stringstream s; + s << state; + logger->debug("Signaling state changed: {}", s.str()); } -void PeerConnection::onLocalCandidate(rtc::Candidate cand) -{ - logger->debug("New local candidate: {}", std::string { cand }); - - auto lock = std::unique_lock { mutex }; - - client->sendMessage({ cand }); +void PeerConnection::onGatheringStateChange( + rtc::PeerConnection::GatheringState state) { + std::stringstream s; + s << state; + logger->debug("Gathering state changed: {}", s.str()); } -void PeerConnection::onConnectionStateChange(rtc::PeerConnection::State state) -{ - logger->debug("Connection State changed: {}", state); +void PeerConnection::onSignalingConnected() { + logger->debug("Signaling connection established"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - switch (state) { - case rtc::PeerConnection::State::New: { - logger->debug("New peer connection"); - break; - } - - case rtc::PeerConnection::State::Connecting: { - logger->debug("Peer connection connecting."); - break; - } - - case rtc::PeerConnection::State::Connected: { - rtc::Candidate local, remote; - std::optional rtt = conn->rtt(); - if (conn->getSelectedCandidatePair(&local, &remote)) { - std::stringstream l, r; - l << local, r << remote; - logger->debug( - "Peer connection connected:\n" - "local: {}\n" - "remote: {}\n" - "bytes sent: {} / bytes received: {} / rtt: {}\n", - l.str(), - r.str(), - conn->bytesSent(), - conn->bytesReceived(), - rtt.value_or(decltype(rtt)::value_type { 0 }) - ); - } else { - logger->debug( - "Peer connection connected.\n" - "Could not get candidate pair info.\n" - ); - } - break; - } - - case rtc::PeerConnection::State::Disconnected: - case rtc::PeerConnection::State::Failed: { - logger->debug("Closing peer connection"); - break; - } - - case rtc::PeerConnection::State::Closed: { - logger->debug("Closed peer connection"); - resetConnectionAndStandby(lock); - break; - } - } + client->sendMessage({*signals}); } -void PeerConnection::onSignalingStateChange(rtc::PeerConnection::SignalingState state) -{ - std::stringstream s; - s << state; - logger->debug("Signaling state changed: {}", s.str()); +void PeerConnection::onSignalingDisconnected() { + logger->debug("Signaling connection closed"); + + auto lock = std::unique_lock{mutex}; + + resetConnectionAndStandby(lock); } -void PeerConnection::onGatheringStateChange(rtc::PeerConnection::GatheringState state) -{ - std::stringstream s; - s << state; - logger->debug("Gathering state changed: {}", s.str()); +void PeerConnection::onSignalingError(std::string err) { + logger->debug("Signaling connection error: {}", err); + + auto lock = std::unique_lock{mutex}; + + resetConnectionAndStandby(lock); } -void PeerConnection::onSignalingConnected() -{ - logger->debug("Signaling connection established"); +void PeerConnection::onSignalingMessage(SignalingMessage msg) { + logger->debug("Signaling message received: {}", msg.toString()); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - client->sendMessage({ *signals }); + std::visit( + villas::utils::overloaded{ + [&](RelayMessage &c) { extraServers = std::move(c.servers); }, + + [&](ControlMessage &c) { + auto const &id = c.peerID; + + if (c.peers.size() < 2) { + resetConnectionAndStandby(lock); + return; + } + + auto fst = INT_MAX, snd = INT_MAX; + for (auto &c : c.peers) { + if (c.id < fst) { + snd = fst; + fst = c.id; + } else if (c.id < snd) { + snd = c.id; + } + } + + standby = (id != fst && id != snd); + + if (standby) { + logger->error("There are already two peers connected to this " + "session. Waiting in standby."); + return; + } + + if (fst == firstID && snd == secondID) { + logger->debug("Ignoring control message. This connection is " + "already being established."); + return; + } + + resetConnection(lock); + + first = (id == fst); + firstID = fst; + secondID = snd; + + setupPeerConnection(); + + if (!first) { + setupDataChannel(); + conn->setLocalDescription(rtc::Description::Type::Offer); + } + + logger->trace("New connection pair: first={}, second={}, I am {}", + firstID, secondID, first ? "first" : "second"); + }, + + [&](rtc::Description d) { + if (standby || !conn || + (!first && d.type() == rtc::Description::Type::Offer)) + return; + + conn->setRemoteDescription(d); + }, + + [&](rtc::Candidate c) { + if (standby || !conn) + return; + + conn->addRemoteCandidate(c); + }, + + [&](auto other) { logger->warn("unknown signaling message"); }}, + msg.message); } -void PeerConnection::onSignalingDisconnected() -{ - logger->debug("Signaling connection closed"); +void PeerConnection::onDataChannel(std::shared_ptr dc) { + logger->debug( + "New data channel: {}protocol={}, max_msg_size={}, label={}", + dc->id() && dc->stream() + ? fmt::format("id={}, stream={}, ", *(dc->id()), *(dc->stream())) + : "", + dc->protocol(), dc->maxMessageSize(), dc->label()); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); + setupDataChannel(std::move(dc)); } -void PeerConnection::onSignalingError(std::string err) -{ - logger->debug("Signaling connection error: {}", err); +void PeerConnection::onDataChannelOpen() { + logger->debug("Datachannel opened"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); + chan->send("Hello from VILLASnode"); + + notifyStartup(); } -void PeerConnection::onSignalingMessage(SignalingMessage msg) -{ - logger->debug("Signaling message received: {}", msg.toString()); +void PeerConnection::onDataChannelClosed() { + logger->debug("Datachannel closed"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - std::visit(villas::utils::overloaded { - [&](RelayMessage &c){ - extraServers = std::move(c.servers); - }, - - [&](ControlMessage &c){ - auto const &id = c.peerID; - - if (c.peers.size() < 2) { - resetConnectionAndStandby(lock); - return; - } - - auto fst = INT_MAX, snd = INT_MAX; - for (auto &c : c.peers) { - if (c.id < fst) { - snd = fst; - fst = c.id; - } else if (c.id < snd) { - snd = c.id; - } - } - - standby = (id != fst && id != snd); - - if (standby) { - logger->error("There are already two peers connected to this session. Waiting in standby."); - return; - } - - if (fst == firstID && snd == secondID) { - logger->debug("Ignoring control message. This connection is already being established."); - return; - } - - resetConnection(lock); - - first = (id == fst); - firstID = fst; - secondID = snd; - - setupPeerConnection(); - - if (!first) { - setupDataChannel(); - conn->setLocalDescription(rtc::Description::Type::Offer); - } - - logger->trace("New connection pair: first={}, second={}, I am {}", firstID, secondID, first ? "first" : "second"); - }, - - [&](rtc::Description d){ - if (standby || !conn || (!first && d.type() == rtc::Description::Type::Offer)) - return; - - conn->setRemoteDescription(d); - }, - - [&](rtc::Candidate c){ - if (standby || !conn) - return; - - conn->addRemoteCandidate(c); - }, - - [&](auto other){ - logger->warn("unknown signaling message"); - } - }, msg.message); + resetConnectionAndStandby(lock); } -void PeerConnection::onDataChannel(std::shared_ptr dc) -{ - logger->debug("New data channel: {}protocol={}, max_msg_size={}, label={}", - dc->id() && dc->stream() ? fmt::format("id={}, stream={}, ", - *(dc->id()), - *(dc->stream()) - ) : "", - dc->protocol(), - dc->maxMessageSize(), - dc->label() - ); +void PeerConnection::onDataChannelError(std::string err) { + logger->error("Datachannel error: {}", err); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - setupDataChannel(std::move(dc)); + resetConnectionAndStandby(lock); } -void PeerConnection::onDataChannelOpen() -{ - logger->debug("Datachannel opened"); - - auto lock = std::unique_lock { mutex }; - - chan->send("Hello from VILLASnode"); - - notifyStartup(); +void PeerConnection::onDataChannelMessage(rtc::string msg) { + logger->info("Received: {}", msg); } -void PeerConnection::onDataChannelClosed() -{ - logger->debug("Datachannel closed"); +void PeerConnection::onDataChannelMessage(rtc::binary msg) { + logger->trace("Received binary data"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); -} - -void PeerConnection::onDataChannelError(std::string err) -{ - logger->error("Datachannel error: {}", err); - - auto lock = std::unique_lock { mutex }; - - resetConnectionAndStandby(lock); -} - -void PeerConnection::onDataChannelMessage(rtc::string msg) -{ - logger->info("Received: {}", msg); -} - -void PeerConnection::onDataChannelMessage(rtc::binary msg) -{ - logger->trace("Received binary data"); - - auto lock = std::unique_lock { mutex }; - - if (onMessageCallback) - onMessageCallback(msg); + if (onMessageCallback) + onMessageCallback(msg); } diff --git a/lib/nodes/webrtc/signaling_client.cpp b/lib/nodes/webrtc/signaling_client.cpp index aa3ab8fd9..fb3d6f28f 100644 --- a/lib/nodes/webrtc/signaling_client.cpp +++ b/lib/nodes/webrtc/signaling_client.cpp @@ -9,163 +9,164 @@ #include -#include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::node::webrtc; -SignalingClient::SignalingClient(const std::string &server, const std::string &session, const std::string &peer, Web *w) : - retry_count(0), - web(w), - running(false), - logger(logging.get("webrtc:signal")) -{ - int ret; - const char *prot, *a, *p; +SignalingClient::SignalingClient(const std::string &server, + const std::string &session, + const std::string &peer, Web *w) + : retry_count(0), web(w), running(false), + logger(logging.get("webrtc:signal")) { + int ret; + const char *prot, *a, *p; - memset(&info, 0, sizeof(info)); + memset(&info, 0, sizeof(info)); - ret = asprintf(&uri, "%s/%s/%s", server.c_str(), session.c_str(), peer.c_str()); - if (ret < 0) - throw RuntimeError { "Could not format signaling server uri" }; + ret = + asprintf(&uri, "%s/%s/%s", server.c_str(), session.c_str(), peer.c_str()); + if (ret < 0) + throw RuntimeError{"Could not format signaling server uri"}; - ret = lws_parse_uri(uri, &prot, &a, &info.port, &p); - if (ret) - throw RuntimeError("Failed to parse WebSocket URI: '{}'", uri); + ret = lws_parse_uri(uri, &prot, &a, &info.port, &p); + if (ret) + throw RuntimeError("Failed to parse WebSocket URI: '{}'", uri); - ret = asprintf(&path, "/%s", p); - if (ret < 0) - throw RuntimeError { "Could not format signaling client path" }; + ret = asprintf(&path, "/%s", p); + if (ret < 0) + throw RuntimeError{"Could not format signaling client path"}; - info.ssl_connection = !strcmp(prot, "https"); - info.address = a; - info.path = path; - info.host = a; - info.origin = a; - info.protocol = "webrtc-signaling"; - info.local_protocol_name = "webrtc-signaling"; - info.pwsi = &wsi; - info.retry_and_idle_policy = &retry; - info.ietf_version_or_minus_one = -1; - info.userdata = this; + info.ssl_connection = !strcmp(prot, "https"); + info.address = a; + info.path = path; + info.host = a; + info.origin = a; + info.protocol = "webrtc-signaling"; + info.local_protocol_name = "webrtc-signaling"; + info.pwsi = &wsi; + info.retry_and_idle_policy = &retry; + info.ietf_version_or_minus_one = -1; + info.userdata = this; - sul_helper.self = this; - sul_helper.sul = {}; + sul_helper.self = this; + sul_helper.sul = {}; } -SignalingClient::~SignalingClient() -{ - disconnect(); +SignalingClient::~SignalingClient() { + disconnect(); - free(path); - free(uri); + free(path); + free(uri); } -void SignalingClient::connect() -{ - running = true; +void SignalingClient::connect() { + running = true; - info.context = web->getContext(); + info.context = web->getContext(); - lws_sul_schedule(info.context, 0, &sul_helper.sul, connectStatic, 1 * LWS_US_PER_SEC); + lws_sul_schedule(info.context, 0, &sul_helper.sul, connectStatic, + 1 * LWS_US_PER_SEC); } -void SignalingClient::disconnect() -{ - running = false; - // TODO: - // - wait for connectStatic to exit - // - close LWS connection - if (wsi) - lws_callback_on_writable(wsi); +void SignalingClient::disconnect() { + running = false; + // TODO: + // - wait for connectStatic to exit + // - close LWS connection + if (wsi) + lws_callback_on_writable(wsi); } -void SignalingClient::connectStatic(struct lws_sorted_usec_list *sul) -{ - auto *sh = lws_container_of(sul, struct sul_offsetof_helper, sul); - auto *c = sh->self; +void SignalingClient::connectStatic(struct lws_sorted_usec_list *sul) { + auto *sh = lws_container_of(sul, struct sul_offsetof_helper, sul); + auto *c = sh->self; - if (!lws_client_connect_via_info(&c->info)) { - /* Failed... schedule a retry... we can't use the _retry_wsi() + if (!lws_client_connect_via_info(&c->info)) { + /* Failed... schedule a retry... we can't use the _retry_wsi() * convenience wrapper api here because no valid wsi at this * point. */ - if (lws_retry_sul_schedule(c->info.context, 0, sul, nullptr, connectStatic, &c->retry_count)) - c->logger->error("Signaling connection attempts exhausted"); - } + if (lws_retry_sul_schedule(c->info.context, 0, sul, nullptr, connectStatic, + &c->retry_count)) + c->logger->error("Signaling connection attempts exhausted"); + } } -int SignalingClient::protocolCallbackStatic(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - auto *c = reinterpret_cast(user); +int SignalingClient::protocolCallbackStatic(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + auto *c = reinterpret_cast(user); - return c->protocolCallback(wsi, reason, in, len); + return c->protocolCallback(wsi, reason, in, len); } -int SignalingClient::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *in, size_t len) -{ - int ret; +int SignalingClient::protocolCallback(struct lws *wsi, + enum lws_callback_reasons reason, + void *in, size_t len) { + int ret; - switch (reason) { - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - cbError(in ? (char *) in : "unknown error"); - goto do_retry; + switch (reason) { + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + cbError(in ? (char *)in : "unknown error"); + goto do_retry; - case LWS_CALLBACK_CLIENT_RECEIVE: - if (lws_is_first_fragment(wsi)) - buffer.clear(); + case LWS_CALLBACK_CLIENT_RECEIVE: + if (lws_is_first_fragment(wsi)) + buffer.clear(); - buffer.append((char *) in, len); + buffer.append((char *)in, len); - if (lws_is_final_fragment(wsi)) { - logger->trace("Signaling message received: {:.{}}", buffer.data(), buffer.size()); + if (lws_is_final_fragment(wsi)) { + logger->trace("Signaling message received: {:.{}}", buffer.data(), + buffer.size()); - auto *json = buffer.decode(); - if (json == nullptr) { - logger->error("Failed to decode JSON"); - goto do_retry; - } + auto *json = buffer.decode(); + if (json == nullptr) { + logger->error("Failed to decode JSON"); + goto do_retry; + } - cbMessage(SignalingMessage::fromJson(json)); + cbMessage(SignalingMessage::fromJson(json)); - json_decref(json); - } + json_decref(json); + } - break; + break; - case LWS_CALLBACK_CLIENT_ESTABLISHED: - retry_count = 0; - cbConnected(); - break; + case LWS_CALLBACK_CLIENT_ESTABLISHED: + retry_count = 0; + cbConnected(); + break; - case LWS_CALLBACK_CLIENT_CLOSED: - cbDisconnected(); - goto do_retry; + case LWS_CALLBACK_CLIENT_CLOSED: + cbDisconnected(); + goto do_retry; - case LWS_CALLBACK_CLIENT_WRITEABLE: { - ret = writable(); - if (ret) - goto do_retry; + case LWS_CALLBACK_CLIENT_WRITEABLE: { + ret = writable(); + if (ret) + goto do_retry; - break; - } + break; + } - default: - break; - } + default: + break; + } - return lws_callback_http_dummy(wsi, reason, this, in, len); + return lws_callback_http_dummy(wsi, reason, this, in, len); do_retry: - logger->info("Attempting to reconnect..."); + logger->info("Attempting to reconnect..."); - /* Retry the connection to keep it nailed up + /* Retry the connection to keep it nailed up * * For this example, we try to conceal any problem for one set of * backoff retries and then exit the app. @@ -174,53 +175,54 @@ do_retry: * elements in the backoff table, it will never give up and keep * retrying at the last backoff delay plus the random jitter amount. */ - if (lws_retry_sul_schedule_retry_wsi(wsi, &sul_helper.sul, connectStatic, &retry_count)) - logger->error("Signaling connection attempts exhausted"); + if (lws_retry_sul_schedule_retry_wsi(wsi, &sul_helper.sul, connectStatic, + &retry_count)) + logger->error("Signaling connection attempts exhausted"); - return -1; + return -1; } -int SignalingClient::writable() -{ - if (!running) { - auto reason = "Signaling Client Closing"; - lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *) reason, strlen(reason)); - return 0; - } +int SignalingClient::writable() { + if (!running) { + auto reason = "Signaling Client Closing"; + lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *)reason, + strlen(reason)); + return 0; + } - // Skip if we have nothing to send - if (outgoingMessages.empty()) { - return 0; - } + // Skip if we have nothing to send + if (outgoingMessages.empty()) { + return 0; + } - auto msg = outgoingMessages.pop(); - auto *jsonMsg = msg.toJson(); + auto msg = outgoingMessages.pop(); + auto *jsonMsg = msg.toJson(); - if (!jsonMsg) { - return 0; - } + if (!jsonMsg) { + return 0; + } - char buf[LWS_PRE + 4096]; - auto len = json_dumpb(jsonMsg, buf + LWS_PRE, 4096, JSON_INDENT(2)); - if (len > sizeof(buf) - LWS_PRE) - return -1; + char buf[LWS_PRE + 4096]; + auto len = json_dumpb(jsonMsg, buf + LWS_PRE, 4096, JSON_INDENT(2)); + if (len > sizeof(buf) - LWS_PRE) + return -1; - logger->trace("Signaling message send: {:.{}}", buf + LWS_PRE, len); + logger->trace("Signaling message send: {:.{}}", buf + LWS_PRE, len); - auto ret = lws_write(wsi, (unsigned char *) buf + LWS_PRE, len, LWS_WRITE_TEXT); - if (ret < 0) - return ret; + auto ret = + lws_write(wsi, (unsigned char *)buf + LWS_PRE, len, LWS_WRITE_TEXT); + if (ret < 0) + return ret; - // Reschedule callback if there are more messages to be send - if (!outgoingMessages.empty()) - lws_callback_on_writable(wsi); + // Reschedule callback if there are more messages to be send + if (!outgoingMessages.empty()) + lws_callback_on_writable(wsi); - return 0; + return 0; } -void SignalingClient::sendMessage(SignalingMessage msg) -{ - outgoingMessages.push(msg); +void SignalingClient::sendMessage(SignalingMessage msg) { + outgoingMessages.push(msg); - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } diff --git a/lib/nodes/webrtc/signaling_message.cpp b/lib/nodes/webrtc/signaling_message.cpp index 99e61660a..f7c6d0567 100644 --- a/lib/nodes/webrtc/signaling_message.cpp +++ b/lib/nodes/webrtc/signaling_message.cpp @@ -7,227 +7,187 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::node::webrtc; -json_t * Peer::toJson() const -{ - return json_pack("{ s: i, s: s*, s: s*, s: s* }", - "id", id, - "name", name.empty() ? nullptr : name.c_str(), - "remote", remote.empty() ? nullptr : remote.c_str(), - "user_agent", userAgent.empty() ? nullptr : userAgent.c_str() - // TODO: created, connected - ); +json_t *Peer::toJson() const { + return json_pack("{ s: i, s: s*, s: s*, s: s* }", "id", id, "name", + name.empty() ? nullptr : name.c_str(), "remote", + remote.empty() ? nullptr : remote.c_str(), "user_agent", + userAgent.empty() ? nullptr : userAgent.c_str() + // TODO: created, connected + ); } -Peer::Peer(json_t *json) -{ - const char *nme = nullptr, *rem = nullptr, *ua = nullptr, *tscreat, *tsconn; +Peer::Peer(json_t *json) { + const char *nme = nullptr, *rem = nullptr, *ua = nullptr, *tscreat, *tsconn; - int ret = json_unpack(json, "{ s: i, s?: s, s?: s, s?: s, s?: s, s?: s }", - "id", &id, - "name", &nme, - "remote", &rem, - "user_agent", &ua, - "created", &tscreat, - "connected", &tsconn - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + int ret = json_unpack(json, "{ s: i, s?: s, s?: s, s?: s, s?: s, s?: s }", + "id", &id, "name", &nme, "remote", &rem, "user_agent", + &ua, "created", &tscreat, "connected", &tsconn); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - if (nme) - name = nme; + if (nme) + name = nme; - if (rem) - remote = rem; + if (rem) + remote = rem; - if (ua) - userAgent = ua; + if (ua) + userAgent = ua; - // TODO: created, connected + // TODO: created, connected } -RelayMessage::RelayMessage(json_t *json) -{ +RelayMessage::RelayMessage(json_t *json) { - if (!json_is_array(json)) - throw RuntimeError("Failed to decode signaling message"); + if (!json_is_array(json)) + throw RuntimeError("Failed to decode signaling message"); - int ret; - char *url; - char *user; - char *pass; - char *realm; - char *expires; - json_t *json_server; - size_t i; - json_array_foreach(json, i, json_server) { - ret = json_unpack(json_server, "{ s: s, s: s, s: s, s: s, s: s }", - "url", &url, - "user", &user, - "pass", &pass, - "realm", &realm, - "expires", &expires - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + int ret; + char *url; + char *user; + char *pass; + char *realm; + char *expires; + json_t *json_server; + size_t i; + json_array_foreach(json, i, json_server) { + ret = json_unpack(json_server, "{ s: s, s: s, s: s, s: s, s: s }", "url", + &url, "user", &user, "pass", &pass, "realm", &realm, + "expires", &expires); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - auto &server = servers.emplace_back(url); - server.username = user; - server.password = pass; + auto &server = servers.emplace_back(url); + server.username = user; + server.password = pass; - // TODO: warn about unsupported realm - // TODO: log info about expires time - } + // TODO: warn about unsupported realm + // TODO: log info about expires time + } } -json_t * ControlMessage::toJson() const -{ - json_t *json_peers = json_array(); +json_t *ControlMessage::toJson() const { + json_t *json_peers = json_array(); - for (auto &p : peers) { - json_t *json_peer = p.toJson(); + for (auto &p : peers) { + json_t *json_peer = p.toJson(); - json_array_append_new(json_peers, json_peer); - } + json_array_append_new(json_peers, json_peer); + } - return json_pack("{ s: i, s: o }", - "peer_id", peerID, - "peers", json_peers - ); + return json_pack("{ s: i, s: o }", "peer_id", peerID, "peers", json_peers); } -ControlMessage::ControlMessage(json_t *j) -{ - int ret; +ControlMessage::ControlMessage(json_t *j) { + int ret; - json_t *json_peers; + json_t *json_peers; - ret = json_unpack(j, "{ s: i, s: o }", - "peer_id", &peerID, - "peers", &json_peers - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + ret = json_unpack(j, "{ s: i, s: o }", "peer_id", &peerID, "peers", + &json_peers); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - if (!json_is_array(json_peers)) - throw RuntimeError("Failed to decode signaling message"); + if (!json_is_array(json_peers)) + throw RuntimeError("Failed to decode signaling message"); - json_t *json_peer; - size_t i; - // cppcheck-suppress unknownMacro - json_array_foreach(json_peers, i, json_peer) - peers.emplace_back(json_peer); + json_t *json_peer; + size_t i; + // cppcheck-suppress unknownMacro + json_array_foreach(json_peers, i, json_peer) peers.emplace_back(json_peer); } -json_t * SignalingMessage::toJson() const -{ - return std::visit(villas::utils::overloaded { - [](ControlMessage const &c){ - return json_pack("{ s: o }", "control", c.toJson()); - }, - [](SignalList const &s){ - return json_pack("{ s: o }", "signals", s.toJson()); - }, - [](rtc::Description const &d){ - return json_pack("{ s: { s: s, s: s } }", "description", - "spd", d.generateSdp().c_str(), - "type", d.typeString().c_str() - ); - }, - [](rtc::Candidate const &c){ - return json_pack("{ s: { s: s, s: s } }", "candidate", - "spd", c.candidate().c_str(), - "mid", c.mid().c_str() - ); - }, - [](auto &other){ - return (json_t *) { nullptr }; - } - }, message); +json_t *SignalingMessage::toJson() const { + return std::visit( + villas::utils::overloaded{ + [](ControlMessage const &c) { + return json_pack("{ s: o }", "control", c.toJson()); + }, + [](SignalList const &s) { + return json_pack("{ s: o }", "signals", s.toJson()); + }, + [](rtc::Description const &d) { + return json_pack("{ s: { s: s, s: s } }", "description", "spd", + d.generateSdp().c_str(), "type", + d.typeString().c_str()); + }, + [](rtc::Candidate const &c) { + return json_pack("{ s: { s: s, s: s } }", "candidate", "spd", + c.candidate().c_str(), "mid", c.mid().c_str()); + }, + [](auto &other) { return (json_t *){nullptr}; }}, + message); } -std::string SignalingMessage::toString() const -{ - return std::visit(villas::utils::overloaded { - [](RelayMessage const &r){ - return fmt::format("type=relay"); - }, - [](ControlMessage const &c){ - return fmt::format("type=control, control={}", json_dumps(c.toJson(), 0)); - }, - [](SignalList const &s){ - return fmt::format("type=signal"); - }, - [](rtc::Description const &d){ - return fmt::format("type=description, type={}, spd=\n{}", d.typeString(), d.generateSdp()); - }, - [](rtc::Candidate const &c){ - return fmt::format("type=candidate, mid={}, spd=\n{}", c.candidate(), c.mid()); - }, - [](auto other){ - return fmt::format("invalid signaling message"); - } - }, message); +std::string SignalingMessage::toString() const { + return std::visit( + villas::utils::overloaded{ + [](RelayMessage const &r) { return fmt::format("type=relay"); }, + [](ControlMessage const &c) { + return fmt::format("type=control, control={}", + json_dumps(c.toJson(), 0)); + }, + [](SignalList const &s) { return fmt::format("type=signal"); }, + [](rtc::Description const &d) { + return fmt::format("type=description, type={}, spd=\n{}", + d.typeString(), d.generateSdp()); + }, + [](rtc::Candidate const &c) { + return fmt::format("type=candidate, mid={}, spd=\n{}", + c.candidate(), c.mid()); + }, + [](auto other) { return fmt::format("invalid signaling message"); }}, + message); } -SignalingMessage SignalingMessage::fromJson(json_t *json) -{ - auto self = SignalingMessage { std::monostate() }; +SignalingMessage SignalingMessage::fromJson(json_t *json) { + auto self = SignalingMessage{std::monostate()}; - // Relay message - json_t *rlys = nullptr; - // Signal message - json_t *sigs = nullptr; - // Control message - json_t *ctrl = nullptr; - // Candidate message - const char *cand = nullptr; - const char *mid = nullptr; - // Description message - const char *desc = nullptr; - const char *typ = nullptr; + // Relay message + json_t *rlys = nullptr; + // Signal message + json_t *sigs = nullptr; + // Control message + json_t *ctrl = nullptr; + // Candidate message + const char *cand = nullptr; + const char *mid = nullptr; + // Description message + const char *desc = nullptr; + const char *typ = nullptr; - int ret = json_unpack(json, "{ s?: o, s?: o, s?: o, s?: { s: s, s: s }, s?: { s: s, s: s } }", - "servers", &rlys, - "signals", &sigs, - "control", &ctrl, - "candidate", - "spd", &cand, - "mid", &mid, - "description", - "spd", &desc, - "type", &typ - ); + int ret = json_unpack( + json, "{ s?: o, s?: o, s?: o, s?: { s: s, s: s }, s?: { s: s, s: s } }", + "servers", &rlys, "signals", &sigs, "control", &ctrl, "candidate", "spd", + &cand, "mid", &mid, "description", "spd", &desc, "type", &typ); - // Exactly 1 field may be specified - const void *fields[] = { ctrl, cand, desc }; - if (ret || std::count(std::begin(fields), std::end(fields), nullptr) < std::make_signed_t(std::size(fields)) - 1) - throw RuntimeError("Failed to decode signaling message"); + // Exactly 1 field may be specified + const void *fields[] = {ctrl, cand, desc}; + if (ret || std::count(std::begin(fields), std::end(fields), nullptr) < + std::make_signed_t(std::size(fields)) - 1) + throw RuntimeError("Failed to decode signaling message"); - if (rlys) { - self.message.emplace(rlys); - } - else if (sigs) { - self.message.emplace(sigs); - } - else if (ctrl) { - self.message.emplace(ctrl); - } - else if (cand) { - self.message.emplace(cand, mid); - } - else if (desc) { - self.message.emplace(desc, typ); - } + if (rlys) { + self.message.emplace(rlys); + } else if (sigs) { + self.message.emplace(sigs); + } else if (ctrl) { + self.message.emplace(ctrl); + } else if (cand) { + self.message.emplace(cand, mid); + } else if (desc) { + self.message.emplace(desc, typ); + } - return self; + return self; } diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index c20516efc..2e34ebf6a 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -7,18 +7,18 @@ #include #include -#include #include #include +#include #include -#include #include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::node; @@ -27,129 +27,124 @@ using namespace villas::utils; #define DEFAULT_WEBSOCKET_BUFFER_SIZE (1 << 12) // Private static storage -static -std::list connections; // List of active libwebsocket connections which receive samples from all nodes (catch all) -static -std::mutex connections_lock; +static std::list + connections; // List of active libwebsocket connections which receive samples from all nodes (catch all) +static std::mutex connections_lock; -static -villas::node::Web *web; -static -villas::Logger logger = logging.get("websocket"); +static villas::node::Web *web; +static villas::Logger logger = logging.get("websocket"); // Forward declarations -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static -void websocket_destination_destroy(struct websocket_destination *d) -{ - free(d->uri); +static void websocket_destination_destroy(struct websocket_destination *d) { + free(d->uri); - free((char *) d->info.path); - free((char *) d->info.address); + free((char *)d->info.path); + free((char *)d->info.address); } -static -int websocket_connection_init(struct websocket_connection *c) -{ - int ret; +static int websocket_connection_init(struct websocket_connection *c) { + int ret; - ret = queue_init(&c->queue, DEFAULT_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_init(&c->queue, DEFAULT_QUEUE_LENGTH); + if (ret) + return ret; - c->formatter->start(c->node->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + c->formatter->start(c->node->getInputSignals(false), + ~(int)SampleFlags::HAS_OFFSET); - c->buffers.recv = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); - c->buffers.send = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); + c->buffers.recv = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); + c->buffers.send = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); - if (!c->buffers.recv || !c->buffers.send) - throw MemoryAllocationError(); + if (!c->buffers.recv || !c->buffers.send) + throw MemoryAllocationError(); - c->state = websocket_connection::State::INITIALIZED; + c->state = websocket_connection::State::INITIALIZED; - return 0; + return 0; } -static -int websocket_connection_destroy(struct websocket_connection *c) -{ - int ret; +static int websocket_connection_destroy(struct websocket_connection *c) { + int ret; - assert(c->state != websocket_connection::State::DESTROYED); + assert(c->state != websocket_connection::State::DESTROYED); - // Return all samples to pool - int avail; - struct Sample *smp; + // Return all samples to pool + int avail; + struct Sample *smp; - while ((avail = queue_pull(&c->queue, (void **) &smp))) - sample_decref(smp); + while ((avail = queue_pull(&c->queue, (void **)&smp))) + sample_decref(smp); - ret = queue_destroy(&c->queue); - if (ret) - return ret; + ret = queue_destroy(&c->queue); + if (ret) + return ret; - delete c->formatter; - delete c->buffers.recv; - delete c->buffers.send; + delete c->formatter; + delete c->buffers.recv; + delete c->buffers.send; - c->wsi = nullptr; - c->state = websocket_connection::State::DESTROYED; + c->wsi = nullptr; + c->state = websocket_connection::State::DESTROYED; - return 0; + return 0; } -static -int websocket_connection_write(struct websocket_connection *c, struct Sample * const smps[], unsigned cnt) -{ - int pushed; +static int websocket_connection_write(struct websocket_connection *c, + struct Sample *const smps[], + unsigned cnt) { + int pushed; - if (c->state != websocket_connection::State::ESTABLISHED) - return -1; + if (c->state != websocket_connection::State::ESTABLISHED) + return -1; - pushed = queue_push_many(&c->queue, (void **) smps, cnt); - if (pushed < (int) cnt) - c->node->logger->warn("Queue overrun in WebSocket connection: {}", c->toString()); + pushed = queue_push_many(&c->queue, (void **)smps, cnt); + if (pushed < (int)cnt) + c->node->logger->warn("Queue overrun in WebSocket connection: {}", + c->toString()); - sample_incref_many(smps, pushed); + sample_incref_many(smps, pushed); - c->node->logger->debug("Enqueued {} samples to {}", pushed, c->toString()); + c->node->logger->debug("Enqueued {} samples to {}", pushed, c->toString()); - // Client connections which are currently connecting don't have an associate c->wsi yet - if (c->wsi) - web->callbackOnWritable(c->wsi); - else - c->node->logger->warn("No WSI for conn?"); + // Client connections which are currently connecting don't have an associate c->wsi yet + if (c->wsi) + web->callbackOnWritable(c->wsi); + else + c->node->logger->warn("No WSI for conn?"); - return 0; + return 0; } -static -void websocket_connection_close(struct websocket_connection *c, struct lws *wsi, enum lws_close_status status, const char *reason) -{ - lws_close_reason(wsi, status, (unsigned char *) reason, strlen(reason)); +static void websocket_connection_close(struct websocket_connection *c, + struct lws *wsi, + enum lws_close_status status, + const char *reason) { + lws_close_reason(wsi, status, (unsigned char *)reason, strlen(reason)); - c->node->logger->debug("Closing WebSocket connection with {}: status={}, reason={}", c->toString(), status, reason); + c->node->logger->debug( + "Closing WebSocket connection with {}: status={}, reason={}", + c->toString(), status, reason); - c->state = websocket_connection::State::CLOSED; + c->state = websocket_connection::State::CLOSED; } -int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret, recvd, pulled, cnt = 128; - struct websocket_connection *c = (struct websocket_connection *) user; +int villas::node::websocket_protocol_cb(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret, recvd, pulled, cnt = 128; + struct websocket_connection *c = (struct websocket_connection *)user; - switch (reason) { - case LWS_CALLBACK_CLIENT_ESTABLISHED: - case LWS_CALLBACK_ESTABLISHED: - if (reason == LWS_CALLBACK_CLIENT_ESTABLISHED) - c->mode = websocket_connection::Mode::CLIENT; - else { - c->mode = websocket_connection::Mode::SERVER; - /* We use the URI to associate this connection to a node + switch (reason) { + case LWS_CALLBACK_CLIENT_ESTABLISHED: + case LWS_CALLBACK_ESTABLISHED: + if (reason == LWS_CALLBACK_CLIENT_ESTABLISHED) + c->mode = websocket_connection::Mode::CLIENT; + else { + c->mode = websocket_connection::Mode::SERVER; + /* We use the URI to associate this connection to a node * and choose a protocol. * * Example: ws://example.com/node_1.json @@ -157,488 +152,507 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso * and format 'json'. */ - // Get path of incoming request - char *node, *format, *lasts; - char uri[64]; + // Get path of incoming request + char *node, *format, *lasts; + char uri[64]; - lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); /* The path component of the*/ - if (strlen(uri) <= 0) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, "Invalid URL"); - logger->warn("Failed to get request URI"); - return -1; - } + lws_hdr_copy(wsi, uri, sizeof(uri), + WSI_TOKEN_GET_URI); /* The path component of the*/ + if (strlen(uri) <= 0) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, + "Invalid URL"); + logger->warn("Failed to get request URI"); + return -1; + } - node = strtok_r(uri, "/.", &lasts); - if (!node) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to tokenize request URI"); - return -1; - } + node = strtok_r(uri, "/.", &lasts); + if (!node) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to tokenize request URI"); + return -1; + } - format = strtok_r(nullptr, "", &lasts); - if (!format) - format = (char *) "villas.web"; + format = strtok_r(nullptr, "", &lasts); + if (!format) + format = (char *)"villas.web"; - // Search for node whose name matches the URI - auto *n = ncp.instances.lookup(node); - if (!n) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to find node: {}", node); - return -1; - } + // Search for node whose name matches the URI + auto *n = ncp.instances.lookup(node); + if (!n) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to find node: {}", node); + return -1; + } - c->node = dynamic_cast(n); - if (!c->node) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to find node: {}", node); - return -1; - } + c->node = dynamic_cast(n); + if (!c->node) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to find node: {}", node); + return -1; + } - c->formatter = FormatFactory::make(format); - if (!c->formatter) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown format"); - c->node->logger->warn("Failed to find format: format={}", format); - return -1; - } - } + c->formatter = FormatFactory::make(format); + if (!c->formatter) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown format"); + c->node->logger->warn("Failed to find format: format={}", format); + return -1; + } + } - ret = websocket_connection_init(c); - if (ret) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Internal error"); - c->node->logger->warn("Failed to intialize WebSocket connection: reason={}", ret); - return -1; - } + ret = websocket_connection_init(c); + if (ret) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Internal error"); + c->node->logger->warn( + "Failed to intialize WebSocket connection: reason={}", ret); + return -1; + } - c->wsi = wsi; - c->state = websocket_connection::State::ESTABLISHED; - c->node->logger->info("Established WebSocket connection: {}", c->toString()); + c->wsi = wsi; + c->state = websocket_connection::State::ESTABLISHED; + c->node->logger->info("Established WebSocket connection: {}", + c->toString()); - { - std::lock_guard guard(connections_lock); - connections.push_back(c); - } + { + std::lock_guard guard(connections_lock); + connections.push_back(c); + } - break; + break; - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - c->state = websocket_connection::State::ERROR; + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + c->state = websocket_connection::State::ERROR; - logger->warn("Failed to establish WebSocket connection: reason={}", in ? (char *) in : "unknown"); + logger->warn("Failed to establish WebSocket connection: reason={}", + in ? (char *)in : "unknown"); - return -1; + return -1; - case LWS_CALLBACK_CLOSED: - c->state = websocket_connection::State::CLOSED; - c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); + case LWS_CALLBACK_CLOSED: + c->state = websocket_connection::State::CLOSED; + c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); - if (c->state != websocket_connection::State::CLOSING) { - // TODO: Attempt reconnect here - } + if (c->state != websocket_connection::State::CLOSING) { + // TODO: Attempt reconnect here + } - { - std::lock_guard guard(connections_lock); - connections.remove(c); - } + { + std::lock_guard guard(connections_lock); + connections.remove(c); + } - ret = websocket_connection_destroy(c); - if (ret) - return ret; + ret = websocket_connection_destroy(c); + if (ret) + return ret; - if (c->mode == websocket_connection::Mode::CLIENT) - delete c; + if (c->mode == websocket_connection::Mode::CLIENT) + delete c; - break; + break; - case LWS_CALLBACK_CLIENT_WRITEABLE: - case LWS_CALLBACK_SERVER_WRITEABLE: { - struct Sample *smps[cnt]; + case LWS_CALLBACK_CLIENT_WRITEABLE: + case LWS_CALLBACK_SERVER_WRITEABLE: { + struct Sample *smps[cnt]; - pulled = queue_pull_many(&c->queue, (void **) smps, cnt); - if (pulled > 0) { - size_t wbytes; - c->formatter->sprint(c->buffers.send->data() + LWS_PRE, c->buffers.send->size() - LWS_PRE, &wbytes, smps, pulled); + pulled = queue_pull_many(&c->queue, (void **)smps, cnt); + if (pulled > 0) { + size_t wbytes; + c->formatter->sprint(c->buffers.send->data() + LWS_PRE, + c->buffers.send->size() - LWS_PRE, &wbytes, smps, + pulled); - auto isBinary = dynamic_cast(c->formatter) != nullptr; - ret = lws_write(wsi, (unsigned char *) c->buffers.send->data() + LWS_PRE, wbytes, isBinary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT); + auto isBinary = dynamic_cast(c->formatter) != nullptr; + ret = lws_write(wsi, (unsigned char *)c->buffers.send->data() + LWS_PRE, + wbytes, isBinary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT); - sample_decref_many(smps, pulled); + sample_decref_many(smps, pulled); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - c->node->logger->debug("Send {} samples to connection: {}, bytes={}", pulled, c->toString(), ret); - } + c->node->logger->debug("Send {} samples to connection: {}, bytes={}", + pulled, c->toString(), ret); + } - if (queue_available(&c->queue) > 0) - lws_callback_on_writable(wsi); - else if (c->state == websocket_connection::State::CLOSING) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Node stopped"); - return -1; - } + if (queue_available(&c->queue) > 0) + lws_callback_on_writable(wsi); + else if (c->state == websocket_connection::State::CLOSING) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, + "Node stopped"); + return -1; + } - break; - } + break; + } - case LWS_CALLBACK_CLIENT_RECEIVE: - case LWS_CALLBACK_RECEIVE: - if (lws_is_first_fragment(wsi)) - c->buffers.recv->clear(); + case LWS_CALLBACK_CLIENT_RECEIVE: + case LWS_CALLBACK_RECEIVE: + if (lws_is_first_fragment(wsi)) + c->buffers.recv->clear(); - c->buffers.recv->append((char *) in, len); + c->buffers.recv->append((char *)in, len); - // We dont try to parse the frame yet, as we have to wait for the remaining fragments - if (lws_is_final_fragment(wsi)) { - struct timespec ts_recv = time_now(); - auto *n = c->node; + // We dont try to parse the frame yet, as we have to wait for the remaining fragments + if (lws_is_final_fragment(wsi)) { + struct timespec ts_recv = time_now(); + auto *n = c->node; - int avail, enqueued; - auto *w = n->getData(); - struct Sample *smps[cnt]; + int avail, enqueued; + auto *w = n->getData(); + struct Sample *smps[cnt]; - avail = sample_alloc_many(&w->pool, smps, cnt); - if (avail < cnt) - c->node->logger->warn("Pool underrun for connection: {}", c->toString()); + avail = sample_alloc_many(&w->pool, smps, cnt); + if (avail < cnt) + c->node->logger->warn("Pool underrun for connection: {}", + c->toString()); - recvd = c->formatter->sscan(c->buffers.recv->data(), c->buffers.recv->size(), nullptr, smps, avail); - if (recvd < 0) { - c->node->logger->warn("Failed to parse sample data received on connection: {}", c->toString()); - break; - } + recvd = + c->formatter->sscan(c->buffers.recv->data(), c->buffers.recv->size(), + nullptr, smps, avail); + if (recvd < 0) { + c->node->logger->warn( + "Failed to parse sample data received on connection: {}", + c->toString()); + break; + } - c->node->logger->debug("Received {} samples from connection: {}", recvd, c->toString()); + c->node->logger->debug("Received {} samples from connection: {}", recvd, + c->toString()); - // Set receive timestamp - for (int i = 0; i < recvd; i++) { - smps[i]->ts.received = ts_recv; - smps[i]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + // Set receive timestamp + for (int i = 0; i < recvd; i++) { + smps[i]->ts.received = ts_recv; + smps[i]->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - enqueued = queue_signalled_push_many(&w->queue, (void **) smps, recvd); - if (enqueued < recvd) - c->node->logger->warn("Queue overrun in connection: {}", c->toString()); + enqueued = queue_signalled_push_many(&w->queue, (void **)smps, recvd); + if (enqueued < recvd) + c->node->logger->warn("Queue overrun in connection: {}", c->toString()); - // Release unused samples back to pool - if (enqueued < avail) - sample_decref_many(&smps[enqueued], avail - enqueued); + // Release unused samples back to pool + if (enqueued < avail) + sample_decref_many(&smps[enqueued], avail - enqueued); - c->buffers.recv->clear(); + c->buffers.recv->clear(); - if (c->state == websocket_connection::State::CLOSING) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Node stopped"); - return -1; - } - } + if (c->state == websocket_connection::State::CLOSING) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, + "Node stopped"); + return -1; + } + } - break; + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -int villas::node::websocket_type_start(villas::node::SuperNode *sn) -{ - if (sn == nullptr) - throw RuntimeError("WebSocket node-type requires super-node"); +int villas::node::websocket_type_start(villas::node::SuperNode *sn) { + if (sn == nullptr) + throw RuntimeError("WebSocket node-type requires super-node"); - web = sn->getWeb(); - if (!web->isEnabled()) - return -1; + web = sn->getWeb(); + if (!web->isEnabled()) + return -1; - return 0; + return 0; } -int villas::node::websocket_init(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::websocket_init(NodeCompat *n) { + auto *w = n->getData(); - w->wait = false; + w->wait = false; - int ret = list_init(&w->destinations); - if (ret) - return ret; + int ret = list_init(&w->destinations); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_start(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::websocket_start(NodeCompat *n) { + int ret; + auto *w = n->getData(); - ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUE_LENGTH); + if (ret) + return ret; - for (size_t i = 0; i < list_length(&w->destinations); i++) { - const char *format; - auto *d = (struct websocket_destination *) list_at(&w->destinations, i); - auto *c = new struct websocket_connection; - if (!c) - throw MemoryAllocationError(); + for (size_t i = 0; i < list_length(&w->destinations); i++) { + const char *format; + auto *d = (struct websocket_destination *)list_at(&w->destinations, i); + auto *c = new struct websocket_connection; + if (!c) + throw MemoryAllocationError(); - c->state = websocket_connection::State::CONNECTING; + c->state = websocket_connection::State::CONNECTING; - format = strchr(d->info.path, '.'); - if (format) - format = format + 1; // Removes "." - else - format = "villas.web"; + format = strchr(d->info.path, '.'); + if (format) + format = format + 1; // Removes "." + else + format = "villas.web"; - c->formatter = FormatFactory::make(format); - if (!c->formatter) - return -1; + c->formatter = FormatFactory::make(format); + if (!c->formatter) + return -1; - c->node = n; - c->destination = d; + c->node = n; + c->destination = d; - d->info.context = web->getContext(); - d->info.vhost = web->getVHost(); - d->info.userdata = c; + d->info.context = web->getContext(); + d->info.vhost = web->getVHost(); + d->info.userdata = c; - lws_client_connect_via_info(&d->info); - } + lws_client_connect_via_info(&d->info); + } - // Wait until all destinations are connected - if (w->wait) { - unsigned connected = 0, total = list_length(&w->destinations); - do { - { - std::lock_guard guard(connections_lock); + // Wait until all destinations are connected + if (w->wait) { + unsigned connected = 0, total = list_length(&w->destinations); + do { + { + std::lock_guard guard(connections_lock); - connected = 0; - for (auto *c : connections) { - if (c->mode == websocket_connection::Mode::CLIENT && - c->state == websocket_connection::State::ESTABLISHED && - c->node == n) - connected++; - } - } + connected = 0; + for (auto *c : connections) { + if (c->mode == websocket_connection::Mode::CLIENT && + c->state == websocket_connection::State::ESTABLISHED && + c->node == n) + connected++; + } + } - if (connected < total) { - n->logger->info("Wait until all destinations are connected: pending={}", total - connected); - sleep(1); - } - } while (connected < total); - } + if (connected < total) { + n->logger->info("Wait until all destinations are connected: pending={}", + total - connected); + sleep(1); + } + } while (connected < total); + } - return 0; + return 0; } -int villas::node::websocket_stop(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::websocket_stop(NodeCompat *n) { + int ret; + auto *w = n->getData(); - unsigned open_connections; - do { - { - std::lock_guard guard(connections_lock); + unsigned open_connections; + do { + { + std::lock_guard guard(connections_lock); - open_connections = 0; - for (auto *c : connections) { - if (c->node == n) { - if (c->state != websocket_connection::State::CLOSED) { - open_connections++; + open_connections = 0; + for (auto *c : connections) { + if (c->node == n) { + if (c->state != websocket_connection::State::CLOSED) { + open_connections++; - c->state = websocket_connection::State::CLOSING; - lws_callback_on_writable(c->wsi); - } - } - } - } + c->state = websocket_connection::State::CLOSING; + lws_callback_on_writable(c->wsi); + } + } + } + } - if (open_connections > 0) { - n->logger->info("Waiting for open connections to be closed: pending={}", open_connections); - sleep(1); - } - } while (open_connections > 0); + if (open_connections > 0) { + n->logger->info("Waiting for open connections to be closed: pending={}", + open_connections); + sleep(1); + } + } while (open_connections > 0); - ret = queue_signalled_close(&w->queue); - if (ret) - return ret; + ret = queue_signalled_close(&w->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_destroy(NodeCompat *n) -{ - auto *w = n->getData(); - int ret; +int villas::node::websocket_destroy(NodeCompat *n) { + auto *w = n->getData(); + int ret; - ret = queue_signalled_destroy(&w->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&w->queue); + if (ret) + return ret; - ret = pool_destroy(&w->pool); - if (ret) - return ret; + ret = pool_destroy(&w->pool); + if (ret) + return ret; - ret = list_destroy(&w->destinations, (dtor_cb_t) websocket_destination_destroy, true); - if (ret) - return ret; + ret = list_destroy(&w->destinations, (dtor_cb_t)websocket_destination_destroy, + true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int avail; +int villas::node::websocket_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int avail; - auto *w = n->getData(); - struct Sample *cpys[cnt]; + auto *w = n->getData(); + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&w->queue, (void **) cpys, cnt); - if (avail < 0) - return avail; + avail = queue_signalled_pull_many(&w->queue, (void **)cpys, cnt); + if (avail < 0) + return avail; - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int villas::node::websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int avail; +int villas::node::websocket_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int avail; - auto *w = n->getData(); - struct Sample *cpys[cnt]; + auto *w = n->getData(); + struct Sample *cpys[cnt]; - // Make copies of all samples - avail = sample_alloc_many(&w->pool, cpys, cnt); - if (avail < (int) cnt) - n->logger->warn("Pool underrun: avail={}", avail); + // Make copies of all samples + avail = sample_alloc_many(&w->pool, cpys, cnt); + if (avail < (int)cnt) + n->logger->warn("Pool underrun: avail={}", avail); - sample_copy_many(cpys, smps, avail); + sample_copy_many(cpys, smps, avail); - { - std::lock_guard guard(connections_lock); - for (auto *c : connections) { - if (c->node == n) - websocket_connection_write(c, cpys, cnt); - } - } + { + std::lock_guard guard(connections_lock); + for (auto *c : connections) { + if (c->node == n) + websocket_connection_write(c, cpys, cnt); + } + } - sample_decref_many(cpys, avail); + sample_decref_many(cpys, avail); - return cnt; + return cnt; } -int villas::node::websocket_parse(NodeCompat *n, json_t *json) -{ - auto *w = n->getData(); - int ret; +int villas::node::websocket_parse(NodeCompat *n, json_t *json) { + auto *w = n->getData(); + int ret; - size_t i; - json_t *json_dests = nullptr; - json_t *json_dest; - json_error_t err; - int wc = -1; + size_t i; + json_t *json_dests = nullptr; + json_t *json_dest; + json_error_t err; + int wc = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b }", - "destinations", &json_dests, - "wait_connected", &wc - ); - if (ret) - throw ConfigError(json, err, "node-config-node-websocket"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b }", "destinations", + &json_dests, "wait_connected", &wc); + if (ret) + throw ConfigError(json, err, "node-config-node-websocket"); - if (wc >= 0) - w->wait = wc != 0; + if (wc >= 0) + w->wait = wc != 0; - list_clear(&w->destinations); - if (json_dests) { - if (!json_is_array(json_dests)) - throw ConfigError(json_dests, err, "node-config-node-websocket-destinations", "The 'destinations' setting must be an array of URLs"); + list_clear(&w->destinations); + if (json_dests) { + if (!json_is_array(json_dests)) + throw ConfigError(json_dests, err, + "node-config-node-websocket-destinations", + "The 'destinations' setting must be an array of URLs"); - json_array_foreach(json_dests, i, json_dest) { - const char *uri, *prot, *ads, *path; + json_array_foreach(json_dests, i, json_dest) { + const char *uri, *prot, *ads, *path; - uri = json_string_value(json_dest); - if (!uri) - throw ConfigError(json_dest, err, "node-config-node-websocket-destinations", "The 'destinations' setting must be an array of URLs"); + uri = json_string_value(json_dest); + if (!uri) + throw ConfigError( + json_dest, err, "node-config-node-websocket-destinations", + "The 'destinations' setting must be an array of URLs"); - auto *d = new struct websocket_destination; - if (!d) - throw MemoryAllocationError(); + auto *d = new struct websocket_destination; + if (!d) + throw MemoryAllocationError(); - memset(d, 0, sizeof(struct websocket_destination)); + memset(d, 0, sizeof(struct websocket_destination)); - d->uri = strdup(uri); + d->uri = strdup(uri); - ret = lws_parse_uri(d->uri, &prot, &ads, &d->info.port, &path); - if (ret) - throw ConfigError(json_dest, err, "node-config-node-websocket-destinations", "Failed to parse WebSocket URI: '{}'", uri); + ret = lws_parse_uri(d->uri, &prot, &ads, &d->info.port, &path); + if (ret) + throw ConfigError(json_dest, err, + "node-config-node-websocket-destinations", + "Failed to parse WebSocket URI: '{}'", uri); - d->info.ssl_connection = !strcmp(prot, "https"); - d->info.address = strdup(ads); - d->info.path = strf("/%s", path); - d->info.host = d->info.address; - d->info.origin = d->info.address; - d->info.ietf_version_or_minus_one = -1; - d->info.protocol = "live"; + d->info.ssl_connection = !strcmp(prot, "https"); + d->info.address = strdup(ads); + d->info.path = strf("/%s", path); + d->info.host = d->info.address; + d->info.origin = d->info.address; + d->info.ietf_version_or_minus_one = -1; + d->info.protocol = "live"; - list_push(&w->destinations, d); - } - } + list_push(&w->destinations, d); + } + } - return 0; + return 0; } -char * villas::node::websocket_print(NodeCompat *n) -{ - auto *w = n->getData(); +char *villas::node::websocket_print(NodeCompat *n) { + auto *w = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - buf = strcatf(&buf, "destinations=[ "); + buf = strcatf(&buf, "destinations=[ "); - for (size_t i = 0; i < list_length(&w->destinations); i++) { - struct websocket_destination *d = (struct websocket_destination *) list_at(&w->destinations, i); + for (size_t i = 0; i < list_length(&w->destinations); i++) { + struct websocket_destination *d = + (struct websocket_destination *)list_at(&w->destinations, i); - buf = strcatf(&buf, "%s://%s:%d/%s ", - d->info.ssl_connection ? "wss" : "ws", - d->info.address, - d->info.port, - d->info.path - ); - } + buf = strcatf(&buf, "%s://%s:%d/%s ", d->info.ssl_connection ? "wss" : "ws", + d->info.address, d->info.port, d->info.path); + } - buf = strcatf(&buf, "]"); + buf = strcatf(&buf, "]"); - return buf; + return buf; } -int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) -{ - auto *w = n->getData(); +int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) { + auto *w = n->getData(); - fds[0] = queue_signalled_fd(&w->queue); + fds[0] = queue_signalled_fd(&w->queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void UNIQUE(__ctor)() { - p.name = "websocket"; - p.description = "Send and receive samples of a WebSocket connection (libwebsockets)"; - p.vectorize = 0; - p.size = sizeof(struct websocket); - p.type.start = websocket_type_start; - p.init = websocket_init; - p.destroy = websocket_destroy; - p.parse = websocket_parse; - p.print = websocket_print; - p.start = websocket_start; - p.stop = websocket_stop; - p.read = websocket_read; - p.write = websocket_write; - p.poll_fds = websocket_poll_fds; - p.flags = (int) NodeFactory::Flags::REQUIRES_WEB; +__attribute__((constructor(110))) static void UNIQUE(__ctor)() { + p.name = "websocket"; + p.description = + "Send and receive samples of a WebSocket connection (libwebsockets)"; + p.vectorize = 0; + p.size = sizeof(struct websocket); + p.type.start = websocket_type_start; + p.init = websocket_init; + p.destroy = websocket_destroy; + p.parse = websocket_parse; + p.print = websocket_print; + p.start = websocket_start; + p.stop = websocket_stop; + p.read = websocket_read; + p.write = websocket_write; + p.poll_fds = websocket_poll_fds; + p.flags = (int)NodeFactory::Flags::REQUIRES_WEB; } diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 216dbc071..23ef45675 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -9,649 +9,636 @@ #include #if ZMQ_VERSION_MAJOR < 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR <= 1) - #include +#include #endif +#include #include #include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void *context; +static void *context; /* Read one event off the monitor socket; return value and address * by reference, if not null, and event number by value. * * @returnval -1 In case of error. */ -static -int get_monitor_event(void *monitor, int *value, char **address) -{ - // First frame in message contains event number and value - zmq_msg_t msg; - zmq_msg_init (&msg); - if (zmq_msg_recv (&msg, monitor, 0) == -1) - return -1; // Interruped, presumably +static int get_monitor_event(void *monitor, int *value, char **address) { + // First frame in message contains event number and value + zmq_msg_t msg; + zmq_msg_init(&msg); + if (zmq_msg_recv(&msg, monitor, 0) == -1) + return -1; // Interruped, presumably - assert(zmq_msg_more (&msg)); + assert(zmq_msg_more(&msg)); - uint8_t *data = (uint8_t *) zmq_msg_data(&msg); - uint16_t event = *(uint16_t *) (data); - if (value) - *value = *(uint32_t *) (data + 2); + uint8_t *data = (uint8_t *)zmq_msg_data(&msg); + uint16_t event = *(uint16_t *)(data); + if (value) + *value = *(uint32_t *)(data + 2); - // Second frame in message contains event address - zmq_msg_init(&msg); - if (zmq_msg_recv(&msg, monitor, 0) == -1) - return -1; // Interruped, presumably + // Second frame in message contains event address + zmq_msg_init(&msg); + if (zmq_msg_recv(&msg, monitor, 0) == -1) + return -1; // Interruped, presumably - assert(!zmq_msg_more(&msg)); + assert(!zmq_msg_more(&msg)); - if (address) { - uint8_t *data = (uint8_t *) zmq_msg_data(&msg); - size_t size = zmq_msg_size(&msg); - *address = (char *) malloc(size + 1); - memcpy(*address, data, size); - *address [size] = 0; - } + if (address) { + uint8_t *data = (uint8_t *)zmq_msg_data(&msg); + size_t size = zmq_msg_size(&msg); + *address = (char *)malloc(size + 1); + memcpy(*address, data, size); + *address[size] = 0; + } - return event; + return event; } -int villas::node::zeromq_reverse(NodeCompat *n) -{ - auto *z = n->getData(); +int villas::node::zeromq_reverse(NodeCompat *n) { + auto *z = n->getData(); - if (list_length(&z->out.endpoints) != 1 || - list_length(&z->in.endpoints) != 1) - return -1; + if (list_length(&z->out.endpoints) != 1 || list_length(&z->in.endpoints) != 1) + return -1; - char *subscriber = (char *) list_first(&z->in.endpoints); - char *publisher = (char *) list_first(&z->out.endpoints); + char *subscriber = (char *)list_first(&z->in.endpoints); + char *publisher = (char *)list_first(&z->out.endpoints); - list_set(&z->in.endpoints, 0, publisher); - list_set(&z->out.endpoints, 0, subscriber); + list_set(&z->in.endpoints, 0, publisher); + list_set(&z->out.endpoints, 0, subscriber); - return 0; + return 0; } -int villas::node::zeromq_init(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_init(NodeCompat *n) { + int ret; + auto *z = n->getData(); - z->out.bind = 1; - z->in.bind = 0; + z->out.bind = 1; + z->in.bind = 0; - z->curve.enabled = false; - z->ipv6 = 0; + z->curve.enabled = false; + z->ipv6 = 0; - z->in.pending = 0; - z->out.pending = 0; + z->in.pending = 0; + z->out.pending = 0; - ret = list_init(&z->in.endpoints); - if (ret) - return ret; + ret = list_init(&z->in.endpoints); + if (ret) + return ret; - ret = list_init(&z->out.endpoints); - if (ret) - return ret; + ret = list_init(&z->out.endpoints); + if (ret) + return ret; - z->formatter = nullptr; + z->formatter = nullptr; - return 0; + return 0; } -static -int zeromq_parse_endpoints(json_t *json_ep, struct List *epl) -{ - json_t *json_val; - size_t i; - const char *ep; +static int zeromq_parse_endpoints(json_t *json_ep, struct List *epl) { + json_t *json_val; + size_t i; + const char *ep; - switch (json_typeof(json_ep)) { - case JSON_ARRAY: - json_array_foreach(json_ep, i, json_val) { - ep = json_string_value(json_val); - if (!ep) - throw ConfigError(json_val, "node-config-node-publish", "All 'publish' settings must be strings"); + switch (json_typeof(json_ep)) { + case JSON_ARRAY: + json_array_foreach(json_ep, i, json_val) { + ep = json_string_value(json_val); + if (!ep) + throw ConfigError(json_val, "node-config-node-publish", + "All 'publish' settings must be strings"); - list_push(epl, strdup(ep)); - } - break; + list_push(epl, strdup(ep)); + } + break; - case JSON_STRING: - ep = json_string_value(json_ep); - list_push(epl, strdup(ep)); - break; + case JSON_STRING: + ep = json_string_value(json_ep); + list_push(epl, strdup(ep)); + break; - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } -int villas::node::zeromq_parse(NodeCompat *n, json_t *json) -{ - auto *z = n->getData(); +int villas::node::zeromq_parse(NodeCompat *n, json_t *json) { + auto *z = n->getData(); - int ret; - const char *type = nullptr; - const char *in_filter = nullptr; - const char *out_filter = nullptr; + int ret; + const char *type = nullptr; + const char *in_filter = nullptr; + const char *out_filter = nullptr; - json_error_t err; - json_t *json_in_ep = nullptr; - json_t *json_out_ep = nullptr; - json_t *json_curve = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_in_ep = nullptr; + json_t *json_out_ep = nullptr; + json_t *json_curve = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: s, s?: b }, s?: { s?: o, s?: s, s?: b }, s?: o, s?: s, s?: b, s?: o }", - "in", - "subscribe", &json_in_ep, - "filter", &in_filter, - "bind", &z->in.bind, - "out", - "publish", &json_out_ep, - "filter", &out_filter, - "bind", &z->out.bind, - "curve", &json_curve, - "pattern", &type, - "ipv6", &z->ipv6, - "format", &json_format - ); - if (ret) - throw ConfigError(json, err, "node-config-node-zeromq"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: o, s?: s, s?: b }, s?: { s?: o, s?: s, s?: " + "b }, s?: o, s?: s, s?: b, s?: o }", + "in", "subscribe", &json_in_ep, "filter", &in_filter, + "bind", &z->in.bind, "out", "publish", &json_out_ep, + "filter", &out_filter, "bind", &z->out.bind, "curve", + &json_curve, "pattern", &type, "ipv6", &z->ipv6, + "format", &json_format); + if (ret) + throw ConfigError(json, err, "node-config-node-zeromq"); - z->in.filter = in_filter ? strdup(in_filter) : nullptr; - z->out.filter = out_filter ? strdup(out_filter) : nullptr; + z->in.filter = in_filter ? strdup(in_filter) : nullptr; + z->out.filter = out_filter ? strdup(out_filter) : nullptr; - // Format - if (z->formatter) - delete z->formatter; - z->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!z->formatter) - throw ConfigError(json_format, "node-config-node-zeromq-format", "Invalid format configuration"); + // Format + if (z->formatter) + delete z->formatter; + z->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!z->formatter) + throw ConfigError(json_format, "node-config-node-zeromq-format", + "Invalid format configuration"); - if (json_out_ep) { - ret = zeromq_parse_endpoints(json_out_ep, &z->out.endpoints); - if (ret) - throw ConfigError(json_out_ep, "node-config-node-zeromq-publish", "Failed to parse list of publish endpoints"); - } + if (json_out_ep) { + ret = zeromq_parse_endpoints(json_out_ep, &z->out.endpoints); + if (ret) + throw ConfigError(json_out_ep, "node-config-node-zeromq-publish", + "Failed to parse list of publish endpoints"); + } - if (json_in_ep) { - ret = zeromq_parse_endpoints(json_in_ep, &z->in.endpoints); - if (ret) - throw ConfigError(json_out_ep, "node-config-node-zeromq-subscribe", "Failed to parse list of subscribe endpoints"); - } + if (json_in_ep) { + ret = zeromq_parse_endpoints(json_in_ep, &z->in.endpoints); + if (ret) + throw ConfigError(json_out_ep, "node-config-node-zeromq-subscribe", + "Failed to parse list of subscribe endpoints"); + } - if (json_curve) { - const char *public_key, *secret_key; + if (json_curve) { + const char *public_key, *secret_key; - z->curve.enabled = true; + z->curve.enabled = true; - ret = json_unpack_ex(json_curve, &err, 0, "{ s: s, s: s, s?: b }", - "public_key", &public_key, - "secret_key", &secret_key, - "enabled", &z->curve.enabled - ); - if (ret) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Failed to parse setting 'curve'"); + ret = json_unpack_ex(json_curve, &err, 0, "{ s: s, s: s, s?: b }", + "public_key", &public_key, "secret_key", &secret_key, + "enabled", &z->curve.enabled); + if (ret) + throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", + "Failed to parse setting 'curve'"); - if (strlen(secret_key) != 40) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Setting 'curve.secret_key' must be a Z85 encoded CurveZMQ key"); + if (strlen(secret_key) != 40) + throw ConfigError( + json_curve, err, "node-config-node-zeromq-curve", + "Setting 'curve.secret_key' must be a Z85 encoded CurveZMQ key"); - if (strlen(public_key) != 40) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Setting 'curve.public_key' must be a Z85 encoded CurveZMQ key"); + if (strlen(public_key) != 40) + throw ConfigError( + json_curve, err, "node-config-node-zeromq-curve", + "Setting 'curve.public_key' must be a Z85 encoded CurveZMQ key"); - memcpy(z->curve.server.public_key, public_key, 41); - memcpy(z->curve.server.secret_key, secret_key, 41); - } + memcpy(z->curve.server.public_key, public_key, 41); + memcpy(z->curve.server.secret_key, secret_key, 41); + } - // TODO: We should fix this. Its mostly done. - if (z->curve.enabled) - throw ConfigError(json_curve, "node-config-zeromq-curve", "CurveZMQ support is currently broken"); + // TODO: We should fix this. Its mostly done. + if (z->curve.enabled) + throw ConfigError(json_curve, "node-config-zeromq-curve", + "CurveZMQ support is currently broken"); - if (type) { - if (!strcmp(type, "pubsub")) - z->pattern = zeromq::Pattern::PUBSUB; + if (type) { + if (!strcmp(type, "pubsub")) + z->pattern = zeromq::Pattern::PUBSUB; #ifdef ZMQ_BUILD_DISH - else if (!strcmp(type, "radiodish")) - z->pattern = zeromq::Pattern::RADIODISH; + else if (!strcmp(type, "radiodish")) + z->pattern = zeromq::Pattern::RADIODISH; #endif - else - throw ConfigError(json, "node-config-node-zeromq-type", "Invalid type for ZeroMQ node: {}", n->getNameShort()); - } + else + throw ConfigError(json, "node-config-node-zeromq-type", + "Invalid type for ZeroMQ node: {}", n->getNameShort()); + } - return 0; + return 0; } -char * villas::node::zeromq_print(NodeCompat *n) -{ - auto *z = n->getData(); +char *villas::node::zeromq_print(NodeCompat *n) { + auto *z = n->getData(); - char *buf = nullptr; - const char *pattern = nullptr; + char *buf = nullptr; + const char *pattern = nullptr; - switch (z->pattern) { - case zeromq::Pattern::PUBSUB: - pattern = "pubsub"; - break; + switch (z->pattern) { + case zeromq::Pattern::PUBSUB: + pattern = "pubsub"; + break; #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - pattern = "radiodish"; - break; + case zeromq::Pattern::RADIODISH: + pattern = "radiodish"; + break; #endif - } + } - strcatf(&buf, "pattern=%s, ipv6=%s, crypto=%s, in.bind=%s, out.bind=%s, in.subscribe=[ ", - pattern, - z->ipv6 ? "yes" : "no", - z->curve.enabled ? "yes" : "no", - z->in.bind ? "yes" : "no", - z->out.bind ? "yes" : "no" - ); + strcatf(&buf, + "pattern=%s, ipv6=%s, crypto=%s, in.bind=%s, out.bind=%s, " + "in.subscribe=[ ", + pattern, z->ipv6 ? "yes" : "no", z->curve.enabled ? "yes" : "no", + z->in.bind ? "yes" : "no", z->out.bind ? "yes" : "no"); - for (size_t i = 0; i < list_length(&z->in.endpoints); i++) { - char *ep = (char *) list_at(&z->in.endpoints, i); + for (size_t i = 0; i < list_length(&z->in.endpoints); i++) { + char *ep = (char *)list_at(&z->in.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "], out.publish=[ "); + strcatf(&buf, "], out.publish=[ "); - for (size_t i = 0; i < list_length(&z->out.endpoints); i++) { - char *ep = (char *) list_at(&z->out.endpoints, i); + for (size_t i = 0; i < list_length(&z->out.endpoints); i++) { + char *ep = (char *)list_at(&z->out.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "]"); + strcatf(&buf, "]"); - if (z->in.filter) - strcatf(&buf, ", in.filter=%s", z->in.filter); + if (z->in.filter) + strcatf(&buf, ", in.filter=%s", z->in.filter); - if (z->out.filter) - strcatf(&buf, ", out.filter=%s", z->out.filter); + if (z->out.filter) + strcatf(&buf, ", out.filter=%s", z->out.filter); - return buf; + return buf; } -int villas::node::zeromq_check(NodeCompat *n) -{ - auto *z = n->getData(); +int villas::node::zeromq_check(NodeCompat *n) { + auto *z = n->getData(); - if (list_length(&z->in.endpoints) == 0 && - list_length(&z->out.endpoints) == 0) - return -1; + if (list_length(&z->in.endpoints) == 0 && list_length(&z->out.endpoints) == 0) + return -1; - return 0; + return 0; } -int villas::node::zeromq_type_start(villas::node::SuperNode *sn) -{ - context = zmq_ctx_new(); +int villas::node::zeromq_type_start(villas::node::SuperNode *sn) { + context = zmq_ctx_new(); - return context == nullptr; + return context == nullptr; } -int villas::node::zeromq_type_stop() -{ - return zmq_ctx_term(context); -} +int villas::node::zeromq_type_stop() { return zmq_ctx_term(context); } -int villas::node::zeromq_start(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_start(NodeCompat *n) { + int ret; + auto *z = n->getData(); - struct zeromq::Dir* dirs[] = { &z->out, &z->in }; + struct zeromq::Dir *dirs[] = {&z->out, &z->in}; - z->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + z->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - switch (z->pattern) { + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - z->in.socket = zmq_socket(context, ZMQ_DISH); - z->out.socket = zmq_socket(context, ZMQ_RADIO); - break; + case zeromq::Pattern::RADIODISH: + z->in.socket = zmq_socket(context, ZMQ_DISH); + z->out.socket = zmq_socket(context, ZMQ_RADIO); + break; #endif - case zeromq::Pattern::PUBSUB: - z->in.socket = zmq_socket(context, ZMQ_SUB); - z->out.socket = zmq_socket(context, ZMQ_PUB); - break; - } + case zeromq::Pattern::PUBSUB: + z->in.socket = zmq_socket(context, ZMQ_SUB); + z->out.socket = zmq_socket(context, ZMQ_PUB); + break; + } - if (!z->in.socket || !z->out.socket) { - ret = -1; - goto fail; - } + if (!z->in.socket || !z->out.socket) { + ret = -1; + goto fail; + } - // Join group - switch (z->pattern) { + // Join group + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - ret = zmq_join(z->in.socket, z->in.filter); - break; + case zeromq::Pattern::RADIODISH: + ret = zmq_join(z->in.socket, z->in.filter); + break; #endif - case zeromq::Pattern::PUBSUB: - ret = zmq_setsockopt(z->in.socket, ZMQ_SUBSCRIBE, z->in.filter, z->in.filter ? strlen(z->in.filter) : 0); - break; + case zeromq::Pattern::PUBSUB: + ret = zmq_setsockopt(z->in.socket, ZMQ_SUBSCRIBE, z->in.filter, + z->in.filter ? strlen(z->in.filter) : 0); + break; - default: - ret = -1; - } + default: + ret = -1; + } - if (ret < 0) - goto fail; + if (ret < 0) + goto fail; - if (z->curve.enabled) { - // Publisher has server role - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SECRETKEY, z->curve.server.secret_key, 41); - if (ret) - goto fail; + if (z->curve.enabled) { + // Publisher has server role + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SECRETKEY, + z->curve.server.secret_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_PUBLICKEY, z->curve.server.public_key, 41); - if (ret) - goto fail; + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_PUBLICKEY, + z->curve.server.public_key, 41); + if (ret) + goto fail; - int curve_server = 1; - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SERVER, &curve_server, sizeof(curve_server)); - if (ret) - goto fail; + int curve_server = 1; + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SERVER, &curve_server, + sizeof(curve_server)); + if (ret) + goto fail; - // Create temporary client keys first - ret = zmq_curve_keypair(z->curve.client.public_key, z->curve.client.secret_key); - if (ret) - goto fail; + // Create temporary client keys first + ret = zmq_curve_keypair(z->curve.client.public_key, + z->curve.client.secret_key); + if (ret) + goto fail; - // Subscriber has client role - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SECRETKEY, z->curve.client.secret_key, 41); - if (ret) - goto fail; + // Subscriber has client role + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SECRETKEY, + z->curve.client.secret_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_PUBLICKEY, z->curve.client.public_key, 41); - if (ret) - goto fail; + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_PUBLICKEY, + z->curve.client.public_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SERVERKEY, z->curve.server.public_key, 41); - if (ret) - goto fail; - } + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SERVERKEY, + z->curve.server.public_key, 41); + if (ret) + goto fail; + } - for (auto d : dirs) { - const char *mon_ep = d == &z->in ? "inproc://monitor-in" : "inproc://monitor-out"; + for (auto d : dirs) { + const char *mon_ep = + d == &z->in ? "inproc://monitor-in" : "inproc://monitor-out"; - ret = zmq_setsockopt(d->socket, ZMQ_IPV6, &z->ipv6, sizeof(z->ipv6)); - if (ret) - goto fail; + ret = zmq_setsockopt(d->socket, ZMQ_IPV6, &z->ipv6, sizeof(z->ipv6)); + if (ret) + goto fail; - int linger = 1000; - ret = zmq_setsockopt(d->socket, ZMQ_LINGER, &linger, sizeof(linger)); - if (ret) - goto fail; + int linger = 1000; + ret = zmq_setsockopt(d->socket, ZMQ_LINGER, &linger, sizeof(linger)); + if (ret) + goto fail; - // Monitor events on the server - ret = zmq_socket_monitor(d->socket, mon_ep, ZMQ_EVENT_ALL); - if (ret < 0) - goto fail; + // Monitor events on the server + ret = zmq_socket_monitor(d->socket, mon_ep, ZMQ_EVENT_ALL); + if (ret < 0) + goto fail; - // Create socket for collecting monitor events - d->mon_socket = zmq_socket(context, ZMQ_PAIR); - if (!d->mon_socket) { - ret = -1; - goto fail; - } + // Create socket for collecting monitor events + d->mon_socket = zmq_socket(context, ZMQ_PAIR); + if (!d->mon_socket) { + ret = -1; + goto fail; + } - // Connect it to the inproc endpoints so they'll get events - ret = zmq_connect(d->mon_socket, mon_ep); - if (ret < 0) - goto fail; + // Connect it to the inproc endpoints so they'll get events + ret = zmq_connect(d->mon_socket, mon_ep); + if (ret < 0) + goto fail; - // Connect / bind sockets to endpoints - for (size_t i = 0; i < list_length(&d->endpoints); i++) { - char *ep = (char *) list_at(&d->endpoints, i); + // Connect / bind sockets to endpoints + for (size_t i = 0; i < list_length(&d->endpoints); i++) { + char *ep = (char *)list_at(&d->endpoints, i); - if (d->bind) { - ret = zmq_bind(d->socket, ep); - if (ret < 0) - goto fail; - } - else { - ret = zmq_connect(d->socket, ep); - if (ret < 0) - goto fail; - } + if (d->bind) { + ret = zmq_bind(d->socket, ep); + if (ret < 0) + goto fail; + } else { + ret = zmq_connect(d->socket, ep); + if (ret < 0) + goto fail; + } - d->pending++; - } - } + d->pending++; + } + } - // Wait for all connections to be connected - for (auto d : dirs) { - while (d->pending > 0) { - int evt = d->bind ? ZMQ_EVENT_LISTENING : ZMQ_EVENT_CONNECTED; + // Wait for all connections to be connected + for (auto d : dirs) { + while (d->pending > 0) { + int evt = d->bind ? ZMQ_EVENT_LISTENING : ZMQ_EVENT_CONNECTED; - ret = get_monitor_event(d->mon_socket, nullptr, nullptr); - if (ret == evt) - d->pending--; - } - } + ret = get_monitor_event(d->mon_socket, nullptr, nullptr); + if (ret == evt) + d->pending--; + } + } -#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_MAJOR_VERSION >= 4 && ZMQ_MINOR_VERSION >= 2 && ZMQ_MINOR_VERSION >= 3 - if (z->curve.enabled) { - ret = get_monitor_event(z->in.mon_socket, nullptr, nullptr); - return ret == ZMQ_EVENT_HANDSHAKE_SUCCEEDED; - } - else - return 0; // The handshake events are only emitted for CurveZMQ sessions +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_MAJOR_VERSION >= 4 && \ + ZMQ_MINOR_VERSION >= 2 && ZMQ_MINOR_VERSION >= 3 + if (z->curve.enabled) { + ret = get_monitor_event(z->in.mon_socket, nullptr, nullptr); + return ret == ZMQ_EVENT_HANDSHAKE_SUCCEEDED; + } else + return 0; // The handshake events are only emitted for CurveZMQ sessions #else - return 0; + return 0; #endif fail: - n->logger->info("Failed to start: {}", zmq_strerror(errno)); + n->logger->info("Failed to start: {}", zmq_strerror(errno)); - return ret; + return ret; } -int villas::node::zeromq_stop(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_stop(NodeCompat *n) { + int ret; + auto *z = n->getData(); - struct zeromq::Dir* dirs[] = { &z->out, &z->in }; + struct zeromq::Dir *dirs[] = {&z->out, &z->in}; - for (auto d : dirs) { - ret = zmq_close(d->socket); - if (ret) - return ret; + for (auto d : dirs) { + ret = zmq_close(d->socket); + if (ret) + return ret; - ret = zmq_close(d->mon_socket); - if (ret) - return ret; - } + ret = zmq_close(d->mon_socket); + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::zeromq_destroy(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_destroy(NodeCompat *n) { + int ret; + auto *z = n->getData(); - if (z->in.filter) - free(z->in.filter); + if (z->in.filter) + free(z->in.filter); - if (z->out.filter) - free(z->out.filter); + if (z->out.filter) + free(z->out.filter); - ret = list_destroy(&z->out.endpoints, nullptr, true); - if (ret) - return ret; + ret = list_destroy(&z->out.endpoints, nullptr, true); + if (ret) + return ret; - if (z->formatter) - delete z->formatter; + if (z->formatter) + delete z->formatter; - return 0; + return 0; } -int villas::node::zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int recv, ret; - auto *z = n->getData(); +int villas::node::zeromq_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int recv, ret; + auto *z = n->getData(); - zmq_msg_t m; + zmq_msg_t m; - ret = zmq_msg_init(&m); - if (ret < 0) - return ret; + ret = zmq_msg_init(&m); + if (ret < 0) + return ret; - if (z->in.filter) { - switch (z->pattern) { - case zeromq::Pattern::PUBSUB: - // Discard envelope - zmq_recv(z->in.socket, nullptr, 0, 0); - break; + if (z->in.filter) { + switch (z->pattern) { + case zeromq::Pattern::PUBSUB: + // Discard envelope + zmq_recv(z->in.socket, nullptr, 0, 0); + break; - default: { } - } - } + default: { + } + } + } - // Receive payload - ret = zmq_msg_recv(&m, z->in.socket, 0); - if (ret < 0) - return ret; + // Receive payload + ret = zmq_msg_recv(&m, z->in.socket, 0); + if (ret < 0) + return ret; - recv = z->formatter->sscan((const char *) zmq_msg_data(&m), zmq_msg_size(&m), nullptr, smps, cnt); + recv = z->formatter->sscan((const char *)zmq_msg_data(&m), zmq_msg_size(&m), + nullptr, smps, cnt); - ret = zmq_msg_close(&m); - if (ret) - return ret; + ret = zmq_msg_close(&m); + if (ret) + return ret; - return recv; + return recv; } -int villas::node::zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *z = n->getData(); - size_t wbytes; - zmq_msg_t m; + size_t wbytes; + zmq_msg_t m; - char data[DEFAULT_FORMAT_BUFFER_LENGTH]; + char data[DEFAULT_FORMAT_BUFFER_LENGTH]; - ret = z->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = z->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - ret = zmq_msg_init_size(&m, wbytes); + ret = zmq_msg_init_size(&m, wbytes); - if (z->out.filter) { - switch (z->pattern) { + if (z->out.filter) { + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - ret = zmq_msg_set_group(&m, z->out.filter); - if (ret < 0) - goto fail; - break; + case zeromq::Pattern::RADIODISH: + ret = zmq_msg_set_group(&m, z->out.filter); + if (ret < 0) + goto fail; + break; #endif - case zeromq::Pattern::PUBSUB: // Send envelope - zmq_send(z->out.socket, z->out.filter, strlen(z->out.filter), ZMQ_SNDMORE); - break; - } - } + case zeromq::Pattern::PUBSUB: // Send envelope + zmq_send(z->out.socket, z->out.filter, strlen(z->out.filter), + ZMQ_SNDMORE); + break; + } + } - memcpy(zmq_msg_data(&m), data, wbytes); + memcpy(zmq_msg_data(&m), data, wbytes); - ret = zmq_msg_send(&m, z->out.socket, 0); - if (ret < 0) - goto fail; + ret = zmq_msg_send(&m, z->out.socket, 0); + if (ret < 0) + goto fail; - ret = zmq_msg_close(&m); - if (ret < 0) - return ret; + ret = zmq_msg_close(&m); + if (ret < 0) + return ret; - return cnt; + return cnt; fail: - zmq_msg_close(&m); + zmq_msg_close(&m); - return ret; + return ret; } -int villas::node::zeromq_poll_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_poll_fds(NodeCompat *n, int fds[]) { + int ret; + auto *z = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = zmq_getsockopt(z->in.socket, ZMQ_FD, &fd, &len); - if (ret) - return ret; + ret = zmq_getsockopt(z->in.socket, ZMQ_FD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) { + int ret; + auto *z = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = zmq_getsockopt(z->out.socket, ZMQ_FD, &fd, &len); - if (ret) - return ret; + ret = zmq_getsockopt(z->out.socket, ZMQ_FD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "zeromq"; - p.description = "ZeroMQ Distributed Messaging (libzmq)"; - p.vectorize = 0; - p.size = sizeof(struct zeromq); - p.type.start = zeromq_type_start; - p.type.stop = zeromq_type_stop; - p.init = zeromq_init; - p.destroy = zeromq_destroy; - p.check = zeromq_check; - p.parse = zeromq_parse; - p.print = zeromq_print; - p.start = zeromq_start; - p.stop = zeromq_stop; - p.read = zeromq_read; - p.write = zeromq_write; - p.reverse = zeromq_reverse; - p.poll_fds = zeromq_poll_fds; - p.netem_fds = zeromq_netem_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "zeromq"; + p.description = "ZeroMQ Distributed Messaging (libzmq)"; + p.vectorize = 0; + p.size = sizeof(struct zeromq); + p.type.start = zeromq_type_start; + p.type.stop = zeromq_type_stop; + p.init = zeromq_init; + p.destroy = zeromq_destroy; + p.check = zeromq_check; + p.parse = zeromq_parse; + p.print = zeromq_print; + p.start = zeromq_start; + p.stop = zeromq_stop; + p.read = zeromq_read; + p.write = zeromq_write; + p.reverse = zeromq_reverse; + p.poll_fds = zeromq_poll_fds; + p.netem_fds = zeromq_netem_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/path.cpp b/lib/path.cpp index 4855623b2..9b6207d31 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -5,46 +5,43 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include #include +#include #include #include -#include -#include #include +#include -#include -#include #include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -void * Path::runWrapper(void *arg) -{ - auto *p = (Path *) arg; +void *Path::runWrapper(void *arg) { + auto *p = (Path *)arg; - return p->poll - ? p->runPoll() - : p->runSingle(); + return p->poll ? p->runPoll() : p->runSingle(); } /* Main thread function per path: @@ -55,23 +52,22 @@ void * Path::runWrapper(void *arg) * In this case we case save a call to poll() and directly call * PathSource::read() / Node::read(). */ -void * Path::runSingle() -{ - int ret; - auto ps = sources.front(); // there is only a single source +void *Path::runSingle() { + int ret; + auto ps = sources.front(); // there is only a single source - while (state == State::STARTED) { - pthread_testcancel(); + while (state == State::STARTED) { + pthread_testcancel(); - ret = ps->read(0); - if (ret <= 0) - continue; + ret = ps->read(0); + if (ret <= 0) + continue; - for (auto pd : destinations) - pd->write(); - } + for (auto pd : destinations) + pd->write(); + } - return nullptr; + return nullptr; } /* Main thread function per path: @@ -80,655 +76,626 @@ void * Path::runSingle() * This variant of the path uses poll() to listen on an event from * all path sources. */ -void * Path::runPoll() -{ - while (state == State::STARTED) { - int ret = ::poll(pfds.data(), pfds.size(), -1); - if (ret < 0) - throw SystemError("Failed to poll"); +void *Path::runPoll() { + while (state == State::STARTED) { + int ret = ::poll(pfds.data(), pfds.size(), -1); + if (ret < 0) + throw SystemError("Failed to poll"); - logger->debug("Returned from poll(2): ret={}", ret); + logger->debug("Returned from poll(2): ret={}", ret); - for (unsigned i = 0; i < pfds.size(); i++) { - auto &pfd = pfds[i]; + for (unsigned i = 0; i < pfds.size(); i++) { + auto &pfd = pfds[i]; - if (pfd.revents & POLLIN) { - // Timeout: re-enqueue the last sample - if (pfd.fd == timeout.getFD()) { - timeout.wait(); + if (pfd.revents & POLLIN) { + // Timeout: re-enqueue the last sample + if (pfd.fd == timeout.getFD()) { + timeout.wait(); - last_sample->sequence = last_sequence++; + last_sample->sequence = last_sequence++; - PathDestination::enqueueAll(this, &last_sample, 1); - } - // A source is ready to receive samples - else { - auto ps = sources[i]; + PathDestination::enqueueAll(this, &last_sample, 1); + } + // A source is ready to receive samples + else { + auto ps = sources[i]; - ps->read(i); - } - } - } + ps->read(i); + } + } + } - for (auto pd : destinations) - pd->write(); - } + for (auto pd : destinations) + pd->write(); + } - return nullptr; + return nullptr; } -Path::Path() : - state(State::INITIALIZED), - mode(Mode::ANY), - timeout(CLOCK_MONOTONIC), - rate(0), // Disabled - affinity(0), - enabled(true), - poll(-1), - reversed(false), - builtin(true), - original_sequence_no(-1), - queuelen(DEFAULT_QUEUE_LENGTH), - logger(logging.get(fmt::format("path:{}", id++))) -{ - uuid_clear(uuid); +Path::Path() + : state(State::INITIALIZED), mode(Mode::ANY), timeout(CLOCK_MONOTONIC), + rate(0), // Disabled + affinity(0), enabled(true), poll(-1), reversed(false), builtin(true), + original_sequence_no(-1), queuelen(DEFAULT_QUEUE_LENGTH), + logger(logging.get(fmt::format("path:{}", id++))) { + uuid_clear(uuid); - pool.state = State::DESTROYED; + pool.state = State::DESTROYED; } -void Path::startPoll() -{ - pfds.clear(); +void Path::startPoll() { + pfds.clear(); - for (auto ps : sources) { - auto fds = ps->getNode()->getPollFDs(); - for (auto fd : fds) { - if (fd < 0) - throw RuntimeError("Failed to get file descriptor for node {}", ps->getNode()->getName()); + for (auto ps : sources) { + auto fds = ps->getNode()->getPollFDs(); + for (auto fd : fds) { + if (fd < 0) + throw RuntimeError("Failed to get file descriptor for node {}", + ps->getNode()->getName()); - // This slot is only used if it is not masked - struct pollfd pfd = { - .fd = fd, - .events = POLLIN - }; + // This slot is only used if it is not masked + struct pollfd pfd = {.fd = fd, .events = POLLIN}; - pfds.push_back(pfd); - } - } + pfds.push_back(pfd); + } + } - // We use the last slot for the timeout timer - if (rate > 0) { - timeout.setRate(rate); + // We use the last slot for the timeout timer + if (rate > 0) { + timeout.setRate(rate); - struct pollfd pfd = { - .fd = timeout.getFD(), - .events = POLLIN - }; + struct pollfd pfd = {.fd = timeout.getFD(), .events = POLLIN}; - if (pfd.fd < 0) - throw RuntimeError("Failed to get file descriptor for timer of path {}", this->toString()); + if (pfd.fd < 0) + throw RuntimeError("Failed to get file descriptor for timer of path {}", + this->toString()); - pfds.push_back(pfd); - } + pfds.push_back(pfd); + } } -void Path::prepare(NodeList &nodes) -{ - int ret; +void Path::prepare(NodeList &nodes) { + int ret; - struct memory::Type *pool_mt = memory::default_type; + struct memory::Type *pool_mt = memory::default_type; - assert(state == State::CHECKED); + assert(state == State::CHECKED); - mask.reset(); - signals = std::make_shared(); + mask.reset(); + signals = std::make_shared(); - // Prepare mappings - ret = mappings.prepare(nodes); - if (ret) - throw RuntimeError("Failed to prepare mappings of path: {}", this->toString()); + // Prepare mappings + ret = mappings.prepare(nodes); + if (ret) + throw RuntimeError("Failed to prepare mappings of path: {}", + this->toString()); - // Create path sources - std::map psm; - unsigned i = 0, j = 0; - for (auto me : mappings) { - Node *n = me->node; - PathSource::Ptr ps; + // Create path sources + std::map psm; + unsigned i = 0, j = 0; + for (auto me : mappings) { + Node *n = me->node; + PathSource::Ptr ps; - if (psm.find(n) != psm.end()) - // We already have a path source for this mapping entry - ps = psm[n]; - else { - /* Depending on weather the node belonging to this mapping is already + if (psm.find(n) != psm.end()) + // We already have a path source for this mapping entry + ps = psm[n]; + else { + /* Depending on weather the node belonging to this mapping is already * used by another path or not, we will create a master or secondary * path source. * A secondary path source uses an internal loopback node / queue * to forward samples from on path to another. */ - bool isSecondary = n->sources.size() > 0; + bool isSecondary = n->sources.size() > 0; - // Create new path source - if (isSecondary) { - // Get master path source - auto mps = std::dynamic_pointer_cast(n->sources.front()); - if (!mps) - throw RuntimeError("Failed to find master path source"); + // Create new path source + if (isSecondary) { + // Get master path source + auto mps = + std::dynamic_pointer_cast(n->sources.front()); + if (!mps) + throw RuntimeError("Failed to find master path source"); - auto sps = std::make_shared(this, n, nodes, mps); - if (!sps) - throw MemoryAllocationError(); + auto sps = std::make_shared(this, n, nodes, mps); + if (!sps) + throw MemoryAllocationError(); - mps->addSecondary(sps); + mps->addSecondary(sps); - ps = sps; - } - else { - ps = std::make_shared(this, n); - if (!ps) - throw MemoryAllocationError(); - } + ps = sps; + } else { + ps = std::make_shared(this, n); + if (!ps) + throw MemoryAllocationError(); + } - if (masked.empty() || std::find(masked.begin(), masked.end(), n) != masked.end()) { - ps->masked = true; - mask.set(j); - } + if (masked.empty() || + std::find(masked.begin(), masked.end(), n) != masked.end()) { + ps->masked = true; + mask.set(j); + } - /* Get the real node backing this path source + /* Get the real node backing this path source * In case of a secondary path source, its the internal loopback node! */ - auto *rn = ps->getNode(); + auto *rn = ps->getNode(); - rn->sources.push_back(ps); + rn->sources.push_back(ps); - sources.push_back(ps); - j++; - psm[n] = ps; - } + sources.push_back(ps); + j++; + psm[n] = ps; + } - SignalList::Ptr sigs = me->node->getInputSignals(); + SignalList::Ptr sigs = me->node->getInputSignals(); - // Update signals of path - for (unsigned j = 0; j < (unsigned) me->length; j++) { - Signal::Ptr sig; + // Update signals of path + for (unsigned j = 0; j < (unsigned)me->length; j++) { + Signal::Ptr sig; - /* For data mappings we simple refer to the existing + /* For data mappings we simple refer to the existing * signal descriptors of the source node. */ - if (me->type == MappingEntry::Type::DATA) { - sig = sigs->getByIndex(me->data.offset + j); - if (!sig) { - logger->warn("Failed to create signal description for path {}", this->toString()); - continue; - } - } - // For other mappings we create new signal descriptors - else { - sig = me->toSignal(j); - if (!sig) - throw RuntimeError("Failed to create signal from mapping"); - } + if (me->type == MappingEntry::Type::DATA) { + sig = sigs->getByIndex(me->data.offset + j); + if (!sig) { + logger->warn("Failed to create signal description for path {}", + this->toString()); + continue; + } + } + // For other mappings we create new signal descriptors + else { + sig = me->toSignal(j); + if (!sig) + throw RuntimeError("Failed to create signal from mapping"); + } - signals->resize(me->offset + j + 1); - (*signals)[me->offset + j] = sig; - } + signals->resize(me->offset + j + 1); + (*signals)[me->offset + j] = sig; + } - ps->mappings.push_back(me); - i++; - } + ps->mappings.push_back(me); + i++; + } - // Prepare path destinations - int mt_cnt = 0; - for (auto pd : destinations) { - auto *pd_mt = pd->node->getMemoryType(); - if (pd_mt != pool_mt) { - if (mt_cnt > 0) { - throw RuntimeError("Mixed memory types between path destinations"); - } + // Prepare path destinations + int mt_cnt = 0; + for (auto pd : destinations) { + auto *pd_mt = pd->node->getMemoryType(); + if (pd_mt != pool_mt) { + if (mt_cnt > 0) { + throw RuntimeError("Mixed memory types between path destinations"); + } - pool_mt = pd_mt; - mt_cnt++; - } + pool_mt = pd_mt; + mt_cnt++; + } - ret = pd->prepare(queuelen); - if (ret) - throw RuntimeError("Failed to prepare path destination {} of path {}", pd->node->getName(), this->toString()); - } + ret = pd->prepare(queuelen); + if (ret) + throw RuntimeError("Failed to prepare path destination {} of path {}", + pd->node->getName(), this->toString()); + } - // Autodetect whether to use original sequence numbers or not - if (original_sequence_no == -1) - original_sequence_no = sources.size() == 1; + // Autodetect whether to use original sequence numbers or not + if (original_sequence_no == -1) + original_sequence_no = sources.size() == 1; - // Autodetect whether to use poll() for this path or not - if (poll == -1) { - if (rate > 0) - poll = 1; - else if (sources.size()> 1) - poll = 1; - else - poll = 0; - } + // Autodetect whether to use poll() for this path or not + if (poll == -1) { + if (rate > 0) + poll = 1; + else if (sources.size() > 1) + poll = 1; + else + poll = 0; + } #ifdef WITH_HOOKS - // Prepare path hooks - int m = builtin - ? (int) Hook::Flags::PATH | - (int) Hook::Flags::BUILTIN - : 0; + // Prepare path hooks + int m = builtin ? (int)Hook::Flags::PATH | (int)Hook::Flags::BUILTIN : 0; - // Add internal hooks if they are not already in the list - hooks.prepare(signals, m, this, nullptr); - hooks.dump(logger, fmt::format("path {}", this->toString())); + // Add internal hooks if they are not already in the list + hooks.prepare(signals, m, this, nullptr); + hooks.dump(logger, fmt::format("path {}", this->toString())); #endif // WITH_HOOKS - // Prepare pool - auto osigs = getOutputSignals(); - unsigned pool_size = MAX(1UL, destinations.size()) * queuelen; + // Prepare pool + auto osigs = getOutputSignals(); + unsigned pool_size = MAX(1UL, destinations.size()) * queuelen; - ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(osigs->size()), pool_mt); - if (ret) - throw RuntimeError("Failed to initialize pool of path: {}", this->toString()); + ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(osigs->size()), pool_mt); + if (ret) + throw RuntimeError("Failed to initialize pool of path: {}", + this->toString()); - logger->debug("Prepared path {} with {} output signals:", this->toString(), osigs->size()); - if (logger->level() <= spdlog::level::debug) - osigs->dump(logger); + logger->debug("Prepared path {} with {} output signals:", this->toString(), + osigs->size()); + if (logger->level() <= spdlog::level::debug) + osigs->dump(logger); - checkPrepared(); + checkPrepared(); - state = State::PREPARED; + state = State::PREPARED; } -void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) -{ - int ret, en = -1, rev = -1; +void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) { + int ret, en = -1, rev = -1; - json_error_t err; - json_t *json_in; - json_t *json_out = nullptr; - json_t *json_hooks = nullptr; - json_t *json_mask = nullptr; + json_error_t err; + json_t *json_in; + json_t *json_out = nullptr; + json_t *json_hooks = nullptr; + json_t *json_mask = nullptr; - const char *mode_str = nullptr; - const char *uuid_str = nullptr; + const char *mode_str = nullptr; + const char *uuid_str = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: o, s?: o, s?: b, s?: b, s?: b, s?: i, s?: s, s?: b, s?: F, s?: o, s?: b, s?: s, s?: i }", - "in", &json_in, - "out", &json_out, - "hooks", &json_hooks, - "reverse", &rev, - "enabled", &en, - "builtin", &builtin, - "queuelen", &queuelen, - "mode", &mode_str, - "poll", &poll, - "rate", &rate, - "mask", &json_mask, - "original_sequence_no", &original_sequence_no, - "uuid", &uuid_str, - "affinity", &affinity - ); - if (ret) - throw ConfigError(json, err, "node-config-path", "Failed to parse path configuration"); + ret = json_unpack_ex(json, &err, 0, + "{ s: o, s?: o, s?: o, s?: b, s?: b, s?: b, s?: i, s?: " + "s, s?: b, s?: F, s?: o, s?: b, s?: s, s?: i }", + "in", &json_in, "out", &json_out, "hooks", &json_hooks, + "reverse", &rev, "enabled", &en, "builtin", &builtin, + "queuelen", &queuelen, "mode", &mode_str, "poll", &poll, + "rate", &rate, "mask", &json_mask, + "original_sequence_no", &original_sequence_no, "uuid", + &uuid_str, "affinity", &affinity); + if (ret) + throw ConfigError(json, err, "node-config-path", + "Failed to parse path configuration"); - if (en >= 0) - enabled = en != 0; + if (en >= 0) + enabled = en != 0; - if (rev >= 0) - reversed = rev != 0; + if (rev >= 0) + reversed = rev != 0; - // Optional settings - if (mode_str) { - if (!strcmp(mode_str, "any")) - mode = Mode::ANY; - else if (!strcmp(mode_str, "all")) - mode = Mode::ALL; - else - throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", mode_str); - } + // Optional settings + if (mode_str) { + if (!strcmp(mode_str, "any")) + mode = Mode::ANY; + else if (!strcmp(mode_str, "all")) + mode = Mode::ALL; + else + throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", + mode_str); + } - // UUID - if (uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(json, "node-config-path-uuid", "Failed to parse UUID: {}", uuid_str); - } - else - // Generate UUID from hashed config - uuid::generateFromJson(uuid, json, sn_uuid); + // UUID + if (uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(json, "node-config-path-uuid", + "Failed to parse UUID: {}", uuid_str); + } else + // Generate UUID from hashed config + uuid::generateFromJson(uuid, json, sn_uuid); - // Input node(s) - ret = mappings.parse(json_in); - if (ret) - throw ConfigError(json_in, "node-config-path-in", "Failed to parse input mapping of path {}", this->toString()); + // Input node(s) + ret = mappings.parse(json_in); + if (ret) + throw ConfigError(json_in, "node-config-path-in", + "Failed to parse input mapping of path {}", + this->toString()); - // Output node(s) - NodeList dests; - if (json_out) { - ret = dests.parse(json_out, nodes); - if (ret) - throw ConfigError(json_out, "node-config-path-out", "Failed to parse output nodes"); - } + // Output node(s) + NodeList dests; + if (json_out) { + ret = dests.parse(json_out, nodes); + if (ret) + throw ConfigError(json_out, "node-config-path-out", + "Failed to parse output nodes"); + } - for (auto *n : dests) { - if (n->out.path) - throw ConfigError(json, "node-config-path", "Every node must only be used by a single path as destination"); + for (auto *n : dests) { + if (n->out.path) + throw ConfigError( + json, "node-config-path", + "Every node must only be used by a single path as destination"); - n->out.path = this; + n->out.path = this; - auto pd = std::make_shared(this, n); - if (!pd) - throw MemoryAllocationError(); + auto pd = std::make_shared(this, n); + if (!pd) + throw MemoryAllocationError(); - n->destinations.push_back(pd); - destinations.push_back(pd); - } + n->destinations.push_back(pd); + destinations.push_back(pd); + } #ifdef WITH_HOOKS - if (json_hooks) - hooks.parse(json_hooks, (int) Hook::Flags::PATH, this, nullptr); + if (json_hooks) + hooks.parse(json_hooks, (int)Hook::Flags::PATH, this, nullptr); #endif // WITH_HOOKS - if (json_mask) - parseMask(json_mask, nodes); + if (json_mask) + parseMask(json_mask, nodes); - config = json; - state = State::PARSED; + config = json; + state = State::PARSED; } -void Path::parseMask(json_t *json_mask, NodeList &nodes) -{ - json_t *json_entry; - size_t i; +void Path::parseMask(json_t *json_mask, NodeList &nodes) { + json_t *json_entry; + size_t i; - if (!json_is_array(json_mask)) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' setting must be a list of node names"); + if (!json_is_array(json_mask)) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' setting must be a list of node names"); - json_array_foreach(json_mask, i, json_entry) { - const char *name; - Node *node; + json_array_foreach(json_mask, i, json_entry) { + const char *name; + Node *node; - name = json_string_value(json_entry); - if (!name) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' setting must be a list of node names"); + name = json_string_value(json_entry); + if (!name) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' setting must be a list of node names"); - node = nodes.lookup(name); - if (!node) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' entry '{}' is not a valid node name", name); + node = nodes.lookup(name); + if (!node) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' entry '{}' is not a valid node name", name); - masked.push_back(node); - } + masked.push_back(node); + } } -void Path::check() -{ - assert(state != State::DESTROYED); +void Path::check() { + assert(state != State::DESTROYED); - if (rate < 0) - throw RuntimeError("Setting 'rate' of path {} must be a positive number.", this->toString()); + if (rate < 0) + throw RuntimeError("Setting 'rate' of path {} must be a positive number.", + this->toString()); - if (!IS_POW2(queuelen)) { - queuelen = LOG2_CEIL(queuelen); - logger->warn("Queue length should always be a power of 2. Adjusting to {}", queuelen); - } + if (!IS_POW2(queuelen)) { + queuelen = LOG2_CEIL(queuelen); + logger->warn("Queue length should always be a power of 2. Adjusting to {}", + queuelen); + } #ifdef WITH_HOOKS - hooks.check(); + hooks.check(); #endif // WITH_HOOKS - state = State::CHECKED; + state = State::CHECKED; } -void Path::checkPrepared() -{ - if (poll == 0) { - // Check that we do not need to multiplex between multiple sources when polling is disabled - if (sources.size() > 1) - throw RuntimeError("Setting 'poll' must be active if the path has more than one source"); +void Path::checkPrepared() { + if (poll == 0) { + // Check that we do not need to multiplex between multiple sources when polling is disabled + if (sources.size() > 1) + throw RuntimeError( + "Setting 'poll' must be active if the path has more than one source"); - // Check that we do not use the fixed rate feature when polling is disabled - if (rate > 0) - throw RuntimeError("Setting 'poll' must be activated when used together with setting 'rate'"); - } - else { - if (rate <= 0) { - // Check that all path sources provide a file descriptor for polling if fixed rate is disabled - for (auto ps : sources) { - if (!(ps->getNode()->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_POLL)) - throw RuntimeError("Node {} can not be used in polling mode with path {}", ps->getNode()->getName(), this->toString()); - } - } - } + // Check that we do not use the fixed rate feature when polling is disabled + if (rate > 0) + throw RuntimeError("Setting 'poll' must be activated when used together " + "with setting 'rate'"); + } else { + if (rate <= 0) { + // Check that all path sources provide a file descriptor for polling if fixed rate is disabled + for (auto ps : sources) { + if (!(ps->getNode()->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_POLL)) + throw RuntimeError( + "Node {} can not be used in polling mode with path {}", + ps->getNode()->getName(), this->toString()); + } + } + } } -void Path::start() -{ - int ret; - const char *mode_str; +void Path::start() { + int ret; + const char *mode_str; - assert(state == State::PREPARED); + assert(state == State::PREPARED); - switch (mode) { - case Mode::ANY: - mode_str = "any"; - break; + switch (mode) { + case Mode::ANY: + mode_str = "any"; + break; - case Mode::ALL: - mode_str = "all"; - break; + case Mode::ALL: + mode_str = "all"; + break; - default: - mode_str = "unknown"; - break; - } + default: + mode_str = "unknown"; + break; + } - logger->info("Starting path {}: #signals={}/{}, #hooks={}, #sources={}, " - "#destinations={}, mode={}, poll={}, mask=0b{:b}, rate={}, " - "enabled={}, reversed={}, queuelen={}, original_sequence_no={}", - this->toString(), - signals->size(), - getOutputSignals()->size(), - hooks.size(), - sources.size(), - destinations.size(), - mode_str, - poll ? "yes" : "no", - mask.to_ullong(), - rate, - isEnabled() ? "yes" : "no", - isReversed() ? "yes" : "no", - queuelen, - original_sequence_no ? "yes" : "no" - ); + logger->info("Starting path {}: #signals={}/{}, #hooks={}, #sources={}, " + "#destinations={}, mode={}, poll={}, mask=0b{:b}, rate={}, " + "enabled={}, reversed={}, queuelen={}, original_sequence_no={}", + this->toString(), signals->size(), getOutputSignals()->size(), + hooks.size(), sources.size(), destinations.size(), mode_str, + poll ? "yes" : "no", mask.to_ullong(), rate, + isEnabled() ? "yes" : "no", isReversed() ? "yes" : "no", + queuelen, original_sequence_no ? "yes" : "no"); #ifdef WITH_HOOKS - hooks.start(); + hooks.start(); #endif // WITH_HOOKS - last_sequence = 0; + last_sequence = 0; - received.reset(); + received.reset(); - // We initialize the intial sample - last_sample = sample_alloc(&pool); - if (!last_sample) - throw MemoryAllocationError(); + // We initialize the intial sample + last_sample = sample_alloc(&pool); + if (!last_sample) + throw MemoryAllocationError(); - last_sample->length = signals->size(); - last_sample->signals = signals; + last_sample->length = signals->size(); + last_sample->signals = signals; - last_sample->ts.origin = time_now(); - last_sample->flags = (int) SampleFlags::HAS_TS_ORIGIN; + last_sample->ts.origin = time_now(); + last_sample->flags = (int)SampleFlags::HAS_TS_ORIGIN; - last_sample->sequence = 0; - last_sample->flags |= (int) SampleFlags::HAS_SEQUENCE; + last_sample->sequence = 0; + last_sample->flags |= (int)SampleFlags::HAS_SEQUENCE; - if (last_sample->length > 0) - last_sample->flags |= (int) SampleFlags::HAS_DATA; + if (last_sample->length > 0) + last_sample->flags |= (int)SampleFlags::HAS_DATA; - for (size_t i = 0; i < last_sample->length; i++) { - auto sig = signals->getByIndex(i); + for (size_t i = 0; i < last_sample->length; i++) { + auto sig = signals->getByIndex(i); - last_sample->data[i] = sig->init; - } + last_sample->data[i] = sig->init; + } - if (poll > 0) - startPoll(); + if (poll > 0) + startPoll(); - state = State::STARTED; + state = State::STARTED; - /* Start one thread per path for sending to destinations + /* Start one thread per path for sending to destinations * * Special case: If the path only has a single source and this source * does not offer a file descriptor for polling, we will use a special * thread function. */ - ret = pthread_create(&tid, nullptr, runWrapper, this); - if (ret) - throw RuntimeError("Failed to create path thread"); + ret = pthread_create(&tid, nullptr, runWrapper, this); + if (ret) + throw RuntimeError("Failed to create path thread"); - if (affinity) - kernel::rt::setThreadAffinity(tid, affinity); + if (affinity) + kernel::rt::setThreadAffinity(tid, affinity); } -void Path::stop() -{ - int ret; +void Path::stop() { + int ret; - if (state != State::STARTED && - state != State::STOPPING) - return; + if (state != State::STARTED && state != State::STOPPING) + return; - logger->info("Stopping path: {}", this->toString()); + logger->info("Stopping path: {}", this->toString()); - if (state != State::STOPPING) - state = State::STOPPING; + if (state != State::STOPPING) + state = State::STOPPING; - /* Cancel the thread in case is currently in a blocking syscall. + /* Cancel the thread in case is currently in a blocking syscall. * * We dont care if the thread has already been terminated. */ - ret = pthread_cancel(tid); - if (ret && ret != ESRCH) - throw RuntimeError("Failed to cancel path thread"); + ret = pthread_cancel(tid); + if (ret && ret != ESRCH) + throw RuntimeError("Failed to cancel path thread"); - ret = pthread_join(tid, nullptr); - if (ret) - throw RuntimeError("Failed to join path thread"); + ret = pthread_join(tid, nullptr); + if (ret) + throw RuntimeError("Failed to join path thread"); #ifdef WITH_HOOKS - hooks.stop(); + hooks.stop(); #endif // WITH_HOOKS - sample_decref(last_sample); + sample_decref(last_sample); - state = State::STOPPED; + state = State::STOPPED; } -Path::~Path() -{ - int ret __attribute__((unused)); +Path::~Path() { + int ret __attribute__((unused)); - assert(state != State::DESTROYED); + assert(state != State::DESTROYED); - ret = pool_destroy(&pool); + ret = pool_destroy(&pool); } -bool Path::isSimple() const -{ - int ret; - const char *in = nullptr, *out = nullptr; +bool Path::isSimple() const { + int ret; + const char *in = nullptr, *out = nullptr; - json_error_t err; - ret = json_unpack_ex(config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); - if (ret) - return false; + json_error_t err; + ret = + json_unpack_ex(config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); + if (ret) + return false; - ret = Node::isValidName(in); - if (!ret) - return false; + ret = Node::isValidName(in); + if (!ret) + return false; - ret = Node::isValidName(out); - if (!ret) - return false; + ret = Node::isValidName(out); + if (!ret) + return false; - return true; + return true; } -bool Path::isMuxed() const -{ - if (sources.size() > 0) - return true; +bool Path::isMuxed() const { + if (sources.size() > 0) + return true; - if (mappings.size() > 0) - return true; + if (mappings.size() > 0) + return true; - auto me = mappings.front(); + auto me = mappings.front(); - if (me->type != MappingEntry::Type::DATA) - return true; + if (me->type != MappingEntry::Type::DATA) + return true; - if (me->data.offset != 0) - return true; + if (me->data.offset != 0) + return true; - if (me->length != -1) - return true; + if (me->length != -1) + return true; - return false; + return false; } -SignalList::Ptr Path::getOutputSignals(bool after_hooks) -{ +SignalList::Ptr Path::getOutputSignals(bool after_hooks) { #ifdef WITH_HOOKS - if (after_hooks && hooks.size() > 0) - return hooks.getSignals(); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif // WITH_HOOKS - return signals; + return signals; } -unsigned Path::getOutputSignalsMaxCount() -{ +unsigned Path::getOutputSignalsMaxCount() { #ifdef WITH_HOOKS - if (hooks.size() > 0) - return MAX(signals->size(), hooks.getSignalsMaxCount()); + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif // WITH_HOOKS - return signals->size(); + return signals->size(); } -json_t * Path::toJson() const -{ - json_t *json_signals = signals->toJson(); +json_t *Path::toJson() const { + json_t *json_signals = signals->toJson(); #ifdef WITH_HOOKS - json_t *json_hooks = hooks.toJson(); + json_t *json_hooks = hooks.toJson(); #else - json_t *json_hooks = json_array(); + json_t *json_hooks = json_array(); #endif // WITH_HOOKS - json_t *json_sources = json_array(); - json_t *json_destinations = json_array(); + json_t *json_sources = json_array(); + json_t *json_destinations = json_array(); - for (auto ps : sources) - json_array_append_new(json_sources, json_string(ps->node->getNameShort().c_str())); + for (auto ps : sources) + json_array_append_new(json_sources, + json_string(ps->node->getNameShort().c_str())); - for (auto pd : destinations) - json_array_append_new(json_destinations, json_string(pd->node->getNameShort().c_str())); + for (auto pd : destinations) + json_array_append_new(json_destinations, + json_string(pd->node->getNameShort().c_str())); - json_t *json_path = json_pack("{ s: s, s: s, s: s, s: b, s: b s: b, s: b, s: b, s: b s: i, s: o, s: o, s: o, s: o }", - "uuid", uuid::toString(uuid).c_str(), - "state", stateToString(state).c_str(), - "mode", mode == Mode::ANY ? "any" : "all", - "enabled", enabled, - "builtin", builtin, - "reversed", reversed, - "original_sequence_no", original_sequence_no, - "last_sequence", last_sequence, - "poll", poll, - "queuelen", queuelen, - "signals", json_signals, - "hooks", json_hooks, - "in", json_sources, - "out", json_destinations - ); + json_t *json_path = json_pack( + "{ s: s, s: s, s: s, s: b, s: b s: b, s: b, s: b, s: b s: i, s: o, s: o, " + "s: o, s: o }", + "uuid", uuid::toString(uuid).c_str(), "state", + stateToString(state).c_str(), "mode", mode == Mode::ANY ? "any" : "all", + "enabled", enabled, "builtin", builtin, "reversed", reversed, + "original_sequence_no", original_sequence_no, "last_sequence", + last_sequence, "poll", poll, "queuelen", queuelen, "signals", + json_signals, "hooks", json_hooks, "in", json_sources, "out", + json_destinations); - return json_path; + return json_path; } int villas::node::Path::id = 0; diff --git a/lib/path_destination.cpp b/lib/path_destination.cpp index 08535ad9c..c51332955 100644 --- a/lib/path_destination.cpp +++ b/lib/path_destination.cpp @@ -5,103 +5,105 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include #include +#include +#include +#include #include +#include +#include using namespace villas; using namespace villas::node; -PathDestination::PathDestination(Path *p, Node *n) : - node(n), - path(p) -{ - queue.state = State::DESTROYED; +PathDestination::PathDestination(Path *p, Node *n) : node(n), path(p) { + queue.state = State::DESTROYED; } -PathDestination::~PathDestination() -{ - int ret __attribute__((unused)); +PathDestination::~PathDestination() { + int ret __attribute__((unused)); - ret = queue_destroy(&queue); + ret = queue_destroy(&queue); } -int PathDestination::prepare(int queuelen) -{ - int ret; +int PathDestination::prepare(int queuelen) { + int ret; - ret = queue_init(&queue, queuelen); - if (ret) - return ret; + ret = queue_init(&queue, queuelen); + if (ret) + return ret; - return 0; + return 0; } -void PathDestination::enqueueAll(Path *p, const struct Sample * const smps[], unsigned cnt) -{ - unsigned enqueued, cloned; +void PathDestination::enqueueAll(Path *p, const struct Sample *const smps[], + unsigned cnt) { + unsigned enqueued, cloned; - struct Sample *clones[cnt]; + struct Sample *clones[cnt]; - cloned = sample_clone_many(clones, smps, cnt); - if (cloned < cnt) - p->logger->warn("Pool underrun in path {}", p->toString()); + cloned = sample_clone_many(clones, smps, cnt); + if (cloned < cnt) + p->logger->warn("Pool underrun in path {}", p->toString()); - for (auto pd : p->destinations) { - enqueued = queue_push_many(&pd->queue, (void **) clones, cloned); - if (enqueued != cnt) - p->logger->warn("Queue overrun for path {}", p->toString()); + for (auto pd : p->destinations) { + enqueued = queue_push_many(&pd->queue, (void **)clones, cloned); + if (enqueued != cnt) + p->logger->warn("Queue overrun for path {}", p->toString()); - // Increase reference counter of these samples as they are now also owned by the queue - sample_incref_many(clones, cloned); + // Increase reference counter of these samples as they are now also owned by the queue + sample_incref_many(clones, cloned); - p->logger->debug("Enqueued {} samples to destination {} of path {}", enqueued, pd->node->getName(), p->toString()); - } + p->logger->debug("Enqueued {} samples to destination {} of path {}", + enqueued, pd->node->getName(), p->toString()); + } - sample_decref_many(clones, cloned); + sample_decref_many(clones, cloned); } -void PathDestination::write() -{ - int cnt = node->out.vectorize; - int sent; - int allocated; +void PathDestination::write() { + int cnt = node->out.vectorize; + int sent; + int allocated; - struct Sample *smps[cnt]; + struct Sample *smps[cnt]; - // As long as there are still samples in the queue - while (true) { - allocated = queue_pull_many(&queue, (void **) smps, cnt); - if (allocated == 0) - break; - else if (allocated < cnt) - path->logger->debug("Queue underrun for path {}: allocated={} expected={}", path->toString(), allocated, cnt); + // As long as there are still samples in the queue + while (true) { + allocated = queue_pull_many(&queue, (void **)smps, cnt); + if (allocated == 0) + break; + else if (allocated < cnt) + path->logger->debug( + "Queue underrun for path {}: allocated={} expected={}", + path->toString(), allocated, cnt); - path->logger->debug("Dequeued {} samples from queue of node {} which is part of path {}", allocated, node->getName(), path->toString()); + path->logger->debug( + "Dequeued {} samples from queue of node {} which is part of path {}", + allocated, node->getName(), path->toString()); - sent = node->write(smps, allocated); - if (sent < 0) { - path->logger->error("Failed to sent {} samples to node {}: reason={}", cnt, node->getName(), sent); - return; - } - else if (sent < allocated) - path->logger->debug("Partial write to node {}: written={}, expected={}", node->getName(), sent, allocated); + sent = node->write(smps, allocated); + if (sent < 0) { + path->logger->error("Failed to sent {} samples to node {}: reason={}", + cnt, node->getName(), sent); + return; + } else if (sent < allocated) + path->logger->debug("Partial write to node {}: written={}, expected={}", + node->getName(), sent, allocated); - int released = sample_decref_many(smps, allocated); + int released = sample_decref_many(smps, allocated); - path->logger->debug("Released {} samples back to memory pool", released); - } + path->logger->debug("Released {} samples back to memory pool", released); + } } -void PathDestination::check() -{ - if (!node->isEnabled()) - throw RuntimeError("Destination {} is not enabled", node->getName()); +void PathDestination::check() { + if (!node->isEnabled()) + throw RuntimeError("Destination {} is not enabled", node->getName()); - if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_WRITE)) - throw RuntimeError("Destination node {} is not supported as a sink for path ", node->getName()); + if (!(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_WRITE)) + throw RuntimeError( + "Destination node {} is not supported as a sink for path ", + node->getName()); } diff --git a/lib/path_list.cpp b/lib/path_list.cpp index b2b8214da..deff55c26 100644 --- a/lib/path_list.cpp +++ b/lib/path_list.cpp @@ -5,27 +5,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas::node; -Path * PathList::lookup(const uuid_t &uuid) const -{ - for (auto *p : *this) { - if (!uuid_compare(uuid, p->uuid)) - return p; - } +Path *PathList::lookup(const uuid_t &uuid) const { + for (auto *p : *this) { + if (!uuid_compare(uuid, p->uuid)) + return p; + } - return nullptr; + return nullptr; } -json_t * PathList::toJson() const -{ - json_t *json_paths = json_array(); +json_t *PathList::toJson() const { + json_t *json_paths = json_array(); - for (auto *p : *this) - json_array_append_new(json_paths, p->toJson()); + for (auto *p : *this) + json_array_append_new(json_paths, p->toJson()); - return json_paths; + return json_paths; } diff --git a/lib/path_source.cpp b/lib/path_source.cpp index 8e6922648..ec138e71d 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -7,12 +7,12 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include @@ -22,201 +22,195 @@ using namespace villas; using namespace villas::node; -PathSource::PathSource(Path *p, Node *n) : - node(n), - path(p), - masked(false) -{ - int ret; +PathSource::PathSource(Path *p, Node *n) : node(n), path(p), masked(false) { + int ret; - int pool_size = MAX(DEFAULT_QUEUE_LENGTH, 20 * node->in.vectorize); - ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(node->getInputSignalsMaxCount()), node->getMemoryType()); - if (ret) - throw RuntimeError("Failed to initialize pool"); + int pool_size = MAX(DEFAULT_QUEUE_LENGTH, 20 * node->in.vectorize); + ret = pool_init(&pool, pool_size, + SAMPLE_LENGTH(node->getInputSignalsMaxCount()), + node->getMemoryType()); + if (ret) + throw RuntimeError("Failed to initialize pool"); } -PathSource::~PathSource() -{ - int ret __attribute__((unused)); +PathSource::~PathSource() { + int ret __attribute__((unused)); - ret = pool_destroy(&pool); + ret = pool_destroy(&pool); } -int PathSource::read(int i) -{ - int ret, recv, tomux, allocated, cnt, toenqueue, enqueued = 0, muxed_initialized = 0; +int PathSource::read(int i) { + int ret, recv, tomux, allocated, cnt, toenqueue, enqueued = 0, + muxed_initialized = 0; - cnt = node->in.vectorize; + cnt = node->in.vectorize; - struct Sample *read_smps[cnt]; - struct Sample *muxed_smps[cnt]; - struct Sample **tomux_smps; + struct Sample *read_smps[cnt]; + struct Sample *muxed_smps[cnt]; + struct Sample **tomux_smps; - // Fill smps[] free sample blocks from the pool - allocated = sample_alloc_many(&pool, read_smps, cnt); - if (allocated != cnt) - path->logger->warn("Pool underrun for path source {}", node->getName()); + // Fill smps[] free sample blocks from the pool + allocated = sample_alloc_many(&pool, read_smps, cnt); + if (allocated != cnt) + path->logger->warn("Pool underrun for path source {}", node->getName()); - // Read ready samples and store them to blocks pointed by smps[] - recv = node->read(read_smps, allocated); - if (recv == 0) { - enqueued = 0; - goto read_decref_read_smps; - } - else if (recv < 0) { - if (node->getState() == State::STOPPING) { - path->state = State::STOPPING; + // Read ready samples and store them to blocks pointed by smps[] + recv = node->read(read_smps, allocated); + if (recv == 0) { + enqueued = 0; + goto read_decref_read_smps; + } else if (recv < 0) { + if (node->getState() == State::STOPPING) { + path->state = State::STOPPING; - enqueued = -1; - goto read_decref_read_smps; - } - else { - path->logger->error("Failed to read samples from node {}", node->getName()); - enqueued = 0; - goto read_decref_read_smps; - } - } - else if (recv < allocated) - path->logger->warn("Partial read for path {}: read={}, expected={}", path->toString(), recv, allocated); + enqueued = -1; + goto read_decref_read_smps; + } else { + path->logger->error("Failed to read samples from node {}", + node->getName()); + enqueued = 0; + goto read_decref_read_smps; + } + } else if (recv < allocated) + path->logger->warn("Partial read for path {}: read={}, expected={}", + path->toString(), recv, allocated); - // Let the master path sources forward received samples to their secondaries - writeToSecondaries(read_smps, recv); + // Let the master path sources forward received samples to their secondaries + writeToSecondaries(read_smps, recv); - if (path->mode == Path::Mode::ANY) { // Mux all samples - tomux_smps = read_smps; - tomux = recv; - } - else { // Mux only last sample and discard others - tomux_smps = read_smps + recv - 1; - tomux = 1; - } + if (path->mode == Path::Mode::ANY) { // Mux all samples + tomux_smps = read_smps; + tomux = recv; + } else { // Mux only last sample and discard others + tomux_smps = read_smps + recv - 1; + tomux = 1; + } - for (int i = 0; i < tomux; i++) { - muxed_smps[i] = i == 0 - ? sample_clone(path->last_sample) - : sample_clone(muxed_smps[i-1]); - if (!muxed_smps[i]) { - path->logger->error("Pool underrun in path {}", path->toString()); - muxed_initialized = i == 0 ? 0 : i-1; - enqueued = -1; - goto read_decref_muxed_smps; - } + for (int i = 0; i < tomux; i++) { + muxed_smps[i] = i == 0 ? sample_clone(path->last_sample) + : sample_clone(muxed_smps[i - 1]); + if (!muxed_smps[i]) { + path->logger->error("Pool underrun in path {}", path->toString()); + muxed_initialized = i == 0 ? 0 : i - 1; + enqueued = -1; + goto read_decref_muxed_smps; + } - if (path->original_sequence_no) { - muxed_smps[i]->sequence = tomux_smps[i]->sequence; - muxed_smps[i]->flags |= tomux_smps[i]->flags & (int) SampleFlags::HAS_SEQUENCE; - } - else { - muxed_smps[i]->sequence = path->last_sequence++; - muxed_smps[i]->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (path->original_sequence_no) { + muxed_smps[i]->sequence = tomux_smps[i]->sequence; + muxed_smps[i]->flags |= + tomux_smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE; + } else { + muxed_smps[i]->sequence = path->last_sequence++; + muxed_smps[i]->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - /* We reset the sample length after each restart of the simulation. + /* We reset the sample length after each restart of the simulation. * This is necessary for the test_rtt node to work properly. */ - if (tomux_smps[i]->flags & (int) SampleFlags::IS_FIRST) - muxed_smps[i]->length = 0; + if (tomux_smps[i]->flags & (int)SampleFlags::IS_FIRST) + muxed_smps[i]->length = 0; - muxed_smps[i]->ts = tomux_smps[i]->ts; - muxed_smps[i]->flags |= tomux_smps[i]->flags & (int) SampleFlags::HAS_TS; + muxed_smps[i]->ts = tomux_smps[i]->ts; + muxed_smps[i]->flags |= tomux_smps[i]->flags & (int)SampleFlags::HAS_TS; - ret = mappings.remap(muxed_smps[i], tomux_smps[i]); - if (ret < 0) { - enqueued = ret; - muxed_initialized = i; - goto read_decref_muxed_smps; - } + ret = mappings.remap(muxed_smps[i], tomux_smps[i]); + if (ret < 0) { + enqueued = ret; + muxed_initialized = i; + goto read_decref_muxed_smps; + } - if (muxed_smps[i]->length > 0) - muxed_smps[i]->flags |= (int) SampleFlags::HAS_DATA; - } - muxed_initialized = tomux; + if (muxed_smps[i]->length > 0) + muxed_smps[i]->flags |= (int)SampleFlags::HAS_DATA; + } + muxed_initialized = tomux; - sample_copy(path->last_sample, muxed_smps[tomux-1]); + sample_copy(path->last_sample, muxed_smps[tomux - 1]); #ifdef WITH_HOOKS - toenqueue = path->hooks.process(muxed_smps, tomux); - if (toenqueue == -1) { - path->logger->error("An error occured during hook processing. Skipping sample"); + toenqueue = path->hooks.process(muxed_smps, tomux); + if (toenqueue == -1) { + path->logger->error( + "An error occured during hook processing. Skipping sample"); - } - else if (toenqueue != tomux) { - int skipped = tomux - toenqueue; + } else if (toenqueue != tomux) { + int skipped = tomux - toenqueue; - path->logger->debug("Hooks skipped {} out of {} samples for path {}", skipped, tomux, path->toString()); - } + path->logger->debug("Hooks skipped {} out of {} samples for path {}", + skipped, tomux, path->toString()); + } #else - toenqueue = tomux; + toenqueue = tomux; #endif - path->received.set(i); + path->received.set(i); - path->logger->debug("received=0b{:b}, mask=0b{:b}", path->received.to_ullong(), path->mask.to_ullong()); + path->logger->debug("received=0b{:b}, mask=0b{:b}", + path->received.to_ullong(), path->mask.to_ullong()); - if (path->mask.test(i)) { - // Enqueue always - if (path->mode == Path::Mode::ANY) { - enqueued = toenqueue; - PathDestination::enqueueAll(path, muxed_smps, toenqueue); - } - // Enqueue only if received == mask bitset - else if (path->mode == Path::Mode::ALL) { - if (path->mask == path->received) { - PathDestination::enqueueAll(path, muxed_smps, toenqueue); + if (path->mask.test(i)) { + // Enqueue always + if (path->mode == Path::Mode::ANY) { + enqueued = toenqueue; + PathDestination::enqueueAll(path, muxed_smps, toenqueue); + } + // Enqueue only if received == mask bitset + else if (path->mode == Path::Mode::ALL) { + if (path->mask == path->received) { + PathDestination::enqueueAll(path, muxed_smps, toenqueue); - path->received.reset(); + path->received.reset(); - enqueued = toenqueue; - } - else - enqueued = 0; - } - } - else - enqueued = 0; + enqueued = toenqueue; + } else + enqueued = 0; + } + } else + enqueued = 0; read_decref_muxed_smps: - sample_decref_many(muxed_smps, muxed_initialized); + sample_decref_many(muxed_smps, muxed_initialized); read_decref_read_smps: - sample_decref_many(read_smps, allocated); + sample_decref_many(read_smps, allocated); - return enqueued; + return enqueued; } -void PathSource::check() -{ - if (!node->isEnabled()) - throw RuntimeError("Source {} is not enabled", node->getName()); +void PathSource::check() { + if (!node->isEnabled()) + throw RuntimeError("Source {} is not enabled", node->getName()); - if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_READ)) - throw RuntimeError("Node {} is not supported as a source for a path", node->getName()); + if (!(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_READ)) + throw RuntimeError("Node {} is not supported as a source for a path", + node->getName()); } -MasterPathSource::MasterPathSource(Path *p, Node *n) : - PathSource(p, n) -{ } +MasterPathSource::MasterPathSource(Path *p, Node *n) : PathSource(p, n) {} -void MasterPathSource::writeToSecondaries(struct Sample *smps[], unsigned cnt) -{ - for (auto sps : secondaries) { - int sent = sps->getNode()->write(smps, cnt); - if (sent < 0) - throw RuntimeError("Failed to write secondary path source {} of path {}", sps->getNode()->getName(), path->toString()); - else if ((unsigned) sent < cnt) - path->logger->warn("Partial write to secondary path source {} of path {}", sps->getNode()->getName(), path->toString()); - } +void MasterPathSource::writeToSecondaries(struct Sample *smps[], unsigned cnt) { + for (auto sps : secondaries) { + int sent = sps->getNode()->write(smps, cnt); + if (sent < 0) + throw RuntimeError("Failed to write secondary path source {} of path {}", + sps->getNode()->getName(), path->toString()); + else if ((unsigned)sent < cnt) + path->logger->warn("Partial write to secondary path source {} of path {}", + sps->getNode()->getName(), path->toString()); + } } -SecondaryPathSource::SecondaryPathSource(Path *p, Node *n, NodeList &nodes, PathSource::Ptr m) : - PathSource(p, n), - master(m) -{ - auto mps = std::dynamic_pointer_cast(m); +SecondaryPathSource::SecondaryPathSource(Path *p, Node *n, NodeList &nodes, + PathSource::Ptr m) + : PathSource(p, n), master(m) { + auto mps = std::dynamic_pointer_cast(m); - node = new InternalLoopbackNode(n, mps->getSecondaries().size(), mps->getPath()->queuelen); - if (!node) - throw RuntimeError("Failed to create internal loopback"); + node = new InternalLoopbackNode(n, mps->getSecondaries().size(), + mps->getPath()->queuelen); + if (!node) + throw RuntimeError("Failed to create internal loopback"); - // Register new loopback node in node list of super node - nodes.push_back(node); + // Register new loopback node in node list of super node + nodes.push_back(node); } diff --git a/lib/pool.cpp b/lib/pool.cpp index a34cf839d..f3c4c0465 100644 --- a/lib/pool.cpp +++ b/lib/pool.cpp @@ -5,83 +5,81 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include #include +#include +#include +#include using namespace villas; -int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *m) -{ - int ret; - auto logger = logging.get("pool"); +int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, + struct memory::Type *m) { + int ret; + auto logger = logging.get("pool"); - // Make sure that we use a block size that is aligned to the size of a cache line - p->alignment = kernel::getCachelineSize(); - p->blocksz = p->alignment * CEIL(blocksz, p->alignment); - p->len = cnt * p->blocksz; + // Make sure that we use a block size that is aligned to the size of a cache line + p->alignment = kernel::getCachelineSize(); + p->blocksz = p->alignment * CEIL(blocksz, p->alignment); + p->len = cnt * p->blocksz; - logger->debug("New memory pool: alignment={}, blocksz={}, len={}, memory={}", p->alignment, p->blocksz, p->len, m->name); + logger->debug("New memory pool: alignment={}, blocksz={}, len={}, memory={}", + p->alignment, p->blocksz, p->len, m->name); - void *buffer = memory::alloc_aligned(p->len, p->alignment, m); - if (!buffer) - throw MemoryAllocationError(); + void *buffer = memory::alloc_aligned(p->len, p->alignment, m); + if (!buffer) + throw MemoryAllocationError(); - logger->debug("Allocated {:#x} bytes for memory pool", p->len); + logger->debug("Allocated {:#x} bytes for memory pool", p->len); - p->buffer_off = (char*) buffer - (char*) p; + p->buffer_off = (char *)buffer - (char *)p; - ret = queue_init(&p->queue, LOG2_CEIL(cnt), m); - if (ret) - return ret; + ret = queue_init(&p->queue, LOG2_CEIL(cnt), m); + if (ret) + return ret; - for (unsigned i = 0; i < cnt; i++) - queue_push(&p->queue, (char *) buffer + i * p->blocksz); + for (unsigned i = 0; i < cnt; i++) + queue_push(&p->queue, (char *)buffer + i * p->blocksz); - p->state = State::INITIALIZED; + p->state = State::INITIALIZED; - return 0; + return 0; } -int villas::node::pool_destroy(struct Pool *p) -{ - int ret; +int villas::node::pool_destroy(struct Pool *p) { + int ret; - if (p->state == State::DESTROYED) - return 0; + if (p->state == State::DESTROYED) + return 0; - ret = queue_destroy(&p->queue); - if (ret) - return ret; + ret = queue_destroy(&p->queue); + if (ret) + return ret; - void *buffer = (char *) p + p->buffer_off; - ret = memory::free(buffer); - if (ret == 0) - p->state = State::DESTROYED; + void *buffer = (char *)p + p->buffer_off; + ret = memory::free(buffer); + if (ret == 0) + p->state = State::DESTROYED; - return ret; + return ret; } -ssize_t villas::node::pool_get_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_pull_many(&p->queue, blocks, cnt); +ssize_t villas::node::pool_get_many(struct Pool *p, void *blocks[], + size_t cnt) { + return queue_pull_many(&p->queue, blocks, cnt); } -ssize_t villas::node::pool_put_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_push_many(&p->queue, blocks, cnt); +ssize_t villas::node::pool_put_many(struct Pool *p, void *blocks[], + size_t cnt) { + return queue_push_many(&p->queue, blocks, cnt); } -void * villas::node::pool_get(struct Pool *p) -{ - void *ptr; - return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; +void *villas::node::pool_get(struct Pool *p) { + void *ptr; + return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; } -int villas::node::pool_put(struct Pool *p, void *buf) -{ - return queue_push(&p->queue, buf); +int villas::node::pool_put(struct Pool *p, void *buf) { + return queue_push(&p->queue, buf); } diff --git a/lib/queue.cpp b/lib/queue.cpp index c37f495cd..eb1f96407 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -31,172 +31,175 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include -#include -#include using namespace villas; // Initialize MPMC queue -int villas::node::queue_init(struct CQueue *q, size_t size, struct memory::Type *m) -{ - // Queue size must be 2 exponent - if (!IS_POW2(size)) { - size_t old_size = size; - size = LOG2_CEIL(size); +int villas::node::queue_init(struct CQueue *q, size_t size, + struct memory::Type *m) { + // Queue size must be 2 exponent + if (!IS_POW2(size)) { + size_t old_size = size; + size = LOG2_CEIL(size); - auto logger = logging.get("queue"); - logger->warn("A queue size was changed from {} to {}", old_size, size); - } + auto logger = logging.get("queue"); + logger->warn("A queue size was changed from {} to {}", old_size, size); + } - q->buffer_mask = size - 1; - struct CQueue_cell *buffer = (struct CQueue_cell *) memory::alloc(sizeof(struct CQueue_cell) * size, m); - if (!buffer) - return -2; + q->buffer_mask = size - 1; + struct CQueue_cell *buffer = + (struct CQueue_cell *)memory::alloc(sizeof(struct CQueue_cell) * size, m); + if (!buffer) + return -2; - q->buffer_off = (char *) buffer - (char *) q; + q->buffer_off = (char *)buffer - (char *)q; - for (size_t i = 0; i != size; i += 1) - std::atomic_store_explicit(&buffer[i].sequence, i, std::memory_order_relaxed); + for (size_t i = 0; i != size; i += 1) + std::atomic_store_explicit(&buffer[i].sequence, i, + std::memory_order_relaxed); #ifndef __arm__ - std::atomic_store_explicit(&q->tail, 0ul, std::memory_order_relaxed); - std::atomic_store_explicit(&q->head, 0ul, std::memory_order_relaxed); + std::atomic_store_explicit(&q->tail, 0ul, std::memory_order_relaxed); + std::atomic_store_explicit(&q->head, 0ul, std::memory_order_relaxed); #else - std::atomic_store_explicit(&q->tail, 0u, std::memory_order_relaxed); - std::atomic_store_explicit(&q->head, 0u, std::memory_order_relaxed); + std::atomic_store_explicit(&q->tail, 0u, std::memory_order_relaxed); + std::atomic_store_explicit(&q->head, 0u, std::memory_order_relaxed); #endif - q->state = State::INITIALIZED; + q->state = State::INITIALIZED; - return 0; + return 0; } -int villas::node::queue_destroy(struct CQueue *q) -{ - void *buffer = (char *) q + q->buffer_off; - int ret = 0; +int villas::node::queue_destroy(struct CQueue *q) { + void *buffer = (char *)q + q->buffer_off; + int ret = 0; - if (q->state == State::DESTROYED) - return 0; + if (q->state == State::DESTROYED) + return 0; - ret = memory::free(buffer); - if (ret == 0) - q->state = State::DESTROYED; + ret = memory::free(buffer); + if (ret == 0) + q->state = State::DESTROYED; - return ret; + return ret; } -size_t villas::node::queue_available(struct CQueue *q) -{ - return std::atomic_load_explicit(&q->tail, std::memory_order_relaxed) - - std::atomic_load_explicit(&q->head, std::memory_order_relaxed); +size_t villas::node::queue_available(struct CQueue *q) { + return std::atomic_load_explicit(&q->tail, std::memory_order_relaxed) - + std::atomic_load_explicit(&q->head, std::memory_order_relaxed); } -int villas::node::queue_push(struct CQueue *q, void *ptr) -{ - struct CQueue_cell *cell, *buffer; - size_t pos, seq; - intptr_t diff; +int villas::node::queue_push(struct CQueue *q, void *ptr) { + struct CQueue_cell *cell, *buffer; + size_t pos, seq; + intptr_t diff; - if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == State::STOPPED) - return -1; + if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == + State::STOPPED) + return -1; - buffer = (struct CQueue_cell *) ((char *) q + q->buffer_off); - pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); - while (true) { - cell = &buffer[pos & q->buffer_mask]; - seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); - diff = (intptr_t) seq - (intptr_t) pos; + buffer = (struct CQueue_cell *)((char *)q + q->buffer_off); + pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); + while (true) { + cell = &buffer[pos & q->buffer_mask]; + seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); + diff = (intptr_t)seq - (intptr_t)pos; - if (diff == 0) { - if (std::atomic_compare_exchange_weak_explicit(&q->tail, &pos, pos + 1, std::memory_order_relaxed, std::memory_order_relaxed)) - break; - } - else if (diff < 0) - return 0; - else - pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); - } + if (diff == 0) { + if (std::atomic_compare_exchange_weak_explicit(&q->tail, &pos, pos + 1, + std::memory_order_relaxed, + std::memory_order_relaxed)) + break; + } else if (diff < 0) + return 0; + else + pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); + } - cell->data_off = (char *) ptr - (char *) q; - std::atomic_store_explicit(&cell->sequence, pos + 1, std::memory_order_release); + cell->data_off = (char *)ptr - (char *)q; + std::atomic_store_explicit(&cell->sequence, pos + 1, + std::memory_order_release); - return 1; + return 1; } -int villas::node::queue_pull(struct CQueue *q, void **ptr) -{ - struct CQueue_cell *cell, *buffer; - size_t pos, seq; - intptr_t diff; +int villas::node::queue_pull(struct CQueue *q, void **ptr) { + struct CQueue_cell *cell, *buffer; + size_t pos, seq; + intptr_t diff; - if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == State::STOPPED) - return -1; + if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == + State::STOPPED) + return -1; - buffer = (struct CQueue_cell *) ((char *) q + q->buffer_off); - pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); - while (true) { - cell = &buffer[pos & q->buffer_mask]; - seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); - diff = (intptr_t) seq - (intptr_t) (pos + 1); + buffer = (struct CQueue_cell *)((char *)q + q->buffer_off); + pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); + while (true) { + cell = &buffer[pos & q->buffer_mask]; + seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); + diff = (intptr_t)seq - (intptr_t)(pos + 1); - if (diff == 0) { - if (atomic_compare_exchange_weak_explicit(&q->head, &pos, pos + 1, std::memory_order_relaxed, std::memory_order_relaxed)) - break; - } - else if (diff < 0) - return 0; - else - pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); - } + if (diff == 0) { + if (atomic_compare_exchange_weak_explicit(&q->head, &pos, pos + 1, + std::memory_order_relaxed, + std::memory_order_relaxed)) + break; + } else if (diff < 0) + return 0; + else + pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); + } - *ptr = (char *) q + cell->data_off; - std::atomic_store_explicit(&cell->sequence, pos + q->buffer_mask + 1, std::memory_order_release); + *ptr = (char *)q + cell->data_off; + std::atomic_store_explicit(&cell->sequence, pos + q->buffer_mask + 1, + std::memory_order_release); - return 1; + return 1; } -int villas::node::queue_push_many(struct CQueue *q, void *ptr[], size_t cnt) -{ - int ret; - size_t i; +int villas::node::queue_push_many(struct CQueue *q, void *ptr[], size_t cnt) { + int ret; + size_t i; - for (ret = 0, i = 0; i < cnt; i++) { - ret = queue_push(q, ptr[i]); - if (ret <= 0) - break; - } + for (ret = 0, i = 0; i < cnt; i++) { + ret = queue_push(q, ptr[i]); + if (ret <= 0) + break; + } - if (ret == -1 && i == 0) - return -1; + if (ret == -1 && i == 0) + return -1; - return i; + return i; } -int villas::node::queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt) -{ - int ret; - size_t i; +int villas::node::queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt) { + int ret; + size_t i; - for (ret = 0, i = 0; i < cnt; i++) { - ret = queue_pull(q, &ptr[i]); - if (ret <= 0) - break; - } + for (ret = 0, i = 0; i < cnt; i++) { + ret = queue_pull(q, &ptr[i]); + if (ret <= 0) + break; + } - if (ret == -1 && i == 0) - return -1; + if (ret == -1 && i == 0) + return -1; - return i; + return i; } -int villas::node::queue_close(struct CQueue *q) -{ - enum State expected = State::INITIALIZED; - if (std::atomic_compare_exchange_weak_explicit(&q->state, &expected, State::STOPPED, std::memory_order_relaxed, std::memory_order_relaxed)) - return 0; +int villas::node::queue_close(struct CQueue *q) { + enum State expected = State::INITIALIZED; + if (std::atomic_compare_exchange_weak_explicit( + &q->state, &expected, State::STOPPED, std::memory_order_relaxed, + std::memory_order_relaxed)) + return 0; - return -1; + return -1; } diff --git a/lib/queue_signalled.cpp b/lib/queue_signalled.cpp index f8fbeaad2..0b3ec44f4 100644 --- a/lib/queue_signalled.cpp +++ b/lib/queue_signalled.cpp @@ -9,293 +9,284 @@ #include #ifdef HAS_EVENTFD - #include +#include #endif using namespace villas::node; -static -void queue_signalled_cleanup(void *p) -{ - struct CQueueSignalled *qs = (struct CQueueSignalled *) p; +static void queue_signalled_cleanup(void *p) { + struct CQueueSignalled *qs = (struct CQueueSignalled *)p; - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); } -int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, struct memory::Type *mem, enum QueueSignalledMode mode, int flags) -{ - int ret; +int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, + struct memory::Type *mem, + enum QueueSignalledMode mode, + int flags) { + int ret; - qs->mode = mode; + qs->mode = mode; - if (qs->mode == QueueSignalledMode::AUTO) { + if (qs->mode == QueueSignalledMode::AUTO) { #ifdef __linux__ - if (flags & (int) QueueSignalledFlags::PROCESS_SHARED) - qs->mode = QueueSignalledMode::PTHREAD; - else { + if (flags & (int)QueueSignalledFlags::PROCESS_SHARED) + qs->mode = QueueSignalledMode::PTHREAD; + else { #ifdef HAS_EVENTFD - qs->mode = QueueSignalledMode::EVENTFD; + qs->mode = QueueSignalledMode::EVENTFD; #else - qs->mode = QueueSignalledMode::PTHREAD; + qs->mode = QueueSignalledMode::PTHREAD; #endif - } + } #else - qs->mode = QueueSignalledMode::PTHREAD; + qs->mode = QueueSignalledMode::PTHREAD; #endif - } + } - ret = queue_init(&qs->queue, size, mem); - if (ret < 0) - return ret; + ret = queue_init(&qs->queue, size, mem); + if (ret < 0) + return ret; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_condattr_t cvattr; - pthread_mutexattr_t mtattr; + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_condattr_t cvattr; + pthread_mutexattr_t mtattr; - pthread_mutexattr_init(&mtattr); - pthread_condattr_init(&cvattr); + pthread_mutexattr_init(&mtattr); + pthread_condattr_init(&cvattr); - if (flags & (int) QueueSignalledFlags::PROCESS_SHARED) { - pthread_mutexattr_setpshared(&mtattr, PTHREAD_PROCESS_SHARED); - pthread_condattr_setpshared(&cvattr, PTHREAD_PROCESS_SHARED); - } + if (flags & (int)QueueSignalledFlags::PROCESS_SHARED) { + pthread_mutexattr_setpshared(&mtattr, PTHREAD_PROCESS_SHARED); + pthread_condattr_setpshared(&cvattr, PTHREAD_PROCESS_SHARED); + } - pthread_mutex_init(&qs->pthread.mutex, &mtattr); - pthread_cond_init(&qs->pthread.ready, &cvattr); + pthread_mutex_init(&qs->pthread.mutex, &mtattr); + pthread_cond_init(&qs->pthread.ready, &cvattr); - pthread_mutexattr_destroy(&mtattr); - pthread_condattr_destroy(&cvattr); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + pthread_mutexattr_destroy(&mtattr); + pthread_condattr_destroy(&cvattr); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - qs->eventfd = eventfd(0, 0); - if (qs->eventfd < 0) - return -2; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + qs->eventfd = eventfd(0, 0); + if (qs->eventfd < 0) + return -2; + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } -int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) -{ - int ret; +int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) { + int ret; - ret = queue_destroy(&qs->queue); - if (ret < 0) - return ret; + ret = queue_destroy(&qs->queue); + if (ret < 0) + return ret; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_cond_destroy(&qs->pthread.ready); - pthread_mutex_destroy(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_cond_destroy(&qs->pthread.ready); + pthread_mutex_destroy(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - ret = close(qs->eventfd); - if (ret) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + ret = close(qs->eventfd); + if (ret) + return ret; + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } -int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) -{ - int pushed; +int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) { + int pushed; - pushed = queue_push(&qs->queue, ptr); - if (pushed <= 0) - return pushed; + pushed = queue_push(&qs->queue, ptr); + if (pushed <= 0) + return pushed; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_mutex_lock(&qs->pthread.mutex); - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_mutex_lock(&qs->pthread.mutex); + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return pushed; + return pushed; } -int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) -{ - int pushed; +int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, + void *ptr[], size_t cnt) { + int pushed; - pushed = queue_push_many(&qs->queue, ptr, cnt); - if (pushed <= 0) - return pushed; + pushed = queue_push_many(&qs->queue, ptr, cnt); + if (pushed <= 0) + return pushed; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_mutex_lock(&qs->pthread.mutex); - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_mutex_lock(&qs->pthread.mutex); + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return pushed; + return pushed; } -int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) -{ - int pulled = 0; +int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) { + int pulled = 0; - // Make sure that qs->mutex is unlocked if this thread gets cancelled - pthread_cleanup_push(queue_signalled_cleanup, qs); + // Make sure that qs->mutex is unlocked if this thread gets cancelled + pthread_cleanup_push(queue_signalled_cleanup, qs); - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - while (!pulled) { - pulled = queue_pull(&qs->queue, ptr); - if (pulled < 0) - break; - else if (pulled == 0) { - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); - else if (qs->mode == QueueSignalledMode::POLLING) - continue; // Try again + while (!pulled) { + pulled = queue_pull(&qs->queue, ptr); + if (pulled < 0) + break; + else if (pulled == 0) { + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); + else if (qs->mode == QueueSignalledMode::POLLING) + continue; // Try again #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t cntr; - ret = read(qs->eventfd, &cntr, sizeof(cntr)); - if (ret < 0) - break; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t cntr; + ret = read(qs->eventfd, &cntr, sizeof(cntr)); + if (ret < 0) + break; + } #endif - else - break; - } - } + else + break; + } + } - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); - pthread_cleanup_pop(0); + pthread_cleanup_pop(0); - return pulled; + return pulled; } -int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) -{ - int pulled = 0; +int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, + void *ptr[], size_t cnt) { + int pulled = 0; - // Make sure that qs->mutex is unlocked if this thread gets cancelled - pthread_cleanup_push(queue_signalled_cleanup, qs); + // Make sure that qs->mutex is unlocked if this thread gets cancelled + pthread_cleanup_push(queue_signalled_cleanup, qs); - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - while (!pulled) { - pulled = queue_pull_many(&qs->queue, ptr, cnt); - if (pulled < 0) - break; - else if (pulled == 0) { - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); - else if (qs->mode == QueueSignalledMode::POLLING) - continue; // Try again + while (!pulled) { + pulled = queue_pull_many(&qs->queue, ptr, cnt); + if (pulled < 0) + break; + else if (pulled == 0) { + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); + else if (qs->mode == QueueSignalledMode::POLLING) + continue; // Try again #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t cntr; - ret = read(qs->eventfd, &cntr, sizeof(cntr)); - if (ret < 0) - break; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t cntr; + ret = read(qs->eventfd, &cntr, sizeof(cntr)); + if (ret < 0) + break; + } #endif - else - break; - } - } + else + break; + } + } - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); - pthread_cleanup_pop(0); + pthread_cleanup_pop(0); - return pulled; + return pulled; } -int villas::node::queue_signalled_close(struct CQueueSignalled *qs) -{ - int ret; +int villas::node::queue_signalled_close(struct CQueueSignalled *qs) { + int ret; - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - ret = queue_close(&qs->queue); + ret = queue_close(&qs->queue); - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return ret; + return ret; } -int villas::node::queue_signalled_fd(struct CQueueSignalled *qs) -{ - switch (qs->mode) { +int villas::node::queue_signalled_fd(struct CQueueSignalled *qs) { + switch (qs->mode) { #ifdef HAS_EVENTFD - case QueueSignalledMode::EVENTFD: - return qs->eventfd; + case QueueSignalledMode::EVENTFD: + return qs->eventfd; #endif - default: { } - } + default: { + } + } - return -1; + return -1; } diff --git a/lib/sample.cpp b/lib/sample.cpp index b4ebc1015..c8d81f9ba 100644 --- a/lib/sample.cpp +++ b/lib/sample.cpp @@ -5,319 +5,315 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::sample_init(struct Sample *s) -{ - struct Pool *p = sample_pool(s); +int villas::node::sample_init(struct Sample *s) { + struct Pool *p = sample_pool(s); - s->length = 0; - s->capacity = (p->blocksz - sizeof(struct Sample)) / sizeof(s->data[0]); - s->refcnt = ATOMIC_VAR_INIT(1); + s->length = 0; + s->capacity = (p->blocksz - sizeof(struct Sample)) / sizeof(s->data[0]); + s->refcnt = ATOMIC_VAR_INIT(1); - new (&s->signals) std::shared_ptr; + new (&s->signals) std::shared_ptr; - return 0; + return 0; } -struct Sample * villas::node::sample_alloc(struct Pool *p) -{ - struct Sample *s; +struct Sample *villas::node::sample_alloc(struct Pool *p) { + struct Sample *s; - s = (struct Sample *) pool_get(p); - if (!s) - return nullptr; + s = (struct Sample *)pool_get(p); + if (!s) + return nullptr; - s->pool_off = (char *) p - (char *) s; + s->pool_off = (char *)p - (char *)s; - int ret = sample_init(s); - if (ret) { - pool_put(p, s); - return nullptr; - } + int ret = sample_init(s); + if (ret) { + pool_put(p, s); + return nullptr; + } - return s; + return s; } -struct Sample * villas::node::sample_alloc_mem(int capacity) -{ - size_t sz = SAMPLE_LENGTH(capacity); +struct Sample *villas::node::sample_alloc_mem(int capacity) { + size_t sz = SAMPLE_LENGTH(capacity); - auto *s = (struct Sample *) new char[sz]; - if (!s) - throw MemoryAllocationError(); + auto *s = (struct Sample *)new char[sz]; + if (!s) + throw MemoryAllocationError(); - memset((void *) s, 0, sz); + memset((void *)s, 0, sz); - s->pool_off = SAMPLE_NON_POOL; + s->pool_off = SAMPLE_NON_POOL; - s->length = 0; - s->capacity = capacity; - s->refcnt = ATOMIC_VAR_INIT(1); + s->length = 0; + s->capacity = capacity; + s->refcnt = ATOMIC_VAR_INIT(1); - return s; + return s; } -void villas::node::sample_free(struct Sample *s) -{ - struct Pool *p = sample_pool(s); +void villas::node::sample_free(struct Sample *s) { + struct Pool *p = sample_pool(s); - if (p) - pool_put(p, s); - else - delete[] (char *) s; + if (p) + pool_put(p, s); + else + delete[] (char *)s; } -int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], int cnt) -{ - int ret; +int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], + int cnt) { + int ret; - ret = pool_get_many(p, (void **) smps, cnt); - if (ret < 0) - return ret; + ret = pool_get_many(p, (void **)smps, cnt); + if (ret < 0) + return ret; - for (int i = 0; i < ret; i++) { - smps[i]->pool_off = (char *) p - (char *) smps[i]; + for (int i = 0; i < ret; i++) { + smps[i]->pool_off = (char *)p - (char *)smps[i]; - sample_init(smps[i]); - } + sample_init(smps[i]); + } - return ret; + return ret; } -void villas::node::sample_free_many(struct Sample *smps[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_free(smps[i]); +void villas::node::sample_free_many(struct Sample *smps[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_free(smps[i]); } -int villas::node::sample_decref_many(struct Sample * const smps[], int cnt) -{ - int released = 0; +int villas::node::sample_decref_many(struct Sample *const smps[], int cnt) { + int released = 0; - for (int i = 0; i < cnt; i++) { - if (sample_decref(smps[i]) == 0) - released++; - } + for (int i = 0; i < cnt; i++) { + if (sample_decref(smps[i]) == 0) + released++; + } - return released; + return released; } -int villas::node::sample_incref_many(struct Sample * const smps[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_incref(smps[i]); +int villas::node::sample_incref_many(struct Sample *const smps[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_incref(smps[i]); - return cnt; + return cnt; } -int villas::node::sample_incref(struct Sample *s) -{ - return atomic_fetch_add(&s->refcnt, 1) + 1; +int villas::node::sample_incref(struct Sample *s) { + return atomic_fetch_add(&s->refcnt, 1) + 1; } -int villas::node::sample_decref(struct Sample *s) -{ - int prev = atomic_fetch_sub(&s->refcnt, 1); +int villas::node::sample_decref(struct Sample *s) { + int prev = atomic_fetch_sub(&s->refcnt, 1); - // Did we had the last reference? - if (prev == 1) - sample_free(s); + // Did we had the last reference? + if (prev == 1) + sample_free(s); - return prev - 1; + return prev - 1; } -int villas::node::sample_copy(struct Sample *dst, const struct Sample *src) -{ - dst->length = MIN(src->length, dst->capacity); +int villas::node::sample_copy(struct Sample *dst, const struct Sample *src) { + dst->length = MIN(src->length, dst->capacity); - dst->sequence = src->sequence; - dst->flags = src->flags; - dst->ts = src->ts; - dst->signals = src->signals; + dst->sequence = src->sequence; + dst->flags = src->flags; + dst->ts = src->ts; + dst->signals = src->signals; - memcpy(&dst->data, &src->data, SAMPLE_DATA_LENGTH(dst->length)); + memcpy(&dst->data, &src->data, SAMPLE_DATA_LENGTH(dst->length)); - return 0; + return 0; } -struct Sample * villas::node::sample_clone(struct Sample *orig) -{ - struct Sample *clone; - struct Pool *pool; +struct Sample *villas::node::sample_clone(struct Sample *orig) { + struct Sample *clone; + struct Pool *pool; - pool = sample_pool(orig); - if (!pool) - return nullptr; + pool = sample_pool(orig); + if (!pool) + return nullptr; - clone = sample_alloc(pool); - if (!clone) - return nullptr; + clone = sample_alloc(pool); + if (!clone) + return nullptr; - sample_copy(clone, orig); + sample_copy(clone, orig); - return clone; + return clone; } -int villas::node::sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt) -{ - int alloced, copied; - struct Pool *pool; +int villas::node::sample_clone_many(struct Sample *dsts[], + const struct Sample *const srcs[], + int cnt) { + int alloced, copied; + struct Pool *pool; - if (cnt <= 0) - return 0; + if (cnt <= 0) + return 0; - pool = sample_pool(srcs[0]); - if (!pool) - return 0; + pool = sample_pool(srcs[0]); + if (!pool) + return 0; - alloced = sample_alloc_many(pool, dsts, cnt); + alloced = sample_alloc_many(pool, dsts, cnt); - copied = sample_copy_many(dsts, srcs, alloced); + copied = sample_copy_many(dsts, srcs, alloced); - return copied; + return copied; } -int villas::node::sample_copy_many(struct Sample * const dsts[], const struct Sample * const srcs[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_copy(dsts[i], srcs[i]); +int villas::node::sample_copy_many(struct Sample *const dsts[], + const struct Sample *const srcs[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_copy(dsts[i], srcs[i]); - return cnt; + return cnt; } -int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, int flags) -{ - if ((a->flags & b->flags & flags) != flags) { - printf("flags: a=%#x, b=%#x, wanted=%#x\n", a->flags, b->flags, flags); - return -1; - } +int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, + int flags) { + if ((a->flags & b->flags & flags) != flags) { + printf("flags: a=%#x, b=%#x, wanted=%#x\n", a->flags, b->flags, flags); + return -1; + } - // Compare sequence no - if (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (a->sequence != b->sequence) { - printf("sequence no: %" PRIu64 " != %" PRIu64 "\n", a->sequence, b->sequence); - return 2; - } - } + // Compare sequence no + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (a->sequence != b->sequence) { + printf("sequence no: %" PRIu64 " != %" PRIu64 "\n", a->sequence, + b->sequence); + return 2; + } + } - // Compare timestamp - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - if (time_delta(&a->ts.origin, &b->ts.origin) > epsilon) { - printf("ts.origin: %f != %f\n", time_to_double(&a->ts.origin), time_to_double(&b->ts.origin)); - return 3; - } - } + // Compare timestamp + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + if (time_delta(&a->ts.origin, &b->ts.origin) > epsilon) { + printf("ts.origin: %f != %f\n", time_to_double(&a->ts.origin), + time_to_double(&b->ts.origin)); + return 3; + } + } - // Compare data - if (flags & (int) SampleFlags::HAS_DATA) { - if (a->length != b->length) { - printf("length: %u != %u\n", a->length, b->length); - return 4; - } + // Compare data + if (flags & (int)SampleFlags::HAS_DATA) { + if (a->length != b->length) { + printf("length: %u != %u\n", a->length, b->length); + return 4; + } - for (unsigned i = 0; i < a->length; i++) { - // Compare format - if (sample_format(a, i) != sample_format(b, i)) - return 6; + for (unsigned i = 0; i < a->length; i++) { + // Compare format + if (sample_format(a, i) != sample_format(b, i)) + return 6; - switch (sample_format(a, i)) { - case SignalType::FLOAT: - if (fabs(a->data[i].f - b->data[i].f) > epsilon) { - printf("data[%u].f: %f != %f\n", i, a->data[i].f, b->data[i].f); - return 5; - } - break; + switch (sample_format(a, i)) { + case SignalType::FLOAT: + if (fabs(a->data[i].f - b->data[i].f) > epsilon) { + printf("data[%u].f: %f != %f\n", i, a->data[i].f, b->data[i].f); + return 5; + } + break; - case SignalType::INTEGER: - if (a->data[i].i != b->data[i].i) { - printf("data[%u].i: %" PRId64 " != %" PRId64 "\n", i, a->data[i].i, b->data[i].i); - return 5; - } - break; + case SignalType::INTEGER: + if (a->data[i].i != b->data[i].i) { + printf("data[%u].i: %" PRId64 " != %" PRId64 "\n", i, a->data[i].i, + b->data[i].i); + return 5; + } + break; - case SignalType::BOOLEAN: - if (a->data[i].b != b->data[i].b) { - printf("data[%u].b: %s != %s\n", i, a->data[i].b ? "true" : "false", b->data[i].b ? "true" : "false"); - return 5; - } - break; + case SignalType::BOOLEAN: + if (a->data[i].b != b->data[i].b) { + printf("data[%u].b: %s != %s\n", i, a->data[i].b ? "true" : "false", + b->data[i].b ? "true" : "false"); + return 5; + } + break; - case SignalType::COMPLEX: - if (std::abs(a->data[i].z - b->data[i].z) > epsilon) { - printf("data[%u].z: %f+%fi != %f+%fi\n", i, std::real(a->data[i].z), std::imag(a->data[i].z), std::real(b->data[i].z), std::imag(b->data[i].z)); - return 5; - } - break; + case SignalType::COMPLEX: + if (std::abs(a->data[i].z - b->data[i].z) > epsilon) { + printf("data[%u].z: %f+%fi != %f+%fi\n", i, std::real(a->data[i].z), + std::imag(a->data[i].z), std::real(b->data[i].z), + std::imag(b->data[i].z)); + return 5; + } + break; - default: { } - } - } - } + default: { + } + } + } + } - return 0; + return 0; } -enum SignalType villas::node::sample_format(const struct Sample *s, unsigned idx) -{ - auto sig = s->signals->getByIndex(idx); +enum SignalType villas::node::sample_format(const struct Sample *s, + unsigned idx) { + auto sig = s->signals->getByIndex(idx); - return sig ? sig->type : SignalType::INVALID; + return sig ? sig->type : SignalType::INVALID; } -void villas::node::sample_dump(Logger logger, struct Sample *s) -{ - logger->info("Sample: sequence={}, length={}, capacity={}, " - "flags={:#x}, #signals={}, " - "refcnt={}, pool_off={:#x}", - s->sequence, - s->length, - s->capacity, - s->flags, - s->signals ? s->signals->size() : -1, - atomic_load(&s->refcnt), - s->pool_off); +void villas::node::sample_dump(Logger logger, struct Sample *s) { + logger->info("Sample: sequence={}, length={}, capacity={}, " + "flags={:#x}, #signals={}, " + "refcnt={}, pool_off={:#x}", + s->sequence, s->length, s->capacity, s->flags, + s->signals ? s->signals->size() : -1, atomic_load(&s->refcnt), + s->pool_off); - if (s->flags & (int) SampleFlags::HAS_TS_ORIGIN) - logger->info(" ts.origin={}.{:09d}", s->ts.origin.tv_sec, s->ts.origin.tv_nsec); + if (s->flags & (int)SampleFlags::HAS_TS_ORIGIN) + logger->info(" ts.origin={}.{:09d}", s->ts.origin.tv_sec, + s->ts.origin.tv_nsec); - if (s->flags & (int) SampleFlags::HAS_TS_RECEIVED) - logger->info(" ts.received={}.{:09d}", s->ts.received.tv_sec, s->ts.received.tv_nsec); + if (s->flags & (int)SampleFlags::HAS_TS_RECEIVED) + logger->info(" ts.received={}.{:09d}", s->ts.received.tv_sec, + s->ts.received.tv_nsec); - if (s->signals) { - logger->info(" Signals:"); - s->signals->dump(logger, s->data, s->length); - } + if (s->signals) { + logger->info(" Signals:"); + s->signals->dump(logger, s->data, s->length); + } } -void villas::node::sample_data_insert(struct Sample *smp, const union SignalData *src, size_t offset, size_t len) -{ - memmove(&smp->data[offset + len], &smp->data[offset], sizeof(smp->data[0]) * (smp->length - offset)); - memcpy(&smp->data[offset], src, sizeof(smp->data[0]) * len); +void villas::node::sample_data_insert(struct Sample *smp, + const union SignalData *src, + size_t offset, size_t len) { + memmove(&smp->data[offset + len], &smp->data[offset], + sizeof(smp->data[0]) * (smp->length - offset)); + memcpy(&smp->data[offset], src, sizeof(smp->data[0]) * len); - smp->length += len; + smp->length += len; } -void villas::node::sample_data_remove(struct Sample *smp, size_t offset, size_t len) -{ - size_t sz = sizeof(smp->data[0]) * len; +void villas::node::sample_data_remove(struct Sample *smp, size_t offset, + size_t len) { + size_t sz = sizeof(smp->data[0]) * len; - memmove(&smp->data[offset], &smp->data[offset + len], sz); + memmove(&smp->data[offset], &smp->data[offset + len], sz); - smp->length -= len; + smp->length -= len; } diff --git a/lib/shmem.cpp b/lib/shmem.cpp index 8ca3a1223..9ab914b6b 100644 --- a/lib/shmem.cpp +++ b/lib/shmem.cpp @@ -13,190 +13,196 @@ #include #include -#include #include #include +#include using namespace villas; using namespace villas::node; -size_t villas::node::shmem_total_size(int queuelen, int samplelen) -{ - // We have the constant const of the memory_type header - return sizeof(struct memory::Type) - // and the shared struct itself - + sizeof(struct ShmemShared) - // the size of the actual queue and the queue for the pool - + queuelen * (2 * sizeof(struct CQueue_cell)) - // the size of the pool - + queuelen * kernel::getCachelineSize() * CEIL(SAMPLE_LENGTH(samplelen), kernel::getCachelineSize()) - // a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) - + 4 * sizeof(struct memory::Block) - // and some extra buffer for alignment - + 1024; +size_t villas::node::shmem_total_size(int queuelen, int samplelen) { + // We have the constant const of the memory_type header + return sizeof(struct memory::Type) + // and the shared struct itself + + sizeof(struct ShmemShared) + // the size of the actual queue and the queue for the pool + + queuelen * (2 * sizeof(struct CQueue_cell)) + // the size of the pool + + queuelen * kernel::getCachelineSize() * + CEIL(SAMPLE_LENGTH(samplelen), kernel::getCachelineSize()) + // a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) + + 4 * sizeof(struct memory::Block) + // and some extra buffer for alignment + + 1024; } -int villas::node::shmem_int_open(const char *wname, const char* rname, struct ShmemInterface *shm, struct ShmemConfig *conf) -{ - char *cptr; - int fd, ret; - size_t len; - void *base; - struct memory::Type *manager; - struct ShmemShared *shared; - struct stat stat_buf; - sem_t *sem_own, *sem_other; +int villas::node::shmem_int_open(const char *wname, const char *rname, + struct ShmemInterface *shm, + struct ShmemConfig *conf) { + char *cptr; + int fd, ret; + size_t len; + void *base; + struct memory::Type *manager; + struct ShmemShared *shared; + struct stat stat_buf; + sem_t *sem_own, *sem_other; - // Ensure both semaphores exist - sem_own = sem_open(wname, O_CREAT, 0600, 0); - if (sem_own == SEM_FAILED) - return -1; + // Ensure both semaphores exist + sem_own = sem_open(wname, O_CREAT, 0600, 0); + if (sem_own == SEM_FAILED) + return -1; - sem_other = sem_open(rname, O_CREAT, 0600, 0); - if (sem_other == SEM_FAILED) - return -2; + sem_other = sem_open(rname, O_CREAT, 0600, 0); + if (sem_other == SEM_FAILED) + return -2; - // Open and initialize the shared region for the output queue -retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd < 0) { - if (errno == EEXIST) { - ret = shm_unlink(wname); - if (ret) - return -12; + // Open and initialize the shared region for the output queue +retry: + fd = shm_open(wname, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd < 0) { + if (errno == EEXIST) { + ret = shm_unlink(wname); + if (ret) + return -12; - goto retry; - } + goto retry; + } - return -3; - } + return -3; + } - len = shmem_total_size(conf->queuelen, conf->samplelen); - if (ftruncate(fd, len) < 0) - return -1; + len = shmem_total_size(conf->queuelen, conf->samplelen); + if (ftruncate(fd, len) < 0) + return -1; - base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) - return -4; + base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) + return -4; - close(fd); + close(fd); - manager = memory::managed(base, len); - shared = (struct ShmemShared *) memory::alloc(sizeof(struct ShmemShared), manager); - if (!shared) { - errno = ENOMEM; - return -5; - } + manager = memory::managed(base, len); + shared = + (struct ShmemShared *)memory::alloc(sizeof(struct ShmemShared), manager); + if (!shared) { + errno = ENOMEM; + return -5; + } - shared->polling = conf->polling; + shared->polling = conf->polling; - int flags = (int) QueueSignalledFlags::PROCESS_SHARED; - enum QueueSignalledMode mode = conf->polling - ? QueueSignalledMode::POLLING - : QueueSignalledMode::PTHREAD; + int flags = (int)QueueSignalledFlags::PROCESS_SHARED; + enum QueueSignalledMode mode = + conf->polling ? QueueSignalledMode::POLLING : QueueSignalledMode::PTHREAD; - ret = queue_signalled_init(&shared->queue, conf->queuelen, manager, mode, flags); - if (ret) { - errno = ENOMEM; - return -6; - } + ret = queue_signalled_init(&shared->queue, conf->queuelen, manager, mode, + flags); + if (ret) { + errno = ENOMEM; + return -6; + } - ret = pool_init(&shared->pool, conf->queuelen, SAMPLE_LENGTH(conf->samplelen), manager); - if (ret) { - errno = ENOMEM; - return -7; - } + ret = pool_init(&shared->pool, conf->queuelen, SAMPLE_LENGTH(conf->samplelen), + manager); + if (ret) { + errno = ENOMEM; + return -7; + } - shm->write.base = base; - shm->write.name = wname; - shm->write.len = len; - shm->write.shared = shared; + shm->write.base = base; + shm->write.name = wname; + shm->write.len = len; + shm->write.shared = shared; - /* Post own semaphore and wait on the other one, so both processes know that + /* Post own semaphore and wait on the other one, so both processes know that * both regions are initialized */ - sem_post(sem_own); - sem_wait(sem_other); + sem_post(sem_own); + sem_wait(sem_other); - // Open and map the other region - fd = shm_open(rname, O_RDWR, 0); - if (fd < 0) - return -8; + // Open and map the other region + fd = shm_open(rname, O_RDWR, 0); + if (fd < 0) + return -8; - if (fstat(fd, &stat_buf) < 0) - return -9; + if (fstat(fd, &stat_buf) < 0) + return -9; - len = stat_buf.st_size; - base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + len = stat_buf.st_size; + base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) - return -10; + if (base == MAP_FAILED) + return -10; - cptr = (char *) base + sizeof(struct memory::Type) + sizeof(struct memory::Block); - shared = (struct ShmemShared *) cptr; - shm->read.base = base; - shm->read.name = rname; - shm->read.len = len; - shm->read.shared = shared; + cptr = + (char *)base + sizeof(struct memory::Type) + sizeof(struct memory::Block); + shared = (struct ShmemShared *)cptr; + shm->read.base = base; + shm->read.name = rname; + shm->read.len = len; + shm->read.shared = shared; - shm->readers = 0; - shm->writers = 0; - shm->closed = 0; + shm->readers = 0; + shm->writers = 0; + shm->closed = 0; - // Unlink the semaphores; we don't need them anymore - sem_unlink(wname); + // Unlink the semaphores; we don't need them anymore + sem_unlink(wname); - return 0; + return 0; } -int villas::node::shmem_int_close(struct ShmemInterface *shm) -{ - int ret; +int villas::node::shmem_int_close(struct ShmemInterface *shm) { + int ret; - atomic_store(&shm->closed, 1); + atomic_store(&shm->closed, 1); - ret = queue_signalled_close(&shm->write.shared->queue); - if (ret) - return ret; + ret = queue_signalled_close(&shm->write.shared->queue); + if (ret) + return ret; - shm_unlink(shm->write.name); + shm_unlink(shm->write.name); - if (atomic_load(&shm->readers) == 0) - munmap(shm->read.base, shm->read.len); + if (atomic_load(&shm->readers) == 0) + munmap(shm->read.base, shm->read.len); - if (atomic_load(&shm->writers) == 0) - munmap(shm->write.base, shm->write.len); + if (atomic_load(&shm->writers) == 0) + munmap(shm->write.base, shm->write.len); - return 0; + return 0; } -int villas::node::shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt) -{ - int ret; +int villas::node::shmem_int_read(struct ShmemInterface *shm, + struct Sample *const smps[], unsigned cnt) { + int ret; - atomic_fetch_add(&shm->readers, 1); + atomic_fetch_add(&shm->readers, 1); - ret = queue_signalled_pull_many(&shm->read.shared->queue, (void **) smps, cnt); + ret = queue_signalled_pull_many(&shm->read.shared->queue, (void **)smps, cnt); - if (atomic_fetch_sub(&shm->readers, 1) == 1 && atomic_load(&shm->closed) == 1) - munmap(shm->read.base, shm->read.len); + if (atomic_fetch_sub(&shm->readers, 1) == 1 && atomic_load(&shm->closed) == 1) + munmap(shm->read.base, shm->read.len); - return ret; + return ret; } -int villas::node::shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt) -{ - int ret; +int villas::node::shmem_int_write(struct ShmemInterface *shm, + const struct Sample *const smps[], + unsigned cnt) { + int ret; - atomic_fetch_add(&shm->writers, 1); + atomic_fetch_add(&shm->writers, 1); - ret = queue_signalled_push_many(&shm->write.shared->queue, (void **) smps, cnt); + ret = + queue_signalled_push_many(&shm->write.shared->queue, (void **)smps, cnt); - if (atomic_fetch_sub(&shm->writers, 1) == 1 && atomic_load(&shm->closed) == 1) - munmap(shm->write.base, shm->write.len); + if (atomic_fetch_sub(&shm->writers, 1) == 1 && atomic_load(&shm->closed) == 1) + munmap(shm->write.base, shm->write.len); - return ret; + return ret; } -int villas::node::shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned cnt) -{ - return sample_alloc_many(&shm->write.shared->pool, smps, cnt); +int villas::node::shmem_int_alloc(struct ShmemInterface *shm, + struct Sample *smps[], unsigned cnt) { + return sample_alloc_many(&shm->write.shared->pool, smps, cnt); } diff --git a/lib/signal.cpp b/lib/signal.cpp index 65c0a3c42..58a81bfc9 100644 --- a/lib/signal.cpp +++ b/lib/signal.cpp @@ -5,137 +5,122 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -Signal::Signal(const std::string &n, const std::string &u, enum SignalType t) : - name(n), - unit(u), - init(SignalData::nan()), - type(t) -{ } +Signal::Signal(const std::string &n, const std::string &u, enum SignalType t) + : name(n), unit(u), init(SignalData::nan()), type(t) {} -int Signal::parse(json_t *json) -{ - int ret; - json_error_t err; - json_t *json_init = nullptr; - const char *name_str = nullptr; - const char *unit_str = nullptr; - const char *type_str = "float"; +int Signal::parse(json_t *json) { + int ret; + json_error_t err; + json_t *json_init = nullptr; + const char *name_str = nullptr; + const char *unit_str = nullptr; + const char *type_str = "float"; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: o }", - "name", &name_str, - "unit", &unit_str, - "type", &type_str, - "init", &json_init - ); - if (ret) - return -1; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: o }", "name", + &name_str, "unit", &unit_str, "type", &type_str, "init", + &json_init); + if (ret) + return -1; - if (name_str) - name = name_str; + if (name_str) + name = name_str; - if (unit_str) - unit = unit_str; + if (unit_str) + unit = unit_str; - if (type_str) { - type = signalTypeFromString(type_str); - if (type == SignalType::INVALID) - return -1; - } + if (type_str) { + type = signalTypeFromString(type_str); + if (type == SignalType::INVALID) + return -1; + } - if (json_init) { - ret = init.parseJson(type, json_init); - if (ret) - return ret; - } - else - init.set(type, 0); + if (json_init) { + ret = init.parseJson(type, json_init); + if (ret) + return ret; + } else + init.set(type, 0); - return 0; + return 0; } -json_t * Signal::toJson() const -{ - json_t *json_sig = json_pack("{ s: s }", - "type", signalTypeToString(type).c_str() - ); +json_t *Signal::toJson() const { + json_t *json_sig = + json_pack("{ s: s }", "type", signalTypeToString(type).c_str()); - auto *json_init = init.toJson(type); - if (json_init) - json_object_set_new(json_sig, "init", json_init); + auto *json_init = init.toJson(type); + if (json_init) + json_object_set_new(json_sig, "init", json_init); - if (!name.empty()) - json_object_set_new(json_sig, "name", json_string(name.c_str())); + if (!name.empty()) + json_object_set_new(json_sig, "name", json_string(name.c_str())); - if (!unit.empty()) - json_object_set_new(json_sig, "unit", json_string(unit.c_str())); + if (!unit.empty()) + json_object_set_new(json_sig, "unit", json_string(unit.c_str())); - return json_sig; + return json_sig; } -std::string Signal::toString(const union SignalData *d) const -{ - std::stringstream ss; +std::string Signal::toString(const union SignalData *d) const { + std::stringstream ss; - if (!name.empty()) - ss << " " << name; + if (!name.empty()) + ss << " " << name; - if (!unit.empty()) - ss << " [" << unit << "]"; + if (!unit.empty()) + ss << " [" << unit << "]"; - ss << "(" << signalTypeToString(type) << ")"; + ss << "(" << signalTypeToString(type) << ")"; - if (d) - ss << " = " << d->toString(type); + if (d) + ss << " = " << d->toString(type); - return ss.str(); + return ss.str(); } /* Check if two signal names are numbered ascendingly * * E.g. signal3 -> signal4 */ -static -bool isNextName(const std::string &a, const std::string &b) -{ - // Find common prefix - std::string::const_iterator ia, ib; - for (ia = a.cbegin(), ib = b.cbegin(); - ia != b.cend() && ib != b.cend() && *ia == *ib; - ++ia, ++ib); +static bool isNextName(const std::string &a, const std::string &b) { + // Find common prefix + std::string::const_iterator ia, ib; + for (ia = a.cbegin(), ib = b.cbegin(); + ia != b.cend() && ib != b.cend() && *ia == *ib; ++ia, ++ib) + ; - // Suffixes - auto sa = std::string(ia, a.cend()); - auto sb = std::string(ib, b.cend()); + // Suffixes + auto sa = std::string(ia, a.cend()); + auto sb = std::string(ib, b.cend()); - try { - size_t ea, eb; - auto na = std::stoul(sa, &ea, 10); - auto nb = std::stoul(sb, &eb, 10); + try { + size_t ea, eb; + auto na = std::stoul(sa, &ea, 10); + auto nb = std::stoul(sb, &eb, 10); - return na + 1 == nb; - } catch (std::exception &) { - return false; - } + return na + 1 == nb; + } catch (std::exception &) { + return false; + } } -bool Signal::isNext(const Signal &sig) -{ - if (type != sig.type) - return false; +bool Signal::isNext(const Signal &sig) { + if (type != sig.type) + return false; - if (!unit.empty() && !sig.unit.empty() && unit != sig.unit) - return false; + if (!unit.empty() && !sig.unit.empty() && unit != sig.unit) + return false; - return isNextName(name, sig.name); + return isNextName(name, sig.name); } diff --git a/lib/signal_data.cpp b/lib/signal_data.cpp index 5d7d09575..6a40c4b28 100644 --- a/lib/signal_data.cpp +++ b/lib/signal_data.cpp @@ -5,280 +5,271 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include #include +#include using namespace villas::node; -void SignalData::set(enum SignalType type, double val) -{ - switch (type) { - case SignalType::BOOLEAN: - this->b = val; - break; +void SignalData::set(enum SignalType type, double val) { + switch (type) { + case SignalType::BOOLEAN: + this->b = val; + break; - case SignalType::FLOAT: - this->f = val; - break; + case SignalType::FLOAT: + this->f = val; + break; - case SignalType::INTEGER: - this->i = val; - break; + case SignalType::INTEGER: + this->i = val; + break; - case SignalType::COMPLEX: - this->z = val; - break; + case SignalType::COMPLEX: + this->z = val; + break; - case SignalType::INVALID: - *this = nan(); - break; - } + case SignalType::INVALID: + *this = nan(); + break; + } } -SignalData SignalData::cast(enum SignalType from, enum SignalType to) const -{ - SignalData n = *this; +SignalData SignalData::cast(enum SignalType from, enum SignalType to) const { + SignalData n = *this; - switch (to) { - case SignalType::BOOLEAN: - switch(from) { - case SignalType::INTEGER: - n.b = this->i; - break; + switch (to) { + case SignalType::BOOLEAN: + switch (from) { + case SignalType::INTEGER: + n.b = this->i; + break; - case SignalType::FLOAT: - n.b = this->f; - break; + case SignalType::FLOAT: + n.b = this->f; + break; - case SignalType::COMPLEX: - n.b = std::real(this->z); - break; + case SignalType::COMPLEX: + n.b = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::BOOLEAN: - break; - } - break; + case SignalType::INVALID: + case SignalType::BOOLEAN: + break; + } + break; - case SignalType::INTEGER: - switch(from) { - case SignalType::BOOLEAN: - n.i = this->b; - break; + case SignalType::INTEGER: + switch (from) { + case SignalType::BOOLEAN: + n.i = this->b; + break; - case SignalType::FLOAT: - n.i = this->f; - break; + case SignalType::FLOAT: + n.i = this->f; + break; - case SignalType::COMPLEX: - n.i = std::real(this->z); - break; + case SignalType::COMPLEX: + n.i = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::INTEGER: - break; - } - break; + case SignalType::INVALID: + case SignalType::INTEGER: + break; + } + break; - case SignalType::FLOAT: - switch(from) { - case SignalType::BOOLEAN: - n.f = this->b; - break; + case SignalType::FLOAT: + switch (from) { + case SignalType::BOOLEAN: + n.f = this->b; + break; - case SignalType::INTEGER: - n.f = this->i; - break; + case SignalType::INTEGER: + n.f = this->i; + break; - case SignalType::COMPLEX: - n.f = std::real(this->z); - break; + case SignalType::COMPLEX: + n.f = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::FLOAT: - break; - } - break; + case SignalType::INVALID: + case SignalType::FLOAT: + break; + } + break; - case SignalType::COMPLEX: - switch(from) { - case SignalType::BOOLEAN: - n.z = this->b; - break; + case SignalType::COMPLEX: + switch (from) { + case SignalType::BOOLEAN: + n.z = this->b; + break; - case SignalType::INTEGER: - n.z = this->i; - break; + case SignalType::INTEGER: + n.z = this->i; + break; - case SignalType::FLOAT: - n.z = this->f; - break; + case SignalType::FLOAT: + n.z = this->f; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - break; - } - break; + case SignalType::INVALID: + case SignalType::COMPLEX: + break; + } + break; - default: { } - } + default: { + } + } - return n; + return n; } -int SignalData::parseString(enum SignalType type, const char *ptr, char **end) -{ - switch (type) { - case SignalType::FLOAT: - this->f = strtod(ptr, end); - break; +int SignalData::parseString(enum SignalType type, const char *ptr, char **end) { + switch (type) { + case SignalType::FLOAT: + this->f = strtod(ptr, end); + break; - case SignalType::INTEGER: - this->i = strtol(ptr, end, 10); - break; + case SignalType::INTEGER: + this->i = strtol(ptr, end, 10); + break; - case SignalType::BOOLEAN: - this->b = strtol(ptr, end, 10); - break; + case SignalType::BOOLEAN: + this->b = strtol(ptr, end, 10); + break; - case SignalType::COMPLEX: { - float real, imag = 0; + case SignalType::COMPLEX: { + float real, imag = 0; - real = strtod(ptr, end); - if (*end == ptr) - return -1; + real = strtod(ptr, end); + if (*end == ptr) + return -1; - ptr = *end; + ptr = *end; - if (*ptr == 'i' || *ptr == 'j') { - imag = real; - real = 0; + if (*ptr == 'i' || *ptr == 'j') { + imag = real; + real = 0; - (*end)++; - } - else if (*ptr == '-' || *ptr == '+') { - imag = strtod(ptr, end); - if (*end == ptr) - return -1; + (*end)++; + } else if (*ptr == '-' || *ptr == '+') { + imag = strtod(ptr, end); + if (*end == ptr) + return -1; - if (**end != 'i' && **end != 'j') - return -1; + if (**end != 'i' && **end != 'j') + return -1; - (*end)++; - } + (*end)++; + } - this->z = std::complex(real, imag); - break; - } + this->z = std::complex(real, imag); + break; + } - case SignalType::INVALID: - return -1; - } + case SignalType::INVALID: + return -1; + } - return 0; + return 0; } -int SignalData::parseJson(enum SignalType type, json_t *json) -{ - int ret; +int SignalData::parseJson(enum SignalType type, json_t *json) { + int ret; - switch (type) { - case SignalType::FLOAT: - if (!json_is_number(json)) - return -1; + switch (type) { + case SignalType::FLOAT: + if (!json_is_number(json)) + return -1; - this->f = json_number_value(json); - break; + this->f = json_number_value(json); + break; - case SignalType::INTEGER: - if (!json_is_integer(json)) - return -1; + case SignalType::INTEGER: + if (!json_is_integer(json)) + return -1; - this->i = json_integer_value(json); - break; + this->i = json_integer_value(json); + break; - case SignalType::BOOLEAN: - if (!json_is_boolean(json)) - return -1; + case SignalType::BOOLEAN: + if (!json_is_boolean(json)) + return -1; - this->b = json_boolean_value(json); - break; + this->b = json_boolean_value(json); + break; - case SignalType::COMPLEX: { - double real, imag; + case SignalType::COMPLEX: { + double real, imag; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: F, s: F }", - "real", &real, - "imag", &imag - ); - if (ret) - return -1; + json_error_t err; + ret = json_unpack_ex(json, &err, 0, "{ s: F, s: F }", "real", &real, "imag", + &imag); + if (ret) + return -1; - this->z = std::complex(real, imag); - break; - } + this->z = std::complex(real, imag); + break; + } - case SignalType::INVALID: - return -2; - } + case SignalType::INVALID: + return -2; + } - return 0; + return 0; } -json_t * SignalData::toJson(enum SignalType type) const -{ - switch (type) { - case SignalType::INTEGER: - return json_integer(this->i); +json_t *SignalData::toJson(enum SignalType type) const { + switch (type) { + case SignalType::INTEGER: + return json_integer(this->i); - case SignalType::FLOAT: - return json_real(this->f); + case SignalType::FLOAT: + return json_real(this->f); - case SignalType::BOOLEAN: - return json_boolean(this->b); + case SignalType::BOOLEAN: + return json_boolean(this->b); - case SignalType::COMPLEX: - return json_pack("{ s: f, s: f }", - "real", std::real(this->z), - "imag", std::imag(this->z) - ); + case SignalType::COMPLEX: + return json_pack("{ s: f, s: f }", "real", std::real(this->z), "imag", + std::imag(this->z)); - case SignalType::INVALID: - return nullptr; - } + case SignalType::INVALID: + return nullptr; + } - return nullptr; + return nullptr; } -int SignalData::printString(enum SignalType type, char *buf, size_t len, int precision) const -{ - switch (type) { - case SignalType::FLOAT: - return snprintf(buf, len, "%.*f", precision, this->f); +int SignalData::printString(enum SignalType type, char *buf, size_t len, + int precision) const { + switch (type) { + case SignalType::FLOAT: + return snprintf(buf, len, "%.*f", precision, this->f); - case SignalType::INTEGER: - return snprintf(buf, len, "%" PRIi64, this->i); + case SignalType::INTEGER: + return snprintf(buf, len, "%" PRIi64, this->i); - case SignalType::BOOLEAN: - return snprintf(buf, len, "%u", this->b); + case SignalType::BOOLEAN: + return snprintf(buf, len, "%u", this->b); - case SignalType::COMPLEX: - return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(this->z), precision, std::imag(this->z)); + case SignalType::COMPLEX: + return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(this->z), + precision, std::imag(this->z)); - default: - return snprintf(buf, len, ""); - } + default: + return snprintf(buf, len, ""); + } } -std::string SignalData::toString(enum SignalType type, int precission) const -{ - char buf[128]; +std::string SignalData::toString(enum SignalType type, int precission) const { + char buf[128]; - printString(type, buf, sizeof(buf), precission); + printString(type, buf, sizeof(buf), precission); - return buf; + return buf; } diff --git a/lib/signal_list.cpp b/lib/signal_list.cpp index 18717d0d4..dd1359973 100644 --- a/lib/signal_list.cpp +++ b/lib/signal_list.cpp @@ -5,158 +5,149 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include -#include #include #include -#include +#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int SignalList::parse(json_t *json) -{ - int ret; +int SignalList::parse(json_t *json) { + int ret; - if (!json_is_array(json)) - return -1; + if (!json_is_array(json)) + return -1; - size_t i; - json_t *json_signal; - json_array_foreach(json, i, json_signal) { - auto sig = std::make_shared(); - if (!sig) - throw MemoryAllocationError(); + size_t i; + json_t *json_signal; + json_array_foreach(json, i, json_signal) { + auto sig = std::make_shared(); + if (!sig) + throw MemoryAllocationError(); - ret = sig->parse(json_signal); - if (ret) - return ret; + ret = sig->parse(json_signal); + if (ret) + return ret; - push_back(sig); - } + push_back(sig); + } - return 0; + return 0; } -SignalList::SignalList(unsigned len, enum SignalType typ) -{ - char name[32]; +SignalList::SignalList(unsigned len, enum SignalType typ) { + char name[32]; - for (unsigned i = 0; i < len; i++) { - snprintf(name, sizeof(name), "signal%u", i); + for (unsigned i = 0; i < len; i++) { + snprintf(name, sizeof(name), "signal%u", i); - auto sig = std::make_shared(name, "", typ); - if (!sig) - throw RuntimeError("Failed to create signal list"); + auto sig = std::make_shared(name, "", typ); + if (!sig) + throw RuntimeError("Failed to create signal list"); - push_back(sig); - } + push_back(sig); + } } -SignalList::SignalList(const char *dt) -{ - int len, i = 0; - char name[32], *e; - enum SignalType typ; +SignalList::SignalList(const char *dt) { + int len, i = 0; + char name[32], *e; + enum SignalType typ; - for (const char *t = dt; *t; t = e + 1) { - len = strtoul(t, &e, 10); - if (t == e) - len = 1; + for (const char *t = dt; *t; t = e + 1) { + len = strtoul(t, &e, 10); + if (t == e) + len = 1; - typ = signalTypeFromFormatString(*e); - if (typ == SignalType::INVALID) - throw RuntimeError("Failed to create signal list"); + typ = signalTypeFromFormatString(*e); + if (typ == SignalType::INVALID) + throw RuntimeError("Failed to create signal list"); - for (int j = 0; j < len; j++) { - snprintf(name, sizeof(name), "signal%d", i++); + for (int j = 0; j < len; j++) { + snprintf(name, sizeof(name), "signal%d", i++); - auto sig = std::make_shared(name, "", typ); - if (!sig) - throw RuntimeError("Failed to create signal list"); + auto sig = std::make_shared(name, "", typ); + if (!sig) + throw RuntimeError("Failed to create signal list"); - push_back(sig); - } - } + push_back(sig); + } + } } -void SignalList::dump(Logger logger, const union SignalData *data, unsigned len) const -{ - const char *pfx; - bool abbrev = false; +void SignalList::dump(Logger logger, const union SignalData *data, + unsigned len) const { + const char *pfx; + bool abbrev = false; - Signal::Ptr prevSig; - unsigned i = 0; - for (auto sig : *this) { - // Check if this is a sequence of similar signals which can be abbreviated - if (i >= 1 && i < size() - 1) { - if (prevSig->isNext(*sig)) { - abbrev = true; - goto skip; - } - } + Signal::Ptr prevSig; + unsigned i = 0; + for (auto sig : *this) { + // Check if this is a sequence of similar signals which can be abbreviated + if (i >= 1 && i < size() - 1) { + if (prevSig->isNext(*sig)) { + abbrev = true; + goto skip; + } + } - if (abbrev) { - pfx = "..."; - abbrev = false; - } - else - pfx = " "; + if (abbrev) { + pfx = "..."; + abbrev = false; + } else + pfx = " "; - logger->info(" {}{:>3}: {}", pfx, i, sig->toString(i < len ? &data[i] : nullptr)); + logger->info(" {}{:>3}: {}", pfx, i, + sig->toString(i < len ? &data[i] : nullptr)); -skip: prevSig = sig; - i++; - } + skip: + prevSig = sig; + i++; + } } -json_t * SignalList::toJson() const -{ - json_t *json_signals = json_array(); +json_t *SignalList::toJson() const { + json_t *json_signals = json_array(); - for (const auto &sig : *this) - json_array_append_new(json_signals, sig->toJson()); + for (const auto &sig : *this) + json_array_append_new(json_signals, sig->toJson()); - return json_signals; + return json_signals; } -Signal::Ptr SignalList::getByIndex(unsigned idx) -{ - return this->at(idx); +Signal::Ptr SignalList::getByIndex(unsigned idx) { return this->at(idx); } + +int SignalList::getIndexByName(const std::string &name) { + unsigned i = 0; + for (auto s : *this) { + if (name == s->name) + return i; + + i++; + } + + return -1; } -int SignalList::getIndexByName(const std::string &name) -{ - unsigned i = 0; - for (auto s : *this) { - if (name == s->name) - return i; +Signal::Ptr SignalList::getByName(const std::string &name) { + for (auto s : *this) { + if (name == s->name) + return s; + } - i++; - } - - return -1; + return Signal::Ptr(); } -Signal::Ptr SignalList::getByName(const std::string &name) -{ - for (auto s : *this) { - if (name == s->name) - return s; - } +SignalList::Ptr SignalList::clone() { + auto l = std::make_shared(); - return Signal::Ptr(); -} - -SignalList::Ptr SignalList::clone() -{ - auto l = std::make_shared(); - - for (auto s : *this) - l->push_back(s); - - return l; + for (auto s : *this) + l->push_back(s); + + return l; } diff --git a/lib/signal_type.cpp b/lib/signal_type.cpp index 40c770822..a42410935 100644 --- a/lib/signal_type.cpp +++ b/lib/signal_type.cpp @@ -11,75 +11,71 @@ using namespace villas::node; -enum SignalType villas::node::signalTypeFromString(const std::string &str) -{ - if (str == "boolean") - return SignalType::BOOLEAN; - else if (str == "complex") - return SignalType::COMPLEX; - else if (str == "float") - return SignalType::FLOAT; - else if (str == "integer") - return SignalType::INTEGER; - else - return SignalType::INVALID; +enum SignalType villas::node::signalTypeFromString(const std::string &str) { + if (str == "boolean") + return SignalType::BOOLEAN; + else if (str == "complex") + return SignalType::COMPLEX; + else if (str == "float") + return SignalType::FLOAT; + else if (str == "integer") + return SignalType::INTEGER; + else + return SignalType::INVALID; } -enum SignalType villas::node::signalTypeFromFormatString(char c) -{ - switch (c) { - case 'f': - return SignalType::FLOAT; +enum SignalType villas::node::signalTypeFromFormatString(char c) { + switch (c) { + case 'f': + return SignalType::FLOAT; - case 'i': - return SignalType::INTEGER; + case 'i': + return SignalType::INTEGER; - case 'c': - return SignalType::COMPLEX; + case 'c': + return SignalType::COMPLEX; - case 'b': - return SignalType::BOOLEAN; + case 'b': + return SignalType::BOOLEAN; - default: - return SignalType::INVALID; - } + default: + return SignalType::INVALID; + } } -std::string villas::node::signalTypeToString(enum SignalType fmt) -{ - switch (fmt) { - case SignalType::BOOLEAN: - return "boolean"; +std::string villas::node::signalTypeToString(enum SignalType fmt) { + switch (fmt) { + case SignalType::BOOLEAN: + return "boolean"; - case SignalType::COMPLEX: - return "complex"; + case SignalType::COMPLEX: + return "complex"; - case SignalType::FLOAT: - return "float"; + case SignalType::FLOAT: + return "float"; - case SignalType::INTEGER: - return "integer"; + case SignalType::INTEGER: + return "integer"; - case SignalType::INVALID: - return "invalid"; - } + case SignalType::INVALID: + return "invalid"; + } - return nullptr; + return nullptr; } -enum SignalType villas::node::signalTypeDetect(const std::string &val) -{ - int len; +enum SignalType villas::node::signalTypeDetect(const std::string &val) { + int len; - if (val.find('i') != std::string::npos) - return SignalType::COMPLEX; + if (val.find('i') != std::string::npos) + return SignalType::COMPLEX; - if (val.find(',') != std::string::npos) - return SignalType::FLOAT; + if (val.find(',') != std::string::npos) + return SignalType::FLOAT; - len = val.size(); - if (len == 1 && (val[0] == '1' || val[0] == '0')) - return SignalType::BOOLEAN; + len = val.size(); + if (len == 1 && (val[0] == '1' || val[0] == '0')) + return SignalType::BOOLEAN; - return SignalType::INTEGER; + return SignalType::INTEGER; } diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index faa5a6d94..a8e4e5f4c 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -5,221 +5,224 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include -#include +#include +#include #include #include -#include #ifdef WITH_SOCKET_LAYER_ETH - #include +#include #endif // WITH_SOCKET_LAYER_ETH using namespace villas; using namespace villas::node; using namespace villas::utils; -char * villas::node::socket_print_addr(struct sockaddr *saddr) -{ - union sockaddr_union *sa = (union sockaddr_union *) saddr; - auto *buf = reinterpret_cast(::malloc(256)); - if (!buf) - throw MemoryAllocationError(); +char *villas::node::socket_print_addr(struct sockaddr *saddr) { + union sockaddr_union *sa = (union sockaddr_union *)saddr; + auto *buf = reinterpret_cast(::malloc(256)); + if (!buf) + throw MemoryAllocationError(); - // Address - switch (sa->sa.sa_family) { - case AF_INET6: - inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); - break; + // Address + switch (sa->sa.sa_family) { + case AF_INET6: + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); + break; - case AF_INET: - inet_ntop(AF_INET, &sa->sin.sin_addr, buf, 64); - break; + case AF_INET: + inet_ntop(AF_INET, &sa->sin.sin_addr, buf, 64); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - strcatf(&buf, "%02x", sa->sll.sll_addr[0]); - for (int i = 1; i < sa->sll.sll_halen; i++) - strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); - break; + case AF_PACKET: + strcatf(&buf, "%02x", sa->sll.sll_addr[0]); + for (int i = 1; i < sa->sll.sll_halen; i++) + strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); + break; #endif // WITH_SOCKET_LAYER_ETH - case AF_UNIX: - snprintf(buf, 256, "%s", sa->sun.sun_path); - break; + case AF_UNIX: + snprintf(buf, 256, "%s", sa->sun.sun_path); + break; - default: - throw RuntimeError("Unknown address family: '{}'", sa->sa.sa_family); - } + default: + throw RuntimeError("Unknown address family: '{}'", sa->sa.sa_family); + } - // Port / Interface - switch (sa->sa.sa_family) { - case AF_INET6: - case AF_INET: - strcatf(&buf, ":%hu", ntohs(sa->sin.sin_port)); - break; + // Port / Interface + switch (sa->sa.sa_family) { + case AF_INET6: + case AF_INET: + strcatf(&buf, ":%hu", ntohs(sa->sin.sin_port)); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: { - struct nl_cache *cache = nl_cache_mngt_require("route/link"); - struct rtnl_link *link = rtnl_link_get(cache, sa->sll.sll_ifindex); - if (!link) - throw RuntimeError("Failed to get interface for index: {}", sa->sll.sll_ifindex); + case AF_PACKET: { + struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct rtnl_link *link = rtnl_link_get(cache, sa->sll.sll_ifindex); + if (!link) + throw RuntimeError("Failed to get interface for index: {}", + sa->sll.sll_ifindex); - strcatf(&buf, "%%%s", rtnl_link_get_name(link)); - strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); - break; - } + strcatf(&buf, "%%%s", rtnl_link_get_name(link)); + strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); + break; + } #endif // WITH_SOCKET_LAYER_ETH - } + } - return buf; + return buf; } -int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLayer layer, int flags) -{ - // TODO: Add support for IPv6 - union sockaddr_union *sa = (union sockaddr_union *) saddr; +int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, + enum SocketLayer layer, int flags) { + // TODO: Add support for IPv6 + union sockaddr_union *sa = (union sockaddr_union *)saddr; - char *copy = strdup(addr); - int ret; + char *copy = strdup(addr); + int ret; - if (layer == SocketLayer::UNIX) { // Format: "/path/to/socket" - sa->sun.sun_family = AF_UNIX; + if (layer == SocketLayer::UNIX) { // Format: "/path/to/socket" + sa->sun.sun_family = AF_UNIX; - if (strlen(addr) > sizeof(sa->sun.sun_path) - 1) - throw RuntimeError("Length of unix socket path is too long!"); + if (strlen(addr) > sizeof(sa->sun.sun_path) - 1) + throw RuntimeError("Length of unix socket path is too long!"); - memcpy(sa->sun.sun_path, addr, strlen(addr) + 1); + memcpy(sa->sun.sun_path, addr, strlen(addr) + 1); - ret = 0; - } + ret = 0; + } #ifdef WITH_SOCKET_LAYER_ETH - else if (layer == SocketLayer::ETH) { // Format: "ab:cd:ef:12:34:56%ifname:protocol" - // Split string - char *lasts; - char *node = strtok_r(copy, "%", &lasts); - char *ifname = strtok_r(nullptr, ":", &lasts); - char *proto = strtok_r(nullptr, "\0", &lasts); + else if (layer == + SocketLayer::ETH) { // Format: "ab:cd:ef:12:34:56%ifname:protocol" + // Split string + char *lasts; + char *node = strtok_r(copy, "%", &lasts); + char *ifname = strtok_r(nullptr, ":", &lasts); + char *proto = strtok_r(nullptr, "\0", &lasts); - // Parse link layer (MAC) address - struct ether_addr *mac = ether_aton(node); - if (!mac) - throw RuntimeError("Failed to parse MAC address: {}", node); + // Parse link layer (MAC) address + struct ether_addr *mac = ether_aton(node); + if (!mac) + throw RuntimeError("Failed to parse MAC address: {}", node); - memcpy(&sa->sll.sll_addr, &mac->ether_addr_octet, ETHER_ADDR_LEN); + memcpy(&sa->sll.sll_addr, &mac->ether_addr_octet, ETHER_ADDR_LEN); - // Get interface index from name - kernel::nl::init(); + // Get interface index from name + kernel::nl::init(); - struct nl_cache *cache = nl_cache_mngt_require("route/link"); - struct rtnl_link *link = rtnl_link_get_by_name(cache, ifname); - if (!link) - throw RuntimeError("Failed to get network interface: '{}'", ifname); + struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct rtnl_link *link = rtnl_link_get_by_name(cache, ifname); + if (!link) + throw RuntimeError("Failed to get network interface: '{}'", ifname); - sa->sll.sll_protocol = htons(proto ? strtol(proto, nullptr, 0) : ETH_P_VILLAS); - sa->sll.sll_halen = ETHER_ADDR_LEN; - sa->sll.sll_family = AF_PACKET; - sa->sll.sll_ifindex = rtnl_link_get_ifindex(link); + sa->sll.sll_protocol = + htons(proto ? strtol(proto, nullptr, 0) : ETH_P_VILLAS); + sa->sll.sll_halen = ETHER_ADDR_LEN; + sa->sll.sll_family = AF_PACKET; + sa->sll.sll_ifindex = rtnl_link_get_ifindex(link); - ret = 0; - } -#endif // WITH_SOCKET_LAYER_ETH - else { // Format: "192.168.0.10:12001" - struct addrinfo hint = { - .ai_flags = flags, - .ai_family = AF_UNSPEC - }; + ret = 0; + } +#endif // WITH_SOCKET_LAYER_ETH + else { // Format: "192.168.0.10:12001" + struct addrinfo hint = {.ai_flags = flags, .ai_family = AF_UNSPEC}; - // Split string - char *lasts; - char *node = strtok_r(copy, ":", &lasts); - char *service = strtok_r(nullptr, "\0", &lasts); + // Split string + char *lasts; + char *node = strtok_r(copy, ":", &lasts); + char *service = strtok_r(nullptr, "\0", &lasts); - if (node && !strcmp(node, "*")) - node = nullptr; + if (node && !strcmp(node, "*")) + node = nullptr; - if (service && !strcmp(service, "*")) - service = nullptr; + if (service && !strcmp(service, "*")) + service = nullptr; - switch (layer) { - case SocketLayer::IP: - hint.ai_socktype = SOCK_RAW; - hint.ai_protocol = (service) ? strtol(service, nullptr, 0) : IPPROTO_VILLAS; - hint.ai_flags |= AI_NUMERICSERV; - break; + switch (layer) { + case SocketLayer::IP: + hint.ai_socktype = SOCK_RAW; + hint.ai_protocol = + (service) ? strtol(service, nullptr, 0) : IPPROTO_VILLAS; + hint.ai_flags |= AI_NUMERICSERV; + break; - case SocketLayer::UDP: - hint.ai_socktype = SOCK_DGRAM; - hint.ai_protocol = IPPROTO_UDP; - break; + case SocketLayer::UDP: + hint.ai_socktype = SOCK_DGRAM; + hint.ai_protocol = IPPROTO_UDP; + break; - default: - throw RuntimeError("Invalid address type"); - } + default: + throw RuntimeError("Invalid address type"); + } - // Lookup address - struct addrinfo *result; - ret = getaddrinfo(node, (layer == SocketLayer::IP) ? nullptr : service, &hint, &result); - if (!ret) { - if (layer == SocketLayer::IP) { - // We mis-use the sin_port field to store the IP protocol number on RAW sockets - struct sockaddr_in *sin = (struct sockaddr_in *) result->ai_addr; - sin->sin_port = htons(result->ai_protocol); - } + // Lookup address + struct addrinfo *result; + ret = getaddrinfo(node, (layer == SocketLayer::IP) ? nullptr : service, + &hint, &result); + if (!ret) { + if (layer == SocketLayer::IP) { + // We mis-use the sin_port field to store the IP protocol number on RAW sockets + struct sockaddr_in *sin = (struct sockaddr_in *)result->ai_addr; + sin->sin_port = htons(result->ai_protocol); + } - memcpy(sa, result->ai_addr, result->ai_addrlen); - freeaddrinfo(result); - } - } + memcpy(sa, result->ai_addr, result->ai_addrlen); + freeaddrinfo(result); + } + } - free(copy); + free(copy); - return ret; + return ret; } -int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) -{ -#define CMP(a, b) if (a != b) return a < b ? -1 : 1 +int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) { +#define CMP(a, b) \ + if (a != b) \ + return a < b ? -1 : 1 - union sockaddr_union *xu = (union sockaddr_union *) x; - union sockaddr_union *yu = (union sockaddr_union *) y; + union sockaddr_union *xu = (union sockaddr_union *)x; + union sockaddr_union *yu = (union sockaddr_union *)y; - CMP(x->sa_family, y->sa_family); + CMP(x->sa_family, y->sa_family); - switch (x->sa_family) { - case AF_UNIX: - return strcmp(xu->sun.sun_path, yu->sun.sun_path); + switch (x->sa_family) { + case AF_UNIX: + return strcmp(xu->sun.sun_path, yu->sun.sun_path); - case AF_INET: - CMP(ntohl(xu->sin.sin_addr.s_addr), ntohl(yu->sin.sin_addr.s_addr)); - CMP(ntohs(xu->sin.sin_port), ntohs(yu->sin.sin_port)); + case AF_INET: + CMP(ntohl(xu->sin.sin_addr.s_addr), ntohl(yu->sin.sin_addr.s_addr)); + CMP(ntohs(xu->sin.sin_port), ntohs(yu->sin.sin_port)); - return 0; + return 0; - case AF_INET6: - CMP(ntohs(xu->sin6.sin6_port), ntohs(yu->sin6.sin6_port)); -// CMP(xu->sin6.sin6_flowinfo, yu->sin6.sin6_flowinfo); -// CMP(xu->sin6.sin6_scope_id, yu->sin6.sin6_scope_id); + case AF_INET6: + CMP(ntohs(xu->sin6.sin6_port), ntohs(yu->sin6.sin6_port)); + // CMP(xu->sin6.sin6_flowinfo, yu->sin6.sin6_flowinfo); + // CMP(xu->sin6.sin6_scope_id, yu->sin6.sin6_scope_id); - return memcmp(xu->sin6.sin6_addr.s6_addr, yu->sin6.sin6_addr.s6_addr, sizeof(xu->sin6.sin6_addr.s6_addr)); + return memcmp(xu->sin6.sin6_addr.s6_addr, yu->sin6.sin6_addr.s6_addr, + sizeof(xu->sin6.sin6_addr.s6_addr)); #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - CMP(ntohs(xu->sll.sll_protocol), ntohs(yu->sll.sll_protocol)); - CMP(xu->sll.sll_ifindex, yu->sll.sll_ifindex); -// CMP(xu->sll.sll_pkttype, yu->sll.sll_pkttype); -// CMP(xu->sll.sll_hatype, yu->sll.sll_hatype); + case AF_PACKET: + CMP(ntohs(xu->sll.sll_protocol), ntohs(yu->sll.sll_protocol)); + CMP(xu->sll.sll_ifindex, yu->sll.sll_ifindex); + // CMP(xu->sll.sll_pkttype, yu->sll.sll_pkttype); + // CMP(xu->sll.sll_hatype, yu->sll.sll_hatype); - CMP(xu->sll.sll_halen, yu->sll.sll_halen); - return memcmp(xu->sll.sll_addr, yu->sll.sll_addr, xu->sll.sll_halen); + CMP(xu->sll.sll_halen, yu->sll.sll_halen); + return memcmp(xu->sll.sll_addr, yu->sll.sll_addr, xu->sll.sll_halen); #endif // WITH_SOCKET_LAYER_ETH - default: - return -1; - } + default: + return -1; + } #undef CMP } diff --git a/lib/stats.cpp b/lib/stats.cpp index e20cb9db0..d6b352dcd 100644 --- a/lib/stats.cpp +++ b/lib/stats.cpp @@ -7,250 +7,243 @@ #include -#include #include +#include +#include #include -#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; std::unordered_map Stats::metrics = { - { Stats::Metric::SMPS_SKIPPED, { "skipped", "samples", "Skipped samples and the distance between them" }}, - { Stats::Metric::SMPS_REORDERED, { "reordered", "samples", "Reordered samples and the distance between them" }}, - { Stats::Metric::GAP_SAMPLE, { "gap_sent", "seconds", "Inter-message timestamps (as sent by remote)" }}, - { Stats::Metric::GAP_RECEIVED, { "gap_received", "seconds", "Inter-message arrival time (as received by this instance)" }}, - { Stats::Metric::OWD, { "owd", "seconds", "One-way-delay (OWD) of received messages" }}, - { Stats::Metric::AGE, { "age", "seconds", "Processing time of packets within the from receive to sent" }}, - { Stats::Metric::SIGNAL_COUNT, { "signal_cnt", "signals", "Number of signals per sample" }}, - { Stats::Metric::RTP_LOSS_FRACTION, { "rtp.loss_fraction", "percent", "Fraction lost since last RTP SR/RR." }}, - { Stats::Metric::RTP_PKTS_LOST, { "rtp.pkts_lost", "packets", "Cumulative number of packets lost" }}, - { Stats::Metric::RTP_JITTER, { "rtp.jitter", "seconds", "Interarrival jitter" }}, + {Stats::Metric::SMPS_SKIPPED, + {"skipped", "samples", "Skipped samples and the distance between them"}}, + {Stats::Metric::SMPS_REORDERED, + {"reordered", "samples", + "Reordered samples and the distance between them"}}, + {Stats::Metric::GAP_SAMPLE, + {"gap_sent", "seconds", "Inter-message timestamps (as sent by remote)"}}, + {Stats::Metric::GAP_RECEIVED, + {"gap_received", "seconds", + "Inter-message arrival time (as received by this instance)"}}, + {Stats::Metric::OWD, + {"owd", "seconds", "One-way-delay (OWD) of received messages"}}, + {Stats::Metric::AGE, + {"age", "seconds", + "Processing time of packets within the from receive to sent"}}, + {Stats::Metric::SIGNAL_COUNT, + {"signal_cnt", "signals", "Number of signals per sample"}}, + {Stats::Metric::RTP_LOSS_FRACTION, + {"rtp.loss_fraction", "percent", "Fraction lost since last RTP SR/RR."}}, + {Stats::Metric::RTP_PKTS_LOST, + {"rtp.pkts_lost", "packets", "Cumulative number of packets lost"}}, + {Stats::Metric::RTP_JITTER, + {"rtp.jitter", "seconds", "Interarrival jitter"}}, }; std::unordered_map Stats::types = { - { Stats::Type::LAST, { "last", SignalType::FLOAT }}, - { Stats::Type::HIGHEST, { "highest", SignalType::FLOAT }}, - { Stats::Type::LOWEST, { "lowest", SignalType::FLOAT }}, - { Stats::Type::MEAN, { "mean", SignalType::FLOAT }}, - { Stats::Type::VAR, { "var", SignalType::FLOAT }}, - { Stats::Type::STDDEV, { "stddev", SignalType::FLOAT }}, - { Stats::Type::TOTAL, { "total", SignalType::INTEGER }} -}; + {Stats::Type::LAST, {"last", SignalType::FLOAT}}, + {Stats::Type::HIGHEST, {"highest", SignalType::FLOAT}}, + {Stats::Type::LOWEST, {"lowest", SignalType::FLOAT}}, + {Stats::Type::MEAN, {"mean", SignalType::FLOAT}}, + {Stats::Type::VAR, {"var", SignalType::FLOAT}}, + {Stats::Type::STDDEV, {"stddev", SignalType::FLOAT}}, + {Stats::Type::TOTAL, {"total", SignalType::INTEGER}}}; std::vector Stats::columns = { - { 10, TableColumn::Alignment::LEFT, "Node", "%s" }, - { 10, TableColumn::Alignment::RIGHT, "Recv", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Sent", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Drop", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Skip", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "OWD last", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "OWD mean", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "Rate last", "%lf", "pkt/sec" }, - { 10, TableColumn::Alignment::RIGHT, "Rate mean", "%lf", "pkt/sec" }, - { 10, TableColumn::Alignment::RIGHT, "Age mean", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "Age Max", "%lf", "sec" }, - { 8, TableColumn::Alignment::RIGHT, "Signals", "%ju", "signals" } -}; + {10, TableColumn::Alignment::LEFT, "Node", "%s"}, + {10, TableColumn::Alignment::RIGHT, "Recv", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Sent", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Drop", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Skip", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "OWD last", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "OWD mean", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "Rate last", "%lf", "pkt/sec"}, + {10, TableColumn::Alignment::RIGHT, "Rate mean", "%lf", "pkt/sec"}, + {10, TableColumn::Alignment::RIGHT, "Age mean", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "Age Max", "%lf", "sec"}, + {8, TableColumn::Alignment::RIGHT, "Signals", "%ju", "signals"}}; -enum Stats::Format Stats::lookupFormat(const std::string &str) -{ - if (str == "human") - return Format::HUMAN; - else if (str == "json") - return Format::JSON; - else if (str == "matlab") - return Format::MATLAB; +enum Stats::Format Stats::lookupFormat(const std::string &str) { + if (str == "human") + return Format::HUMAN; + else if (str == "json") + return Format::JSON; + else if (str == "matlab") + return Format::MATLAB; - throw std::invalid_argument("Invalid format"); + throw std::invalid_argument("Invalid format"); } -enum Stats::Metric Stats::lookupMetric(const std::string &str) -{ - for (auto m : metrics) { - if (str == m.second.name) - return m.first; - } +enum Stats::Metric Stats::lookupMetric(const std::string &str) { + for (auto m : metrics) { + if (str == m.second.name) + return m.first; + } - throw std::invalid_argument("Invalid stats metric"); + throw std::invalid_argument("Invalid stats metric"); } -enum Stats::Type Stats::lookupType(const std::string &str) -{ - for (auto t : types) { - if (str == t.second.name) - return t.first; - } +enum Stats::Type Stats::lookupType(const std::string &str) { + for (auto t : types) { + if (str == t.second.name) + return t.first; + } - throw std::invalid_argument("Invalid stats type"); + throw std::invalid_argument("Invalid stats type"); } -Stats::Stats(int buckets, int warmup) : - logger(logging.get("stats")) -{ - for (auto m : metrics) { - histograms.emplace( - std::piecewise_construct, - std::forward_as_tuple(m.first), - std::forward_as_tuple(buckets, warmup) - ); - } +Stats::Stats(int buckets, int warmup) : logger(logging.get("stats")) { + for (auto m : metrics) { + histograms.emplace(std::piecewise_construct, std::forward_as_tuple(m.first), + std::forward_as_tuple(buckets, warmup)); + } } -void Stats::update(enum Metric m, double val) -{ - histograms[m].put(val); +void Stats::update(enum Metric m, double val) { histograms[m].put(val); } + +void Stats::reset() { + for (auto m : metrics) + histograms[m.first].reset(); } -void Stats::reset() -{ - for (auto m : metrics) - histograms[m.first].reset(); +json_t *Stats::toJson() const { + json_t *obj = json_object(); + + for (auto m : metrics) { + const Hist &h = histograms.at(m.first); + + json_object_set_new(obj, m.second.name, h.toJson()); + } + + return obj; } -json_t * Stats::toJson() const -{ - json_t *obj = json_object(); +void Stats::printHeader(enum Format fmt) { + switch (fmt) { + case Format::HUMAN: + setupTable(); + table->header(); + break; - for (auto m : metrics) { - const Hist &h = histograms.at(m.first); - - json_object_set_new(obj, m.second.name, h.toJson()); - } - - return obj; + default: { + } + } } -void Stats::printHeader(enum Format fmt) -{ - switch (fmt) { - case Format::HUMAN: - setupTable(); - table->header(); - break; - - default: { } - } +void Stats::setupTable() { + if (!table) { + auto logger = logging.get("stats"); + table = std::make_shared
(logger, columns); + } } -void Stats::setupTable() -{ - if (!table) { - auto logger = logging.get("stats"); - table = std::make_shared
(logger, columns); - } +void Stats::printPeriodic(FILE *f, enum Format fmt, node::Node *n) const { + switch (fmt) { + case Format::HUMAN: + setupTable(); + table->row(11, n->getNameShort().c_str(), + (uintmax_t)histograms.at(Metric::OWD).getTotal(), + (uintmax_t)histograms.at(Metric::AGE).getTotal(), + (uintmax_t)histograms.at(Metric::SMPS_REORDERED).getTotal(), + (uintmax_t)histograms.at(Metric::SMPS_SKIPPED).getTotal(), + (double)histograms.at(Metric::OWD).getLast(), + (double)histograms.at(Metric::OWD).getMean(), + (double)1.0 / histograms.at(Metric::GAP_RECEIVED).getLast(), + (double)1.0 / histograms.at(Metric::GAP_RECEIVED).getMean(), + (double)histograms.at(Metric::AGE).getMean(), + (double)histograms.at(Metric::AGE).getHighest(), + (uintmax_t)histograms.at(Metric::SIGNAL_COUNT).getLast()); + break; + + case Format::JSON: { + json_t *json_stats = json_pack( + "{ s: s, s: i, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f, s: f, " + "s: i }", + "node", n->getNameShort().c_str(), "recv", + histograms.at(Metric::OWD).getTotal(), "sent", + histograms.at(Metric::AGE).getTotal(), "dropped", + histograms.at(Metric::SMPS_REORDERED).getTotal(), "skipped", + histograms.at(Metric::SMPS_SKIPPED).getTotal(), "owd_last", + 1.0 / histograms.at(Metric::OWD).getLast(), "owd_mean", + 1.0 / histograms.at(Metric::OWD).getMean(), "rate_last", + 1.0 / histograms.at(Metric::GAP_SAMPLE).getLast(), "rate_mean", + 1.0 / histograms.at(Metric::GAP_SAMPLE).getMean(), "age_mean", + histograms.at(Metric::AGE).getMean(), "age_max", + histograms.at(Metric::AGE).getHighest(), "signals", + histograms.at(Metric::SIGNAL_COUNT).getLast()); + json_dumpf(json_stats, f, 0); + break; + } + + default: { + } + } } -void Stats::printPeriodic(FILE *f, enum Format fmt, node::Node *n) const -{ - switch (fmt) { - case Format::HUMAN: - setupTable(); - table->row(11, - n->getNameShort().c_str(), - (uintmax_t) histograms.at(Metric::OWD).getTotal(), - (uintmax_t) histograms.at(Metric::AGE).getTotal(), - (uintmax_t) histograms.at(Metric::SMPS_REORDERED).getTotal(), - (uintmax_t) histograms.at(Metric::SMPS_SKIPPED).getTotal(), - (double) histograms.at(Metric::OWD).getLast(), - (double) histograms.at(Metric::OWD).getMean(), - (double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getLast(), - (double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getMean(), - (double) histograms.at(Metric::AGE).getMean(), - (double) histograms.at(Metric::AGE).getHighest(), - (uintmax_t) histograms.at(Metric::SIGNAL_COUNT).getLast() - ); - break; +void Stats::print(FILE *f, enum Format fmt, int verbose) const { + switch (fmt) { + case Format::HUMAN: + for (auto m : metrics) { + logger->info("{}: {}", m.second.name, m.second.desc); + histograms.at(m.first).print(logger, verbose); + } + break; - case Format::JSON: { - json_t *json_stats = json_pack("{ s: s, s: i, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f, s: f, s: i }", - "node", n->getNameShort().c_str(), - "recv", histograms.at(Metric::OWD).getTotal(), - "sent", histograms.at(Metric::AGE).getTotal(), - "dropped", histograms.at(Metric::SMPS_REORDERED).getTotal(), - "skipped", histograms.at(Metric::SMPS_SKIPPED).getTotal(), - "owd_last", 1.0 / histograms.at(Metric::OWD).getLast(), - "owd_mean", 1.0 / histograms.at(Metric::OWD).getMean(), - "rate_last", 1.0 / histograms.at(Metric::GAP_SAMPLE).getLast(), - "rate_mean", 1.0 / histograms.at(Metric::GAP_SAMPLE).getMean(), - "age_mean", histograms.at(Metric::AGE).getMean(), - "age_max", histograms.at(Metric::AGE).getHighest(), - "signals", histograms.at(Metric::SIGNAL_COUNT).getLast() - ); - json_dumpf(json_stats, f, 0); - break; - } + case Format::JSON: + json_dumpf(toJson(), f, 0); + fflush(f); + break; - default: { } - } + default: { + } + } } -void Stats::print(FILE *f, enum Format fmt, int verbose) const -{ - switch (fmt) { - case Format::HUMAN: - for (auto m : metrics) { - logger->info("{}: {}", m.second.name, m.second.desc); - histograms.at(m.first).print(logger, verbose); - } - break; +union SignalData Stats::getValue(enum Metric sm, enum Type st) const { + const Hist &h = histograms.at(sm); + union SignalData d; - case Format::JSON: - json_dumpf(toJson(), f, 0); - fflush(f); - break; + switch (st) { + case Type::TOTAL: + d.i = h.getTotal(); + break; - default: { } - } + case Type::LAST: + d.f = h.getLast(); + break; + + case Type::HIGHEST: + d.f = h.getHighest(); + break; + + case Type::LOWEST: + d.f = h.getLowest(); + break; + + case Type::MEAN: + d.f = h.getMean(); + break; + + case Type::STDDEV: + d.f = h.getStddev(); + break; + + case Type::VAR: + d.f = h.getVar(); + break; + + default: + d.f = -1; + } + + return d; } -union SignalData Stats::getValue(enum Metric sm, enum Type st) const -{ - const Hist &h = histograms.at(sm); - union SignalData d; - - switch (st) { - case Type::TOTAL: - d.i = h.getTotal(); - break; - - case Type::LAST: - d.f = h.getLast(); - break; - - case Type::HIGHEST: - d.f = h.getHighest(); - break; - - case Type::LOWEST: - d.f = h.getLowest(); - break; - - case Type::MEAN: - d.f = h.getMean(); - break; - - case Type::STDDEV: - d.f = h.getStddev(); - break; - - case Type::VAR: - d.f = h.getVar(); - break; - - default: - d.f = -1; - } - - return d; -} - -const Hist & Stats::getHistogram(enum Metric sm) const -{ - return histograms.at(sm); +const Hist &Stats::getHistogram(enum Metric sm) const { + return histograms.at(sm); } std::shared_ptr
Stats::table = std::shared_ptr
(); diff --git a/lib/super_node.cpp b/lib/super_node.cpp index 670ece9e1..8cda7a3b3 100644 --- a/lib/super_node.cpp +++ b/lib/super_node.cpp @@ -9,535 +9,510 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef WITH_NETEM - #include +#include #endif using namespace villas; using namespace villas::node; -SuperNode::SuperNode() : - state(State::INITIALIZED), - idleStop(-1), +SuperNode::SuperNode() + : state(State::INITIALIZED), idleStop(-1), #ifdef WITH_API - api(this), + api(this), #endif #ifdef WITH_WEB - #ifdef WITH_API - web(&api), - #else - web(), - #endif +#ifdef WITH_API + web(&api), +#else + web(), #endif - priority(0), - affinity(0), - hugepages(DEFAULT_NR_HUGEPAGES), - statsRate(1.0), - task(CLOCK_REALTIME), - started(time_now()) -{ - int ret; +#endif + priority(0), affinity(0), hugepages(DEFAULT_NR_HUGEPAGES), statsRate(1.0), + task(CLOCK_REALTIME), started(time_now()) { + int ret; - char hname[128]; - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw SystemError("Failed to determine hostname"); + char hname[128]; + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw SystemError("Failed to determine hostname"); - // Default UUID is derived from hostname - uuid::generateFromString(uuid, hname); + // Default UUID is derived from hostname + uuid::generateFromString(uuid, hname); #ifdef WITH_NETEM - kernel::nl::init(); // Fill link cache -#endif // WITH_NETEM + kernel::nl::init(); // Fill link cache +#endif // WITH_NETEM - logger = logging.get("super_node"); + logger = logging.get("super_node"); } -void SuperNode::parse(const std::string &u) -{ - config.root = config.load(u); +void SuperNode::parse(const std::string &u) { + config.root = config.load(u); - parse(config.root); + parse(config.root); } -void SuperNode::parse(json_t *root) -{ - int ret; +void SuperNode::parse(json_t *root) { + int ret; - assert(state == State::PARSED || - state == State::INITIALIZED || - state == State::CHECKED); + assert(state == State::PARSED || state == State::INITIALIZED || + state == State::CHECKED); - const char *uuid_str = nullptr; + const char *uuid_str = nullptr; - json_t *json_nodes = nullptr; - json_t *json_paths = nullptr; - json_t *json_logging = nullptr; - json_t *json_http = nullptr; + json_t *json_nodes = nullptr; + json_t *json_paths = nullptr; + json_t *json_logging = nullptr; + json_t *json_http = nullptr; - json_error_t err; + json_error_t err; - idleStop = 1; + idleStop = 1; - ret = json_unpack_ex(root, &err, 0, "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: i, s?: b, s?: s }", - "stats", &statsRate, - "http", &json_http, - "logging", &json_logging, - "nodes", &json_nodes, - "paths", &json_paths, - "hugepages", &hugepages, - "affinity", &affinity, - "priority", &priority, - "idle_stop", &idleStop, - "uuid", &uuid_str - ); - if (ret) - throw ConfigError(root, err, "node-config", "Unpacking top-level config failed"); + ret = + json_unpack_ex(root, &err, 0, + "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: " + "i, s?: b, s?: s }", + "stats", &statsRate, "http", &json_http, "logging", + &json_logging, "nodes", &json_nodes, "paths", &json_paths, + "hugepages", &hugepages, "affinity", &affinity, "priority", + &priority, "idle_stop", &idleStop, "uuid", &uuid_str); + if (ret) + throw ConfigError(root, err, "node-config", + "Unpacking top-level config failed"); - if (uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(root, "node-config-uuid", "Failed to parse UUID: {}", uuid_str); - } + if (uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(root, "node-config-uuid", "Failed to parse UUID: {}", + uuid_str); + } #ifdef WITH_WEB - if (json_http) - web.parse(json_http); + if (json_http) + web.parse(json_http); #endif // WITH_WEB - if (json_logging) - logging.parse(json_logging); + if (json_logging) + logging.parse(json_logging); - // Parse nodes - if (json_nodes) { - if (!json_is_object(json_nodes)) - throw ConfigError(json_nodes, "node-config-nodes", "Setting 'nodes' must be a group with node name => group mappings."); + // Parse nodes + if (json_nodes) { + if (!json_is_object(json_nodes)) + throw ConfigError( + json_nodes, "node-config-nodes", + "Setting 'nodes' must be a group with node name => group mappings."); - const char *node_name; - json_t *json_node; - json_object_foreach(json_nodes, node_name, json_node) { - uuid_t node_uuid; - const char *node_type; - const char *node_uuid_str = nullptr; + const char *node_name; + json_t *json_node; + json_object_foreach(json_nodes, node_name, json_node) { + uuid_t node_uuid; + const char *node_type; + const char *node_uuid_str = nullptr; - ret = Node::isValidName(node_name); - if (!ret) - throw RuntimeError("Invalid name for node: {}", node_name); + ret = Node::isValidName(node_name); + if (!ret) + throw RuntimeError("Invalid name for node: {}", node_name); - ret = json_unpack_ex(json_node, &err, 0, "{ s: s, s?: s }", - "type", &node_type, - "uuid", &node_uuid_str - ); - if (ret) - throw ConfigError(root, err, "node-config-node-type", "Failed to parse type of node '{}'", node_name); + ret = json_unpack_ex(json_node, &err, 0, "{ s: s, s?: s }", "type", + &node_type, "uuid", &node_uuid_str); + if (ret) + throw ConfigError(root, err, "node-config-node-type", + "Failed to parse type of node '{}'", node_name); - if (node_uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(json_node, "node-config-node-uuid", "Failed to parse UUID: {}", uuid_str); - } - else - // Generate UUID from node name and super-node UUID - uuid::generateFromString(node_uuid, node_name, uuid::toString(uuid)); + if (node_uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(json_node, "node-config-node-uuid", + "Failed to parse UUID: {}", uuid_str); + } else + // Generate UUID from node name and super-node UUID + uuid::generateFromString(node_uuid, node_name, uuid::toString(uuid)); - auto *n = NodeFactory::make(node_type, node_uuid, node_name); - if (!n) - throw MemoryAllocationError(); + auto *n = NodeFactory::make(node_type, node_uuid, node_name); + if (!n) + throw MemoryAllocationError(); - ret = n->parse(json_node); - if (ret) { - auto config_id = fmt::format("node-config-node-{}", node_type); - throw ConfigError(json_node, config_id, "Failed to parse configuration of node '{}'", node_name); - } + ret = n->parse(json_node); + if (ret) { + auto config_id = fmt::format("node-config-node-{}", node_type); + throw ConfigError(json_node, config_id, + "Failed to parse configuration of node '{}'", + node_name); + } - nodes.push_back(n); - } - } + nodes.push_back(n); + } + } - // Parse paths - if (json_paths) { - if (!json_is_array(json_paths)) - logger->warn("Setting 'paths' must be a list of objects"); + // Parse paths + if (json_paths) { + if (!json_is_array(json_paths)) + logger->warn("Setting 'paths' must be a list of objects"); - size_t i; - json_t *json_path; - json_array_foreach(json_paths, i, json_path) { -parse: auto *p = new Path(); - if (!p) - throw MemoryAllocationError(); + size_t i; + json_t *json_path; + json_array_foreach(json_paths, i, json_path) { + parse: + auto *p = new Path(); + if (!p) + throw MemoryAllocationError(); - p->parse(json_path, nodes, uuid); + p->parse(json_path, nodes, uuid); - paths.push_back(p); + paths.push_back(p); - if (p->isReversed()) { - // Only simple paths can be reversed - ret = p->isSimple(); - if (!ret) - throw RuntimeError("Complex paths can not be reversed!"); + if (p->isReversed()) { + // Only simple paths can be reversed + ret = p->isSimple(); + if (!ret) + throw RuntimeError("Complex paths can not be reversed!"); - // Parse a second time with in/out reversed - json_path = json_copy(json_path); + // Parse a second time with in/out reversed + json_path = json_copy(json_path); - json_t *json_in = json_object_get(json_path, "in"); - json_t *json_out = json_object_get(json_path, "out"); + json_t *json_in = json_object_get(json_path, "in"); + json_t *json_out = json_object_get(json_path, "out"); - if (json_equal(json_in, json_out)) - throw RuntimeError("Can not reverse path with identical in/out nodes!"); + if (json_equal(json_in, json_out)) + throw RuntimeError( + "Can not reverse path with identical in/out nodes!"); - json_object_set(json_path, "reverse", json_false()); - json_object_set(json_path, "in", json_out); - json_object_set(json_path, "out", json_in); + json_object_set(json_path, "reverse", json_false()); + json_object_set(json_path, "in", json_out); + json_object_set(json_path, "out", json_in); - goto parse; - } - } - } + goto parse; + } + } + } - state = State::PARSED; + state = State::PARSED; } -void SuperNode::check() -{ - int ret; +void SuperNode::check() { + int ret; - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED); + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED); - for (auto *n : nodes) { - ret = n->check(); - if (ret) - throw RuntimeError("Invalid configuration for node {}", n->getName()); - } + for (auto *n : nodes) { + ret = n->check(); + if (ret) + throw RuntimeError("Invalid configuration for node {}", n->getName()); + } - for (auto *p : paths) - p->check(); + for (auto *p : paths) + p->check(); - state = State::CHECKED; + state = State::CHECKED; } -void SuperNode::prepareNodeTypes() -{ - int ret; +void SuperNode::prepareNodeTypes() { + int ret; - for (auto *n : nodes) { - auto *nf = n->getFactory(); + for (auto *n : nodes) { + auto *nf = n->getFactory(); - if (nf->getState() == State::STARTED) - continue; + if (nf->getState() == State::STARTED) + continue; - ret = nf->start(this); - if (ret) - throw RuntimeError("Failed to start node-type: {}", n->getFactory()->getName()); - } + ret = nf->start(this); + if (ret) + throw RuntimeError("Failed to start node-type: {}", + n->getFactory()->getName()); + } } -void SuperNode::startInterfaces() -{ +void SuperNode::startInterfaces() { #ifdef WITH_NETEM - int ret; + int ret; - for (auto *i : interfaces) { - ret = i->start(); - if (ret) - throw RuntimeError("Failed to start network interface: {}", i->getName()); - } + for (auto *i : interfaces) { + ret = i->start(); + if (ret) + throw RuntimeError("Failed to start network interface: {}", i->getName()); + } #endif // WITH_NETEM } -void SuperNode::startNodes() -{ - int ret; +void SuperNode::startNodes() { + int ret; - for (auto *n : nodes) { - if (!n->isEnabled()) - continue; + for (auto *n : nodes) { + if (!n->isEnabled()) + continue; - ret = n->start(); - if (ret) - throw RuntimeError("Failed to start node: {}", n->getName()); - } + ret = n->start(); + if (ret) + throw RuntimeError("Failed to start node: {}", n->getName()); + } } -void SuperNode::startPaths() -{ - for (auto *p : paths) { - if (!p->isEnabled()) - continue; +void SuperNode::startPaths() { + for (auto *p : paths) { + if (!p->isEnabled()) + continue; - p->start(); - } + p->start(); + } } -void SuperNode::prepareNodes() -{ - int ret; +void SuperNode::prepareNodes() { + int ret; - for (auto *n : nodes) { - if (!n->isEnabled()) - continue; + for (auto *n : nodes) { + if (!n->isEnabled()) + continue; - ret = n->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node: {}", n->getName()); - } + ret = n->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node: {}", n->getName()); + } } -void SuperNode::preparePaths() -{ - for (auto *p : paths) { - if (!p->isEnabled()) - continue; +void SuperNode::preparePaths() { + for (auto *p : paths) { + if (!p->isEnabled()) + continue; - p->prepare(nodes); - } + p->prepare(nodes); + } } -void SuperNode::prepare() -{ - int ret; +void SuperNode::prepare() { + int ret; - assert(state == State::CHECKED); + assert(state == State::CHECKED); - ret = memory::init(hugepages); - if (ret) - throw RuntimeError("Failed to initialize memory system"); + ret = memory::init(hugepages); + if (ret) + throw RuntimeError("Failed to initialize memory system"); - kernel::rt::init(priority, affinity); + kernel::rt::init(priority, affinity); - prepareNodeTypes(); - prepareNodes(); - preparePaths(); + prepareNodeTypes(); + prepareNodes(); + preparePaths(); - for (auto *n : nodes) { - if (n->sources.size() == 0 && - n->destinations.size() == 0) { - logger->info("Node {} is not used by any path. Disabling...", n->getName()); - n->setEnabled(false); - } - } + for (auto *n : nodes) { + if (n->sources.size() == 0 && n->destinations.size() == 0) { + logger->info("Node {} is not used by any path. Disabling...", + n->getName()); + n->setEnabled(false); + } + } - state = State::PREPARED; + state = State::PREPARED; } -void SuperNode::start() -{ - assert(state == State::PREPARED); +void SuperNode::start() { + assert(state == State::PREPARED); #ifdef WITH_API - api.start(); + api.start(); #endif #ifdef WITH_WEB - web.start(); + web.start(); #endif - startInterfaces(); - startNodes(); - startPaths(); + startInterfaces(); + startNodes(); + startPaths(); - if (statsRate > 0) // A rate <0 will disable the periodic stats - task.setRate(statsRate); + if (statsRate > 0) // A rate <0 will disable the periodic stats + task.setRate(statsRate); - Stats::printHeader(Stats::Format::HUMAN); + Stats::printHeader(Stats::Format::HUMAN); - state = State::STARTED; + state = State::STARTED; } -void SuperNode::stopPaths() -{ - for (auto *p : paths) { - if (p->getState() == State::STARTED || - p->getState() == State::PAUSED) - p->stop(); - } +void SuperNode::stopPaths() { + for (auto *p : paths) { + if (p->getState() == State::STARTED || p->getState() == State::PAUSED) + p->stop(); + } } -void SuperNode::stopNodes() -{ - int ret; +void SuperNode::stopNodes() { + int ret; - for (auto *n : nodes) { - if (n->getState() == State::STARTED || - n->getState() == State::PAUSED || - n->getState() == State::STOPPING) { - ret = n->stop(); - if (ret) - throw RuntimeError("Failed to stop node: {}", n->getName()); - } - } + for (auto *n : nodes) { + if (n->getState() == State::STARTED || n->getState() == State::PAUSED || + n->getState() == State::STOPPING) { + ret = n->stop(); + if (ret) + throw RuntimeError("Failed to stop node: {}", n->getName()); + } + } } -void SuperNode::stopNodeTypes() -{ - int ret; +void SuperNode::stopNodeTypes() { + int ret; - for (auto *n : nodes) { - auto *nf = n->getFactory(); + for (auto *n : nodes) { + auto *nf = n->getFactory(); - if (nf->getState() != State::STARTED) - continue; + if (nf->getState() != State::STARTED) + continue; - ret = nf->stop(); - if (ret) - throw RuntimeError("Failed to stop node-type: {}", n->getFactory()->getName()); - } + ret = nf->stop(); + if (ret) + throw RuntimeError("Failed to stop node-type: {}", + n->getFactory()->getName()); + } } -void SuperNode::stopInterfaces() -{ +void SuperNode::stopInterfaces() { #ifdef WITH_NETEM - int ret; + int ret; - for (auto *i : interfaces) { - ret = i->stop(); - if (ret) - throw RuntimeError("Failed to stop interface: {}", i->getName()); - } + for (auto *i : interfaces) { + ret = i->stop(); + if (ret) + throw RuntimeError("Failed to stop interface: {}", i->getName()); + } #endif // WITH_NETEM } -void SuperNode::stop() -{ - stopNodes(); - stopPaths(); - stopNodeTypes(); - stopInterfaces(); +void SuperNode::stop() { + stopNodes(); + stopPaths(); + stopNodeTypes(); + stopInterfaces(); #ifdef WITH_API - api.stop(); + api.stop(); #endif #ifdef WITH_WEB - web.stop(); + web.stop(); #endif - state = State::STOPPED; + state = State::STOPPED; } -void SuperNode::run() -{ - int ret; +void SuperNode::run() { + int ret; - while (state == State::STARTED) { - task.wait(); + while (state == State::STARTED) { + task.wait(); - ret = periodic(); - if (ret) - state = State::STOPPING; - } + ret = periodic(); + if (ret) + state = State::STOPPING; + } } -SuperNode::~SuperNode() -{ - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED || - state == State::STOPPED || - state == State::PREPARED); +SuperNode::~SuperNode() { + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED || state == State::STOPPED || + state == State::PREPARED); - for (auto *p : paths) - delete p; + for (auto *p : paths) + delete p; - for (auto *n : nodes) - delete n; + for (auto *n : nodes) + delete n; } -int SuperNode::periodic() -{ - int started = 0; +int SuperNode::periodic() { + int started = 0; - for (auto *p : paths) { - if (p->getState() == State::STARTED) { - started++; + for (auto *p : paths) { + if (p->getState() == State::STARTED) { + started++; #ifdef WITH_HOOKS - p->hooks.periodic(); + p->hooks.periodic(); #endif // WITH_HOOKS - } - } + } + } - for (auto *n : nodes) { - if (n->getState() == State::STARTED) { + for (auto *n : nodes) { + if (n->getState() == State::STARTED) { #ifdef WITH_HOOKS - n->in.hooks.periodic(); - n->out.hooks.periodic(); + n->in.hooks.periodic(); + n->out.hooks.periodic(); #endif // WITH_HOOKS - } - } + } + } - if (idleStop > 0 && state == State::STARTED && started == 0) { - logger->info("No more active paths. Stopping super-node"); + if (idleStop > 0 && state == State::STARTED && started == 0) { + logger->info("No more active paths. Stopping super-node"); - return -1; - } + return -1; + } - return 0; + return 0; } #ifdef WITH_GRAPHVIZ -static -void set_attr(void *ptr, const std::string &key, const std::string &value, bool html = false) { - Agraph_t *g = agraphof(ptr); +static void set_attr(void *ptr, const std::string &key, + const std::string &value, bool html = false) { + Agraph_t *g = agraphof(ptr); - char *d = (char *) ""; - char *k = (char *) key.c_str(); - char *v = (char *) value.c_str(); - char *vd = html ? agstrdup_html(g, v) : agstrdup(g, v); + char *d = (char *)""; + char *k = (char *)key.c_str(); + char *v = (char *)value.c_str(); + char *vd = html ? agstrdup_html(g, v) : agstrdup(g, v); - agsafeset(ptr, k, vd, d); + agsafeset(ptr, k, vd, d); } -graph_t * SuperNode::getGraph() -{ - Agraph_t *g; - Agnode_t *m; +graph_t *SuperNode::getGraph() { + Agraph_t *g; + Agnode_t *m; - g = agopen((char *) "g", Agdirected, 0); + g = agopen((char *)"g", Agdirected, 0); - std::map nodeMap; + std::map nodeMap; - for (auto *n : nodes) { - nodeMap[n] = agnode(g, (char *) n->getNameShort().c_str(), 1); + for (auto *n : nodes) { + nodeMap[n] = agnode(g, (char *)n->getNameShort().c_str(), 1); - set_attr(nodeMap[n], "shape", "ellipse"); - set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", n->getFactory()->getName(), uuid::toString(n->getUuid()).c_str())); - // set_attr(nodeMap[n], "fixedsize", "true"); - // set_attr(nodeMap[n], "width", "0.15"); - // set_attr(nodeMap[n], "height", "0.15"); - } + set_attr(nodeMap[n], "shape", "ellipse"); + set_attr(nodeMap[n], "tooltip", + fmt::format("type={}, uuid={}", n->getFactory()->getName(), + uuid::toString(n->getUuid()).c_str())); + // set_attr(nodeMap[n], "fixedsize", "true"); + // set_attr(nodeMap[n], "width", "0.15"); + // set_attr(nodeMap[n], "height", "0.15"); + } - unsigned i = 0; - for (auto *p : paths) { - auto name = fmt::format("path_{}", i++); + unsigned i = 0; + for (auto *p : paths) { + auto name = fmt::format("path_{}", i++); - m = agnode(g, (char *) name.c_str(), 1); + m = agnode(g, (char *)name.c_str(), 1); - set_attr(m, "shape", "box"); - set_attr(m, "tooltip", fmt::format("uuid={}", uuid::toString(p->getUuid()).c_str())); + set_attr(m, "shape", "box"); + set_attr(m, "tooltip", + fmt::format("uuid={}", uuid::toString(p->getUuid()).c_str())); - for (auto ps : p->sources) - agedge(g, nodeMap[ps->getNode()], m, nullptr, 1); + for (auto ps : p->sources) + agedge(g, nodeMap[ps->getNode()], m, nullptr, 1); - for (auto pd : p->destinations) - agedge(g, m, nodeMap[pd->getNode()], nullptr, 1); - } - - return g; + for (auto pd : p->destinations) + agedge(g, m, nodeMap[pd->getNode()], nullptr, 1); + } + return g; } #endif // WITH_GRAPHVIZ diff --git a/lib/usb.cpp b/lib/usb.cpp index ed3cd3499..6c3f3dd79 100644 --- a/lib/usb.cpp +++ b/lib/usb.cpp @@ -5,146 +5,131 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::usb; -static -struct libusb_context *context = nullptr; +static struct libusb_context *context = nullptr; -static -int context_users = 0; +static int context_users = 0; -static -Logger logger; +static Logger logger; -static -enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) -{ - switch (lvl) { - case Log::Level::trace: - case Log::Level::debug: - return LIBUSB_LOG_LEVEL_DEBUG; +static enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) { + switch (lvl) { + case Log::Level::trace: + case Log::Level::debug: + return LIBUSB_LOG_LEVEL_DEBUG; - case Log::Level::info: - return LIBUSB_LOG_LEVEL_INFO; + case Log::Level::info: + return LIBUSB_LOG_LEVEL_INFO; - case Log::Level::warn: - return LIBUSB_LOG_LEVEL_WARNING; + case Log::Level::warn: + return LIBUSB_LOG_LEVEL_WARNING; - case Log::Level::err: - case Log::Level::critical: - return LIBUSB_LOG_LEVEL_ERROR; + case Log::Level::err: + case Log::Level::critical: + return LIBUSB_LOG_LEVEL_ERROR; - default: - case Log::Level::off: - return LIBUSB_LOG_LEVEL_NONE; - - } + default: + case Log::Level::off: + return LIBUSB_LOG_LEVEL_NONE; + } } -static -Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) -{ - switch (lvl) { - case LIBUSB_LOG_LEVEL_ERROR: - return Log::Level::err; +static Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) { + switch (lvl) { + case LIBUSB_LOG_LEVEL_ERROR: + return Log::Level::err; - case LIBUSB_LOG_LEVEL_WARNING: - return Log::Level::warn; + case LIBUSB_LOG_LEVEL_WARNING: + return Log::Level::warn; - case LIBUSB_LOG_LEVEL_INFO: - return Log::Level::info; + case LIBUSB_LOG_LEVEL_INFO: + return Log::Level::info; - case LIBUSB_LOG_LEVEL_DEBUG: - return Log::Level::debug; + case LIBUSB_LOG_LEVEL_DEBUG: + return Log::Level::debug; - case LIBUSB_LOG_LEVEL_NONE: - default: - return Log::Level::off; - } + case LIBUSB_LOG_LEVEL_NONE: + default: + return Log::Level::off; + } } -static -void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, const char *str) -{ - auto level = libusb_to_spdlog_log_level(lvl); +static void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, + const char *str) { + auto level = libusb_to_spdlog_log_level(lvl); - logger->log(level, str); + logger->log(level, str); } -void villas::usb::detach(struct libusb_device_handle *handle, int iface) -{ - int ret; +void villas::usb::detach(struct libusb_device_handle *handle, int iface) { + int ret; - ret = libusb_detach_kernel_driver(handle, iface); - if (ret != LIBUSB_SUCCESS) - throw Error(ret, "Failed to detach USB device from kernel driver"); + ret = libusb_detach_kernel_driver(handle, iface); + if (ret != LIBUSB_SUCCESS) + throw Error(ret, "Failed to detach USB device from kernel driver"); } -struct libusb_context * villas::usb::init() -{ - int ret; - struct libusb_context *ctx; +struct libusb_context *villas::usb::init() { + int ret; + struct libusb_context *ctx; - logger = logging.get("usb"); + logger = logging.get("usb"); - ret = libusb_init(&ctx); - if (ret) - throw Error(ret, "Failed to initialize libusb context"); + ret = libusb_init(&ctx); + if (ret) + throw Error(ret, "Failed to initialize libusb context"); - auto lvl = spdlog_to_libusb_log_level(logger->level()); + auto lvl = spdlog_to_libusb_log_level(logger->level()); #if LIBUSBX_API_VERSION < 0x01000106 - libusb_set_debug(ctx, lvl); + libusb_set_debug(ctx, lvl); #else - ret = libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, lvl); - if (ret) - throw Error(ret, "Failed to set libusb log level"); + ret = libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, lvl); + if (ret) + throw Error(ret, "Failed to set libusb log level"); #endif - libusb_set_log_cb(ctx, log_cb, LIBUSB_LOG_CB_GLOBAL); + libusb_set_log_cb(ctx, log_cb, LIBUSB_LOG_CB_GLOBAL); - return ctx; + return ctx; } -void villas::usb::deinit_context(struct libusb_context *ctx) -{ - context_users--; +void villas::usb::deinit_context(struct libusb_context *ctx) { + context_users--; - if (context_users == 0) { - libusb_exit(ctx); - context = nullptr; - } + if (context_users == 0) { + libusb_exit(ctx); + context = nullptr; + } } -struct libusb_context * villas::usb::get_context() -{ - if (context == nullptr) - context = init(); +struct libusb_context *villas::usb::get_context() { + if (context == nullptr) + context = init(); - context_users++; + context_users++; - return context; + return context; } -bool Device::match(const Filter *flt) const -{ - return (flt->bus < 0 || flt->bus == getBus()) && - (flt->port < 0 || flt->port == getPort()) && - (flt->vendor_id < 0 || flt->vendor_id == getDescriptor().idVendor) && - (flt->product_id < 0 || flt->product_id == getDescriptor().idProduct); +bool Device::match(const Filter *flt) const { + return (flt->bus < 0 || flt->bus == getBus()) && + (flt->port < 0 || flt->port == getPort()) && + (flt->vendor_id < 0 || flt->vendor_id == getDescriptor().idVendor) && + (flt->product_id < 0 || flt->product_id == getDescriptor().idProduct); } -std::string Device::getStringDescriptor(uint8_t desc_id) const -{ - int ret; - unsigned char buf[256]; +std::string Device::getStringDescriptor(uint8_t desc_id) const { + int ret; + unsigned char buf[256]; - ret = libusb_get_string_descriptor_ascii(handle, desc_id, buf, sizeof(buf)); - if (ret != LIBUSB_SUCCESS) - throw RuntimeError("Failed to get USB string descriptor"); + ret = libusb_get_string_descriptor_ascii(handle, desc_id, buf, sizeof(buf)); + if (ret != LIBUSB_SUCCESS) + throw RuntimeError("Failed to get USB string descriptor"); - return (char *) buf; + return (char *)buf; } diff --git a/lib/web.cpp b/lib/web.cpp index 5c95d2455..b3e6d2251 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -7,17 +7,17 @@ #include -#include -#include -#include -#include #include #include +#include +#include #include #include +#include +#include #ifdef WITH_NODE_WEBRTC - #include +#include #endif using namespace villas; @@ -28,267 +28,242 @@ lws_callback_function villas::node::websocket_protocol_cb; // List of libwebsockets protocols. lws_protocols protocols[] = { - { - .name = "http", - .callback = lws_callback_http_dummy, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, + {.name = "http", + .callback = lws_callback_http_dummy, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, #ifdef WITH_API - { - .name = "http-api", - .callback = api::Session::protocolCallback, - .per_session_data_size = sizeof(api::Session), - .rx_buffer_size = 1024 - }, + {.name = "http-api", + .callback = api::Session::protocolCallback, + .per_session_data_size = sizeof(api::Session), + .rx_buffer_size = 1024}, #endif // WITH_API #ifdef WITH_NODE_WEBSOCKET - { - .name = "live", - .callback = websocket_protocol_cb, - .per_session_data_size = sizeof(websocket_connection), - .rx_buffer_size = 0 - }, + {.name = "live", + .callback = websocket_protocol_cb, + .per_session_data_size = sizeof(websocket_connection), + .rx_buffer_size = 0}, #endif // WITH_NODE_WEBSOCKET #ifdef WITH_NODE_WEBRTC - { - .name = "webrtc-signaling", - .callback = webrtc::SignalingClient::protocolCallbackStatic, - .per_session_data_size = sizeof(webrtc::SignalingClient), - .rx_buffer_size = 0 - }, + {.name = "webrtc-signaling", + .callback = webrtc::SignalingClient::protocolCallbackStatic, + .per_session_data_size = sizeof(webrtc::SignalingClient), + .rx_buffer_size = 0}, #endif - { - .name = nullptr, - } -}; + { + .name = nullptr, + }}; // List of libwebsockets mounts. -static -lws_http_mount mounts[] = { +static lws_http_mount mounts[] = { #ifdef WITH_API - { - .mount_next = nullptr, // linked-list "next" - .mountpoint = "/api/v2", // mountpoint URL - .origin = "http-api", // protocol - .def = nullptr, - .protocol = "http-api", - .cgienv = nullptr, - .extra_mimetypes = nullptr, - .interpret = nullptr, - .cgi_timeout = 0, - .cache_max_age = 0, - .auth_mask = 0, - .cache_reusable = 0, - .cache_revalidate = 0, - .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, // dynamic - .mountpoint_len = 7 // char count - } + { + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v2", // mountpoint URL + .origin = "http-api", // protocol + .def = nullptr, + .protocol = "http-api", + .cgienv = nullptr, + .extra_mimetypes = nullptr, + .interpret = nullptr, + .cgi_timeout = 0, + .cache_max_age = 0, + .auth_mask = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7 // char count + } #endif // WITH_API }; // List of libwebsockets extensions. -static -const lws_extension extensions[] = { +static const lws_extension extensions[] = { #ifdef LWS_DEFLATE_FOUND - { - .name = "permessage-deflate", - .callback = lws_extension_callback_pm_deflate, - .client_offer = "permessage-deflate" - }, - { - .name = "deflate-frame", - .callback = lws_extension_callback_pm_deflate, - .client_offer = "deflate_frame" - }, + {.name = "permessage-deflate", + .callback = lws_extension_callback_pm_deflate, + .client_offer = "permessage-deflate"}, + {.name = "deflate-frame", + .callback = lws_extension_callback_pm_deflate, + .client_offer = "deflate_frame"}, #endif // LWS_DEFLATE_FOUND - { nullptr /* terminator */ } -}; + {nullptr /* terminator */}}; void Web::lwsLogger(int lws_lvl, const char *msg) { - char *nl; + char *nl; - nl = (char *) strchr(msg, '\n'); - if (nl) - *nl = 0; + nl = (char *)strchr(msg, '\n'); + if (nl) + *nl = 0; - // Decrease severity for some errors - if (strstr(msg, "Unable to open") == msg) - lws_lvl = LLL_WARN; + // Decrease severity for some errors + if (strstr(msg, "Unable to open") == msg) + lws_lvl = LLL_WARN; - Logger logger = logging.get("lws"); + Logger logger = logging.get("lws"); - switch (lws_lvl) { - case LLL_ERR: - logger->error("{}", msg); - break; + switch (lws_lvl) { + case LLL_ERR: + logger->error("{}", msg); + break; - case LLL_WARN: - logger->warn("{}", msg); - break; + case LLL_WARN: + logger->warn("{}", msg); + break; - case LLL_NOTICE: - case LLL_INFO: - logger->info("{}", msg); - break; + case LLL_NOTICE: + case LLL_INFO: + logger->info("{}", msg); + break; - default: // Everything else is debug - logger->debug("{}", msg); - } + default: // Everything else is debug + logger->debug("{}", msg); + } } int Web::lwsLogLevel(Log::Level lvl) { - int lwsLvl = 0; + int lwsLvl = 0; - switch (lvl) { - case Log::Level::trace: - lwsLvl |= LLL_THREAD | LLL_USER | LLL_LATENCY | LLL_CLIENT | LLL_EXT | LLL_HEADER | LLL_PARSER; - case Log::Level::debug: - lwsLvl |= LLL_DEBUG | LLL_NOTICE | LLL_INFO; - case Log::Level::info: - case Log::Level::warn: - lwsLvl |= LLL_WARN; - case Log::Level::err: - lwsLvl |= LLL_ERR; - case Log::Level::critical: - case Log::Level::off: - default: { } - } + switch (lvl) { + case Log::Level::trace: + lwsLvl |= LLL_THREAD | LLL_USER | LLL_LATENCY | LLL_CLIENT | LLL_EXT | + LLL_HEADER | LLL_PARSER; + case Log::Level::debug: + lwsLvl |= LLL_DEBUG | LLL_NOTICE | LLL_INFO; + case Log::Level::info: + case Log::Level::warn: + lwsLvl |= LLL_WARN; + case Log::Level::err: + lwsLvl |= LLL_ERR; + case Log::Level::critical: + case Log::Level::off: + default: { + } + } - return lwsLvl; + return lwsLvl; } -void Web::worker() -{ - logger->info("Started worker"); +void Web::worker() { + logger->info("Started worker"); - while (running) { - lws_service(context, 0); + while (running) { + lws_service(context, 0); - while (!writables.empty()) { - auto *wsi = writables.pop(); + while (!writables.empty()) { + auto *wsi = writables.pop(); - lws_callback_on_writable(wsi); - } - } + lws_callback_on_writable(wsi); + } + } - logger->info("Stopped worker"); + logger->info("Stopped worker"); } -Web::Web(Api *a) : - state(State::INITIALIZED), - logger(logging.get("web")), - context(nullptr), - vhost(nullptr), - port(getuid() > 0 ? 8080 : 80), - api(a) -{ - lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); +Web::Web(Api *a) + : state(State::INITIALIZED), logger(logging.get("web")), context(nullptr), + vhost(nullptr), port(getuid() > 0 ? 8080 : 80), api(a) { + lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); } -Web::~Web() -{ - if (state == State::STARTED) - stop(); +Web::~Web() { + if (state == State::STARTED) + stop(); } -int Web::parse(json_t *json) -{ - int ret, enabled = 1; - const char *cert = nullptr; - const char *pkey = nullptr; - json_error_t err; +int Web::parse(json_t *json) { + int ret, enabled = 1; + const char *cert = nullptr; + const char *pkey = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: i, s?: b }", - "ssl_cert", &cert, - "ssl_private_key", &pkey, - "port", &port, - "enabled", &enabled - ); - if (ret) - throw ConfigError(json, err, "node-config-http"); + ret = json_unpack_ex( + json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: i, s?: b }", "ssl_cert", + &cert, "ssl_private_key", &pkey, "port", &port, "enabled", &enabled); + if (ret) + throw ConfigError(json, err, "node-config-http"); - if (cert) - ssl_cert = cert; + if (cert) + ssl_cert = cert; - if (pkey) - ssl_private_key = pkey; + if (pkey) + ssl_private_key = pkey; - if (!enabled) - port = CONTEXT_PORT_NO_LISTEN; + if (!enabled) + port = CONTEXT_PORT_NO_LISTEN; - state = State::PARSED; + state = State::PARSED; - return 0; + return 0; } -void Web::start() -{ - // Start server - lws_context_creation_info ctx_info; +void Web::start() { + // Start server + lws_context_creation_info ctx_info; - memset(&ctx_info, 0, sizeof(ctx_info)); + memset(&ctx_info, 0, sizeof(ctx_info)); - ctx_info.port = port; - ctx_info.protocols = protocols; + ctx_info.port = port; + ctx_info.protocols = protocols; #ifndef LWS_WITHOUT_EXTENSIONS - ctx_info.extensions = extensions; + ctx_info.extensions = extensions; #endif - ctx_info.ssl_cert_filepath = ssl_cert.empty() ? nullptr : ssl_cert.c_str(); - ctx_info.ssl_private_key_filepath = ssl_private_key.empty() ? nullptr : ssl_private_key.c_str(); - ctx_info.gid = -1; - ctx_info.uid = -1; - ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctx_info.user = (void *) this; + ctx_info.ssl_cert_filepath = ssl_cert.empty() ? nullptr : ssl_cert.c_str(); + ctx_info.ssl_private_key_filepath = + ssl_private_key.empty() ? nullptr : ssl_private_key.c_str(); + ctx_info.gid = -1; + ctx_info.uid = -1; + ctx_info.options = + LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctx_info.user = (void *)this; #if LWS_LIBRARY_VERSION_NUMBER <= 3000000 - // See: https://github.com/warmcat/libwebsockets/issues/1249 - ctx_info.max_http_header_pool = 1024; + // See: https://github.com/warmcat/libwebsockets/issues/1249 + ctx_info.max_http_header_pool = 1024; #endif - ctx_info.mounts = mounts; + ctx_info.mounts = mounts; - logger->info("Starting sub-system"); + logger->info("Starting sub-system"); - context = lws_create_context(&ctx_info); - if (context == nullptr) - throw RuntimeError("Failed to initialize server context"); + context = lws_create_context(&ctx_info); + if (context == nullptr) + throw RuntimeError("Failed to initialize server context"); - for (int tries = 10; tries > 0; tries--) { - vhost = lws_create_vhost(context, &ctx_info); - if (vhost) - break; + for (int tries = 10; tries > 0; tries--) { + vhost = lws_create_vhost(context, &ctx_info); + if (vhost) + break; - ctx_info.port++; - logger->warn("Failed to setup vhost. Trying another port: {}", ctx_info.port); - } + ctx_info.port++; + logger->warn("Failed to setup vhost. Trying another port: {}", + ctx_info.port); + } - if (vhost == nullptr) - throw RuntimeError("Failed to initialize virtual host"); + if (vhost == nullptr) + throw RuntimeError("Failed to initialize virtual host"); - // Start thread - running = true; - thread = std::thread(&Web::worker, this); + // Start thread + running = true; + thread = std::thread(&Web::worker, this); - state = State::STARTED; + state = State::STARTED; } -void Web::stop() -{ - assert(state == State::STARTED); +void Web::stop() { + assert(state == State::STARTED); - logger->info("Stopping sub-system"); + logger->info("Stopping sub-system"); - running = false; - lws_cancel_service(context); - thread.join(); + running = false; + lws_cancel_service(context); + thread.join(); - lws_context_destroy(context); + lws_context_destroy(context); - state = State::STOPPED; + state = State::STOPPED; } -void Web::callbackOnWritable(lws *wsi) -{ - writables.push(wsi); - lws_cancel_service(context); +void Web::callbackOnWritable(lws *wsi) { + writables.push(wsi); + lws_cancel_service(context); } diff --git a/plugins/example_hook.cpp b/plugins/example_hook.cpp index 0ab18dfca..1c56ce885 100644 --- a/plugins/example_hook.cpp +++ b/plugins/example_hook.cpp @@ -14,19 +14,17 @@ namespace node { class ExampleHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - void restart() - { - logger->info("The path {} restarted!", path->toString()); - } + virtual void restart() { + logger->info("The path {} restarted!", path->toString()); + } }; // Register hook static char n[] = "example"; static char d[] = "This is just a simple example hook"; -static HookPlugin p; +static HookPlugin p; } // namespace node } // namespace villas diff --git a/src/villas-compare.cpp b/src/villas-compare.cpp index 6305ede22..09fa071b7 100644 --- a/src/villas-compare.cpp +++ b/src/villas-compare.cpp @@ -10,14 +10,14 @@ #include -#include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include using namespace villas; @@ -28,251 +28,250 @@ namespace tools { class CompareSide { public: - std::string path; - std::string dtypes; - std::string format; + std::string path; + std::string dtypes; + std::string format; - struct Sample *sample; + struct Sample *sample; - Format *formatter; + Format *formatter; - FILE *stream; + FILE *stream; - CompareSide(const CompareSide&) = delete; - CompareSide & operator=(const CompareSide&) = delete; + CompareSide(const CompareSide &) = delete; + CompareSide &operator=(const CompareSide &) = delete; - CompareSide(const std::string &pth, const std::string &fmt, const std::string &dt, struct Pool *p) : - path(pth), - dtypes(dt), - format(fmt) - { - json_t *json_format; - json_error_t err; + CompareSide(const std::string &pth, const std::string &fmt, + const std::string &dt, struct Pool *p) + : path(pth), dtypes(dt), format(fmt) { + json_t *json_format; + json_error_t err; - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize formatter"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize formatter"); - formatter->start(dtypes); + formatter->start(dtypes); - stream = fopen(path.c_str(), "r"); - if (!stream) - throw SystemError("Failed to open file: {}", path); + stream = fopen(path.c_str(), "r"); + if (!stream) + throw SystemError("Failed to open file: {}", path); - sample = sample_alloc(p); - if (!sample) - throw RuntimeError("Failed to allocate samples"); - } + sample = sample_alloc(p); + if (!sample) + throw RuntimeError("Failed to allocate samples"); + } - ~CompareSide() noexcept(false) - { - int ret __attribute((unused)); + ~CompareSide() noexcept(false) { + int ret __attribute((unused)); - ret = fclose(stream); + ret = fclose(stream); - delete formatter; + delete formatter; - sample_decref(sample); - } + sample_decref(sample); + } }; class Compare : public Tool { public: - Compare(int argc, char *argv[]) : - Tool(argc, argv, "test-cmp"), - pool(), - epsilon(1e-6), - format("villas.human"), - dtypes("64f"), - flags((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN) - { - int ret; + Compare(int argc, char *argv[]) + : Tool(argc, argv, "test-cmp"), pool(), epsilon(1e-6), + format("villas.human"), dtypes("64f"), + flags((int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - struct Pool pool; + struct Pool pool; - double epsilon; - std::string format; - std::string dtypes; - int flags; + double epsilon; + std::string format; + std::string dtypes; + int flags; - std::vector filenames; + std::vector filenames; - void usage() - { - std::cout << "Usage: villas-compare [OPTIONS] FILE1 FILE2 ... FILEn" << std::endl - << " FILE a list of files to compare" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL adjust the debug level" << std::endl - << " -e EPS set epsilon for floating point comparisons to EPS" << std::endl - << " -v ignore data values" << std::endl - << " -T ignore timestamp" << std::endl - << " -s ignore sequence no" << std::endl - << " -f FMT file format for all files" << std::endl - << " -t DT the data-type format string" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl - << "Return codes:" << std::endl - << " 0 files are equal" << std::endl - << " 1 file length not equal" << std::endl - << " 2 sequence no not equal" << std::endl - << " 3 timestamp not equal" << std::endl - << " 4 number of values is not equal" << std::endl - << " 5 data is not equal" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-compare [OPTIONS] FILE1 FILE2 ... FILEn" + << std::endl + << " FILE a list of files to compare" << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -d LVL adjust the debug level" << std::endl + << " -e EPS set epsilon for floating point comparisons to EPS" + << std::endl + << " -v ignore data values" << std::endl + << " -T ignore timestamp" << std::endl + << " -s ignore sequence no" << std::endl + << " -f FMT file format for all files" << std::endl + << " -t DT the data-type format string" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl + << "Return codes:" << std::endl + << " 0 files are equal" << std::endl + << " 1 file length not equal" << std::endl + << " 2 sequence no not equal" << std::endl + << " 3 timestamp not equal" << std::endl + << " 4 number of values is not equal" << std::endl + << " 5 data is not equal" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse Arguments - int c; - char *endptr; - while ((c = getopt (argc, argv, "he:vTsf:t:Vd:")) != -1) { - switch (c) { - case 'e': - epsilon = strtod(optarg, &endptr); - goto check; + void parse() { + // Parse Arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "he:vTsf:t:Vd:")) != -1) { + switch (c) { + case 'e': + epsilon = strtod(optarg, &endptr); + goto check; - case 'v': - flags &= ~(int) SampleFlags::HAS_DATA; - break; + case 'v': + flags &= ~(int)SampleFlags::HAS_DATA; + break; - case 'T': - flags &= ~(int) SampleFlags::HAS_TS_ORIGIN; - break; + case 'T': + flags &= ~(int)SampleFlags::HAS_TS_ORIGIN; + break; - case 's': - flags &= ~(int) SampleFlags::HAS_SEQUENCE; - break; + case 's': + flags &= ~(int)SampleFlags::HAS_SEQUENCE; + break; - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc - optind < 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 2) { + usage(); + exit(EXIT_FAILURE); + } - // Open files - for (int i = 0; i < argc - optind; i++) - filenames.push_back(argv[optind + i]); - } + // Open files + for (int i = 0; i < argc - optind; i++) + filenames.push_back(argv[optind + i]); + } - int main() - { - int ret, rc = 0, line, failed; - unsigned eofs; + int main() { + int ret, rc = 0, line, failed; + unsigned eofs; - ret = pool_init(&pool, filenames.size(), SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); - if (ret) - throw RuntimeError("Failed to initialize pool"); + ret = pool_init(&pool, filenames.size(), + SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); + if (ret) + throw RuntimeError("Failed to initialize pool"); - // Open files - std::vector sides; - for (auto filename : filenames) { - auto *s = new CompareSide(filename, format, dtypes, &pool); - if (!s) - throw MemoryAllocationError(); + // Open files + std::vector sides; + for (auto filename : filenames) { + auto *s = new CompareSide(filename, format, dtypes, &pool); + if (!s) + throw MemoryAllocationError(); - sides.push_back(s); - } + sides.push_back(s); + } - line = 0; - while (true) { - // Read next sample from all files -retry: eofs = 0; - for (auto side : sides) { - ret = feof(side->stream); - if (ret) - eofs++; - } + line = 0; + while (true) { + // Read next sample from all files + retry: + eofs = 0; + for (auto side : sides) { + ret = feof(side->stream); + if (ret) + eofs++; + } - if (eofs) { - if (eofs == sides.size()) - ret = 0; - else { - std::cout << "length unequal" << std::endl; - rc = 1; - } + if (eofs) { + if (eofs == sides.size()) + ret = 0; + else { + std::cout << "length unequal" << std::endl; + rc = 1; + } - goto out; - } + goto out; + } - failed = 0; - for (auto side : sides) { - ret = side->formatter->scan(side->stream, side->sample); - if (ret <= 0) - failed++; - } - if (failed) - goto retry; + failed = 0; + for (auto side : sides) { + ret = side->formatter->scan(side->stream, side->sample); + if (ret <= 0) + failed++; + } + if (failed) + goto retry; - // We compare all files against the first one - for (auto side : sides) { - ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags); - if (ret) { - rc = ret; - goto out; - } - } + // We compare all files against the first one + for (auto side : sides) { + ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags); + if (ret) { + rc = ret; + goto out; + } + } - line++; - } + line++; + } -out: for (auto side : sides) - delete side; + out: + for (auto side : sides) + delete side; - ret = pool_destroy(&pool); - if (ret) - throw RuntimeError("Failed to destroy pool"); + ret = pool_destroy(&pool); + if (ret) + throw RuntimeError("Failed to destroy pool"); - return rc; - } + return rc; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Compare t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Compare t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-conf2json.cpp b/src/villas-conf2json.cpp index aea969fc2..9217321f6 100644 --- a/src/villas-conf2json.cpp +++ b/src/villas-conf2json.cpp @@ -5,15 +5,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include #include #include -#include #include +#include namespace villas { namespace node { @@ -22,69 +22,65 @@ namespace tools { class Config2Json : public Tool { public: - Config2Json(int argc, char *argv[]) : - Tool(argc, argv, "conf2json") - { } + Config2Json(int argc, char *argv[]) : Tool(argc, argv, "conf2json") {} protected: + void usage() { + std::cout << "Usage: conf2json input.conf > output.json" << std::endl + << std::endl; - void usage() - { - std::cout << "Usage: conf2json input.conf > output.json" << std::endl << std::endl; + printCopyright(); + } - printCopyright(); - } + int main() { + int ret; + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - int main() - { - int ret; - config_t cfg; - config_setting_t *cfg_root; - json_t *json; + if (argc != 2) { + usage(); + exit(EXIT_FAILURE); + } - if (argc != 2) { - usage(); - exit(EXIT_FAILURE); - } + FILE *f = fopen(argv[1], "r"); + if (f == nullptr) + return -1; - FILE *f = fopen(argv[1], "r"); - if (f == nullptr) - return -1; + const char *confdir = dirname(argv[1]); - const char *confdir = dirname(argv[1]); + config_init(&cfg); - config_init(&cfg); + config_set_include_dir(&cfg, confdir); - config_set_include_dir(&cfg, confdir); + ret = config_read(&cfg, f); + if (ret != CONFIG_TRUE) + return -2; - ret = config_read(&cfg, f); - if (ret != CONFIG_TRUE) - return -2; + cfg_root = config_root_setting(&cfg); - cfg_root = config_root_setting(&cfg); + json = config_to_json(cfg_root); + if (!json) + return -3; - json = config_to_json(cfg_root); - if (!json) - return -3; + ret = json_dumpf(json, stdout, JSON_INDENT(2)); + fflush(stdout); + if (ret) + return ret; - ret = json_dumpf(json, stdout, JSON_INDENT(2)); fflush(stdout); - if (ret) - return ret; + json_decref(json); + config_destroy(&cfg); - json_decref(json); - config_destroy(&cfg); - - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Config2Json t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Config2Json t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index 14d248c95..89b28166e 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -8,16 +8,16 @@ #include #include -#include -#include -#include +#include #include #include -#include -#include -#include +#include #include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -29,144 +29,139 @@ namespace tools { class Convert : public Tool { public: - Convert(int argc, char *argv[]) : - Tool(argc, argv, "convert"), - dtypes("64f") - { - int ret; + Convert(int argc, char *argv[]) : Tool(argc, argv, "convert"), dtypes("64f") { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { - dirs[i].name = i == 0 ? "in" : "out"; - dirs[i].format = "villas.human"; - } - } + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { + dirs[i].name = i == 0 ? "in" : "out"; + dirs[i].format = "villas.human"; + } + } protected: - std::string dtypes; + std::string dtypes; - struct { - std::string name; - std::string format; - Format *formatter; - } dirs[2]; + struct { + std::string name; + std::string format; + Format *formatter; + } dirs[2]; - void usage() - { - std::cout << "Usage: villas-convert [OPTIONS]" << std::endl - << " OPTIONS are:" << std::endl - << " -i FMT set the input format" << std::endl - << " -o FMT set the output format" << std::endl - << " -t DT the data-type format string" << std::endl - << " -d LVL set debug log level to LVL" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-convert [OPTIONS]" << std::endl + << " OPTIONS are:" << std::endl + << " -i FMT set the input format" << std::endl + << " -o FMT set the output format" << std::endl + << " -t DT the data-type format string" << std::endl + << " -d LVL set debug log level to LVL" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" + << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse optional command line arguments - int c; - while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + void parse() { + // Parse optional command line arguments + int c; + while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'i': - dirs[0].format = optarg; - break; + case 'i': + dirs[0].format = optarg; + break; - case 'o': - dirs[1].format = optarg; - break; + case 'o': + dirs[1].format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + } - if (argc != optind) { - usage(); - exit(EXIT_FAILURE); - } - } + if (argc != optind) { + usage(); + exit(EXIT_FAILURE); + } + } - int main() - { - int ret; + int main() { + int ret; - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { - json_t *json_format; - json_error_t err; - std::string format = dirs[i].format; + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { + json_t *json_format; + json_error_t err; + std::string format = dirs[i].format; - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - dirs[i].formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!dirs[i].formatter) - throw RuntimeError("Failed to initialize format: {}", dirs[i].name); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + dirs[i].formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!dirs[i].formatter) + throw RuntimeError("Failed to initialize format: {}", dirs[i].name); - dirs[i].formatter->start(dtypes); - } + dirs[i].formatter->start(dtypes); + } - // Line based formats are processed sample-by-sample - // while for others, we process them in chunks of 128 samples - auto isLine = dynamic_cast(dirs[0].formatter) != nullptr; - auto cnt = isLine ? 1 : 128; + // Line based formats are processed sample-by-sample + // while for others, we process them in chunks of 128 samples + auto isLine = dynamic_cast(dirs[0].formatter) != nullptr; + auto cnt = isLine ? 1 : 128; - // Initialize memory - struct Pool pool; - ret = pool_init(&pool, cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); - if (ret) - throw RuntimeError("Failed to allocate memory for pool."); + // Initialize memory + struct Pool pool; + ret = pool_init(&pool, cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), + &memory::heap); + if (ret) + throw RuntimeError("Failed to allocate memory for pool."); - struct Sample *smps[cnt]; - ret = sample_alloc_many(&pool, smps, cnt); - if (ret < 0) - throw MemoryAllocationError(); + struct Sample *smps[cnt]; + ret = sample_alloc_many(&pool, smps, cnt); + if (ret < 0) + throw MemoryAllocationError(); - while (!feof(stdin)) { - ret = dirs[0].formatter->scan(stdin, smps, cnt); - if (ret == 0) - continue; - else if (ret < 0) - break; + while (!feof(stdin)) { + ret = dirs[0].formatter->scan(stdin, smps, cnt); + if (ret == 0) + continue; + else if (ret < 0) + break; - dirs[1].formatter->print(stdout, smps, ret); - } + dirs[1].formatter->print(stdout, smps, ret); + } - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) - delete dirs[i].formatter; + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) + delete dirs[i].formatter; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Convert t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Convert t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index cc368c6cd..77116880b 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -7,22 +7,22 @@ #include -#include #include +#include +#include #include #include -#include using namespace villas; struct GVC_s { - GVCOMMON_t common; + GVCOMMON_t common; - char *config_path; - bool config_found; + char *config_path; + bool config_found; - char **input_filenames; // gvParseArgs + char **input_filenames; // gvParseArgs }; namespace villas { @@ -32,105 +32,95 @@ namespace tools { class Graph : public Tool { public: - Graph(int argc, char *argv[]) : - Tool(argc, argv, "graph", { SIGUSR1, SIGINT }), - gvc(nullptr), - graph(nullptr) - { - int ret; + Graph(int argc, char *argv[]) + : Tool(argc, argv, "graph", {SIGUSR1, SIGINT}), gvc(nullptr), + graph(nullptr) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - this->argv[0] = (char *) "neato"; // Default layout engine + this->argv[0] = (char *)"neato"; // Default layout engine - gvc = gvContext(); - } + gvc = gvContext(); + } - ~Graph() - { - gvFreeContext(gvc); - } + ~Graph() { gvFreeContext(gvc); } protected: - GVC_t *gvc; - graph_t *graph; + GVC_t *gvc; + graph_t *graph; - std::string configFilename; + std::string configFilename; - void usage() - { - std::cout << "Usage: villas-graph [OPTIONS]" << std::endl - << "For OPTIONS see dot(1)."; + void usage() { + std::cout << "Usage: villas-graph [OPTIONS]" << std::endl + << "For OPTIONS see dot(1)."; - printCopyright(); - } + printCopyright(); + } - void parse() - { - gvParseArgs(gvc, argc, argv); + void parse() { + gvParseArgs(gvc, argc, argv); - std::list filenames; - int i; - for (i = 0; gvc->input_filenames[i]; i++) - filenames.emplace_back(gvc->input_filenames[i]); + std::list filenames; + int i; + for (i = 0; gvc->input_filenames[i]; i++) + filenames.emplace_back(gvc->input_filenames[i]); - if (i == 0) - throw RuntimeError("No configuration file given!"); + if (i == 0) + throw RuntimeError("No configuration file given!"); - configFilename = filenames.front(); - } + configFilename = filenames.front(); + } - virtual - void handler(int signal, siginfo_t *siginfp, void *) - { + virtual void handler(int signal, siginfo_t *siginfp, void *) { #ifndef _WIN32 - switch (signal) { - case SIGINT: - // If interrupted we try to produce a partial rendering before exiting - if (graph) - gvRenderJobs(gvc, graph); - break; + switch (signal) { + case SIGINT: + // If interrupted we try to produce a partial rendering before exiting + if (graph) + gvRenderJobs(gvc, graph); + break; - case SIGUSR1: - // Note that we don't call gvFinalize() so that we don't start event-driven - // devices like -Tgtk or -Txlib */ - exit(gvFreeContext(gvc)); - break; + case SIGUSR1: + // Note that we don't call gvFinalize() so that we don't start event-driven + // devices like -Tgtk or -Txlib */ + exit(gvFreeContext(gvc)); + break; - default: { } - } + default: { + } + } #endif // _WIN32 - } + } - int main() - { - int ret; + int main() { + int ret; - villas::node::SuperNode sn; + villas::node::SuperNode sn; - sn.parse(configFilename); - sn.check(); - sn.prepare(); + sn.parse(configFilename); + sn.check(); + sn.prepare(); - graph = sn.getGraph(); + graph = sn.getGraph(); - ret = gvLayoutJobs(gvc, graph); // Take layout engine from command line - if (ret) - return ret; + ret = gvLayoutJobs(gvc, graph); // Take layout engine from command line + if (ret) + return ret; - return gvRenderJobs(gvc, graph); - } + return gvRenderJobs(gvc, graph); + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - node::tools::Graph t(argc, argv); +int main(int argc, char *argv[]) { + node::tools::Graph t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index 240ff0a32..97b41782e 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -5,25 +5,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include #include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -36,286 +36,276 @@ namespace tools { class Hook : public Tool { public: - Hook(int argc, char *argv[]) : - Tool(argc, argv, "hook"), - stop(false), - input_format("villas.human"), - dtypes("64f"), - p(), - input(), - output(), - cnt(1) - { - int ret; + Hook(int argc, char *argv[]) + : Tool(argc, argv, "hook"), stop(false), input_format("villas.human"), + dtypes("64f"), p(), input(), output(), cnt(1) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - config = json_object(); - } + config = json_object(); + } - ~Hook() - { - json_decref(config); - } + ~Hook() { json_decref(config); } protected: + std::atomic stop; - std::atomic stop; + std::string hook; - std::string hook; + std::string output_format; + std::string input_format; + std::string dtypes; - std::string output_format; - std::string input_format; - std::string dtypes; + struct Pool p; + Format *input; + Format *output; - struct Pool p; - Format *input; - Format *output; + int cnt; - int cnt; + json_t *config; - json_t *config; + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void usage() { + std::cout << "Usage: villas-hook [OPTIONS] NAME" << std::endl + << " NAME the name of the hook function" << std::endl + << " PARAM* a string of configuration settings for the hook" + << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -c CONFIG a JSON file containing just the hook " + "configuration" + << std::endl + << " -f FMT the input data format" << std::endl + << " -F FMT the output data format (defaults to " + "input format)" + << std::endl + << " -t DT the data-type format string" << std::endl + << " -d LVL set debug level to LVL" << std::endl + << " -v CNT process CNT smps at once" << std::endl + << " -o PARAM=VALUE provide parameters for hook configuration" + << std::endl + << " -h show this help" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - void usage() - { - std::cout << "Usage: villas-hook [OPTIONS] NAME" << std::endl - << " NAME the name of the hook function" << std::endl - << " PARAM* a string of configuration settings for the hook" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -c CONFIG a JSON file containing just the hook configuration" << std::endl - << " -f FMT the input data format" << std::endl - << " -F FMT the output data format (defaults to input format)" << std::endl - << " -t DT the data-type format string" << std::endl - << " -d LVL set debug level to LVL" << std::endl - << " -v CNT process CNT smps at once" << std::endl - << " -o PARAM=VALUE provide parameters for hook configuration" << std::endl - << " -h show this help" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + std::cout << "Supported hooks:" << std::endl; + for (Plugin *p : registry->lookup()) + std::cout << " - " << *p << ": " << p->getDescription() << std::endl; + std::cout << std::endl; - std::cout << "Supported hooks:" << std::endl; - for (Plugin *p : registry->lookup()) - std::cout << " - " << *p << ": " << p->getDescription() << std::endl; - std::cout << std::endl; + std::cout << "Supported IO formats:" << std::endl; + for (Plugin *p : registry->lookup()) + std::cout << " - " << *p << ": " << p->getDescription() << std::endl; + std::cout << std::endl; - std::cout << "Supported IO formats:" << std::endl; - for (Plugin *p : registry->lookup()) - std::cout << " - " << *p << ": " << p->getDescription() << std::endl; - std::cout << std::endl; + std::cout << "Example:" << std::endl + << " villas-signal random | villas-hook skip_first seconds=10" + << std::endl + << std::endl; - std::cout << "Example:" << std::endl - << " villas-signal random | villas-hook skip_first seconds=10" << std::endl - << std::endl; + printCopyright(); + } - printCopyright(); - } + void parse() { + int ret; + std::string file; - void parse() - { - int ret; - std::string file; + // Parse optional command line arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "Vhv:d:f:F:t:o:c:")) != -1) { + switch (c) { + case 'c': + file = optarg; + break; - // Parse optional command line arguments - int c; - char *endptr; - while ((c = getopt(argc, argv, "Vhv:d:f:F:t:o:c:")) != -1) { - switch (c) { - case 'c': - file = optarg; - break; + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'f': + input_format = optarg; + break; - case 'f': - input_format = optarg; - break; + case 'F': + output_format = optarg; + break; - case 'F': - output_format = optarg; - break; + case 't': + dtypes = optarg; + break; - case 't': - dtypes = optarg; - break; + case 'v': + cnt = strtoul(optarg, &endptr, 0); + goto check; - case 'v': - cnt = strtoul(optarg, &endptr, 0); - goto check; + case 'd': + logging.setLevel(optarg); + break; - case 'd': - logging.setLevel(optarg); - break; + case 'o': + ret = json_object_extend_str(config, optarg); + if (ret) + throw RuntimeError("Invalid option: {}", optarg); + break; - case 'o': - ret = json_object_extend_str(config, optarg); - if (ret) - throw RuntimeError("Invalid option: {}", optarg); - break; + case '?': + case 'h': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - case '?': - case 'h': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + continue; - continue; + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); + if (output_format.empty()) + output_format = input_format; - } + if (!file.empty()) { + json_error_t err; + json_t *j = json_load_file(file.c_str(), 0, &err); + if (!j) + throw JanssonParseError(err); - if (output_format.empty()) - output_format = input_format; + json_object_update_missing(config, j); + } - if (!file.empty()) { - json_error_t err; - json_t *j = json_load_file(file.c_str(), 0, &err); - if (!j) - throw JanssonParseError(err); + if (argc < optind + 1) { + usage(); + exit(EXIT_FAILURE); + } - json_object_update_missing(config, j); - } + hook = argv[optind]; + } - if (argc < optind + 1) { - usage(); - exit(EXIT_FAILURE); - } + int main() { + int ret, recv, sent; + struct Sample *smps[cnt]; - hook = argv[optind]; - } + if (cnt < 1) + throw RuntimeError("Vectorize option must be greater than 0"); - int main() - { - int ret, recv, sent; - struct Sample *smps[cnt]; + ret = pool_init(&p, 10 * cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH)); + if (ret) + throw RuntimeError("Failed to initilize memory pool"); - if (cnt < 1) - throw RuntimeError("Vectorize option must be greater than 0"); + // Initialize IO + struct desc { + std::string dir; + std::string format; + Format **formatter; + }; + std::list descs = {{"in", input_format.c_str(), &input}, + {"out", output_format.c_str(), &output}}; - ret = pool_init(&p, 10 * cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH)); - if (ret) - throw RuntimeError("Failed to initilize memory pool"); + for (auto &d : descs) { + json_t *json_format; + json_error_t err; - // Initialize IO - struct desc { - std::string dir; - std::string format; - Format **formatter; - }; - std::list descs = { - { "in", input_format.c_str(), &input }, - { "out", output_format.c_str(), &output } - }; + // Try parsing format config as JSON + json_format = json_loads(d.format.c_str(), 0, &err); + (*d.formatter) = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(d.format); + if (!(*d.formatter)) + throw RuntimeError("Failed to initialize {} IO", d.dir); - for (auto &d : descs) { - json_t *json_format; - json_error_t err; + (*d.formatter)->start(dtypes, (int)SampleFlags::HAS_ALL); + } - // Try parsing format config as JSON - json_format = json_loads(d.format.c_str(), 0, &err); - (*d.formatter) = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(d.format); - if (!(*d.formatter)) - throw RuntimeError("Failed to initialize {} IO", d.dir); + // Initialize hook + auto hf = plugin::registry->lookup(hook); + if (!hf) + throw RuntimeError("Unknown hook function '{}'", hook); - (*d.formatter)->start(dtypes, (int) SampleFlags::HAS_ALL); - } + auto h = hf->make(nullptr, nullptr); + if (!h) + throw RuntimeError("Failed to initialize hook"); - // Initialize hook - auto hf = plugin::registry->lookup(hook); - if (!hf) - throw RuntimeError("Unknown hook function '{}'", hook); + h->parse(config); + h->check(); + h->prepare(input->getSignals()); + h->start(); - auto h = hf->make(nullptr, nullptr); - if (!h) - throw RuntimeError("Failed to initialize hook"); + while (!stop && !feof(stdin)) { + ret = sample_alloc_many(&p, smps, cnt); + if (ret != cnt) + throw RuntimeError("Failed to allocate {} smps from pool", cnt); - h->parse(config); - h->check(); - h->prepare(input->getSignals()); - h->start(); + recv = input->scan(stdin, smps, cnt); + if (recv < 0) + throw RuntimeError("Failed to read from stdin"); - while (!stop && !feof(stdin)) { - ret = sample_alloc_many(&p, smps, cnt); - if (ret != cnt) - throw RuntimeError("Failed to allocate {} smps from pool", cnt); + timespec now = time_now(); - recv = input->scan(stdin, smps, cnt); - if (recv < 0) - throw RuntimeError("Failed to read from stdin"); + logger->debug("Read {} smps from stdin", recv); - timespec now = time_now(); + unsigned send = 0; + for (int processed = 0; processed < recv; processed++) { + struct Sample *smp = smps[processed]; - logger->debug("Read {} smps from stdin", recv); + if (!(smp->flags & (int)SampleFlags::HAS_TS_RECEIVED)) { + smp->ts.received = now; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - unsigned send = 0; - for (int processed = 0; processed < recv; processed++) { - struct Sample *smp = smps[processed]; + auto ret = h->process(smp); + switch (ret) { + using Reason = node::Hook::Reason; + case Reason::ERROR: + throw RuntimeError("Failed to process samples"); - if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)){ - smp->ts.received = now; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + case Reason::OK: + smps[send++] = smp; + break; - auto ret = h->process(smp); - switch (ret) { - using Reason = node::Hook::Reason; - case Reason::ERROR: - throw RuntimeError("Failed to process samples"); + case Reason::SKIP_SAMPLE: + break; - case Reason::OK: - smps[send++] = smp; - break; + case Reason::STOP_PROCESSING: + goto stop; + } - case Reason::SKIP_SAMPLE: - break; + smp->signals = h->getSignals(); + } - case Reason::STOP_PROCESSING: - goto stop; - } + stop: + sent = output->print(stdout, smps, send); + if (sent < 0) + throw RuntimeError("Failed to write to stdout"); - smp->signals = h->getSignals(); - } + sample_free_many(smps, cnt); + } -stop: sent = output->print(stdout, smps, send); - if (sent < 0) - throw RuntimeError("Failed to write to stdout"); + h->stop(); - sample_free_many(smps, cnt); - } + for (auto &d : descs) + delete (*d.formatter); - h->stop(); + sample_free_many(smps, cnt); - for (auto &d : descs) - delete (*d.formatter); + ret = pool_destroy(&p); + if (ret) + throw RuntimeError("Failed to destroy memory pool"); - sample_free_many(smps, cnt); - - ret = pool_destroy(&p); - if (ret) - throw RuntimeError("Failed to destroy memory pool"); - - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Hook t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Hook t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-node.cpp b/src/villas-node.cpp index ca2212075..5886777f9 100644 --- a/src/villas-node.cpp +++ b/src/villas-node.cpp @@ -8,34 +8,34 @@ #include #include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include +#include #include -#include -#include #include +#include +#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef WITH_NODE_OPAL - #include +#include #endif using namespace villas; @@ -49,168 +49,172 @@ namespace tools { class Node : public Tool { public: - Node(int argc, char *argv[]) : - Tool(argc, argv, "node") - { } + Node(int argc, char *argv[]) : Tool(argc, argv, "node") {} protected: - SuperNode sn; + SuperNode sn; - std::string uri; - bool showCapabilities = false; + std::string uri; + bool showCapabilities = false; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - switch (signal) { - case SIGALRM: - logger->info("Reached timeout. Terminating..."); - break; + void handler(int signal, siginfo_t *sinfo, void *ctx) { + switch (signal) { + case SIGALRM: + logger->info("Reached timeout. Terminating..."); + break; - default: - logger->info("Received {} signal. Terminating...", strsignal(signal)); - } + default: + logger->info("Received {} signal. Terminating...", strsignal(signal)); + } - sn.setState(State::STOPPING); - } + sn.setState(State::STOPPING); + } - void usage() - { - std::cout << "Usage: villas-node [OPTIONS] [CONFIG]" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -h show this usage information" << std::endl - << " -d LVL set logging level" << std::endl - << " -C show capabilities in JSON format" << std::endl - << " -V show the version of the tool" << std::endl << std::endl - << " CONFIG is the path to an optional configuration file" << std::endl - << " if omitted, VILLASnode will start without a configuration" << std::endl - << " and wait for provisioning over the web interface." << std::endl << std::endl + void usage() { + std::cout + << "Usage: villas-node [OPTIONS] [CONFIG]" << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -h show this usage information" << std::endl + << " -d LVL set logging level" << std::endl + << " -C show capabilities in JSON format" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl + << " CONFIG is the path to an optional configuration file" << std::endl + << " if omitted, VILLASnode will start without a configuration" + << std::endl + << " and wait for provisioning over the web interface." + << std::endl + << std::endl #ifdef WITH_NODE_OPAL - << "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME" << std::endl - << " This type of invocation is used by OPAL-RT Asynchronous processes." << std::endl - << " See in the RT-LAB User Guide for more information." << std::endl << std::endl + << "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE " + "OPAL_PRINT_SHMEM_NAME" + << std::endl + << " This type of invocation is used by OPAL-RT Asynchronous " + "processes." + << std::endl + << " See in the RT-LAB User Guide for more information." << std::endl + << std::endl #endif // WITH_NODE_OPAL - << "Supported node-types:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + << "Supported node-types:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; - std::cout << "Supported IO formats:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported IO formats:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #ifdef WITH_HOOKS - std::cout << "Supported hooks:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported hooks:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #endif // WITH_HOOKS #ifdef WITH_API - std::cout << "Supported API commands:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported API commands:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #endif // WITH_API - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Check arguments + void parse() { + // Check arguments #ifdef WITH_NODE_OPAL - if (argc != 4) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != 4) { + usage(); + exit(EXIT_FAILURE); + } - opal_register_region(argc, argv); + opal_register_region(argc, argv); - uri = "villas-node.conf"; + uri = "villas-node.conf"; #else - // Parse optional command line arguments - int c; - while ((c = getopt(argc, argv, "hCVd:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + // Parse optional command line arguments + int c; + while ((c = getopt(argc, argv, "hCVd:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'C': - showCapabilities = true; - break; + case 'C': + showCapabilities = true; + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; - } + continue; + } - if (argc == optind + 1) - uri = argv[optind]; - else if (argc != optind) { - usage(); - exit(EXIT_FAILURE); - } + if (argc == optind + 1) + uri = argv[optind]; + else if (argc != optind) { + usage(); + exit(EXIT_FAILURE); + } #endif // ENABLE_OPAL_ASYNC - } + } - int main() - { - return showCapabilities - ? capabilities() - : daemon(); - } + int main() { return showCapabilities ? capabilities() : daemon(); } - int capabilities() { - auto *json_caps = getCapabilities(); + int capabilities() { + auto *json_caps = getCapabilities(); - json_dumpf(json_caps, stdout, JSON_INDENT(4)); + json_dumpf(json_caps, stdout, JSON_INDENT(4)); - return 0; - } + return 0; + } - int daemon() { - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + int daemon() { + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - sn.check(); - sn.prepare(); - sn.start(); - sn.run(); - sn.stop(); + sn.check(); + sn.prepare(); + sn.start(); + sn.run(); + sn.stop(); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Node t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Node t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index d7b2baa0d..14d575e46 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -7,28 +7,27 @@ #include #include -#include #include +#include -#include -#include #include +#include +#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include #include #include -#include +#include +#include +#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -39,482 +38,485 @@ class Pipe; class PipeDirection { protected: - struct Pool pool; - Node *node; - Format *formatter; + struct Pool pool; + Node *node; + Format *formatter; - std::thread thread; - Logger logger; + std::thread thread; + Logger logger; + + bool stop; + bool enabled; + int limit; + int count; - bool stop; - bool enabled; - int limit; - int count; public: - PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) : - node(n), - formatter(fmt), - stop(false), - enabled(en), - limit(lim), - count(0) - { - auto loggerName = fmt::format("pipe:{}", name); - logger = logging.get(loggerName); + PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) + : node(n), formatter(fmt), stop(false), enabled(en), limit(lim), + count(0) { + auto loggerName = fmt::format("pipe:{}", name); + logger = logging.get(loggerName); - // Initialize memory - unsigned pool_size = LOG2_CEIL(MAX(node->out.vectorize, node->in.vectorize)); + // Initialize memory + unsigned pool_size = + LOG2_CEIL(MAX(node->out.vectorize, node->in.vectorize)); - int ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), node->getMemoryType()); - if (ret < 0) - throw RuntimeError("Failed to allocate memory for pool."); - } + int ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), + node->getMemoryType()); + if (ret < 0) + throw RuntimeError("Failed to allocate memory for pool."); + } - ~PipeDirection() - { - int ret __attribute__((unused)); + ~PipeDirection() { + int ret __attribute__((unused)); - ret = pool_destroy(&pool); - } + ret = pool_destroy(&pool); + } - virtual - void run() = 0; + virtual void run() = 0; - void startThread() - { - stop = false; + void startThread() { + stop = false; - if (enabled) - thread = std::thread(&PipeDirection::run, this); - } + if (enabled) + thread = std::thread(&PipeDirection::run, this); + } - void stopThread() - { - stop = true; + void stopThread() { + stop = true; - if (enabled) { - // We send a SIGUSR2 to the threads to unblock their blocking read() syscalls - pthread_kill(thread.native_handle(), SIGUSR2); - thread.join(); - } - } + if (enabled) { + // We send a SIGUSR2 to the threads to unblock their blocking read() syscalls + pthread_kill(thread.native_handle(), SIGUSR2); + thread.join(); + } + } }; class PipeSendDirection : public PipeDirection { - friend Pipe; + friend Pipe; public: - PipeSendDirection(Node *n, Format *i, bool en = true, int lim = -1) : - PipeDirection(n, i, en, lim, "send") - { } + PipeSendDirection(Node *n, Format *i, bool en = true, int lim = -1) + : PipeDirection(n, i, en, lim, "send") {} - virtual - void run() - { - logger->debug("Send thread started"); + virtual void run() { + logger->debug("Send thread started"); - unsigned last_sequenceno = 0; - int scanned, sent, allocated; + unsigned last_sequenceno = 0; + int scanned, sent, allocated; - struct Sample *smps[node->out.vectorize]; + struct Sample *smps[node->out.vectorize]; - while (!stop) { - allocated = sample_alloc_many(&pool, smps, node->out.vectorize); - if (allocated < 0) - throw RuntimeError("Failed to get {} samples out of send pool.", node->out.vectorize); - else if (allocated < (int) node->out.vectorize) - logger->warn("Send pool underrun"); + while (!stop) { + allocated = sample_alloc_many(&pool, smps, node->out.vectorize); + if (allocated < 0) + throw RuntimeError("Failed to get {} samples out of send pool.", + node->out.vectorize); + else if (allocated < (int)node->out.vectorize) + logger->warn("Send pool underrun"); - scanned = formatter->scan(stdin, smps, allocated); - if (scanned < 0) { - if (!stop) - logger->warn("Failed to read from stdin"); - } + scanned = formatter->scan(stdin, smps, allocated); + if (scanned < 0) { + if (!stop) + logger->warn("Failed to read from stdin"); + } - // Fill in missing sequence numbers - for (int i = 0; i < scanned; i++) { - if (smps[i]->flags & (int) SampleFlags::HAS_SEQUENCE) - last_sequenceno = smps[i]->sequence; - else - smps[i]->sequence = last_sequenceno++; - } + // Fill in missing sequence numbers + for (int i = 0; i < scanned; i++) { + if (smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE) + last_sequenceno = smps[i]->sequence; + else + smps[i]->sequence = last_sequenceno++; + } - sent = node->write(smps, scanned); + sent = node->write(smps, scanned); - sample_decref_many(smps, allocated); + sample_decref_many(smps, allocated); - count += sent; - if (limit > 0 && count >= limit) - goto leave_limit; + count += sent; + if (limit > 0 && count >= limit) + goto leave_limit; - if (feof(stdin)) - goto leave_eof; - } + if (feof(stdin)) + goto leave_eof; + } - goto leave; + goto leave; -leave_eof: - logger->info("Reached end-of-file."); - raise(SIGUSR1); - goto leave; + leave_eof: + logger->info("Reached end-of-file."); + raise(SIGUSR1); + goto leave; -leave_limit: - logger->info("Reached send limit."); - raise(SIGUSR1); + leave_limit: + logger->info("Reached send limit."); + raise(SIGUSR1); -leave: - logger->debug("Send thread stopped"); - } + leave: + logger->debug("Send thread stopped"); + } }; class PipeReceiveDirection : public PipeDirection { - friend Pipe; + friend Pipe; public: - PipeReceiveDirection(Node *n, Format *i, bool en = true, int lim = -1) : - PipeDirection(n, i, en, lim, "recv") - { } + PipeReceiveDirection(Node *n, Format *i, bool en = true, int lim = -1) + : PipeDirection(n, i, en, lim, "recv") {} - virtual - void run() - { - logger->debug("Receive thread started"); + virtual void run() { + logger->debug("Receive thread started"); - int recv, allocated = 0; - struct Sample *smps[node->in.vectorize]; + int recv, allocated = 0; + struct Sample *smps[node->in.vectorize]; - while (!stop) { - allocated = sample_alloc_many(&pool, smps, node->in.vectorize); - if (allocated < 0) - throw RuntimeError("Failed to allocate {} samples from receive pool.", node->in.vectorize); - else if (allocated < (int) node->in.vectorize) - logger->warn("Receive pool underrun: allocated only {} of {} samples", allocated, node->in.vectorize); + while (!stop) { + allocated = sample_alloc_many(&pool, smps, node->in.vectorize); + if (allocated < 0) + throw RuntimeError("Failed to allocate {} samples from receive pool.", + node->in.vectorize); + else if (allocated < (int)node->in.vectorize) + logger->warn("Receive pool underrun: allocated only {} of {} samples", + allocated, node->in.vectorize); - recv = node->read(smps, allocated); - if (recv < 0) { - if (node->getState() == State::STOPPING || stop) { - sample_decref_many(smps, allocated); - goto leave; - } + recv = node->read(smps, allocated); + if (recv < 0) { + if (node->getState() == State::STOPPING || stop) { + sample_decref_many(smps, allocated); + goto leave; + } - logger->warn("Failed to receive samples from node {}: reason={}", node->getName(), recv); - } else - formatter->print(stdout, smps, recv); + logger->warn("Failed to receive samples from node {}: reason={}", + node->getName(), recv); + } else + formatter->print(stdout, smps, recv); - sample_decref_many(smps, allocated); + sample_decref_many(smps, allocated); - count += recv; - if (limit > 0 && count >= limit) - goto leave_limit; - } + count += recv; + if (limit > 0 && count >= limit) + goto leave_limit; + } - goto leave; + goto leave; -leave_limit: - logger->info("Reached receive limit."); - raise(SIGUSR1); + leave_limit: + logger->info("Reached receive limit."); + raise(SIGUSR1); -leave: - logger->debug("Receive thread stopped"); - } + leave: + logger->debug("Receive thread stopped"); + } }; class Pipe : public Tool { public: - Pipe(int argc, char *argv[]) : - Tool(argc, argv, "pipe"), - stop(false), - formatter(), - timeout(0), - reverse(false), - format("villas.human"), - dtypes("64f"), - config_cli(json_object()) - { - send.enabled = true; - send.limit = -1; + Pipe(int argc, char *argv[]) + : Tool(argc, argv, "pipe"), stop(false), formatter(), timeout(0), + reverse(false), format("villas.human"), dtypes("64f"), + config_cli(json_object()) { + send.enabled = true; + send.limit = -1; - recv.enabled = true; - recv.limit = -1; + recv.enabled = true; + recv.limit = -1; - int ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + int ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } - ~Pipe() - { - json_decref(config_cli); - } + ~Pipe() { json_decref(config_cli); } protected: - std::atomic stop; + std::atomic stop; - SuperNode sn; // The global configuration - Format *formatter; + SuperNode sn; // The global configuration + Format *formatter; - int timeout; - bool reverse; - std::string format; - std::string dtypes; - std::string uri; - std::string nodestr; + int timeout; + bool reverse; + std::string format; + std::string dtypes; + std::string uri; + std::string nodestr; - json_t *config_cli; + json_t *config_cli; - struct { - int limit; - bool enabled; - std::unique_ptr dir; + struct { + int limit; + bool enabled; + std::unique_ptr dir; - } recv; + } recv; - struct { - int limit; - bool enabled; - std::unique_ptr dir; - } send; + struct { + int limit; + bool enabled; + std::unique_ptr dir; + } send; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - logger->debug("Received {} signal.", strsignal(signal)); + void handler(int signal, siginfo_t *sinfo, void *ctx) { + logger->debug("Received {} signal.", strsignal(signal)); - switch (signal) { - case SIGALRM: - logger->info("Reached timeout."); - stop = true; - break; + switch (signal) { + case SIGALRM: + logger->info("Reached timeout."); + stop = true; + break; - case SIGUSR1: - if (recv.dir->enabled) { - if (recv.dir->limit < 0 && feof(stdin)) - stop = true; + case SIGUSR1: + if (recv.dir->enabled) { + if (recv.dir->limit < 0 && feof(stdin)) + stop = true; - if (recv.dir->limit > 0 && recv.dir->count >= recv.dir->limit) - stop = true; - } + if (recv.dir->limit > 0 && recv.dir->count >= recv.dir->limit) + stop = true; + } - if (send.dir->enabled && send.dir->limit > 0) { - if (send.dir->count >= send.dir->limit) - stop = true; - } - break; + if (send.dir->enabled && send.dir->limit > 0) { + if (send.dir->count >= send.dir->limit) + stop = true; + } + break; - default: - stop = true; - break; - } - } + default: + stop = true; + break; + } + } - void usage() - { - std::cout << "Usage: villas-pipe [OPTIONS] CONFIG NODE" << std::endl - << " CONFIG path to a configuration file" << std::endl - << " NODE the name of the node to which samples are sent and received from" << std::endl - << " OPTIONS are:" << std::endl - << " -f FMT set the format" << std::endl - << " -t DT the data-type format string" << std::endl - << " -o OPTION=VALUE overwrite options in config file" << std::endl - << " -x swap read / write endpoints" << std::endl - << " -s only read data from stdin and send it to node" << std::endl - << " -r only read data from node and write it to stdout" << std::endl - << " -T NUM terminate after NUM seconds" << std::endl - << " -L NUM terminate after NUM samples sent" << std::endl - << " -l NUM terminate after NUM samples received" << std::endl - << " -h show this usage information" << std::endl - << " -d set logging level" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout + << "Usage: villas-pipe [OPTIONS] CONFIG NODE" << std::endl + << " CONFIG path to a configuration file" << std::endl + << " NODE the name of the node to which samples are sent and " + "received from" + << std::endl + << " OPTIONS are:" << std::endl + << " -f FMT set the format" << std::endl + << " -t DT the data-type format string" << std::endl + << " -o OPTION=VALUE overwrite options in config file" << std::endl + << " -x swap read / write endpoints" << std::endl + << " -s only read data from stdin and send it to node" + << std::endl + << " -r only read data from node and write it to " + "stdout" + << std::endl + << " -T NUM terminate after NUM seconds" << std::endl + << " -L NUM terminate after NUM samples sent" << std::endl + << " -l NUM terminate after NUM samples received" + << std::endl + << " -h show this usage information" << std::endl + << " -d set logging level" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - int c, ret; - char *endptr; - while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + void parse() { + int c, ret; + char *endptr; + while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'x': - reverse = true; - break; + case 'x': + reverse = true; + break; - case 's': - recv.enabled = false; // send only - break; + case 's': + recv.enabled = false; // send only + break; - case 'r': - send.enabled = false; // receive only - break; + case 'r': + send.enabled = false; // receive only + break; - case 'l': - recv.limit = strtoul(optarg, &endptr, 10); - goto check; + case 'l': + recv.limit = strtoul(optarg, &endptr, 10); + goto check; - case 'L': - send.limit = strtoul(optarg, &endptr, 10); - goto check; + case 'L': + send.limit = strtoul(optarg, &endptr, 10); + goto check; - case 'T': - timeout = strtoul(optarg, &endptr, 10); - goto check; + case 'T': + timeout = strtoul(optarg, &endptr, 10); + goto check; - case 'o': - ret = json_object_extend_str(config_cli, optarg); - if (ret) - throw RuntimeError("Invalid option: {}", optarg); - break; + case 'o': + ret = json_object_extend_str(config_cli, optarg); + if (ret) + throw RuntimeError("Invalid option: {}", optarg); + break; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != optind + 2) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - nodestr = argv[optind+1]; - } + uri = argv[optind]; + nodestr = argv[optind + 1]; + } - int main() - { - int ret; - Node *node; - json_t *json_format; - json_error_t err; + int main() { + int ret; + Node *node; + json_t *json_format; + json_error_t err; - logger->info("Logging level: {}", logging.getLevelName()); + logger->info("Logging level: {}", logging.getLevelName()); - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize formatter"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize formatter"); - formatter->start(dtypes); + formatter->start(dtypes); - node = sn.getNode(nodestr); - if (!node) - throw RuntimeError("Node {} does not exist!", nodestr); + node = sn.getNode(nodestr); + if (!node) + throw RuntimeError("Node {} does not exist!", nodestr); - if (recv.enabled && !(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_READ)) - throw RuntimeError("Node {} can not receive data. Consider using send-only mode by using '-s' option", nodestr); + if (recv.enabled && !(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_READ)) + throw RuntimeError("Node {} can not receive data. Consider using " + "send-only mode by using '-s' option", + nodestr); - if (send.enabled && !(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_WRITE)) - throw RuntimeError("Node {} can not send data. Consider using receive-only mode by using '-r' option", nodestr); + if (send.enabled && !(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_WRITE)) + throw RuntimeError("Node {} can not send data. Consider using " + "receive-only mode by using '-r' option", + nodestr); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - // Only start web subsystem if villas-pipe is used with a websocket node - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { - Web *w = sn.getWeb(); - w->start(); - } + // Only start web subsystem if villas-pipe is used with a websocket node + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::REQUIRES_WEB) { + Web *w = sn.getWeb(); + w->start(); + } #endif // WITH_NODE_WEBSOCKET - if (reverse) - node->reverse(); + if (reverse) + node->reverse(); - ret = node->getFactory()->start(&sn); - if (ret) - throw RuntimeError("Failed to intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(&sn); + if (ret) + throw RuntimeError("Failed to intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - sn.startInterfaces(); + sn.startInterfaces(); - ret = node->check(); - if (ret) - throw RuntimeError("Invalid node configuration"); + ret = node->check(); + if (ret) + throw RuntimeError("Invalid node configuration"); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - recv.dir = std::make_unique(node, formatter, recv.enabled, recv.limit); - send.dir = std::make_unique(node, formatter, send.enabled, send.limit); + recv.dir = std::make_unique(node, formatter, + recv.enabled, recv.limit); + send.dir = std::make_unique(node, formatter, + send.enabled, send.limit); - recv.dir->startThread(); - send.dir->startThread(); + recv.dir->startThread(); + send.dir->startThread(); - // Arm timeout timer - alarm(timeout); + // Arm timeout timer + alarm(timeout); - while (!stop) - usleep(0.1e6); + while (!stop) + usleep(0.1e6); - /* We are stopping the node here in order to unblock the receiving threads + /* We are stopping the node here in order to unblock the receiving threads * Node::read() call and allow it to be joined(). */ - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), ret); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), + ret); - recv.dir->stopThread(); - send.dir->stopThread(); + recv.dir->stopThread(); + send.dir->stopThread(); - sn.stopInterfaces(); + sn.stopInterfaces(); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to stop node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to stop node type {}: reason={}", + node->getFactory()->getName(), ret); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - // Only start web subsystem if villas-pipe is used with a websocket node - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { - Web *w = sn.getWeb(); - w->stop(); - } + // Only start web subsystem if villas-pipe is used with a websocket node + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::REQUIRES_WEB) { + Web *w = sn.getWeb(); + w->stop(); + } #endif // WITH_NODE_WEBSOCKET - delete formatter; + delete formatter; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Pipe t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Pipe t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index 3dc8e108a..a78efeb10 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -16,11 +16,11 @@ #include #include -#include #include +#include +#include #include #include -#include #include #include @@ -33,493 +33,449 @@ namespace villas { namespace node { namespace tools { -RelaySession::RelaySession(Relay *r, Identifier sid) : - identifier(sid), - connects(0) -{ - auto loggerName = fmt::format("relay:{}", sid); - logger = villas::logging.get(loggerName); +RelaySession::RelaySession(Relay *r, Identifier sid) + : identifier(sid), connects(0) { + auto loggerName = fmt::format("relay:{}", sid); + logger = villas::logging.get(loggerName); - logger->info("Session created: {}", identifier); + logger->info("Session created: {}", identifier); - sessions[sid] = this; + sessions[sid] = this; - created = time(nullptr); + created = time(nullptr); - uuid::generateFromString(uuid, identifier, r->uuid); + uuid::generateFromString(uuid, identifier, r->uuid); } -RelaySession::~RelaySession() -{ - logger->info("Session destroyed: {}", identifier); +RelaySession::~RelaySession() { + logger->info("Session destroyed: {}", identifier); - sessions.erase(identifier); + sessions.erase(identifier); } -RelaySession * RelaySession::get(Relay *r, lws *wsi) -{ - char uri[64]; +RelaySession *RelaySession::get(Relay *r, lws *wsi) { + char uri[64]; - /* We use the URI to associate this connection to a session + /* We use the URI to associate this connection to a session * Example: ws://example.com/node_1 * Will select the session with the name 'node_1' */ - // Get path of incoming request - lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); - if (strlen(uri) <= 1) - throw InvalidUrlException(); + // Get path of incoming request + lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); + if (strlen(uri) <= 1) + throw InvalidUrlException(); - Identifier sid = uri + 1; + Identifier sid = uri + 1; - auto it = sessions.find(sid); - if (it == sessions.end()) { - auto *rs = new RelaySession(r, sid); - if (!rs) - throw MemoryAllocationError(); + auto it = sessions.find(sid); + if (it == sessions.end()) { + auto *rs = new RelaySession(r, sid); + if (!rs) + throw MemoryAllocationError(); - return rs; - } - else { - auto logger = logging.get("villas-relay"); - logger->info("Found existing session: {}", sid); + return rs; + } else { + auto logger = logging.get("villas-relay"); + logger->info("Found existing session: {}", sid); - return it->second; - } + return it->second; + } } -json_t * RelaySession::toJson() const -{ - json_t *json_connections = json_array(); +json_t *RelaySession::toJson() const { + json_t *json_connections = json_array(); - for (auto it : connections) { - auto conn = it.second; + for (auto it : connections) { + auto conn = it.second; - json_array_append(json_connections, conn->toJson()); - } + json_array_append(json_connections, conn->toJson()); + } - return json_pack("{ s: s, s: s, s: o, s: I, s: i }", - "identifier", identifier.c_str(), - "uuid", uuid::toString(uuid).c_str(), - "connections", json_connections, - "created", created, - "connects", connects - ); + return json_pack("{ s: s, s: s, s: o, s: I, s: i }", "identifier", + identifier.c_str(), "uuid", uuid::toString(uuid).c_str(), + "connections", json_connections, "created", created, + "connects", connects); } std::map RelaySession::sessions; -RelayConnection::RelayConnection(Relay *r, lws *w, bool lo) : - wsi(w), - currentFrame(std::make_shared()), - outgoingFrames(), - bytes_recv(0), - bytes_sent(0), - frames_recv(0), - frames_sent(0), - loopback(lo) -{ - session = RelaySession::get(r, wsi); - session->connections[wsi] = this; - session->connects++; +RelayConnection::RelayConnection(Relay *r, lws *w, bool lo) + : wsi(w), currentFrame(std::make_shared()), outgoingFrames(), + bytes_recv(0), bytes_sent(0), frames_recv(0), frames_sent(0), + loopback(lo) { + session = RelaySession::get(r, wsi); + session->connections[wsi] = this; + session->connects++; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, sizeof(ip)); + lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, + sizeof(ip)); - created = time(nullptr); + created = time(nullptr); - session->logger->info("New connection established: {} ({})", name, ip); + session->logger->info("New connection established: {} ({})", name, ip); } -RelayConnection::~RelayConnection() -{ - session->logger->info("Connection closed: {} ({})", name, ip); +RelayConnection::~RelayConnection() { + session->logger->info("Connection closed: {} ({})", name, ip); - session->connections.erase(wsi); + session->connections.erase(wsi); - if (session->connections.empty()) - delete session; + if (session->connections.empty()) + delete session; } -json_t * RelayConnection::toJson() const -{ - return json_pack("{ s: s, s: s, s: I, s: I, s: I, s: I, s: I }", - "name", name, - "ip", ip, - "created", created, - "bytes_recv", bytes_recv, - "bytes_sent", bytes_sent, - "frames_recv", frames_recv, - "frames_sent", frames_sent - ); +json_t *RelayConnection::toJson() const { + return json_pack("{ s: s, s: s, s: I, s: I, s: I, s: I, s: I }", "name", name, + "ip", ip, "created", created, "bytes_recv", bytes_recv, + "bytes_sent", bytes_sent, "frames_recv", frames_recv, + "frames_sent", frames_sent); } -void RelayConnection::write() -{ - if (outgoingFrames.empty()) - return; +void RelayConnection::write() { + if (outgoingFrames.empty()) + return; - auto fr = outgoingFrames.front(); + auto fr = outgoingFrames.front(); - int ret = lws_write(wsi, fr->data(), fr->size(), LWS_WRITE_BINARY); - if (ret < 0) - return; + int ret = lws_write(wsi, fr->data(), fr->size(), LWS_WRITE_BINARY); + if (ret < 0) + return; - bytes_sent += fr->size(); - frames_sent++; + bytes_sent += fr->size(); + frames_sent++; - outgoingFrames.pop(); + outgoingFrames.pop(); - if (outgoingFrames.size() > 0) - lws_callback_on_writable(wsi); + if (outgoingFrames.size() > 0) + lws_callback_on_writable(wsi); } -void RelayConnection::read(void *in, size_t len) -{ - currentFrame->insert(currentFrame->end(), (uint8_t *) in, (uint8_t *) in + len); +void RelayConnection::read(void *in, size_t len) { + currentFrame->insert(currentFrame->end(), (uint8_t *)in, (uint8_t *)in + len); - bytes_recv += len; + bytes_recv += len; - if (lws_is_final_fragment(wsi)) { - frames_recv++; - session->logger->debug("Received frame, relaying to {} connections", session->connections.size() - (loopback ? 0 : 1)); + if (lws_is_final_fragment(wsi)) { + frames_recv++; + session->logger->debug("Received frame, relaying to {} connections", + session->connections.size() - (loopback ? 0 : 1)); - for (auto p : session->connections) { - auto c = p.second; + for (auto p : session->connections) { + auto c = p.second; - /* We skip the current connection in order + /* We skip the current connection in order * to avoid receiving our own data */ - if (loopback == false && c == this) - continue; + if (loopback == false && c == this) + continue; - c->outgoingFrames.push(currentFrame); + c->outgoingFrames.push(currentFrame); - lws_callback_on_writable(c->wsi); - } + lws_callback_on_writable(c->wsi); + } - currentFrame = std::make_shared(); - } + currentFrame = std::make_shared(); + } } -Relay::Relay(int argc, char *argv[]) : - Tool(argc, argv, "relay"), - stop(false), - context(nullptr), - vhost(nullptr), - loopback(false), - port(8088), - protocol("live") -{ - int ret; +Relay::Relay(int argc, char *argv[]) + : Tool(argc, argv, "relay"), stop(false), context(nullptr), vhost(nullptr), + loopback(false), port(8088), protocol("live") { + int ret; - char hname[128]; - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw SystemError("Failed to get hostname"); + char hname[128]; + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw SystemError("Failed to get hostname"); - hostname = hname; + hostname = hname; - // Default UUID is derived from hostname - uuid::generateFromString(uuid, hname); + // Default UUID is derived from hostname + uuid::generateFromString(uuid, hname); - ret = memory::init(0); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(0); + if (ret) + throw RuntimeError("Failed to initialize memory"); - // Initialize logging - lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); + // Initialize logging + lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); - protocols = { - { - .name = "http", - .callback = lws_callback_http_dummy, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, - { - .name = "http-api", - .callback = httpProtocolCallback, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, - { - .name = "live", - .callback = protocolCallback, - .per_session_data_size = sizeof(RelayConnection), - .rx_buffer_size = 0 - }, - { nullptr /* terminator */ } - }; + protocols = {{.name = "http", + .callback = lws_callback_http_dummy, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, + {.name = "http-api", + .callback = httpProtocolCallback, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, + {.name = "live", + .callback = protocolCallback, + .per_session_data_size = sizeof(RelayConnection), + .rx_buffer_size = 0}, + {nullptr /* terminator */}}; } -int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret; +int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret; - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - Relay *r = reinterpret_cast(user_ctx); + Relay *r = reinterpret_cast(user_ctx); - switch (reason) { - case LWS_CALLBACK_HTTP: { - unsigned char buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *end = &buf[sizeof(buf) - LWS_PRE - 1], *p = start; + switch (reason) { + case LWS_CALLBACK_HTTP: { + unsigned char buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], + *end = &buf[sizeof(buf) - LWS_PRE - 1], + *p = start; - if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK, - "application/json", - LWS_ILLEGAL_HTTP_CONTENT_LEN, // no content len - &p, end)) - return 1; + if (lws_add_http_common_headers( + wsi, HTTP_STATUS_OK, "application/json", + LWS_ILLEGAL_HTTP_CONTENT_LEN, // no content len + &p, end)) + return 1; - if (lws_finalize_write_http_header(wsi, start, &p, end)) - return 1; + if (lws_finalize_write_http_header(wsi, start, &p, end)) + return 1; - // Write the body separately - lws_callback_on_writable(wsi); + // Write the body separately + lws_callback_on_writable(wsi); - return 0; - } + return 0; + } - case LWS_CALLBACK_HTTP_WRITEABLE: { - size_t len; - std::vector buf; - json_t *json_sessions, *json_body; + case LWS_CALLBACK_HTTP_WRITEABLE: { + size_t len; + std::vector buf; + json_t *json_sessions, *json_body; - json_sessions = json_array(); - for (auto it : RelaySession::sessions) { - auto &session = it.second; + json_sessions = json_array(); + for (auto it : RelaySession::sessions) { + auto &session = it.second; - json_array_append(json_sessions, session->toJson()); - } + json_array_append(json_sessions, session->toJson()); + } - json_body = json_pack("{ s: o, s: s, s: s, s: s, s: { s: b, s: i, s: s } }", - "sessions", json_sessions, - "version", PROJECT_VERSION_STR, - "hostname", r->hostname.c_str(), - "uuid", uuid::toString(r->uuid).c_str(), - "options", - "loopback", r->loopback, - "port", r->port, - "protocol", r->protocol.c_str() - ); - if (!json_body) - return -1; + json_body = json_pack("{ s: o, s: s, s: s, s: s, s: { s: b, s: i, s: s } }", + "sessions", json_sessions, "version", + PROJECT_VERSION_STR, "hostname", r->hostname.c_str(), + "uuid", uuid::toString(r->uuid).c_str(), "options", + "loopback", r->loopback, "port", r->port, "protocol", + r->protocol.c_str()); + if (!json_body) + return -1; - len = 1024; - do { - buf.resize(LWS_PRE + len); + len = 1024; + do { + buf.resize(LWS_PRE + len); - len = json_dumpb(json_body, buf.data() + LWS_PRE, buf.size() - LWS_PRE, JSON_INDENT(4)); - if (len == 0) - return -1; - } while (len > buf.size() - LWS_PRE); + len = json_dumpb(json_body, buf.data() + LWS_PRE, buf.size() - LWS_PRE, + JSON_INDENT(4)); + if (len == 0) + return -1; + } while (len > buf.size() - LWS_PRE); - ret = lws_write(wsi, (unsigned char *)(buf.data() + LWS_PRE), len, LWS_WRITE_HTTP_FINAL); - if (ret < 0) - return ret; + ret = lws_write(wsi, (unsigned char *)(buf.data() + LWS_PRE), len, + LWS_WRITE_HTTP_FINAL); + if (ret < 0) + return ret; - r->logger->info("Handled API request"); + r->logger->info("Handled API request"); - return -1; - } + return -1; + } - default: - break; - } + default: + break; + } - return lws_callback_http_dummy(wsi, reason, user, in, len); + return lws_callback_http_dummy(wsi, reason, user, in, len); } -int Relay::protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); +int Relay::protocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - Relay *r = reinterpret_cast(user_ctx); - RelayConnection *c = reinterpret_cast(user); + Relay *r = reinterpret_cast(user_ctx); + RelayConnection *c = reinterpret_cast(user); - switch (reason) { + switch (reason) { - case LWS_CALLBACK_ESTABLISHED: - try { - new (c) RelayConnection(r, wsi, r->loopback); - } - catch (const InvalidUrlException &e) { - lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *) "Invalid URL", strlen("Invalid URL")); + case LWS_CALLBACK_ESTABLISHED: + try { + new (c) RelayConnection(r, wsi, r->loopback); + } catch (const InvalidUrlException &e) { + lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, + (unsigned char *)"Invalid URL", strlen("Invalid URL")); - return -1; - } - break; + return -1; + } + break; - case LWS_CALLBACK_CLOSED: - c->~RelayConnection(); - break; + case LWS_CALLBACK_CLOSED: + c->~RelayConnection(); + break; - case LWS_CALLBACK_SERVER_WRITEABLE: - c->write(); - break; + case LWS_CALLBACK_SERVER_WRITEABLE: + c->write(); + break; - case LWS_CALLBACK_RECEIVE: - c->read(in, len); - break; + case LWS_CALLBACK_RECEIVE: + c->read(in, len); + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -void Relay::usage() -{ - std::cout << "Usage: villas-relay [OPTIONS]" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -p PORT the port number to listen on" << std::endl - << " -P PROT the websocket protocol" << std::endl - << " -l enable loopback of own data" << std::endl - << " -u UUID unique instance id" << std::endl - << " -V show version and exit" << std::endl - << " -h show usage and exit" << std::endl << std::endl; +void Relay::usage() { + std::cout << "Usage: villas-relay [OPTIONS]" << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -d LVL set debug level" << std::endl + << " -p PORT the port number to listen on" << std::endl + << " -P PROT the websocket protocol" << std::endl + << " -l enable loopback of own data" << std::endl + << " -u UUID unique instance id" << std::endl + << " -V show version and exit" << std::endl + << " -h show usage and exit" << std::endl + << std::endl; - printCopyright(); + printCopyright(); } -void Relay::parse() -{ - int ret; - char c, *endptr; - while ((c = getopt (argc, argv, "hVp:P:ld:u:")) != -1) { - switch (c) { - case 'd': - logging.setLevel(optarg); - lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); - break; +void Relay::parse() { + int ret; + char c, *endptr; + while ((c = getopt(argc, argv, "hVp:P:ld:u:")) != -1) { + switch (c) { + case 'd': + logging.setLevel(optarg); + lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); + break; - case 'p': - port = strtoul(optarg, &endptr, 10); - goto check; + case 'p': + port = strtoul(optarg, &endptr, 10); + goto check; - case 'P': - protocol = optarg; - break; + case 'P': + protocol = optarg; + break; - case 'l': - loopback = true; - break; + case 'l': + loopback = true; + break; - case 'u': - ret = uuid_parse(optarg, uuid); - if (ret) { - logger->error("Failed to parse UUID: {}", optarg); - exit(EXIT_FAILURE); - } - break; + case 'u': + ret = uuid_parse(optarg, uuid); + if (ret) { + logger->error("Failed to parse UUID: {}", optarg); + exit(EXIT_FAILURE); + } + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: - if (optarg == endptr) { - logger->error("Failed to parse parse option argument '-{} {}'", c, optarg); - exit(EXIT_FAILURE); - } - } + check: + if (optarg == endptr) { + logger->error("Failed to parse parse option argument '-{} {}'", c, + optarg); + exit(EXIT_FAILURE); + } + } - if (argc - optind < 0) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 0) { + usage(); + exit(EXIT_FAILURE); + } } int Relay::main() { - // Start server - lws_context_creation_info ctx_info = { 0 }; + // Start server + lws_context_creation_info ctx_info = {0}; - protocols[2].name = protocol.c_str(); + protocols[2].name = protocol.c_str(); - ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctx_info.gid = -1; - ctx_info.uid = -1; - ctx_info.protocols = protocols.data(); + ctx_info.options = + LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctx_info.gid = -1; + ctx_info.uid = -1; + ctx_info.protocols = protocols.data(); #ifndef LWS_WITHOUT_EXTENSIONS - ctx_info.extensions = extensions.data(); + ctx_info.extensions = extensions.data(); #endif - ctx_info.port = port; - ctx_info.mounts = &mount; - ctx_info.user = (void *) this; + ctx_info.port = port; + ctx_info.mounts = &mount; + ctx_info.user = (void *)this; - auto lwsLogger = logging.get("lws"); + auto lwsLogger = logging.get("lws"); - context = lws_create_context(&ctx_info); - if (context == nullptr) { - lwsLogger->error("Failed to initialize server context"); - exit(EXIT_FAILURE); - } + context = lws_create_context(&ctx_info); + if (context == nullptr) { + lwsLogger->error("Failed to initialize server context"); + exit(EXIT_FAILURE); + } - vhost = lws_create_vhost(context, &ctx_info); - if (vhost == nullptr) { - lwsLogger->error("Failed to initialize virtual host"); - exit(EXIT_FAILURE); - } + vhost = lws_create_vhost(context, &ctx_info); + if (vhost == nullptr) { + lwsLogger->error("Failed to initialize virtual host"); + exit(EXIT_FAILURE); + } - while (!stop) - lws_service(context, 100); + while (!stop) + lws_service(context, 100); - return 0; + return 0; } const std::vector Relay::extensions = { #ifdef LWS_DEFLATE_FOUND - { - "permessage-deflate", - lws_extension_callback_pm_deflate, - "permessage-deflate" - }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, + {"permessage-deflate", lws_extension_callback_pm_deflate, + "permessage-deflate"}, + {"deflate-frame", lws_extension_callback_pm_deflate, "deflate_frame"}, #endif // LWS_DEFLATE_FOUND - { nullptr /* terminator */ } -}; + {nullptr /* terminator */}}; const lws_http_mount Relay::mount = { - .mount_next = nullptr, // linked-list "next" - .mountpoint = "/api/v1", // mountpoint URL - .origin = nullptr, // protocol - .def = nullptr, - .protocol = "http-api", - .cgienv = nullptr, - .extra_mimetypes = nullptr, - .interpret = nullptr, - .cgi_timeout = 0, - .cache_max_age = 0, - .auth_mask = 0, - .cache_reusable = 0, - .cache_revalidate = 0, - .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, // dynamic - .mountpoint_len = 7, // char count - .basic_auth_login_file = nullptr, + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v1", // mountpoint URL + .origin = nullptr, // protocol + .def = nullptr, + .protocol = "http-api", + .cgienv = nullptr, + .extra_mimetypes = nullptr, + .interpret = nullptr, + .cgi_timeout = 0, + .cache_max_age = 0, + .auth_mask = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7, // char count + .basic_auth_login_file = nullptr, }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Relay t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Relay t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index c33b35197..069dd1bb1 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include @@ -23,142 +23,130 @@ class Relay; class RelaySession; class RelayConnection; -class InvalidUrlException { }; +class InvalidUrlException {}; typedef std::string Identifier; class Frame : public std::vector { public: - Frame() { - reserve(LWS_PRE); - // lws_write() requires LWS_PRE bytes in front of the payload - insert(end(), LWS_PRE, 0); - } + Frame() { + reserve(LWS_PRE); + // lws_write() requires LWS_PRE bytes in front of the payload + insert(end(), LWS_PRE, 0); + } - uint8_t * data() { - return std::vector::data() + LWS_PRE; - } + uint8_t *data() { return std::vector::data() + LWS_PRE; } - size_type size() { - return std::vector::size() - LWS_PRE; - } + size_type size() { return std::vector::size() - LWS_PRE; } }; class RelaySession { - friend RelayConnection; - friend Relay; + friend RelayConnection; + friend Relay; protected: - time_t created; - uuid_t uuid; + time_t created; + uuid_t uuid; - Identifier identifier; - Logger logger; + Identifier identifier; + Logger logger; - std::map connections; + std::map connections; - int connects; + int connects; - static - std::map sessions; + static std::map sessions; public: - static - RelaySession * get(Relay *r, lws *wsi); + static RelaySession *get(Relay *r, lws *wsi); - RelaySession(Relay *r, Identifier sid); + RelaySession(Relay *r, Identifier sid); - ~RelaySession(); + ~RelaySession(); - json_t * toJson() const; + json_t *toJson() const; }; class RelayConnection { protected: - lws *wsi; + lws *wsi; - std::shared_ptr currentFrame; + std::shared_ptr currentFrame; - std::queue> outgoingFrames; + std::queue> outgoingFrames; - RelaySession *session; + RelaySession *session; - char name[128]; - char ip[128]; + char name[128]; + char ip[128]; - size_t created; - size_t bytes_recv; - size_t bytes_sent; + size_t created; + size_t bytes_recv; + size_t bytes_sent; - size_t frames_recv; - size_t frames_sent; + size_t frames_recv; + size_t frames_sent; - bool loopback; + bool loopback; public: - RelayConnection(Relay *r, lws *w, bool lo); - ~RelayConnection(); + RelayConnection(Relay *r, lws *w, bool lo); + ~RelayConnection(); - json_t * toJson() const; + json_t *toJson() const; - void write(); - void read(void *in, size_t len); + void write(); + void read(void *in, size_t len); }; class Relay : public Tool { public: - friend RelaySession; + friend RelaySession; - Relay(int argc, char *argv[]); + Relay(int argc, char *argv[]); protected: - std::atomic stop; + std::atomic stop; - // The libwebsockets server context. - lws_context *context; + // The libwebsockets server context. + lws_context *context; - // The libwebsockets vhost. - lws_vhost *vhost; + // The libwebsockets vhost. + lws_vhost *vhost; - bool loopback; - int port; - std::string protocol; - std::string hostname; + bool loopback; + int port; + std::string protocol; + std::string hostname; - uuid_t uuid; + uuid_t uuid; - // List of libwebsockets protocols. - std::vector protocols; + // List of libwebsockets protocols. + std::vector protocols; - // List of libwebsockets extensions. - static - const std::vector extensions; + // List of libwebsockets extensions. + static const std::vector extensions; - static - const lws_http_mount mount; + static const lws_http_mount mount; - static - void loggerCallback(int level, const char *msg); + static void loggerCallback(int level, const char *msg); - static - int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - static - int protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - void usage(); + void usage(); - void parse(); + void parse(); - int main(); + int main(); - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } }; } // namespace tools diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index b50f34de5..2794333ce 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -5,23 +5,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include -#include +#include -#include -#include -#include #include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include +#include +#include using namespace villas; @@ -32,294 +32,287 @@ namespace tools { class Signal : public Tool { public: - Signal(int argc, char *argv[]) : - Tool(argc, argv, "signal"), - stop(false), - node(), - formatter(nullptr), - pool(), - format("villas.human") - { - int ret; + Signal(int argc, char *argv[]) + : Tool(argc, argv, "signal"), stop(false), node(), formatter(nullptr), + pool(), format("villas.human") { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::atomic stop; + std::atomic stop; - Node *node; - Format *formatter; - struct Pool pool; + Node *node; + Format *formatter; + struct Pool pool; - std::string format; + std::string format; - void usage() - { - std::cout << "Usage: villas-signal [OPTIONS] SIGNAL" << std::endl - << " SIGNAL is on of the following signal types:" << std::endl - << " mixed" << std::endl - << " random" << std::endl - << " sine" << std::endl - << " triangle" << std::endl - << " square" << std::endl - << " ramp" << std::endl - << " constants" << std::endl - << " counter" << std::endl << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -f FMT set the format" << std::endl - << " -v NUM specifies how many values a message should contain" << std::endl - << " -r HZ how many messages per second" << std::endl - << " -n non real-time mode. do not throttle output." << std::endl - << " -F HZ the frequency of the signal" << std::endl - << " -a FLT the amplitude" << std::endl - << " -D FLT the standard deviation for 'random' signals" << std::endl - << " -o OFF the DC bias" << std::endl - << " -l NUM only send LIMIT messages and stop" << std::endl << std::endl; + void usage() { + std::cout + << "Usage: villas-signal [OPTIONS] SIGNAL" << std::endl + << " SIGNAL is on of the following signal types:" << std::endl + << " mixed" << std::endl + << " random" << std::endl + << " sine" << std::endl + << " triangle" << std::endl + << " square" << std::endl + << " ramp" << std::endl + << " constants" << std::endl + << " counter" << std::endl + << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -d LVL set debug level" << std::endl + << " -f FMT set the format" << std::endl + << " -v NUM specifies how many values a message should contain" + << std::endl + << " -r HZ how many messages per second" << std::endl + << " -n non real-time mode. do not throttle output." + << std::endl + << " -F HZ the frequency of the signal" << std::endl + << " -a FLT the amplitude" << std::endl + << " -D FLT the standard deviation for 'random' signals" + << std::endl + << " -o OFF the DC bias" << std::endl + << " -l NUM only send LIMIT messages and stop" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - json_t * parse_cli(int argc, char *argv[]) - { - // Default values - double rate = 10; - double frequency = 1; - double amplitude = 1; - double stddev = 0.02; - double offset = 0; - double phase = 0.0; - double pulse_low = 0.0; - double pulse_high = 1.0; - double pulse_width = 1.0; + json_t *parse_cli(int argc, char *argv[]) { + // Default values + double rate = 10; + double frequency = 1; + double amplitude = 1; + double stddev = 0.02; + double offset = 0; + double phase = 0.0; + double pulse_low = 0.0; + double pulse_high = 1.0; + double pulse_width = 1.0; - std::string type; - int rt = 1; - int values = 1; - int limit = -1; + std::string type; + int rt = 1; + int values = 1; + int limit = -1; - // Parse optional command line arguments - int c; - char *endptr; - while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { - switch (c) { - case 'n': - rt = 0; - break; + // Parse optional command line arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { + switch (c) { + case 'n': + rt = 0; + break; - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 'l': - limit = strtoul(optarg, &endptr, 10); - goto check; + case 'l': + limit = strtoul(optarg, &endptr, 10); + goto check; - case 'v': - values = strtoul(optarg, &endptr, 10); - goto check; + case 'v': + values = strtoul(optarg, &endptr, 10); + goto check; - case 'r': - rate = strtof(optarg, &endptr); - goto check; + case 'r': + rate = strtof(optarg, &endptr); + goto check; - case 'o': - offset = strtof(optarg, &endptr); - goto check; + case 'o': + offset = strtof(optarg, &endptr); + goto check; - case 'F': - frequency = strtof(optarg, &endptr); - goto check; + case 'F': + frequency = strtof(optarg, &endptr); + goto check; - case 'a': - amplitude = strtof(optarg, &endptr); - goto check; + case 'a': + amplitude = strtof(optarg, &endptr); + goto check; - case 'D': - stddev = strtof(optarg, &endptr); - goto check; + case 'D': + stddev = strtof(optarg, &endptr); + goto check; - case 'p': - phase = strtof(optarg, &endptr); - goto check; + case 'p': + phase = strtof(optarg, &endptr); + goto check; - case 'w': - pulse_width = strtof(optarg, &endptr); - goto check; + case 'w': + pulse_width = strtof(optarg, &endptr); + goto check; - case 'L': - pulse_low = strtof(optarg, &endptr); - goto check; + case 'L': + pulse_low = strtof(optarg, &endptr); + goto check; - case 'H': - pulse_high = strtof(optarg, &endptr); - goto check; + case 'H': + pulse_high = strtof(optarg, &endptr); + goto check; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - logger->warn("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + logger->warn("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 1) - return nullptr; + if (argc != optind + 1) + return nullptr; - type = argv[optind]; + type = argv[optind]; - json_t *json_signals = json_array(); + json_t *json_signals = json_array(); - for (int i = 0; i < values; i++) { - json_t *json_signal = json_pack("{ s: s, s: f, s: f, s: f, s: f, s: f, s: f, s: f, s: f }", - "signal", strdup(type.c_str()), - "frequency", frequency, - "amplitude", amplitude, - "stddev", stddev, - "offset", offset, - "pulse_width", pulse_width, - "pulse_low", pulse_low, - "pulse_high", pulse_high, - "phase", phase - ); + for (int i = 0; i < values; i++) { + json_t *json_signal = json_pack( + "{ s: s, s: f, s: f, s: f, s: f, s: f, s: f, s: f, s: f }", "signal", + strdup(type.c_str()), "frequency", frequency, "amplitude", amplitude, + "stddev", stddev, "offset", offset, "pulse_width", pulse_width, + "pulse_low", pulse_low, "pulse_high", pulse_high, "phase", phase); - json_array_append_new(json_signals, json_signal); - } + json_array_append_new(json_signals, json_signal); + } - return json_pack("{ s: s, s: f, s: b, s: i, s: { s: o } }", - "type", "signal", - "rate", rate, - "realtime", rt, - "limit", limit, - "in", - "signals", json_signals - ); - } + return json_pack("{ s: s, s: f, s: b, s: i, s: { s: o } }", "type", + "signal", "rate", rate, "realtime", rt, "limit", limit, + "in", "signals", json_signals); + } - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - switch (signal) { - case SIGALRM: - logger->info("Reached timeout. Terminating..."); - break; + void handler(int signal, siginfo_t *sinfo, void *ctx) { + switch (signal) { + case SIGALRM: + logger->info("Reached timeout. Terminating..."); + break; - default: - logger->info("Received {} signal. Terminating...", strsignal(signal)); - } + default: + logger->info("Received {} signal. Terminating...", strsignal(signal)); + } - stop = true; - } + stop = true; + } - int main() - { - int ret; - json_t *json, *json_format; - json_error_t err; + int main() { + int ret; + json_t *json, *json_format; + json_error_t err; - struct Sample *t; + struct Sample *t; - node = NodeFactory::make("signal.v2"); - if (!node) - throw MemoryAllocationError(); + node = NodeFactory::make("signal.v2"); + if (!node) + throw MemoryAllocationError(); - json = parse_cli(argc, argv); - if (!json) { - usage(); - exit(EXIT_FAILURE); - } + json = parse_cli(argc, argv); + if (!json) { + usage(); + exit(EXIT_FAILURE); + } - ret = node->parse(json); - if (ret) { - usage(); - exit(EXIT_FAILURE); - } + ret = node->parse(json); + if (ret) { + usage(); + exit(EXIT_FAILURE); + } - ret = node->getFactory()->start(nullptr); - if (ret) - throw RuntimeError("Failed to intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(nullptr); + if (ret) + throw RuntimeError("Failed to intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - ret = node->check(); - if (ret) - throw RuntimeError("Failed to verify node configuration"); + ret = node->check(); + if (ret) + throw RuntimeError("Failed to verify node configuration"); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize output"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize output"); - formatter->start(node->getInputSignals(), ~(int) SampleFlags::HAS_OFFSET); + formatter->start(node->getInputSignals(), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&pool, 16, SAMPLE_LENGTH(node->getInputSignals()->size()), &memory::heap); - if (ret) - throw RuntimeError("Failed to initialize pool"); + ret = pool_init(&pool, 16, SAMPLE_LENGTH(node->getInputSignals()->size()), + &memory::heap); + if (ret) + throw RuntimeError("Failed to initialize pool"); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - while (!stop && node->getState() == State::STARTED) { - t = sample_alloc(&pool); + while (!stop && node->getState() == State::STARTED) { + t = sample_alloc(&pool); -retry: ret = node->read(&t, 1); - if (ret == 0) - goto retry; - else if (ret < 0) - goto out; + retry: + ret = node->read(&t, 1); + if (ret == 0) + goto retry; + else if (ret < 0) + goto out; - formatter->print(stdout, t); - fflush(stdout); + formatter->print(stdout, t); + fflush(stdout); -out: sample_decref(t); - } + out: + sample_decref(t); + } - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node"); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node"); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to de-intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to de-intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - delete node; - delete formatter; + delete node; + delete formatter; - ret = pool_destroy(&pool); - if (ret) - throw RuntimeError("Failed to destroy pool"); + ret = pool_destroy(&pool); + if (ret) + throw RuntimeError("Failed to destroy pool"); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Signal t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Signal t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-test-config.cpp b/src/villas-test-config.cpp index e48976a00..ae618c666 100644 --- a/src/villas-test-config.cpp +++ b/src/villas-test-config.cpp @@ -8,13 +8,13 @@ #include #include -#include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -26,93 +26,90 @@ namespace tools { class TestConfig : public Tool { public: - TestConfig(int argc, char *argv[]) : - Tool(argc, argv, "test-config"), - check(false), - dump(false) - { - int ret; + TestConfig(int argc, char *argv[]) + : Tool(argc, argv, "test-config"), check(false), dump(false) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::string uri; + std::string uri; - bool check; - bool dump; + bool check; + bool dump; - void usage() - { - std::cout << "Usage: villas-test-config [OPTIONS] CONFIG" << std::endl - << " CONFIG is the path to an optional configuration file" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -V show version and exit" << std::endl - << " -c perform plausability checks on config" << std::endl - << " -D dump config in JSON format" << std::endl - << " -h show usage and exit" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-test-config [OPTIONS] CONFIG" << std::endl + << " CONFIG is the path to an optional configuration file" + << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -d LVL set debug level" << std::endl + << " -V show version and exit" << std::endl + << " -c perform plausability checks on config" + << std::endl + << " -D dump config in JSON format" << std::endl + << " -h show usage and exit" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - int c; - while ((c = getopt (argc, argv, "hcVD")) != -1) { - switch (c) { - case 'c': - check = true; - break; + void parse() { + int c; + while ((c = getopt(argc, argv, "hcVD")) != -1) { + switch (c) { + case 'c': + check = true; + break; - case 'D': - dump = true; - break; + case 'D': + dump = true; + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + } - if (argc - optind < 1) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 1) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - } + uri = argv[optind]; + } - int main() - { - SuperNode sn; + int main() { + SuperNode sn; - sn.parse(uri); + sn.parse(uri); - // if (check) - // sn.check(); + // if (check) + // sn.check(); - // if (dump) - // json_dumpf(sn.getConfig(), stdout, JSON_INDENT(2)); + // if (dump) + // json_dumpf(sn.getConfig(), stdout, JSON_INDENT(2)); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::TestConfig t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::TestConfig t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-test-rtt.cpp b/src/villas-test-rtt.cpp index ffd3d09ae..6f2174289 100644 --- a/src/villas-test-rtt.cpp +++ b/src/villas-test-rtt.cpp @@ -5,29 +5,29 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include #include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include -#include -#include -#include #include +#include +#include #include #include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include -#define CLOCK_ID CLOCK_MONOTONIC +#define CLOCK_ID CLOCK_MONOTONIC using namespace villas; using namespace villas::node; @@ -39,211 +39,212 @@ namespace tools { class TestRtt : public Tool { public: - TestRtt(int argc, char *argv[]) : - Tool(argc, argv, "test-rtt"), - stop(false), - fd(STDOUT_FILENO), - count(-1), - hist_warmup(100), - hist_buckets(20) - { - int ret; + TestRtt(int argc, char *argv[]) + : Tool(argc, argv, "test-rtt"), stop(false), fd(STDOUT_FILENO), count(-1), + hist_warmup(100), hist_buckets(20) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::atomic stop; + std::atomic stop; - std::string uri; - std::string nodestr; + std::string uri; + std::string nodestr; - SuperNode sn; + SuperNode sn; - /* File descriptor for Matlab results. + /* File descriptor for Matlab results. * This allows you to write Matlab results in a seperate log file: * * ./test etc/example.conf rtt -f 3 3>> measurement_results.m */ - int fd; + int fd; - // Amount of messages which should be sent (default: -1 for unlimited) - int count; + // Amount of messages which should be sent (default: -1 for unlimited) + int count; - Hist::cnt_t hist_warmup; - int hist_buckets; + Hist::cnt_t hist_warmup; + int hist_buckets; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } - void usage() - { - std::cout << "Usage: villas-test-rtt [OPTIONS] CONFIG NODE" << std::endl - << " CONFIG path to a configuration file" << std::endl - << " NODE name of the node which shoud be used" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -c CNT send CNT messages" << std::endl - << " -f FD use file descriptor FD for result output instead of stdout" << std::endl - << " -b BKTS number of buckets for histogram" << std::endl - << " -w WMUP duration of histogram warmup phase" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-test-rtt [OPTIONS] CONFIG NODE" << std::endl + << " CONFIG path to a configuration file" << std::endl + << " NODE name of the node which shoud be used" << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -c CNT send CNT messages" << std::endl + << " -f FD use file descriptor FD for result output instead " + "of stdout" + << std::endl + << " -b BKTS number of buckets for histogram" << std::endl + << " -w WMUP duration of histogram warmup phase" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse Arguments - int c; - char *endptr; - while ((c = getopt (argc, argv, "w:hr:f:c:b:Vd:")) != -1) { - switch (c) { - case 'c': - count = strtoul(optarg, &endptr, 10); - goto check; + void parse() { + // Parse Arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "w:hr:f:c:b:Vd:")) != -1) { + switch (c) { + case 'c': + count = strtoul(optarg, &endptr, 10); + goto check; - case 'f': - fd = strtoul(optarg, &endptr, 10); - goto check; + case 'f': + fd = strtoul(optarg, &endptr, 10); + goto check; - case 'w': - hist_warmup = strtoul(optarg, &endptr, 10); - goto check; + case 'w': + hist_warmup = strtoul(optarg, &endptr, 10); + goto check; - case 'b': - hist_buckets = strtoul(optarg, &endptr, 10); - goto check; + case 'b': + hist_buckets = strtoul(optarg, &endptr, 10); + goto check; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != optind + 2) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - nodestr = argv[optind + 1]; - } + uri = argv[optind]; + nodestr = argv[optind + 1]; + } - int main() - { - int ret; + int main() { + int ret; - Hist hist(hist_buckets, hist_warmup); - struct timespec send, recv; + Hist hist(hist_buckets, hist_warmup); + struct timespec send, recv; - struct Sample *smp_send = (struct Sample *) new char[SAMPLE_LENGTH(2)]; - struct Sample *smp_recv = (struct Sample *) new char[SAMPLE_LENGTH(2)]; + struct Sample *smp_send = (struct Sample *)new char[SAMPLE_LENGTH(2)]; + struct Sample *smp_recv = (struct Sample *)new char[SAMPLE_LENGTH(2)]; - if (!smp_send || !smp_recv) - throw MemoryAllocationError(); + if (!smp_send || !smp_recv) + throw MemoryAllocationError(); - Node *node; + Node *node; - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - node = sn.getNode(nodestr); - if (!node) - throw RuntimeError("There's no node with the name '{}'", nodestr); + node = sn.getNode(nodestr); + if (!node) + throw RuntimeError("There's no node with the name '{}'", nodestr); - ret = node->getFactory()->start(&sn); - if (ret) - throw RuntimeError("Failed to start node-type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(&sn); + if (ret) + throw RuntimeError("Failed to start node-type {}: reason={}", + node->getFactory()->getName(), ret); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - // Print header - fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev"); + // Print header + fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", + "min", "max", "mean", "stddev"); - while (!stop && (count < 0 || count--)) { - clock_gettime(CLOCK_ID, &send); + while (!stop && (count < 0 || count--)) { + clock_gettime(CLOCK_ID, &send); - node->write(&smp_send, 1); // Ping - node->read(&smp_recv, 1); // Pong + node->write(&smp_send, 1); // Ping + node->read(&smp_recv, 1); // Pong - clock_gettime(CLOCK_ID, &recv); + clock_gettime(CLOCK_ID, &recv); - double rtt = time_delta(&recv, &send); + double rtt = time_delta(&recv, &send); - if (rtt < 0) - logger->warn("Negative RTT: {}", rtt); + if (rtt < 0) + logger->warn("Negative RTT: {}", rtt); - hist.put(rtt); + hist.put(rtt); - smp_send->sequence++; + smp_send->sequence++; - fprintf(stdout, "%10lld.%06lld%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n", - (long long) recv.tv_sec, - (long long) recv.tv_nsec / 1000, smp_send->sequence, - 1e3 * rtt, 1e3 * hist.getLowest(), 1e3 * hist.getHighest(), - 1e3 * hist.getMean(), 1e3 * hist.getStddev()); - } + fprintf(stdout, + "%10lld.%06lld%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n", + (long long)recv.tv_sec, (long long)recv.tv_nsec / 1000, + smp_send->sequence, 1e3 * rtt, 1e3 * hist.getLowest(), + 1e3 * hist.getHighest(), 1e3 * hist.getMean(), + 1e3 * hist.getStddev()); + } - struct stat st; - if (!fstat(fd, &st)) { - FILE *f = fdopen(fd, "w"); - hist.dumpMatlab(f); - fclose(f); - } - else - throw RuntimeError("Invalid file descriptor: {}", fd); + struct stat st; + if (!fstat(fd, &st)) { + FILE *f = fdopen(fd, "w"); + hist.dumpMatlab(f); + fclose(f); + } else + throw RuntimeError("Invalid file descriptor: {}", fd); - hist.print(logger, true); + hist.print(logger, true); - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), ret); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), + ret); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to stop node-type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to stop node-type {}: reason={}", + node->getFactory()->getName(), ret); - delete smp_send; - delete smp_recv; + delete smp_send; + delete smp_recv; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::TestRtt t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::TestRtt t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-zmq-keygen.cpp b/src/villas-zmq-keygen.cpp index c666a6c33..886016ff3 100644 --- a/src/villas-zmq-keygen.cpp +++ b/src/villas-zmq-keygen.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include -#include +#include +#include #include +#include #if ZMQ_VERSION_MAJOR < 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR <= 1) - #include +#include #endif namespace villas { @@ -22,42 +22,41 @@ namespace tools { class ZmqKeygen : public Tool { public: - ZmqKeygen(int argc, char *argv[]) : - Tool(argc, argv, "zmq-keygen") - { } + ZmqKeygen(int argc, char *argv[]) : Tool(argc, argv, "zmq-keygen") {} protected: - int main() - { - int ret; - char public_key[41]; - char secret_key[41]; + int main() { + int ret; + char public_key[41]; + char secret_key[41]; - ret = zmq_curve_keypair(public_key, secret_key); - if (ret) { - if (zmq_errno() == ENOTSUP) - std::cout << "To use " << argv[0] << ", please install libsodium and then rebuild libzmq." << std::endl; + ret = zmq_curve_keypair(public_key, secret_key); + if (ret) { + if (zmq_errno() == ENOTSUP) + std::cout << "To use " << argv[0] + << ", please install libsodium and then rebuild libzmq." + << std::endl; - exit(EXIT_FAILURE); - } + exit(EXIT_FAILURE); + } - std::cout << "# Copy these lines to your 'zeromq' node-configuration" << std::endl; - std::cout << "curve = {" << std::endl; - std::cout << "\tpublic_key = \"" << public_key << "\";" << std::endl; - std::cout << "\tsecret_key = \"" << secret_key << "\";" << std::endl; - std::cout << "}" << std::endl; + std::cout << "# Copy these lines to your 'zeromq' node-configuration" + << std::endl; + std::cout << "curve = {" << std::endl; + std::cout << "\tpublic_key = \"" << public_key << "\";" << std::endl; + std::cout << "\tsecret_key = \"" << secret_key << "\";" << std::endl; + std::cout << "}" << std::endl; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::ZmqKeygen t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::ZmqKeygen t(argc, argv); - return t.run(); + return t.run(); } diff --git a/tests/unit/config.cpp b/tests/unit/config.cpp index ab126d6ee..cdb0f5ba2 100644 --- a/tests/unit/config.cpp +++ b/tests/unit/config.cpp @@ -5,73 +5,71 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include #include +#include using namespace villas::node; // cppcheck-suppress syntaxError -Test(config, env) -{ - const char *cfg_f = "test = \"${MY_ENV_VAR}\"\n"; +Test(config, env) { + const char *cfg_f = "test = \"${MY_ENV_VAR}\"\n"; - std::FILE *f = std::tmpfile(); - std::fputs(cfg_f, f); - std::rewind(f); + std::FILE *f = std::tmpfile(); + std::fputs(cfg_f, f); + std::rewind(f); - auto c = Config(); + auto c = Config(); - char env[] = "MY_ENV_VAR=mobydick"; - putenv(env); + char env[] = "MY_ENV_VAR=mobydick"; + putenv(env); - auto *r = c.load(f); - cr_assert_not_null(r); + auto *r = c.load(f); + cr_assert_not_null(r); - auto *j = json_object_get(r, "test"); - cr_assert_not_null(j); + auto *j = json_object_get(r, "test"); + cr_assert_not_null(j); - cr_assert(json_is_string(j)); - cr_assert_str_eq("mobydick", json_string_value(j)); + cr_assert(json_is_string(j)); + cr_assert_str_eq("mobydick", json_string_value(j)); } -Test(config, include) -{ - const char *cfg_f2 = "magic = 1234\n"; +Test(config, include) { + const char *cfg_f2 = "magic = 1234\n"; - char f2_fn_tpl[] = "/tmp/villas.unit-test.XXXXXX"; - int f2_fd = mkstemp(f2_fn_tpl); + char f2_fn_tpl[] = "/tmp/villas.unit-test.XXXXXX"; + int f2_fd = mkstemp(f2_fn_tpl); - std::FILE *f2 = fdopen(f2_fd, "w"); - std::fputs(cfg_f2, f2); - std::rewind(f2); + std::FILE *f2 = fdopen(f2_fd, "w"); + std::fputs(cfg_f2, f2); + std::rewind(f2); - auto cfg_f1 = fmt::format("subval = \"@include {}\"\n", f2_fn_tpl); + auto cfg_f1 = fmt::format("subval = \"@include {}\"\n", f2_fn_tpl); - std::FILE *f1 = std::tmpfile(); - std::fputs(cfg_f1.c_str(), f1); - std::rewind(f1); + std::FILE *f1 = std::tmpfile(); + std::fputs(cfg_f1.c_str(), f1); + std::rewind(f1); - auto env = fmt::format("INCLUDE_FILE={}", f2_fn_tpl).c_str(); - putenv((char *) env); + auto env = fmt::format("INCLUDE_FILE={}", f2_fn_tpl).c_str(); + putenv((char *)env); - auto c = Config(); + auto c = Config(); - auto *r = c.load(f1); - cr_assert_not_null(r); + auto *r = c.load(f1); + cr_assert_not_null(r); - auto *j = json_object_get(r, "subval"); - cr_assert_not_null(j); + auto *j = json_object_get(r, "subval"); + cr_assert_not_null(j); - auto *j2 = json_object_get(j, "magic"); - cr_assert_not_null(j2); + auto *j2 = json_object_get(j, "magic"); + cr_assert_not_null(j2); - cr_assert(json_is_integer(j2)); - cr_assert_eq(json_number_value(j2), 1234); + cr_assert(json_is_integer(j2)); + cr_assert_eq(json_number_value(j2), 1234); - std::fclose(f2); - std::remove(f2_fn_tpl); + std::fclose(f2); + std::remove(f2_fn_tpl); } diff --git a/tests/unit/config_json.cpp b/tests/unit/config_json.cpp index f0592f17d..268385d82 100644 --- a/tests/unit/config_json.cpp +++ b/tests/unit/config_json.cpp @@ -12,97 +12,95 @@ #include #include -#include #include +#include using namespace villas::node; const char *cfg_example = "test : \n" - "{\n" - " hallo = 1L;\n" - "};\n" - "liste = ( 1.1, 2L, 3L, 4L, \n" - " {\n" - " objekt : \n" - " {\n" - " key = \"value\";\n" - " };\n" - " } );\n"; + "{\n" + " hallo = 1L;\n" + "};\n" + "liste = ( 1.1, 2L, 3L, 4L, \n" + " {\n" + " objekt : \n" + " {\n" + " key = \"value\";\n" + " };\n" + " } );\n"; const char *json_example = "{\n" - " \"test\": {\n" - " \"hallo\": 1\n" - " },\n" - " \"liste\": [\n" - " 1.1000000000000001,\n" - " 2,\n" - " 3,\n" - " 4,\n" - " {\n" - " \"objekt\": {\n" - " \"key\": \"value\"\n" - " }\n" - " }\n" - " ]\n" - "}"; + " \"test\": {\n" + " \"hallo\": 1\n" + " },\n" + " \"liste\": [\n" + " 1.1000000000000001,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " {\n" + " \"objekt\": {\n" + " \"key\": \"value\"\n" + " }\n" + " }\n" + " ]\n" + "}"; // cppcheck-suppress syntaxError -Test(config, config_to_json) -{ - int ret; - config_t cfg; - config_setting_t *cfg_root; - json_t *json; +Test(config, config_to_json) { + int ret; + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - config_init(&cfg); + config_init(&cfg); - ret = config_read_string(&cfg, cfg_example); - cr_assert_eq(ret, CONFIG_TRUE); + ret = config_read_string(&cfg, cfg_example); + cr_assert_eq(ret, CONFIG_TRUE); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json = config_to_json(cfg_root); - cr_assert_not_null(json); + json = config_to_json(cfg_root); + cr_assert_not_null(json); - char *str = json_dumps(json, JSON_INDENT(2)); + char *str = json_dumps(json, JSON_INDENT(2)); - //printf("%s\n", str); + //printf("%s\n", str); - json_decref(json); + json_decref(json); - cr_assert_str_eq(str, json_example); + cr_assert_str_eq(str, json_example); - config_destroy(&cfg); + config_destroy(&cfg); } -Test(config, json_to_config) -{ - config_t cfg; - config_setting_t *cfg_root; - json_t *json; +Test(config, json_to_config) { + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - // For config_write() - FILE *f; - char str[1024]; + // For config_write() + FILE *f; + char str[1024]; - config_init(&cfg); + config_init(&cfg); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json = json_loads(json_example, 0, nullptr); - cr_assert_not_null(json); + json = json_loads(json_example, 0, nullptr); + cr_assert_not_null(json); - json_to_config(json, cfg_root); + json_to_config(json, cfg_root); - //config_write(&cfg, stdout); + //config_write(&cfg, stdout); - f = fmemopen(str, sizeof(str), "w+"); - config_write(&cfg, f); - fclose(f); + f = fmemopen(str, sizeof(str), "w+"); + config_write(&cfg, f); + fclose(f); - cr_assert_str_eq(str, cfg_example); + cr_assert_str_eq(str, cfg_example); - json_decref(json); + json_decref(json); } #endif // WITH_CONFIG diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index 95dbeb2f4..54abc41bb 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -5,350 +5,381 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include #include #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #include "helpers.hpp" using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define NUM_VALUES 10 -using string = std::basic_string, criterion::allocator>; +using string = + std::basic_string, criterion::allocator>; struct Param { public: - Param(const char *f, int c, int b) : - fmt(f), cnt(c), bits(b) - {} + Param(const char *f, int c, int b) : fmt(f), cnt(c), bits(b) {} - string fmt; - int cnt; - int bits; + string fmt; + int cnt; + int bits; }; -void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], unsigned cnt) -{ - struct timespec delta, now; +void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], + unsigned cnt) { + struct timespec delta, now; - now = time_now(); - delta = time_from_double(50e-6); + now = time_now(); + delta = time_from_double(50e-6); - for (unsigned i = 0; i < cnt; i++) { - struct Sample *smp = smps[i]; + for (unsigned i = 0; i < cnt; i++) { + struct Sample *smp = smps[i]; - smps[i]->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN; - smps[i]->length = signals->size(); - smps[i]->sequence = 235 + i; - smps[i]->ts.origin = now; - smps[i]->signals = signals; + smps[i]->flags = (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN; + smps[i]->length = signals->size(); + smps[i]->sequence = 235 + i; + smps[i]->ts.origin = now; + smps[i]->signals = signals; - for (size_t j = 0; j < signals->size(); j++) { - auto sig = signals->getByIndex(j); - auto *data = &smp->data[j]; + for (size_t j = 0; j < signals->size(); j++) { + auto sig = signals->getByIndex(j); + auto *data = &smp->data[j]; - switch (sig->type) { - case SignalType::BOOLEAN: - data->b = j * 0.1 + i * 100; - break; + switch (sig->type) { + case SignalType::BOOLEAN: + data->b = j * 0.1 + i * 100; + break; - case SignalType::COMPLEX: { - // TODO: Port to proper C++ - std::complex z = { j * 0.1f, i * 100.0f }; - memcpy(&data->z, &z, sizeof(data->z)); - break; - } + case SignalType::COMPLEX: { + // TODO: Port to proper C++ + std::complex z = {j * 0.1f, i * 100.0f}; + memcpy(&data->z, &z, sizeof(data->z)); + break; + } - case SignalType::FLOAT: - data->f = j * 0.1 + i * 100; - break; + case SignalType::FLOAT: + data->f = j * 0.1 + i * 100; + break; - case SignalType::INTEGER: - data->i = j + i * 1000; - break; + case SignalType::INTEGER: + data->i = j + i * 1000; + break; - default: { } - } - } + default: { + } + } + } - now = time_add(&now, &delta); - } + now = time_add(&now, &delta); + } } -void cr_assert_eq_sample(struct Sample *a, struct Sample *b, int flags) -{ - cr_assert_eq(a->length, b->length, "a->length=%d, b->length=%d", a->length, b->length); +void cr_assert_eq_sample(struct Sample *a, struct Sample *b, int flags) { + cr_assert_eq(a->length, b->length, "a->length=%d, b->length=%d", a->length, + b->length); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - cr_assert_eq(a->sequence, b->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + cr_assert_eq(a->sequence, b->sequence); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); - cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); + cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned j = 0; j < MIN(a->length, b->length); j++) { - cr_assert_eq(sample_format(a, j), sample_format(b, j)); + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned j = 0; j < MIN(a->length, b->length); j++) { + cr_assert_eq(sample_format(a, j), sample_format(b, j)); - switch (sample_format(b, j)) { - case SignalType::FLOAT: - cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, "Sample data mismatch at index %d: %f != %f", j, a->data[j].f, b->data[j].f); - break; + switch (sample_format(b, j)) { + case SignalType::FLOAT: + cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, + "Sample data mismatch at index %d: %f != %f", j, + a->data[j].f, b->data[j].f); + break; - case SignalType::INTEGER: - cr_assert_eq(a->data[j].i, b->data[j].i, "Sample data mismatch at index %d: %lld != %lld", j, a->data[j].i, b->data[j].i); - break; + case SignalType::INTEGER: + cr_assert_eq(a->data[j].i, b->data[j].i, + "Sample data mismatch at index %d: %lld != %lld", j, + a->data[j].i, b->data[j].i); + break; - case SignalType::BOOLEAN: - cr_assert_eq(a->data[j].b, b->data[j].b, "Sample data mismatch at index %d: %s != %s", j, a->data[j].b ? "true" : "false", b->data[j].b ? "true" : "false"); - break; + case SignalType::BOOLEAN: + cr_assert_eq(a->data[j].b, b->data[j].b, + "Sample data mismatch at index %d: %s != %s", j, + a->data[j].b ? "true" : "false", + b->data[j].b ? "true" : "false"); + break; - case SignalType::COMPLEX: { - auto ca = * (std::complex *) &a->data[j].z; - auto cb = * (std::complex *) &b->data[j].z; + case SignalType::COMPLEX: { + auto ca = *(std::complex *)&a->data[j].z; + auto cb = *(std::complex *)&b->data[j].z; - cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, ca.real(), ca.imag(), cb.real(), cb.imag()); - break; - } + cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, + "Sample data mismatch at index %d: %f+%fi != %f+%fi", + j, ca.real(), ca.imag(), cb.real(), cb.imag()); + break; + } - default: { } - } - } - } + default: { + } + } + } + } } -void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, int bits) -{ - cr_assert_eq(a->length, b->length); +void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, + int bits) { + cr_assert_eq(a->length, b->length); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - cr_assert_eq(a->sequence, b->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + cr_assert_eq(a->sequence, b->sequence); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); - cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); + cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned j = 0; j < MIN(a->length, b->length); j++) { - cr_assert_eq(sample_format(a, j), sample_format(b, j)); + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned j = 0; j < MIN(a->length, b->length); j++) { + cr_assert_eq(sample_format(a, j), sample_format(b, j)); - switch (sample_format(b, j)) { - case SignalType::FLOAT: - if (bits != 8 && bits != 16) - cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, "Sample data mismatch at index %d: %f != %f", j, a->data[j].f, b->data[j].f); - break; + switch (sample_format(b, j)) { + case SignalType::FLOAT: + if (bits != 8 && bits != 16) + cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, + "Sample data mismatch at index %d: %f != %f", j, + a->data[j].f, b->data[j].f); + break; - case SignalType::INTEGER: - cr_assert_eq(a->data[j].i, b->data[j].i, "Sample data mismatch at index %d: %lld != %lld", j, a->data[j].i, b->data[j].i); - break; + case SignalType::INTEGER: + cr_assert_eq(a->data[j].i, b->data[j].i, + "Sample data mismatch at index %d: %lld != %lld", j, + a->data[j].i, b->data[j].i); + break; - case SignalType::BOOLEAN: - cr_assert_eq(a->data[j].b, b->data[j].b, "Sample data mismatch at index %d: %s != %s", j, a->data[j].b ? "true" : "false", b->data[j].b ? "true" : "false"); - break; + case SignalType::BOOLEAN: + cr_assert_eq(a->data[j].b, b->data[j].b, + "Sample data mismatch at index %d: %s != %s", j, + a->data[j].b ? "true" : "false", + b->data[j].b ? "true" : "false"); + break; - case SignalType::COMPLEX: - if (bits != 8 && bits != 16) { - auto ca = * (std::complex *) &a->data[j].z; - auto cb = * (std::complex *) &b->data[j].z; + case SignalType::COMPLEX: + if (bits != 8 && bits != 16) { + auto ca = *(std::complex *)&a->data[j].z; + auto cb = *(std::complex *)&b->data[j].z; - cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, ca.real(), ca.imag(), cb.real(), cb.imag()); - } - break; + cr_assert_float_eq( + std::abs(ca - cb), 0, 1e-6, + "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, + ca.real(), ca.imag(), cb.real(), cb.imag()); + } + break; - default: { } - } - } - } + default: { + } + } + } + } } -ParameterizedTestParameters(format, lowlevel) -{ - static - criterion::parameters params; +ParameterizedTestParameters(format, lowlevel) { + static criterion::parameters params; - params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); - params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); - params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); - params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); - params.emplace_back("{ \"type\": \"csv\" }", 10, 0); - params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); - params.emplace_back("{ \"type\": \"json\" }", 10, 0); - // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names - // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); + params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); + params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); + params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); + params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); + params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); + params.emplace_back("{ \"type\": \"csv\" }", 10, 0); + params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); + params.emplace_back("{ \"type\": \"json\" }", 10, 0); + // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names + // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); #ifdef PROTOBUF_FOUND - params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0 ); + params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0); #endif - return params; + return params; } // cppcheck-suppress unknownMacro -ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) -{ - int ret; - unsigned cnt; - char buf[8192]; - size_t wbytes, rbytes; +ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) { + int ret; + unsigned cnt; + char buf[8192]; + size_t wbytes, rbytes; - Logger logger = logging.get("test:format:lowlevel"); + Logger logger = logging.get("test:format:lowlevel"); - logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); + logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); - struct Pool pool; - Format *fmt; - struct Sample *smps[p->cnt]; - struct Sample *smpt[p->cnt]; + struct Pool pool; + Format *fmt; + struct Sample *smps[p->cnt]; + struct Sample *smpt[p->cnt]; - ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); - cr_assert_eq(ret, 0); + ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); + cr_assert_eq(ret, 0); - auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); + auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); - ret = sample_alloc_many(&pool, smps, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smps, p->cnt); + cr_assert_eq(ret, p->cnt); - ret = sample_alloc_many(&pool, smpt, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smpt, p->cnt); + cr_assert_eq(ret, p->cnt); - fill_sample_data(signals, smps, p->cnt); + fill_sample_data(signals, smps, p->cnt); - json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); - cr_assert_not_null(json_format); + json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); + cr_assert_not_null(json_format); - fmt = FormatFactory::make(json_format); - cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); + fmt = FormatFactory::make(json_format); + cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", + p->fmt.c_str()); - fmt->start(signals, (int) SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::HAS_ALL); - cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt); - cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); + cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt); + cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); - cnt = fmt->sscan(buf, wbytes, &rbytes, smpt, p->cnt); - cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); + cnt = fmt->sscan(buf, wbytes, &rbytes, smpt, p->cnt); + cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); - cr_assert_eq(rbytes, wbytes, "rbytes != wbytes: %#zx != %#zx", rbytes, wbytes); + cr_assert_eq(rbytes, wbytes, "rbytes != wbytes: %#zx != %#zx", rbytes, + wbytes); - for (unsigned i = 0; i < cnt; i++) { - if (p->bits) - cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); - else - cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); - } + for (unsigned i = 0; i < cnt; i++) { + if (p->bits) + cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); + else + cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); + } - sample_free_many(smps, p->cnt); - sample_free_many(smpt, p->cnt); + sample_free_many(smps, p->cnt); + sample_free_many(smpt, p->cnt); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0); } -ParameterizedTestParameters(format, highlevel) -{ - static - criterion::parameters params; +ParameterizedTestParameters(format, highlevel) { + static criterion::parameters params; - params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); - params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); - params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); - params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); - params.emplace_back("{ \"type\": \"csv\" }", 10, 0); - params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); - params.emplace_back("{ \"type\": \"json\" }", 10, 0); - // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names - // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); + params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); + params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); + params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); + params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); + params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); + params.emplace_back("{ \"type\": \"csv\" }", 10, 0); + params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); + params.emplace_back("{ \"type\": \"json\" }", 10, 0); + // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names + // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); #ifdef PROTOBUF_FOUND - params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0 ); + params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0); #endif - return params; + return params; } -ParameterizedTest(Param *p, format, highlevel, .init = init_memory) -{ - int ret, cnt; - char *retp; +ParameterizedTest(Param *p, format, highlevel, .init = init_memory) { + int ret, cnt; + char *retp; - Logger logger = logging.get("test:format:highlevel"); + Logger logger = logging.get("test:format:highlevel"); - logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); + logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); - struct Sample *smps[p->cnt]; - struct Sample *smpt[p->cnt]; + struct Sample *smps[p->cnt]; + struct Sample *smpt[p->cnt]; - struct Pool pool; - Format *fmt; + struct Pool pool; + Format *fmt; - ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); - cr_assert_eq(ret, 0); + ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); + cr_assert_eq(ret, 0); - ret = sample_alloc_many(&pool, smps, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smps, p->cnt); + cr_assert_eq(ret, p->cnt); - ret = sample_alloc_many(&pool, smpt, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smpt, p->cnt); + cr_assert_eq(ret, p->cnt); - auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); + auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); - fill_sample_data(signals, smps, p->cnt); + fill_sample_data(signals, smps, p->cnt); - // Open a file for testing the formatter - char *fn, dir[64]; - strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir)); + // Open a file for testing the formatter + char *fn, dir[64]; + strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir)); - retp = mkdtemp(dir); - cr_assert_not_null(retp); + retp = mkdtemp(dir); + cr_assert_not_null(retp); - ret = asprintf(&fn, "%s/file", dir); - cr_assert_gt(ret, 0); + ret = asprintf(&fn, "%s/file", dir); + cr_assert_gt(ret, 0); - json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); - cr_assert_not_null(json_format); + json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); + cr_assert_not_null(json_format); - fmt = FormatFactory::make(json_format); - cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); + fmt = FormatFactory::make(json_format); + cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", + p->fmt.c_str()); - fmt->start(signals, (int) SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::HAS_ALL); - auto *stream = fopen(fn, "w+"); - cr_assert_not_null(stream); + auto *stream = fopen(fn, "w+"); + cr_assert_not_null(stream); - cnt = fmt->print(stream, smps, p->cnt); - cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); + cnt = fmt->print(stream, smps, p->cnt); + cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); - ret = fflush(stream); - cr_assert_eq(ret, 0); + ret = fflush(stream); + cr_assert_eq(ret, 0); #if 0 // Show the file contents char cmd[128]; @@ -359,34 +390,34 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) system(cmd); #endif - rewind(stream); + rewind(stream); - cnt = fmt->scan(stream, smpt, p->cnt); - cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); + cnt = fmt->scan(stream, smpt, p->cnt); + cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); - for (int i = 0; i < cnt; i++) { - if (p->bits) - cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); - else - cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); - } + for (int i = 0; i < cnt; i++) { + if (p->bits) + cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); + else + cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); + } - ret = fclose(stream); - cr_assert_eq(ret, 0); + ret = fclose(stream); + cr_assert_eq(ret, 0); - delete fmt; + delete fmt; - ret = unlink(fn); - cr_assert_eq(ret, 0); + ret = unlink(fn); + cr_assert_eq(ret, 0); - ret = rmdir(dir); - cr_assert_eq(ret, 0); + ret = rmdir(dir); + cr_assert_eq(ret, 0); - free(fn); + free(fn); - sample_free_many(smps, p->cnt); - sample_free_many(smpt, p->cnt); + sample_free_many(smps, p->cnt); + sample_free_many(smpt, p->cnt); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0); } diff --git a/tests/unit/helpers.cpp b/tests/unit/helpers.cpp index a5df1d0d1..f7569fe5d 100644 --- a/tests/unit/helpers.cpp +++ b/tests/unit/helpers.cpp @@ -11,10 +11,9 @@ #include "helpers.hpp" -char * cr_strdup(const char *str) -{ - char *ptr = (char *) cr_malloc(strlen(str) + 1); - if (ptr) - strcpy(ptr, str); - return ptr; +char *cr_strdup(const char *str) { + char *ptr = (char *)cr_malloc(strlen(str) + 1); + if (ptr) + strcpy(ptr, str); + return ptr; } diff --git a/tests/unit/helpers.hpp b/tests/unit/helpers.hpp index da2079c99..0d01b7919 100644 --- a/tests/unit/helpers.hpp +++ b/tests/unit/helpers.hpp @@ -7,4 +7,4 @@ #pragma once -char * cr_strdup(const char *str); +char *cr_strdup(const char *str); diff --git a/tests/unit/json.cpp b/tests/unit/json.cpp index 5314948f5..9aef6ba73 100644 --- a/tests/unit/json.cpp +++ b/tests/unit/json.cpp @@ -8,81 +8,69 @@ #include #include -#include #include +#include #include "helpers.hpp" using namespace villas::node; struct param { - char *argv[32]; - char *json; + char *argv[32]; + char *json; }; // cppcheck-suppress syntaxError -ParameterizedTestParameters(json, json_load_cli) -{ - const auto d = cr_strdup; +ParameterizedTestParameters(json, json_load_cli) { + const auto d = cr_strdup; - static - criterion::parameters params = { - // Combined long option - { - .argv = { d("dummy"), d("--option=value") }, - .json = d("{ \"option\" : \"value\" }") - }, - // Separated long option - { - .argv = { d("dummy"), d("--option"), d("value") }, - .json = d("{ \"option\" : \"value\" }") - }, - // All kinds of data types - { - .argv = { d("dummy"), d("--integer"), d("1"), d("--real"), d("1.1"), d("--bool"), d("true"), d("--null"), d("null"), d("--string"), d("hello world") }, - .json = d("{ \"integer\" : 1, \"real\" : 1.1, \"bool\" : true, \"null\" : null, \"string\" : \"hello world\" }") - }, - // Array generation - { - .argv = { d("dummy"), d("--bool"), d("true"), d("--bool"), d("false") }, - .json = d("{ \"bool\" : [ true, false ] }") - }, - // Dots in the option name generate sub objects - { - .argv = { d("dummy"), d("--sub.option"), d("value") }, - .json = d("{ \"sub\" : { \"option\" : \"value\" } }") - }, - // Nesting is possible - { - .argv = { d("dummy"), d("--sub.sub.option"), d("value") }, - .json = d("{ \"sub\" : { \"sub\" : { \"option\" : \"value\" } } }") - }, - // Multiple subgroups are merged - { - .argv = { d("dummy"), d("--sub.sub.option"), d("value1"), d("--sub.option"), d("value2") }, - .json = d("{ \"sub\" : { \"option\" : \"value2\", \"sub\" : { \"option\" : \"value1\" } } }") - } - }; + static criterion::parameters params = { + // Combined long option + {.argv = {d("dummy"), d("--option=value")}, + .json = d("{ \"option\" : \"value\" }")}, + // Separated long option + {.argv = {d("dummy"), d("--option"), d("value")}, + .json = d("{ \"option\" : \"value\" }")}, + // All kinds of data types + {.argv = {d("dummy"), d("--integer"), d("1"), d("--real"), d("1.1"), + d("--bool"), d("true"), d("--null"), d("null"), d("--string"), + d("hello world")}, + .json = d("{ \"integer\" : 1, \"real\" : 1.1, \"bool\" : true, \"null\" " + ": null, \"string\" : \"hello world\" }")}, + // Array generation + {.argv = {d("dummy"), d("--bool"), d("true"), d("--bool"), d("false")}, + .json = d("{ \"bool\" : [ true, false ] }")}, + // Dots in the option name generate sub objects + {.argv = {d("dummy"), d("--sub.option"), d("value")}, + .json = d("{ \"sub\" : { \"option\" : \"value\" } }")}, + // Nesting is possible + {.argv = {d("dummy"), d("--sub.sub.option"), d("value")}, + .json = d("{ \"sub\" : { \"sub\" : { \"option\" : \"value\" } } }")}, + // Multiple subgroups are merged + {.argv = {d("dummy"), d("--sub.sub.option"), d("value1"), + d("--sub.option"), d("value2")}, + .json = d("{ \"sub\" : { \"option\" : \"value2\", \"sub\" : { " + "\"option\" : \"value1\" } } }")}}; - return params; + return params; } -ParameterizedTest(struct param *p, json, json_load_cli) -{ - json_error_t err; - json_t *json, *cli; +ParameterizedTest(struct param *p, json, json_load_cli) { + json_error_t err; + json_t *json, *cli; - json = json_loads(p->json, 0, &err); - cr_assert_not_null(json); + json = json_loads(p->json, 0, &err); + cr_assert_not_null(json); - int argc = 0; - while (p->argv[argc]) argc++; + int argc = 0; + while (p->argv[argc]) + argc++; - cli = json_load_cli(argc, (const char **) p->argv); - cr_assert_not_null(cli); + cli = json_load_cli(argc, (const char **)p->argv); + cr_assert_not_null(cli); - //json_dumpf(json, stdout, JSON_INDENT(2)); putc('\n', stdout); - //json_dumpf(cli, stdout, JSON_INDENT(2)); putc('\n', stdout); + //json_dumpf(json, stdout, JSON_INDENT(2)); putc('\n', stdout); + //json_dumpf(cli, stdout, JSON_INDENT(2)); putc('\n', stdout); - cr_assert(json_equal(json, cli)); + cr_assert(json_equal(json, cli)); } diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 299241578..87dc0489f 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -9,8 +9,7 @@ using namespace villas::node; -void init_memory() -{ - int ret __attribute__((unused)); - ret = memory::init(DEFAULT_NR_HUGEPAGES); +void init_memory() { + int ret __attribute__((unused)); + ret = memory::init(DEFAULT_NR_HUGEPAGES); } diff --git a/tests/unit/mapping.cpp b/tests/unit/mapping.cpp index 52417f254..bf85feb32 100644 --- a/tests/unit/mapping.cpp +++ b/tests/unit/mapping.cpp @@ -7,80 +7,79 @@ #include +#include #include #include -#include -#include #include +#include using namespace villas; using namespace villas::node; // cppcheck-suppress syntaxError -Test(mapping, parse_nodes) -{ - int ret; - MappingEntry m; +Test(mapping, parse_nodes) { + int ret; + MappingEntry m; - ret = m.parseString("apple.ts.origin"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "apple"); - cr_assert_eq(m.type, MappingEntry::Type::TIMESTAMP); - cr_assert_eq(m.timestamp.type, MappingEntry::TimestampType::ORIGIN); + ret = m.parseString("apple.ts.origin"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "apple"); + cr_assert_eq(m.type, MappingEntry::Type::TIMESTAMP); + cr_assert_eq(m.timestamp.type, MappingEntry::TimestampType::ORIGIN); - ret = m.parseString("cherry.stats.owd.mean"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "cherry"); - cr_assert_eq(m.type, MappingEntry::Type::STATS); - cr_assert_eq(m.stats.metric, Stats::Metric::OWD); - cr_assert_eq(m.stats.type, Stats::Type::MEAN); + ret = m.parseString("cherry.stats.owd.mean"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "cherry"); + cr_assert_eq(m.type, MappingEntry::Type::STATS); + cr_assert_eq(m.stats.metric, Stats::Metric::OWD); + cr_assert_eq(m.stats.type, Stats::Type::MEAN); - ret = m.parseString("carrot.data[1-2]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "1"); - cr_assert_str_eq(m.data.last, "2"); + ret = m.parseString("carrot.data[1-2]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "1"); + cr_assert_str_eq(m.data.last, "2"); - ret = m.parseString("carrot"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_eq(m.data.first, nullptr); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_eq(m.data.first, nullptr); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data[sole]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.data[sole]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.sole"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.sole"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data.sole"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.data.sole"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data[sole-mio]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_str_eq(m.data.last, "mio"); + ret = m.parseString("carrot.data[sole-mio]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_str_eq(m.data.last, "mio"); - ret = m.parseString("carrot[sole-mio]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_str_eq(m.data.last, "mio"); + ret = m.parseString("carrot[sole-mio]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_str_eq(m.data.last, "mio"); } diff --git a/tests/unit/memory.cpp b/tests/unit/memory.cpp index 8731d231a..5b575145d 100644 --- a/tests/unit/memory.cpp +++ b/tests/unit/memory.cpp @@ -10,97 +10,102 @@ #include -#include -#include #include +#include #include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define PAGESIZE (1 << 12) #define HUGEPAGESIZE (1 << 21) TheoryDataPoints(memory, aligned) = { - DataPoints(size_t, 1, 32, 55, 1 << 10, PAGESIZE, HUGEPAGESIZE), - DataPoints(size_t, 1, 8, PAGESIZE, PAGESIZE), - DataPoints(struct memory::Type *, &memory::heap, &memory::mmap_hugetlb, &memory::mmap_hugetlb) -}; + DataPoints(size_t, 1, 32, 55, 1 << 10, PAGESIZE, HUGEPAGESIZE), + DataPoints(size_t, 1, 8, PAGESIZE, PAGESIZE), + DataPoints(struct memory::Type *, &memory::heap, &memory::mmap_hugetlb, + &memory::mmap_hugetlb)}; // cppcheck-suppress unknownMacro -Theory((size_t len, size_t align, struct memory::Type *mt), memory, aligned, .init = init_memory) { - int ret; - void *ptr; +Theory((size_t len, size_t align, struct memory::Type *mt), memory, aligned, + .init = init_memory) { + int ret; + void *ptr; - if (!utils::isPrivileged() && mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - ptr = memory::alloc_aligned(len, align, mt); - cr_assert_not_null(ptr, "Failed to allocate memory"); + ptr = memory::alloc_aligned(len, align, mt); + cr_assert_not_null(ptr, "Failed to allocate memory"); - cr_assert(IS_ALIGNED(ptr, align), "Memory at %p is not alligned to %#zx byte bounary", ptr, align); + cr_assert(IS_ALIGNED(ptr, align), + "Memory at %p is not alligned to %#zx byte bounary", ptr, align); - if (mt == &memory::mmap_hugetlb) { - cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE), "Memory at %p is not alligned to %#x byte bounary", ptr, HUGEPAGESIZE); - } + if (mt == &memory::mmap_hugetlb) { + cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE), + "Memory at %p is not alligned to %#x byte bounary", ptr, + HUGEPAGESIZE); + } - ret = memory::free(ptr); - cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", ret, ptr, len, strerror(errno)); + ret = memory::free(ptr); + cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", + ret, ptr, len, strerror(errno)); } Test(memory, manager, .init = init_memory) { - size_t total_size; - size_t max_block; + size_t total_size; + size_t max_block; - int ret; - void *p, *p1, *p2, *p3; - struct memory::Type *m; + int ret; + void *p, *p1, *p2, *p3; + struct memory::Type *m; - total_size = 1 << 10; - max_block = total_size - sizeof(struct memory::Type) - sizeof(struct memory::Block); + total_size = 1 << 10; + max_block = + total_size - sizeof(struct memory::Type) - sizeof(struct memory::Block); - p = memory::alloc(total_size, &memory::heap); - cr_assert_not_null(p); + p = memory::alloc(total_size, &memory::heap); + cr_assert_not_null(p); - m = memory::managed(p, total_size); - cr_assert_not_null(m); + m = memory::managed(p, total_size); + cr_assert_not_null(m); - p1 = memory::alloc(16, m); - cr_assert_not_null(p1); + p1 = memory::alloc(16, m); + cr_assert_not_null(p1); - p2 = memory::alloc(32, m); - cr_assert_not_null(p2); + p2 = memory::alloc(32, m); + cr_assert_not_null(p2); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - p1 = memory::alloc_aligned(128, 128, m); - cr_assert_not_null(p1); - cr_assert(IS_ALIGNED(p1, 128)); + p1 = memory::alloc_aligned(128, 128, m); + cr_assert_not_null(p1); + cr_assert(IS_ALIGNED(p1, 128)); - p3 = memory::alloc_aligned(128, 256, m); - cr_assert(p3); - cr_assert(IS_ALIGNED(p3, 256)); + p3 = memory::alloc_aligned(128, 256, m); + cr_assert(p3); + cr_assert(IS_ALIGNED(p3, 256)); - ret = memory::free(p2); - cr_assert(ret == 0); + ret = memory::free(p2); + cr_assert(ret == 0); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - ret = memory::free(p3); - cr_assert(ret == 0); + ret = memory::free(p3); + cr_assert(ret == 0); - p1 = memory::alloc(max_block, m); - cr_assert_not_null(p1); + p1 = memory::alloc(max_block, m); + cr_assert_not_null(p1); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - ret = memory::free(p); - cr_assert(ret == 0); + ret = memory::free(p); + cr_assert(ret == 0); } diff --git a/tests/unit/pool.cpp b/tests/unit/pool.cpp index 87b7b43e1..de98f8a88 100644 --- a/tests/unit/pool.cpp +++ b/tests/unit/pool.cpp @@ -11,72 +11,69 @@ #include #include +#include #include #include -#include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); struct param { - int thread_count; - int pool_size; - size_t block_size; - struct memory::Type *mt; + int thread_count; + int pool_size; + size_t block_size; + struct memory::Type *mt; }; -ParameterizedTestParameters(pool, basic) -{ - static - std::vector params; +ParameterizedTestParameters(pool, basic) { + static std::vector params; - params.clear(); - params.push_back({ 1, 4096, 150, &memory::heap }); - params.push_back({ 1, 128, 8, &memory::mmap }); - params.push_back({ 1, 4, 8192, &memory::mmap_hugetlb }); - params.push_back({ 1, 1 << 13, 4, &memory::mmap_hugetlb }); + params.clear(); + params.push_back({1, 4096, 150, &memory::heap}); + params.push_back({1, 128, 8, &memory::mmap}); + params.push_back({1, 4, 8192, &memory::mmap_hugetlb}); + params.push_back({1, 1 << 13, 4, &memory::mmap_hugetlb}); - return cr_make_param_array(struct param, params.data(), params.size()); + return cr_make_param_array(struct param, params.data(), params.size()); } // cppcheck-suppress unknownMacro -ParameterizedTest(struct param *p, pool, basic, .init = init_memory) -{ - int ret; - struct Pool pool; - void *ptr, *ptrs[p->pool_size]; +ParameterizedTest(struct param *p, pool, basic, .init = init_memory) { + int ret; + struct Pool pool; + void *ptr, *ptrs[p->pool_size]; - logging.setLevel("trace"); + logging.setLevel("trace"); - if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - ret = pool_init(&pool, p->pool_size, p->block_size, p->mt); - cr_assert_eq(ret, 0, "Failed to create pool"); + ret = pool_init(&pool, p->pool_size, p->block_size, p->mt); + cr_assert_eq(ret, 0, "Failed to create pool"); - ptr = pool_get(&pool); - cr_assert_neq(ptr, nullptr); + ptr = pool_get(&pool); + cr_assert_neq(ptr, nullptr); - memset(ptr, 1, p->block_size); // check that we dont get a seg fault + memset(ptr, 1, p->block_size); // check that we dont get a seg fault - int i; - for (i = 1; i < p->pool_size; i++) { - ptrs[i] = pool_get(&pool); + int i; + for (i = 1; i < p->pool_size; i++) { + ptrs[i] = pool_get(&pool); - if (ptrs[i] == nullptr) - break; - } + if (ptrs[i] == nullptr) + break; + } - if (i < p->pool_size) - cr_assert_neq(ptrs[i], nullptr); + if (i < p->pool_size) + cr_assert_neq(ptrs[i], nullptr); - ptr = pool_get(&pool); - cr_assert_eq(ptr, nullptr); + ptr = pool_get(&pool); + cr_assert_eq(ptr, nullptr); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0, "Failed to destroy pool"); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0, "Failed to destroy pool"); } diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index 9c5341ac5..4c21fef4c 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -5,341 +5,321 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include +#include #include #include +#include +#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); -#define SIZE (1 << 10) +#define SIZE (1 << 10) -static -struct CQueue q; +static struct CQueue q; #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -static -pthread_barrier_t barrier; +static pthread_barrier_t barrier; #endif struct param { - int iter_count; - int queue_size; - int thread_count; - bool many; - int batch_size; - struct memory::Type *mt; - volatile int start; - struct CQueue queue; + int iter_count; + int queue_size; + int thread_count; + bool many; + int batch_size; + struct memory::Type *mt; + volatile int start; + struct CQueue queue; }; /* Get thread id as integer * In contrast to pthread_t which is an opaque type */ #ifdef __linux__ - #include +#include #endif -uint64_t thread_get_id() -{ +uint64_t thread_get_id() { #ifdef __MACH__ - uint64_t id; - pthread_threadid_np(pthread_self(), &id); - return id; + uint64_t id; + pthread_threadid_np(pthread_self(), &id); + return id; #elif defined(SYS_gettid) - return (int) syscall(SYS_gettid); + return (int)syscall(SYS_gettid); #endif - return -1; + return -1; } // Sleep, do nothing -__attribute__((always_inline)) static inline -void nop() -{ - __asm__("rep nop;"); +__attribute__((always_inline)) static inline void nop() { __asm__("rep nop;"); } + +static void *producer(void *ctx) { + int ret; + struct param *p = (struct param *)ctx; + + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; + + // Wait for global start signal + while (p->start == 0) + sched_yield(); + + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); + + // Enqueue + for (intptr_t count = 0; count < p->iter_count; count++) { + do { + ret = queue_push(&p->queue, (void *)count); + sched_yield(); + } while (ret != 1); + } + + return nullptr; } -static -void * producer(void *ctx) -{ - int ret; - struct param *p = (struct param *) ctx; +static void *consumer(void *ctx) { + int ret; + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - // Enqueue - for (intptr_t count = 0; count < p->iter_count; count++) { - do { - ret = queue_push(&p->queue, (void *) count); - sched_yield(); - } while (ret != 1); - } + // Dequeue + for (intptr_t count = 0; count < p->iter_count; count++) { + intptr_t ptr; - return nullptr; -} + do { + ret = queue_pull(&p->queue, (void **)&ptr); + } while (ret != 1); -static -void * consumer(void *ctx) -{ - int ret; - struct param *p = (struct param *) ctx; + //logger->info("consumer: {}", count); - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + //cr_assert_eq((intptr_t) ptr, count); + } - // Wait for global start signal - while (p->start == 0) - sched_yield(); - - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); - - // Dequeue - for (intptr_t count = 0; count < p->iter_count; count++) { - intptr_t ptr; - - do { - ret = queue_pull(&p->queue, (void **) &ptr); - } while (ret != 1); - - //logger->info("consumer: {}", count); - - //cr_assert_eq((intptr_t) ptr, count); - } - - return nullptr; + return nullptr; } #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -void * producer_consumer(void *ctx) -{ - struct param *p = (struct param *) ctx; +void *producer_consumer(void *ctx) { + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - for (int iter = 0; iter < p->iter_count; ++iter) { - pthread_barrier_wait(&barrier); + for (int iter = 0; iter < p->iter_count; ++iter) { + pthread_barrier_wait(&barrier); - for (intptr_t i = 0; i < p->batch_size; i++) { - void *ptr = (void *) (iter * p->batch_size + i); - while (!queue_push(&p->queue, ptr)) - sched_yield(); // queue full, let other threads proceed - } + for (intptr_t i = 0; i < p->batch_size; i++) { + void *ptr = (void *)(iter * p->batch_size + i); + while (!queue_push(&p->queue, ptr)) + sched_yield(); // queue full, let other threads proceed + } - for (intptr_t i = 0; i < p->batch_size; i++) { - void *ptr; - while (!queue_pull(&p->queue, &ptr)) - sched_yield(); // queue empty, let other threads proceed - } - } + for (intptr_t i = 0; i < p->batch_size; i++) { + void *ptr; + while (!queue_pull(&p->queue, &ptr)) + sched_yield(); // queue empty, let other threads proceed + } + } - return 0; + return 0; } -void * producer_consumer_many(void *ctx) -{ - struct param *p = (struct param *) ctx; +void *producer_consumer_many(void *ctx) { + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - void *ptrs[p->batch_size]; + void *ptrs[p->batch_size]; - for (int iter = 0; iter < p->iter_count; ++iter) { - for (intptr_t i = 0; i < p->batch_size; i++) - ptrs[i] = (void *) (iter * p->batch_size + i); + for (int iter = 0; iter < p->iter_count; ++iter) { + for (intptr_t i = 0; i < p->batch_size; i++) + ptrs[i] = (void *)(iter * p->batch_size + i); - pthread_barrier_wait(&barrier); + pthread_barrier_wait(&barrier); - int pushed = 0; - do { - pushed += queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); - if (pushed != p->batch_size) - sched_yield(); // queue full, let other threads proceed - } while (pushed < p->batch_size); + int pushed = 0; + do { + pushed += + queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); + if (pushed != p->batch_size) + sched_yield(); // queue full, let other threads proceed + } while (pushed < p->batch_size); - int pulled = 0; - do { - pulled += queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); - if (pulled != p->batch_size) - sched_yield(); // queue empty, let other threads proceed - } while (pulled < p->batch_size); - } + int pulled = 0; + do { + pulled += + queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); + if (pulled != p->batch_size) + sched_yield(); // queue empty, let other threads proceed + } while (pulled < p->batch_size); + } - return 0; + return 0; } #endif // _POSIX_BARRIERS -Test(queue, single_threaded, .init = init_memory) -{ - int ret; - struct param p; +Test(queue, single_threaded, .init = init_memory) { + int ret; + struct param p; - p.iter_count = 1 << 8; - p.queue_size = 1 << 10; - p.start = 1; // we start immeadiatly + p.iter_count = 1 << 8; + p.queue_size = 1 << 10; + p.start = 1; // we start immeadiatly - ret = queue_init(&p.queue, p.queue_size, &memory::heap); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_init(&p.queue, p.queue_size, &memory::heap); + cr_assert_eq(ret, 0, "Failed to create queue"); - producer(&p); - consumer(&p); + producer(&p); + consumer(&p); - cr_assert_eq(queue_available(&q), 0); + cr_assert_eq(queue_available(&q), 0); - ret = queue_destroy(&p.queue); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_destroy(&p.queue); + cr_assert_eq(ret, 0, "Failed to create queue"); } #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -ParameterizedTestParameters(queue, multi_threaded) -{ - static - struct param params[] = { - { - .iter_count = 1 << 12, - .queue_size = 1 << 9, - .thread_count = 32, - .many = true, - .batch_size = 10, - .mt = &memory::heap - }, { - .iter_count = 1 << 8, - .queue_size = 1 << 9, - .thread_count = 4, - .many = true, - .batch_size = 100, - .mt = &memory::heap - }, { - .iter_count = 1 << 16, - .queue_size = 1 << 14, - .thread_count = 16, - .many = true, - .batch_size = 100, - .mt = &memory::heap - }, { - .iter_count = 1 << 8, - .queue_size = 1 << 9, - .thread_count = 4, - .many = true, - .batch_size = 10, - .mt = &memory::heap - }, { - .iter_count = 1 << 16, - .queue_size = 1 << 9, - .thread_count = 16, - .many = false, - .batch_size = 10, - .mt = &memory::mmap_hugetlb - } - }; +ParameterizedTestParameters(queue, multi_threaded) { + static struct param params[] = {{.iter_count = 1 << 12, + .queue_size = 1 << 9, + .thread_count = 32, + .many = true, + .batch_size = 10, + .mt = &memory::heap}, + {.iter_count = 1 << 8, + .queue_size = 1 << 9, + .thread_count = 4, + .many = true, + .batch_size = 100, + .mt = &memory::heap}, + {.iter_count = 1 << 16, + .queue_size = 1 << 14, + .thread_count = 16, + .many = true, + .batch_size = 100, + .mt = &memory::heap}, + {.iter_count = 1 << 8, + .queue_size = 1 << 9, + .thread_count = 4, + .many = true, + .batch_size = 10, + .mt = &memory::heap}, + {.iter_count = 1 << 16, + .queue_size = 1 << 9, + .thread_count = 16, + .many = false, + .batch_size = 10, + .mt = &memory::mmap_hugetlb}}; - return cr_make_param_array(struct param, params, ARRAY_LEN(params)); + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); } -ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, .init = init_memory) -{ - int ret, cycpop; - struct Tsc tsc; +ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, + .init = init_memory) { + int ret, cycpop; + struct Tsc tsc; - Logger logger = logging.get("test:queue:multi_threaded"); + Logger logger = logging.get("test:queue:multi_threaded"); - if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - pthread_t threads[p->thread_count]; + pthread_t threads[p->thread_count]; - p->start = 0; + p->start = 0; - ret = queue_init(&p->queue, p->queue_size, p->mt); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_init(&p->queue, p->queue_size, p->mt); + cr_assert_eq(ret, 0, "Failed to create queue"); - uint64_t start_tsc_time, end_tsc_time; + uint64_t start_tsc_time, end_tsc_time; - pthread_barrier_init(&barrier, nullptr, p->thread_count); + pthread_barrier_init(&barrier, nullptr, p->thread_count); - for (int i = 0; i < p->thread_count; ++i) - pthread_create(&threads[i], nullptr, p->many ? producer_consumer_many : producer_consumer, p); + for (int i = 0; i < p->thread_count; ++i) + pthread_create(&threads[i], nullptr, + p->many ? producer_consumer_many : producer_consumer, p); - sleep(0.2); + sleep(0.2); - ret = tsc_init(&tsc); - cr_assert(!ret); + ret = tsc_init(&tsc); + cr_assert(!ret); - start_tsc_time = tsc_now(&tsc); - p->start = 1; + start_tsc_time = tsc_now(&tsc); + p->start = 1; - for (int i = 0; i < p->thread_count; ++i) - pthread_join(threads[i], nullptr); + for (int i = 0; i < p->thread_count; ++i) + pthread_join(threads[i], nullptr); - end_tsc_time = tsc_now(&tsc); - cycpop = (end_tsc_time - start_tsc_time) / p->iter_count; + end_tsc_time = tsc_now(&tsc); + cycpop = (end_tsc_time - start_tsc_time) / p->iter_count; - if (cycpop < 400) - logger->debug("Cycles/op: {}", cycpop); - else - logger->warn("Cycles/op are very high ({}). Are you running on a hypervisor?", cycpop); + if (cycpop < 400) + logger->debug("Cycles/op: {}", cycpop); + else + logger->warn( + "Cycles/op are very high ({}). Are you running on a hypervisor?", + cycpop); - ret = queue_available(&q); - cr_assert_eq(ret, 0); + ret = queue_available(&q); + cr_assert_eq(ret, 0); - ret = queue_destroy(&p->queue); - cr_assert_eq(ret, 0, "Failed to destroy queue"); + ret = queue_destroy(&p->queue); + cr_assert_eq(ret, 0, "Failed to destroy queue"); - ret = pthread_barrier_destroy(&barrier); - cr_assert_eq(ret, 0, "Failed to destroy barrier"); + ret = pthread_barrier_destroy(&barrier); + cr_assert_eq(ret, 0, "Failed to destroy barrier"); } #endif // _POSIX_BARRIERS -Test(queue, init_destroy, .init = init_memory) -{ - int ret; - struct CQueue q; +Test(queue, init_destroy, .init = init_memory) { + int ret; + struct CQueue q; - ret = queue_init(&q, 1024, &memory::heap); - cr_assert_eq(ret, 0); // Should succeed + ret = queue_init(&q, 1024, &memory::heap); + cr_assert_eq(ret, 0); // Should succeed - ret = queue_destroy(&q); - cr_assert_eq(ret, 0); // Should succeed + ret = queue_destroy(&q); + cr_assert_eq(ret, 0); // Should succeed } diff --git a/tests/unit/queue_signalled.cpp b/tests/unit/queue_signalled.cpp index 04b265328..3f440e523 100644 --- a/tests/unit/queue_signalled.cpp +++ b/tests/unit/queue_signalled.cpp @@ -8,148 +8,142 @@ #include #include -#include #include +#include -#include #include #include +#include using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define NUM_ELEM 1000 struct param { - enum QueueSignalledMode mode; - int flags; - bool polled; + enum QueueSignalledMode mode; + int flags; + bool polled; }; -static -void * producer(void * ctx) -{ - int ret; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +static void *producer(void *ctx) { + int ret; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - for (intptr_t i = 0; i < NUM_ELEM; i++) { - ret = queue_signalled_push(q, (void *) i); - if (ret != 1) - return (void *) 1; // Indicates an error to the parent thread + for (intptr_t i = 0; i < NUM_ELEM; i++) { + ret = queue_signalled_push(q, (void *)i); + if (ret != 1) + return (void *)1; // Indicates an error to the parent thread - usleep(0.1e-3 * 1e6); // 1 ms - } + usleep(0.1e-3 * 1e6); // 1 ms + } - return nullptr; + return nullptr; } -static -void * consumer(void * ctx) -{ - int ret; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +static void *consumer(void *ctx) { + int ret; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - void *data[NUM_ELEM]; + void *data[NUM_ELEM]; - for (intptr_t i = 0; i < NUM_ELEM;) { - ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data)); - if (ret <= 0) - return (void *) 1; // Indicates an error to the parent thread + for (intptr_t i = 0; i < NUM_ELEM;) { + ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data)); + if (ret <= 0) + return (void *)1; // Indicates an error to the parent thread - for (intptr_t j = 0; j < ret; j++, i++) { - if ((intptr_t) data[j] != i) - return (void *) 2; // Indicates an error to the parent thread - } - } + for (intptr_t j = 0; j < ret; j++, i++) { + if ((intptr_t)data[j] != i) + return (void *)2; // Indicates an error to the parent thread + } + } - return nullptr; + return nullptr; } - void * polled_consumer(void *ctx) -{ - int ret, fd; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +void *polled_consumer(void *ctx) { + int ret, fd; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - fd = queue_signalled_fd(q); - cr_assert_geq(fd, 0); + fd = queue_signalled_fd(q); + cr_assert_geq(fd, 0); - struct pollfd pfd = { - .fd = fd, - .events = POLLIN - }; + struct pollfd pfd = {.fd = fd, .events = POLLIN}; - for (intptr_t i = 0; i < NUM_ELEM; i++) { -again: ret = poll(&pfd, 1, -1); - if (ret < 0) - return (void *) 3; - else if (ret == 0) - goto again; + for (intptr_t i = 0; i < NUM_ELEM; i++) { + again: + ret = poll(&pfd, 1, -1); + if (ret < 0) + return (void *)3; + else if (ret == 0) + goto again; - void *p; - ret = queue_signalled_pull(q, &p); - if (ret != 1) - return (void *) 1; // Indicates an error to the parent thread + void *p; + ret = queue_signalled_pull(q, &p); + if (ret != 1) + return (void *)1; // Indicates an error to the parent thread - if ((intptr_t) p != i) - return (void *) 2; // Indicates an error to the parent thread - } + if ((intptr_t)p != i) + return (void *)2; // Indicates an error to the parent thread + } - return nullptr; + return nullptr; } -ParameterizedTestParameters(queue_signalled, simple) -{ - static - struct param params[] = { - { QueueSignalledMode::AUTO, 0, false }, - { QueueSignalledMode::PTHREAD, 0, false }, - { QueueSignalledMode::PTHREAD, 0, false }, - { QueueSignalledMode::PTHREAD, (int) QueueSignalledFlags::PROCESS_SHARED, false }, - { QueueSignalledMode::POLLING, 0, false }, +ParameterizedTestParameters(queue_signalled, simple) { + static struct param params[] = { + {QueueSignalledMode::AUTO, 0, false}, + {QueueSignalledMode::PTHREAD, 0, false}, + {QueueSignalledMode::PTHREAD, 0, false}, + {QueueSignalledMode::PTHREAD, (int)QueueSignalledFlags::PROCESS_SHARED, + false}, + {QueueSignalledMode::POLLING, 0, false}, #if defined(__linux__) && defined(HAS_EVENTFD) - { QueueSignalledMode::EVENTFD, 0, false }, - { QueueSignalledMode::EVENTFD, 0, true } + {QueueSignalledMode::EVENTFD, 0, false}, + {QueueSignalledMode::EVENTFD, 0, true} #endif - }; + }; - return cr_make_param_array(struct param, params, ARRAY_LEN(params)); + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); } // cppcheck-suppress unknownMacro -ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, .init = init_memory) -{ - int ret; - void *r1, *r2; - struct CQueueSignalled q; +ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, + .init = init_memory) { + int ret; + void *r1, *r2; + struct CQueueSignalled q; - pthread_t t1, t2; + pthread_t t1, t2; - ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory::heap, param->mode, param->flags); - cr_assert_eq(ret, 0, "Failed to initialize queue: mode=%d, flags=%#x, ret=%d", (int) param->mode, param->flags, ret); + ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory::heap, + param->mode, param->flags); + cr_assert_eq(ret, 0, "Failed to initialize queue: mode=%d, flags=%#x, ret=%d", + (int)param->mode, param->flags, ret); - ret = pthread_create(&t1, nullptr, producer, &q); - cr_assert_eq(ret, 0); + ret = pthread_create(&t1, nullptr, producer, &q); + cr_assert_eq(ret, 0); - ret = pthread_create(&t2, nullptr, param->polled ? polled_consumer : consumer, &q); - cr_assert_eq(ret, 0); + ret = pthread_create(&t2, nullptr, param->polled ? polled_consumer : consumer, + &q); + cr_assert_eq(ret, 0); - ret = pthread_join(t1, &r1); - cr_assert_eq(ret, 0); + ret = pthread_join(t1, &r1); + cr_assert_eq(ret, 0); - ret = pthread_join(t2, &r2); - cr_assert_eq(ret, 0); + ret = pthread_join(t2, &r2); + cr_assert_eq(ret, 0); - cr_assert_null(r1, "Producer failed: %p", r1); - cr_assert_null(r2, "Consumer failed: %p", r2); + cr_assert_null(r1, "Producer failed: %p", r1); + cr_assert_null(r2, "Consumer failed: %p", r2); - ret = queue_signalled_available(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_available(&q); + cr_assert_eq(ret, 0); - ret = queue_signalled_close(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_close(&q); + cr_assert_eq(ret, 0); - ret = queue_signalled_destroy(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_destroy(&q); + cr_assert_eq(ret, 0); } diff --git a/tests/unit/signal.cpp b/tests/unit/signal.cpp index e7f5438a9..6ad47b812 100644 --- a/tests/unit/signal.cpp +++ b/tests/unit/signal.cpp @@ -11,65 +11,64 @@ using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); // cppcheck-suppress unknownMacro Test(signal_data, parse, .init = init_memory) { - int ret; - enum SignalType type; - union SignalData sd; - const char *str; - char *end; + int ret; + enum SignalType type; + union SignalData sd; + const char *str; + char *end; - str = "1"; - type = SignalType::INTEGER; + str = "1"; + type = SignalType::INTEGER; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_eq(sd.i, 1); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_eq(sd.i, 1); - str = "1.2"; - type = SignalType::FLOAT; + str = "1.2"; + type = SignalType::FLOAT; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(sd.f, 1.2, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(sd.f, 1.2, 1e-6); - str = "1"; - type = SignalType::BOOLEAN; + str = "1"; + type = SignalType::BOOLEAN; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_eq(sd.b, 1); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_eq(sd.b, 1); - str = "1"; - type = SignalType::COMPLEX; + str = "1"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), 1, 1e-6); - cr_assert_float_eq(std::imag(sd.z), 0, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), 1, 1e-6); + cr_assert_float_eq(std::imag(sd.z), 0, 1e-6); - str = "-1-3i"; - type = SignalType::COMPLEX; + str = "-1-3i"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), -1, 1e-6); - cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), -1, 1e-6); + cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); - str = "-3i"; - type = SignalType::COMPLEX; + str = "-3i"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), 0, 1e-6); - cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), 0, 1e-6); + cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); } From 2626ac2e4800c035d38ef3cf2e58cfb061df5f6e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 12:26:36 +0200 Subject: [PATCH 050/100] Add pre-commit hook for clang-format Signed-off-by: Steffen Vogel --- tools/git-pre-commit-hook.sh | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tools/git-pre-commit-hook.sh diff --git a/tools/git-pre-commit-hook.sh b/tools/git-pre-commit-hook.sh new file mode 100644 index 000000000..f6237b56a --- /dev/null +++ b/tools/git-pre-commit-hook.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# +# Install / run pre-commit hook in repo +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +format_file() { + FILE="${1}" + if [ -f ${FILE} ]; then + if ! clang-format --Werror --dry-run ${FILE}; then + clang-format -i ${FILE} + return 1 + fi + fi +} + +case "${1}" in + help) + echo "Run ${0} install to install the git commit hooks" + ;; + + install) + TOP_DIR=$(git rev-parse --show-toplevel) + cp "${BASH_SOURCE[0]}" "${TOP_DIR}/.git/hooks/pre-commit" + ;; + + *) + FILES=$(git diff-index --cached --name-only HEAD | grep -iE '\.(cpp|hpp|c|h)$') + CHANGES=0 + for FILE in ${FILES}; do + if ! format_file "${FILE}"; then + CHANGES=$((CHANGES+1)) + fi + done + + if (( ${CHANGES} > 0 )); then + echo "Formatting of ${CHANGES} files has been fixed. Please stage and commit again." + exit -1 + fi + ;; +esac From 2f8511c818411f8bff9851b76d7f5ff3ae9b4ad7 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 12:51:25 +0200 Subject: [PATCH 051/100] Add Git .mailmap file Signed-off-by: Steffen Vogel --- .mailmap | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..dd5725840 --- /dev/null +++ b/.mailmap @@ -0,0 +1,55 @@ +Anju + +Dennis Potter + +Divya Laxetti +Divya Laxetti +Divya Laxetti + +Eyke Liegmann + +Felix Wege + +Georg Reinke + +Juan Pablo Noreña-Monsalve +Juan Pablo Noreña-Monsalve <34222866+jpnorenam@users.noreply.github.com> + +Manuel Pitz <37443948+windrad6@users.noreply.github.com> +Manuel Pitz + +Marija Stevic + +Markus Grigull + +Markus Mirz + +Marvin Klimke + +Niklas Eiling +Niklas Eiling + +Philipp Jungkamp <56401138+PJungkamp@users.noreply.github.com> +Philipp Jungkamp +Philipp Jungkamp +Philipp Jungkamp + +Sonja Happ + +Sonja Kolen + +Steffen Vogel +Steffen Vogel +Steffen Vogel +Steffen Vogel +Steffen Vogel + +Umar Farooq + +Daniel Krebs + +Iris Köster +Iris Köster + +Ubuntu +root From f61c7d9b8f66949e7c3448449194f79ff80ac78e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 13:00:57 +0200 Subject: [PATCH 052/100] Fix formatting of Dockerfiles Signed-off-by: Steffen Vogel --- packaging/docker/Dockerfile.debian | 2 +- packaging/docker/Dockerfile.debian-multiarch | 14 +++++++------- packaging/docker/Dockerfile.fedora | 2 +- packaging/docker/Dockerfile.ubuntu | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index ad8398c90..b9fcb9801 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -55,7 +55,7 @@ RUN apt-get update && \ # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ - echo /usr/local/lib64 >> /etc/ld.so.conf + echo /usr/local/lib64 >> /etc/ld.so.conf # or install unpackaged dependencies from source ADD packaging/deps.sh / diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index d776dbe3b..a7f858de6 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -63,18 +63,18 @@ RUN apt-get update && \ # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ - echo /usr/local/lib64 >> /etc/ld.so.conf + echo /usr/local/lib64 >> /etc/ld.so.conf ADD cmake/toolchains/debian-${ARCH}.cmake / ENV PKG_CONFIG_PATH=/usr/lib/${TRIPLET}/pkgconfig:/usr/local/lib/${TRIPLET}/pkgconfig ENV CMAKE_EXTRA_OPTS="-DCMAKE_TOOLCHAIN_FILE=/debian-${ARCH}.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_PREFIX_PATH=${PREFIX} \ - -DCMAKE_INSTALL_PREFIX=${PREFIX} \ - -DCMAKE_INSTALL_LIBDIR=${PREFIX}/lib/${TRIPLET} \ - -DLWS_INSTALL_LIB_DIR=${PREFIX}/lib/${TRIPLET}" + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=${PREFIX} \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_INSTALL_LIBDIR=${PREFIX}/lib/${TRIPLET} \ + -DLWS_INSTALL_LIB_DIR=${PREFIX}/lib/${TRIPLET}" ENV CONFIGURE_OPTS="--libdir=${PREFIX}/lib/${TRIPLET}" @@ -111,7 +111,7 @@ COPY . /villas/ RUN rm -rf /villas/build && mkdir /villas/build WORKDIR /villas/build - + RUN cmake ${CMAKE_OPTS} ${CMAKE_EXTRA_OPTS} .. && \ make -j$(nproc) install diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 88d86d39c..2d1ef0c0e 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -69,7 +69,7 @@ RUN dnf -y install \ # Add local and 64-bit locations to linker paths RUN echo /usr/local/lib >> /etc/ld.so.conf && \ - echo /usr/local/lib64 >> /etc/ld.so.conf + echo /usr/local/lib64 >> /etc/ld.so.conf # Install unpackaged dependencies from source ADD packaging/deps.sh / diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 0bfb82217..78f85454d 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -57,7 +57,7 @@ RUN apt-get update && \ # Add local and 64-bit locations to linker paths ENV echo /usr/local/lib >> /etc/ld.so.conf && \ - echo /usr/local/lib64 >> /etc/ld.so.conf + echo /usr/local/lib64 >> /etc/ld.so.conf # or install unpackaged dependencies from source ADD packaging/deps.sh / From 1e19777798758874780d6fed79479dc2d6897ef4 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 13:09:19 +0200 Subject: [PATCH 053/100] Add .git-blame-ignore-revs to hide large refactorings commits from git blame Signed-off-by: Steffen Vogel --- .git-blame-ignore-revs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..b11003261 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,8 @@ +# Introduced clang-format +aa16979fdde7cd377977c38eaee02062c3908515 + +# Make project REUSE compliant +0735eb0f89c976ba8db7abeae7814060fb5dfe3c + +# Update Steffens mail address +7eec1bb75339c60cefe5e9e558d9394e0cceecb6 From 87b16ed25ce3e63de69822390f3bf2b0aa22fb03 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 13:23:13 +0200 Subject: [PATCH 054/100] Update contribution guide Signed-off-by: Steffen Vogel --- CONTRIBUTING.md | 171 +++--------------------------------------------- 1 file changed, 8 insertions(+), 163 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6b34b3c1..3106b0570 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,171 +1,21 @@ # Contribution guidelines -## Coding style + -### Naming +## Coding standards -Variables should use lower case names with underscores. - -There are now special visibility or type prefixes. - -Structure members should not use abbreviated names: - -Good -``` -struct A { - char *message; - int length; -} -``` - -Bad: -``` -struct A { - char *msg; - int len; -} -``` - -### Placement of spaces - -In variable declarations (including in function parameters) we place the asterisk next to the variable name. - -Good: -```c -int *number; -``` - -Bad: -```c -int * number; -int* number; -``` - -In function return values we place the asterisk between spaces - -Good: -```c -void * my_thread() -{ - -} -``` - -Bad: -```c -void *mythread() -{ - -} - -void * mythread() -{ - -} -``` - -In expressions we place spaces between most elements but not between parantheses: - -Good: -``` -int a = ((5 * 10) + 10 ) % 22; -``` - -Bad: -``` -int a = ((5*10)+10)%22; -``` - -We also put spaces infront / after most keywords such as `if`, `while`, ... - -Good: -```c -for (int a = 0; a < 1; a++) { - ... -} -``` - -Bad: -```c -for(int a = 0; a < 1; a++) { - ... -} -``` - -### Line length - -Try to limit line length to about 160 characters. - -### Indention - -We use tabs for indention which should be displayed as 8 spaces by your editor. - -### Brace placement - -For everything except functions we place the opening brace in the same line: - -Good: -```c -struct A { - enum { - A, - B - } choice; -} - -if (true) { - -} -``` - -Bad: -``` -struct A -{ - enum - { - A, - B - } choice; -} - -if (true) -{ - -} -``` - -However, in functions we place the brace in a new line: - -``` -void main() -{ - -} -``` - -### #define and Macro Names - -Are always written UPPERCASE. - -Good: -```c -#define HUGEPAGESIZE (1 << 22) -#define MAX(a, b) (a > b ? a ? b) -``` - -Bad: -```c -#define max(a, b) (a > b ? a ? b) -``` +We are following the [LLVM C++ Coding Standards](https://llvm.org/docs/CodingStandards.html). ## Always work on feature branches -Please branch from `develop` to create a new _feature_ branch. +Please branch from `master` to create a new _feature_ branch. Please create a new _feature_ branch for every new feature or fix. -## Do not commit directly to `master` or `develop`. +## Do not commit directly to `master`. Use your _feature_ branch. @@ -174,8 +24,3 @@ Please rebase your work against the `develop` before submitting a merge reqeuest ## Make the CI happy :-) Only branches which pass the CI can be merged. - -## License - -- SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -- SPDX-License-Identifier: Apache-2.0 From 6e8d4f860d4ae183e7d27e79ec4d98439f342f7d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 14:20:28 +0200 Subject: [PATCH 055/100] Fix wrong package in Ubuntu Dockerfile Signed-off-by: Steffen Vogel --- packaging/docker/Dockerfile.ubuntu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 78f85454d..38f660350 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -24,7 +24,7 @@ RUN apt-get update && \ texinfo git curl tar wget diffutils \ flex bison \ protobuf-compiler protobuf-c-compiler \ - clang-tools-extra clangd + clang-format clangd # Dependencies RUN apt-get update && \ From 926ae841a831d4b51426e2393398a92769bcba07 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Sep 2023 14:21:24 +0200 Subject: [PATCH 056/100] Fix broken include due to auto-formatting Signed-off-by: Steffen Vogel --- include/villas/config_helper.hpp | 8 ++++---- include/villas/node/memory.hpp | 10 +++++----- include/villas/nodes/infiniband.hpp | 1 + include/villas/nodes/websocket.hpp | 1 + include/villas/signal_data.hpp | 2 ++ lib/nodes/websocket.cpp | 2 -- src/villas-graph.cpp | 3 ++- 7 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index 1fa578891..c55bc5b03 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -7,15 +7,15 @@ #pragma once -#ifdef WITH_CONFIG -#include -#endif - #include #include #include +#ifdef WITH_CONFIG +#include +#endif + namespace villas { namespace node { diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index 1fcdc8c54..4e750194b 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -7,16 +7,16 @@ #pragma once -#ifdef IBVERBS_FOUND -#include -#endif // IBVERBS_FOUND - #include #include #include #include +#ifdef IBVERBS_FOUND +#include +#endif // IBVERBS_FOUND + namespace villas { namespace node { namespace memory { @@ -52,7 +52,7 @@ struct Allocation { }; }; -// Initilialize memory subsystem +// Initialize memory subsystem int init(int hugepages) __attribute__((warn_unused_result)); int lock(size_t lock); diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index 8cd1e25f9..b43bab236 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -8,6 +8,7 @@ #pragma once #include + #include #include #include diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index 071fe1af0..d7f91471e 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -7,6 +7,7 @@ #pragma once +#include #include #include diff --git a/include/villas/signal_data.hpp b/include/villas/signal_data.hpp index e4351e84e..3ecfe0284 100644 --- a/include/villas/signal_data.hpp +++ b/include/villas/signal_data.hpp @@ -15,6 +15,8 @@ #include +#include + namespace villas { namespace node { diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index 2e34ebf6a..3520cd8e9 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -11,8 +11,6 @@ #include #include -#include - #include #include #include diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index 77116880b..6306550de 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -7,9 +7,10 @@ #include -#include #include +#include + #include #include #include From 633361556599a7e95c8fdeaa0765652458570128 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 8 Sep 2023 07:54:40 +0000 Subject: [PATCH 057/100] Add clangd configuration file Signed-off-by: Steffen Vogel --- .clangd | 3 +++ .gitignore | 1 + 2 files changed, 4 insertions(+) create mode 100644 .clangd diff --git a/.clangd b/.clangd new file mode 100644 index 000000000..bd2dd8854 --- /dev/null +++ b/.clangd @@ -0,0 +1,3 @@ +--- +Diagnostics: + UnusedIncludes: Strict diff --git a/.gitignore b/.gitignore index 6d33a0f0d..8baeeed29 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ .settings/ .vscode/ .direnv/ +.cache/ *.egg-info/ From 935e73cc4168743f7cf05badd65e83040756f707 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 8 Sep 2023 10:14:09 +0200 Subject: [PATCH 058/100] Add clangd and clang-format VSCode extensions to Devcontainer Signed-off-by: Steffen Vogel --- .devcontainer/devcontainer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d7d74e749..7cdc83470 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,6 +19,8 @@ "vscode": { "extensions": [ "ms-vscode.cpptools-extension-pack", + "llvm-vs-code-extensions.vscode-clangd", + "xaver.clang-format", "EditorConfig.EditorConfig" ] } From 6eb52161e5813a9d22e9b2ef0fd6e32f3d675bea Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 8 Sep 2023 10:18:31 +0200 Subject: [PATCH 059/100] Add missing REUSE headers Signed-off-by: Steffen Vogel --- .clang-format | 3 +++ .clangd | 3 +++ .git-blame-ignore-revs | 4 ++++ .mailmap | 5 +++++ 4 files changed, 15 insertions(+) diff --git a/.clang-format b/.clang-format index 537bac562..1c493308f 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,6 @@ +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 --- BasedOnStyle: LLVM diff --git a/.clangd b/.clangd index bd2dd8854..6c614a474 100644 --- a/.clangd +++ b/.clangd @@ -1,3 +1,6 @@ +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 --- Diagnostics: UnusedIncludes: Strict diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index b11003261..a2cf7c8ec 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,7 @@ +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + # Introduced clang-format aa16979fdde7cd377977c38eaee02062c3908515 diff --git a/.mailmap b/.mailmap index dd5725840..1cfb5ffe6 100644 --- a/.mailmap +++ b/.mailmap @@ -1,3 +1,8 @@ +# Author: Philipp Jungkamp +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +--- + Anju Dennis Potter From 46266e85de7f4b3decc0902fda369c3487c5e223 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 8 Sep 2023 09:03:13 +0000 Subject: [PATCH 060/100] Add script to format all files in repository Signed-off-by: Steffen Vogel --- tools/format-all.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tools/format-all.sh diff --git a/tools/format-all.sh b/tools/format-all.sh new file mode 100644 index 000000000..15e8f3531 --- /dev/null +++ b/tools/format-all.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# +# Format all C++ files in repo +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +TOP_DIR=$(git rev-parse --show-toplevel) + +find ${TOP_DIR} -iname "*.cpp" -o -iname "*.hpp" -o -iname "*.h" -o -iname "*.c" | \ + xargs clang-format --verbose -i From c0edadcf791f2bf33e4f983d89a399e42c63abf4 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 8 Sep 2023 11:21:00 +0200 Subject: [PATCH 061/100] Update VILLAScommon submodule Signed-off-by: Steffen Vogel --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 0edfc697b..08fd24b85 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 0edfc697b75715742957cd0eb88bd364f22f2e72 +Subproject commit 08fd24b85ec4e5b18f370702eb129b4f1d1e4bca From 99c13ba45cdd81268331d132d224d3c18ff6f682 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 8 Sep 2023 13:52:26 +0200 Subject: [PATCH 062/100] packaging-nix: Add clang-tools to dev environment Signed-off-by: Philipp Jungkamp --- packaging/nix/flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index f2a91270b..404057dee 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -159,7 +159,7 @@ pkgs = devPkgsFor system; shellHook = ''[ -z "$PS1" ] || exec "$SHELL"''; hardeningDisable = ["all"]; - packages = with pkgs; [bashInteractive bc boxfort criterion jq libffi libgit2 pcre]; + packages = with pkgs; [bashInteractive bc boxfort criterion jq libffi libgit2 pcre clang-tools]; in rec { default = full; @@ -184,7 +184,7 @@ in { fmt = pkgs.runCommand "check-fmt" {} '' cd ${self} - ${pkgs.alejandra}/bin/alejandra --check . 2> $out + "${pkgs.alejandra}/bin/alejandra" --check . 2>> $out ''; } ); From f583b04d158c1a34c37a7b795959ffd290200ce0 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Mon, 11 Sep 2023 12:14:03 +0200 Subject: [PATCH 063/100] packaging-nix: Add reuse compliance checker Signed-off-by: Philipp Jungkamp --- packaging/nix/flake.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index 404057dee..dd0830d05 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -159,7 +159,18 @@ pkgs = devPkgsFor system; shellHook = ''[ -z "$PS1" ] || exec "$SHELL"''; hardeningDisable = ["all"]; - packages = with pkgs; [bashInteractive bc boxfort criterion jq libffi libgit2 pcre clang-tools]; + packages = with pkgs; [ + bashInteractive + bc + boxfort + clang-tools + criterion + jq + libffi + libgit2 + pcre + reuse + ]; in rec { default = full; From 97b769a80d50ddc8e0f29f65340f35f1b5d7ea7c Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 7 Sep 2023 10:11:32 +0200 Subject: [PATCH 064/100] Replace SampleFlags IS_FIRST/IS_LAST with NEW_SIMULATION Signed-off-by: Philipp Jungkamp --- include/villas/sample.hpp | 4 ++-- lib/hooks/restart.cpp | 2 +- lib/path_source.cpp | 2 +- lua/hooks/test.lua | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index 80f3f3878..e5965e757 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -49,8 +49,8 @@ enum class SampleFlags { HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. HAS_ALL = (1 << 5) - 1, // Enable all output options. - 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 + NEW_SIMULATION = + (1 << 16), // This sample is the first of a new simulation case }; struct Sample { diff --git a/lib/hooks/restart.cpp b/lib/hooks/restart.cpp index 216a932b1..c541cc972 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -50,7 +50,7 @@ public: "(previous->sequence={}, current->sequence={})", node->getName(), prev->sequence, smp->sequence); - smp->flags |= (int)SampleFlags::IS_FIRST; + smp->flags |= (int)SampleFlags::NEW_SIMULATION; // Restart hooks for (auto k : node->in.hooks) diff --git a/lib/path_source.cpp b/lib/path_source.cpp index ec138e71d..e61577e2b 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -108,7 +108,7 @@ int PathSource::read(int i) { /* We reset the sample length after each restart of the simulation. * This is necessary for the test_rtt node to work properly. */ - if (tomux_smps[i]->flags & (int)SampleFlags::IS_FIRST) + if (tomux_smps[i]->flags & (int)SampleFlags::NEW_SIMULATION) muxed_smps[i]->length = 0; muxed_smps[i]->ts = tomux_smps[i]->ts; diff --git a/lua/hooks/test.lua b/lua/hooks/test.lua index 3ed71af18..d4aa24e15 100644 --- a/lua/hooks/test.lua +++ b/lua/hooks/test.lua @@ -22,8 +22,7 @@ SampleFlags = { HAS_DATA = 16, -- "(1 << 5)" Include values in output. HAS_ALL = 15, -- "(1 << 6) -1" Enable all output options. - IS_FIRST = 65536, -- "(1 << 16)" This sample is the first of a new simulation case - IS_LAST = 131072 -- "(1 << 17)" This sample is the last of a running simulation case + NEW_SIMULATION = 65536, -- "(1 << 16)" This sample is the first of a new simulation case } @@ -71,7 +70,7 @@ end function process(smp) - info("Process test_hook") + info("Process test_hook") if smp.sequence == 1 then dump_sample(smp) From 79077c9bb95f825424b4b1a8a4e0fe71b1fae559 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 7 Sep 2023 10:15:29 +0200 Subject: [PATCH 065/100] Add NEW_FRAME to SampleFlags Signed-off-by: Philipp Jungkamp --- include/villas/sample.hpp | 3 ++- lua/hooks/test.lua | 16 +++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index e5965e757..8de132db0 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -49,8 +49,9 @@ enum class SampleFlags { HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. HAS_ALL = (1 << 5) - 1, // Enable all output options. + NEW_FRAME = (1 << 16), // This sample is the last of a running simulation case NEW_SIMULATION = - (1 << 16), // This sample is the first of a new simulation case + (1 << 17) | NEW_FRAME // This sample is the first of a new simulation case }; struct Sample { diff --git a/lua/hooks/test.lua b/lua/hooks/test.lua index d4aa24e15..9a1fcd765 100644 --- a/lua/hooks/test.lua +++ b/lua/hooks/test.lua @@ -15,14 +15,16 @@ Reason = { } SampleFlags = { - HAS_TS_ORIGIN = 1, -- "(1 << 1)" Include origin timestamp in output. - HAS_TS_RECEIVED = 2, -- "(1 << 2)" Include receive timestamp in output. - HAS_OFFSET = 4, -- "(1 << 3)" Include offset (received - origin timestamp) in output. - HAS_SEQUENCE = 8, -- "(1 << 4)" Include sequence number in output. - HAS_DATA = 16, -- "(1 << 5)" Include values in output. - HAS_ALL = 15, -- "(1 << 6) -1" Enable all output options. + HAS_TS_ORIGIN = 1, -- "(1 << 1)" Include origin timestamp in output. + HAS_TS_RECEIVED = 2, -- "(1 << 2)" Include receive timestamp in output. + HAS_OFFSET = 4, -- "(1 << 3)" Include offset (received - origin timestamp) in output. + HAS_SEQUENCE = 8, -- "(1 << 4)" Include sequence number in output. + HAS_DATA = 16, -- "(1 << 5)" Include values in output. - NEW_SIMULATION = 65536, -- "(1 << 16)" This sample is the first of a new simulation case + NEW_FRAME = 65536, -- "(1 << 16)" This sample is the first of a new simulation case + NEW_SIMULATION = 131072, -- "(1 << 16)" This sample is the first of a new simulation case + + ALL = 2147483647, -- "INT_MAX" Enable all output options. } From c2eefabb93ca999fae261a21e42acc4128d02731 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 8 Sep 2023 14:37:52 +0200 Subject: [PATCH 066/100] hook-frame: Add hook to add SampleFlags::NEW_FRAME annotations Signed-off-by: Philipp Jungkamp --- .../schemas/config/hooks/_frame.yaml | 7 + .../schemas/config/hooks/frame.yaml | 36 +++ etc/examples/hooks/frame.conf | 21 ++ lib/hooks/CMakeLists.txt | 1 + lib/hooks/frame.cpp | 250 ++++++++++++++++++ 5 files changed, 315 insertions(+) create mode 100644 doc/openapi/components/schemas/config/hooks/_frame.yaml create mode 100644 doc/openapi/components/schemas/config/hooks/frame.yaml create mode 100644 etc/examples/hooks/frame.conf create mode 100644 lib/hooks/frame.cpp diff --git a/doc/openapi/components/schemas/config/hooks/_frame.yaml b/doc/openapi/components/schemas/config/hooks/_frame.yaml new file mode 100644 index 000000000..75bfcaa32 --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/_frame.yaml @@ -0,0 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +--- +allOf: +- $ref: ../hook_obj.yaml +- $ref: frame.yaml diff --git a/doc/openapi/components/schemas/config/hooks/frame.yaml b/doc/openapi/components/schemas/config/hooks/frame.yaml new file mode 100644 index 000000000..34f4500e0 --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/frame.yaml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +--- +allOf: +- type: object + properties: + trigger: + description: The trigger for new frames. + type: string + default: sequence + enum: + - sequence + - timestamp + + unit: + description: The type of a timestamp trigger. + type: string + enum: + - milliseconds + - seconds + - minutes + - hours + + interval: + description: The interval in which frames are annotated. + type: number + default: 1 + + offset: + description: An offset in the interval for the annotation of new frames. + type: number + default: 0 + +- $ref: ../hook.yaml + diff --git a/etc/examples/hooks/frame.conf b/etc/examples/hooks/frame.conf new file mode 100644 index 000000000..4cd73e016 --- /dev/null +++ b/etc/examples/hooks/frame.conf @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +@include "hook-nodes.conf" + +paths = ( + { + in = "signal_node" + out = "file_node" + + hooks = ( + { + type = "frame" + + trigger = "timestamp" + unit = "seconds" + interval = 10 + } + ) + } +) diff --git a/lib/hooks/CMakeLists.txt b/lib/hooks/CMakeLists.txt index 16c27a575..883472f90 100644 --- a/lib/hooks/CMakeLists.txt +++ b/lib/hooks/CMakeLists.txt @@ -13,6 +13,7 @@ set(HOOK_SRC dump.cpp ebm.cpp fix.cpp + frame.cpp gate.cpp jitter_calc.cpp limit_rate.cpp diff --git a/lib/hooks/frame.cpp b/lib/hooks/frame.cpp new file mode 100644 index 000000000..99b962ab1 --- /dev/null +++ b/lib/hooks/frame.cpp @@ -0,0 +1,250 @@ +/* Frame hook. + * + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace villas { +namespace node { + +enum class Trigger { + TIMESTAMP, + SEQUENCE, +}; + +enum class Unit { + MILLISECONDS, + SECONDS, + MINUTES, + HOURS, +}; + +uint64_t unit_wrap(std::optional unit) { + if (unit) { + switch (*unit) { + case Unit::HOURS: + return 24; + case Unit::MINUTES: + return 60; + case Unit::SECONDS: + return 60; + case Unit::MILLISECONDS: + return 1000; + } + } + + return std::numeric_limits::max(); +} + +class FrameHook : public Hook { + using sample_ptr = std::unique_ptr; + +private: + Trigger trigger; + uint64_t interval; + uint64_t offset; + std::optional unit; + sample_ptr last_smp; + + bool updateInterval(Sample const *next_smp) { + bool changed = false; + + if (!last_smp.get() || + (next_smp->flags & (int)SampleFlags::NEW_SIMULATION) == + (int)SampleFlags::NEW_SIMULATION) { + changed = true; + } else if (trigger == Trigger::SEQUENCE) { + auto last_interval = (last_smp->sequence + interval - offset) / interval; + auto next_interval = (next_smp->sequence + interval - offset) / interval; + changed = last_interval != next_interval; + } else + switch (unit.value()) { + case Unit::HOURS: { + auto last_hour = last_smp->ts.origin.tv_sec / 3'600; + auto next_hour = next_smp->ts.origin.tv_sec / 3'600; + + auto last_day = last_hour / 24; + auto next_day = next_hour / 24; + if (last_day != next_day) { + changed = true; + break; + } + + auto last_hour_of_day = last_hour - 24 * last_day; + auto next_hour_of_day = next_hour - 24 * next_day; + auto last_interval_of_day = + (last_hour_of_day + interval - offset) / interval; + auto next_interval_of_day = + (next_hour_of_day + interval - offset) / interval; + changed = last_interval_of_day != next_interval_of_day; + break; + } + + case Unit::MINUTES: { + auto last_minute = last_smp->ts.origin.tv_sec / 60; + auto next_minute = next_smp->ts.origin.tv_sec / 60; + + auto last_hour = last_minute / 60; + auto next_hour = next_minute / 60; + if (last_hour != next_hour) { + changed = true; + break; + } + + auto last_minute_of_hour = last_minute - 60 * last_hour; + auto next_minute_of_hour = next_minute - 60 * next_hour; + auto last_interval_of_hour = + (last_minute_of_hour + interval - offset) / interval; + auto next_interval_of_hour = + (next_minute_of_hour + interval - offset) / interval; + changed = last_interval_of_hour != next_interval_of_hour; + break; + } + + case Unit::SECONDS: { + auto last_second = last_smp->ts.origin.tv_sec; + auto next_second = next_smp->ts.origin.tv_sec; + + auto last_minute = last_second / 60; + auto next_minute = next_second / 60; + if (last_minute != next_minute) { + changed = true; + break; + } + + auto last_second_of_minute = last_second - 60 * last_minute; + auto next_second_of_minute = next_second - 60 * next_minute; + auto last_interval_of_minute = + (last_second_of_minute + interval - offset) / interval; + auto next_interval_of_minute = + (next_second_of_minute + interval - offset) / interval; + changed = last_interval_of_minute != next_interval_of_minute; + break; + } + + case Unit::MILLISECONDS: { + auto last_second = last_smp->ts.origin.tv_sec; + auto next_second = next_smp->ts.origin.tv_sec; + if (last_second != next_second) { + changed = true; + break; + } + + auto last_millisecond_of_second = + last_smp->ts.origin.tv_nsec / 1'000'000; + auto next_millisecond_of_second = + next_smp->ts.origin.tv_nsec / 1'000'000; + auto last_interval_of_second = + (last_millisecond_of_second + interval - offset) / interval; + auto next_interval_of_second = + (next_millisecond_of_second + interval - offset) / interval; + changed = last_interval_of_second != next_interval_of_second; + break; + } + } + + if (changed) + logger->debug("new frame"); + + return changed; + } + +public: + FrameHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), trigger(Trigger::SEQUENCE), interval(1), + offset(0), unit{std::nullopt}, last_smp{nullptr, &sample_decref} {} + + virtual void parse(json_t *json) override { + Hook::parse(json); + + char *trigger_str = nullptr; + char *unit_str = nullptr; + int interval_int = -1; + int offset_int = -1; + + json_error_t err; + auto ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: i, s?: i }", + "trigger", &trigger_str, "unit", &unit_str, + "interval", &interval_int, "offset", &offset_int); + if (ret) + throw ConfigError(json, err, "node-config-hook-frame"); + + if (trigger_str) { + if (!strcmp(trigger_str, "sequence")) + trigger = Trigger::SEQUENCE; + else if (!strcmp(trigger_str, "timestamp")) + trigger = Trigger::TIMESTAMP; + else + throw ConfigError(json, "node-config-hook-frame-unit"); + } + + if (trigger == Trigger::TIMESTAMP) { + if (!strcmp(unit_str, "milliseconds")) + unit = Unit::MILLISECONDS; + else if (!strcmp(unit_str, "seconds")) + unit = Unit::SECONDS; + else if (!strcmp(unit_str, "minutes")) + unit = Unit::MINUTES; + else if (!strcmp(unit_str, "hours")) + unit = Unit::HOURS; + else + throw ConfigError(json, "node-config-hook-frame-unit"); + } + + if (interval_int != -1) { + if (interval_int <= 0 || (uint64_t)interval_int > unit_wrap(unit)) + throw ConfigError(json, "node-config-hook-frame-interval"); + + interval = interval_int; + } + + if (offset_int != -1) { + if (offset_int < 0 || (uint64_t)offset_int >= unit_wrap(unit)) + throw ConfigError(json, "node-config-hook-frame-offset"); + + offset = offset_int; + } + } + + virtual Hook::Reason process(Sample *smp) override { + Hook::process(smp); + + if (updateInterval(smp)) + smp->flags |= (int)SampleFlags::NEW_FRAME; + else + smp->flags &= ~(int)SampleFlags::NEW_FRAME; + + sample_incref(smp); + last_smp = sample_ptr{smp, &sample_decref}; + + return Reason::OK; + } + + virtual void stop() override { + Hook::stop(); + + last_smp = nullptr; + } +}; + +// Register hook +static char n[] = "frame"; +static char d[] = "Add frame annotations too the stream of samples"; +static HookPlugin p; + +} // namespace node +} // namespace villas From 065de3ab6deac95194e4ea1e8306c4c8d77bb6f2 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Fri, 25 Aug 2023 13:33:57 +0200 Subject: [PATCH 067/100] hook-digest: Add hook for computing digests Signed-off-by: Philipp Jungkamp --- .../components/schemas/config/hook_obj.yaml | 1 + .../schemas/config/hooks/_digest.yaml | 7 + .../schemas/config/hooks/digest.yaml | 24 ++ etc/examples/hooks/digest.conf | 23 ++ lib/hooks/CMakeLists.txt | 1 + lib/hooks/digest.cpp | 261 ++++++++++++++++++ lib/hooks/frame.cpp | 2 + 7 files changed, 319 insertions(+) create mode 100644 doc/openapi/components/schemas/config/hooks/_digest.yaml create mode 100644 doc/openapi/components/schemas/config/hooks/digest.yaml create mode 100644 etc/examples/hooks/digest.conf create mode 100644 lib/hooks/digest.cpp diff --git a/doc/openapi/components/schemas/config/hook_obj.yaml b/doc/openapi/components/schemas/config/hook_obj.yaml index 37d4021b5..38dc07929 100644 --- a/doc/openapi/components/schemas/config/hook_obj.yaml +++ b/doc/openapi/components/schemas/config/hook_obj.yaml @@ -17,6 +17,7 @@ discriminator: average: hooks/_average.yaml cast: hooks/_cast.yaml decimate: hooks/_decimate.yaml + digest: hooks/_digest.yaml dp: hooks/_dp.yaml drop: hooks/_drop.yaml dump: hooks/_dump.yaml diff --git a/doc/openapi/components/schemas/config/hooks/_digest.yaml b/doc/openapi/components/schemas/config/hooks/_digest.yaml new file mode 100644 index 000000000..d97530b19 --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/_digest.yaml @@ -0,0 +1,7 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +--- +allOf: +- $ref: ../hook_obj.yaml +- $ref: digest.yaml diff --git a/doc/openapi/components/schemas/config/hooks/digest.yaml b/doc/openapi/components/schemas/config/hooks/digest.yaml new file mode 100644 index 000000000..884314046 --- /dev/null +++ b/doc/openapi/components/schemas/config/hooks/digest.yaml @@ -0,0 +1,24 @@ +# yaml-language-server: $schema=http://json-schema.org/draft-07/schema +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +--- +allOf: +- type: object + required: + - uri + - mode + - interval + - algorithm + properties: + uri: + description: The output file for digests. + example: digest.txt + type: string + format: uri + + algorithm: + description: The algorithm used for calculating digests. + example: sha256 + type: string + +- $ref: ../hook.yaml diff --git a/etc/examples/hooks/digest.conf b/etc/examples/hooks/digest.conf new file mode 100644 index 000000000..7d8694771 --- /dev/null +++ b/etc/examples/hooks/digest.conf @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +@include "hook-nodes.conf" + +paths = ( + { + in = "signal_node" + out = "file_node" + + hooks = ( + # Use a frame hook to generate NEW_FRAME annotations. + "frame", + { + type = "digest" + # The algorithm used for digest calculation + algorithm = "sha256" + # The output file for digests + uri = "sequence.digest" + } + ) + } +) diff --git a/lib/hooks/CMakeLists.txt b/lib/hooks/CMakeLists.txt index 883472f90..83d2f13f3 100644 --- a/lib/hooks/CMakeLists.txt +++ b/lib/hooks/CMakeLists.txt @@ -8,6 +8,7 @@ set(HOOK_SRC average.cpp cast.cpp decimate.cpp + digest.cpp dp.cpp drop.cpp dump.cpp diff --git a/lib/hooks/digest.cpp b/lib/hooks/digest.cpp new file mode 100644 index 000000000..49fa4bc93 --- /dev/null +++ b/lib/hooks/digest.cpp @@ -0,0 +1,261 @@ +/* Digest hook. + * + * Author: Philipp Jungkamp + * SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace villas { +namespace node { +namespace digest { + +template +static std::array +little_endian_bytes(T const &t) noexcept { + auto bytes = std::array(); + auto const ptr = reinterpret_cast(std::addressof(t)); + std::copy(ptr, ptr + sizeof(T), bytes.begin()); + +#if BYTE_ORDER == BIG_ENDIAN + std::reverse(bytes.begin(), bytes.end()); +#endif + + return bytes; +} + +static void FILE_free(FILE *f) { fclose(f); } + +class DigestHook : public Hook { + using md_ctx_ptr = std::unique_ptr; + using file_ptr = std::unique_ptr; + + // Parameters + std::string algorithm; + std::string uri; + + // Context + md_ctx_ptr md_ctx; + EVP_MD const *md; + file_ptr file; + std::optional first_sequence; + std::optional first_timestamp; + std::optional last_sequence; + std::optional last_timestamp; + std::vector md_buffer; + std::string md_string_buffer; + + void emitDigest() { + if (!first_sequence || !first_timestamp || !last_sequence || + !last_timestamp) + return; + + unsigned int md_size; + unsigned char md_value[EVP_MAX_MD_SIZE]; + if (!EVP_DigestFinal_ex(md_ctx.get(), md_value, &md_size)) + throw RuntimeError{"Could not finalize digest"}; + + if (!EVP_MD_CTX_reset(md_ctx.get())) + throw RuntimeError{"Could not reset digest context"}; + + if (!EVP_DigestInit_ex(md_ctx.get(), md, NULL)) + throw RuntimeError{"Could not initialize digest"}; + + md_string_buffer.clear(); + auto inserter = std::back_inserter(md_string_buffer); + fmt::format_to(inserter, "{}.{:09}-{} ", first_timestamp->tv_sec, + first_timestamp->tv_nsec, *first_sequence); + fmt::format_to(inserter, "{}.{:09}-{} ", last_timestamp->tv_sec, + last_timestamp->tv_nsec, *last_sequence); + fmt::format_to(inserter, "{} ", algorithm); + for (unsigned int i = 0; i < md_size; ++i) + fmt::format_to(inserter, "{:02X}", md_value[i]); + + logger->debug("emit {}", md_string_buffer); + md_string_buffer.push_back('\n'); + fputs(md_string_buffer.c_str(), file.get()); + fflush(file.get()); + } + + void updateInterval(Sample const *smp) { + auto const next_sequence = smp->sequence; + auto const next_timestamp = smp->ts.origin; + + if (smp->flags & (int)SampleFlags::NEW_FRAME) { + emitDigest(); + first_sequence = next_sequence; + first_timestamp = next_timestamp; + } + + last_sequence = next_sequence; + last_timestamp = next_timestamp; + } + + void updateDigest(Sample const *smp) { + md_buffer.clear(); + auto inserter = std::back_inserter(md_buffer); + + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + auto const bytes_sec = + little_endian_bytes(smp->ts.origin.tv_sec); + std::copy(std::cbegin(bytes_sec), std::cend(bytes_sec), inserter); + auto const bytes_nsec = + little_endian_bytes(smp->ts.origin.tv_nsec); + std::copy(std::cbegin(bytes_nsec), std::cend(bytes_nsec), inserter); + } + + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + auto const bytes = little_endian_bytes(smp->sequence); + std::copy(std::cbegin(bytes), std::cend(bytes), inserter); + } + + if (smp->flags & (int)SampleFlags::HAS_DATA) { + if (signals->size() != smp->length) + throw RuntimeError{"Sample length does not match signal list."}; + + for (unsigned int i = 0; i < smp->length; ++i) { + auto const signal = signals->getByIndex(i); + auto const &data = smp->data[i]; + + switch (signal->type) { + case SignalType::BOOLEAN: { + auto const bytes = little_endian_bytes(data.b ? 1 : 0); + std::copy(std::cbegin(bytes), std::cend(bytes), inserter); + break; + } + + case SignalType::INTEGER: { + auto const bytes = little_endian_bytes(data.i); + std::copy(std::cbegin(bytes), std::cend(bytes), inserter); + break; + } + + case SignalType::FLOAT: { + auto const f = (data.f == data.f) ? data.f : std::nan(""); + auto const bytes = little_endian_bytes(f); + std::copy(std::cbegin(bytes), std::cend(bytes), inserter); + break; + } + + case SignalType::COMPLEX: { + auto real = data.z.real(); + real = (real == real) ? real : std::nanf(""); + auto const rbytes = little_endian_bytes(real); + std::copy(std::cbegin(rbytes), std::cend(rbytes), inserter); + + auto imag = data.z.imag(); + imag = (imag == imag) ? imag : std::nanf(""); + auto const ibytes = little_endian_bytes(imag); + std::copy(std::cbegin(ibytes), std::cend(ibytes), inserter); + break; + } + + case SignalType::INVALID: + default: + throw RuntimeError{"Can calculate digest for invalid sample."}; + } + } + } + + if (!EVP_DigestUpdate(md_ctx.get(), md_buffer.data(), md_buffer.size())) + throw RuntimeError{"Could not update digest"}; + } + +public: + DigestHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), algorithm(), uri(), + md_ctx(EVP_MD_CTX_new(), &EVP_MD_CTX_free), md(nullptr), + file(nullptr, &FILE_free), first_sequence(std::nullopt), + first_timestamp(std::nullopt), last_sequence(std::nullopt), + last_timestamp(std::nullopt), md_buffer(), md_string_buffer() {} + + virtual void parse(json_t *json) { + Hook::parse(json); + + char const *uri_str; + char const *mode_str; + char const *algorithm_str; + + json_error_t err; + int ret = + json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s }", "uri", &uri_str, + "mode", &mode_str, "algorithm", &algorithm_str); + if (ret) + throw ConfigError(json, err, "node-config-hook-digest"); + + uri = std::string(uri_str); + + if (algorithm_str) + algorithm = std::string(algorithm_str); + } + + virtual void prepare() { + Hook::prepare(); + + file = file_ptr(fopen(uri.c_str(), "w"), &FILE_free); + if (!file) + throw RuntimeError{"Could not open file {}: {}", uri, strerror(errno)}; + + md = EVP_get_digestbyname(algorithm.c_str()); + if (!md) + throw RuntimeError{"Could not fetch algorithm {}", algorithm}; + } + + virtual void start() { + Hook::start(); + + if (!EVP_DigestInit_ex(md_ctx.get(), md, NULL)) + throw RuntimeError{"Could not initialize digest"}; + } + + virtual Hook::Reason process(struct Sample *smp) { + assert(smp); + assert(state == State::STARTED); + + updateInterval(smp); + updateDigest(smp); + + return Reason::OK; + } + + virtual void stop() { + Hook::stop(); + + first_sequence.reset(); + first_timestamp.reset(); + last_sequence.reset(); + last_timestamp.reset(); + if (!EVP_MD_CTX_reset(md_ctx.get())) + throw RuntimeError{"Could not reset digest context"}; + } +}; + +// Register hook +static char n[] = "digest"; +static char d[] = "Calculate the digest for a range of samples"; +static HookPlugin p; + +} // namespace digest +} // namespace node +} // namespace villas diff --git a/lib/hooks/frame.cpp b/lib/hooks/frame.cpp index 99b962ab1..f13b05bbf 100644 --- a/lib/hooks/frame.cpp +++ b/lib/hooks/frame.cpp @@ -168,6 +168,8 @@ public: : Hook(p, n, fl, prio, en), trigger(Trigger::SEQUENCE), interval(1), offset(0), unit{std::nullopt}, last_smp{nullptr, &sample_decref} {} + virtual ~FrameHook() { (void)last_smp.release(); } + virtual void parse(json_t *json) override { Hook::parse(json); From 043ff81eb5166ada2687091d199cc8d82f42047d Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 13 Sep 2023 10:16:39 +0200 Subject: [PATCH 068/100] Fix SampleFlags HAS_ALL and NEW_FRAME SampleFlags::HAS_ALL was not including the NEW_* style flags. The NEW_SIMULATION flag is now independent from the NEW_FRAME flag, since the dependency made checking that flag unnecessarily difficult. Checking a composite flag like this if ((smp->flags & SampleFlags::NEW_SIMULATION) == SampleFlags::NEW_SIMULATION); is more verbose than checking a simple flag like if (smp->flags & SampleFlags::NEW_SIMULATION); Signed-off-by: Philipp Jungkamp --- include/villas/format.hpp | 4 ++-- include/villas/sample.hpp | 5 +++-- lib/hooks/frame.cpp | 12 +++++++++--- src/villas-hook.cpp | 2 +- tests/unit/format.cpp | 4 ++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 4f670ce3a..76ba1571f 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -50,8 +50,8 @@ public: int getFlags() const { return flags; } - void start(const SignalList::Ptr sigs, int fl = (int)SampleFlags::HAS_ALL); - void start(const std::string &dtypes, int fl = (int)SampleFlags::HAS_ALL); + void start(const SignalList::Ptr sigs, int fl = (int)SampleFlags::ALL); + void start(const std::string &dtypes, int fl = (int)SampleFlags::ALL); virtual void start() {} diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index 8de132db0..4c4059170 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -47,11 +47,12 @@ enum class SampleFlags { HAS_TS = HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. - HAS_ALL = (1 << 5) - 1, // Enable all output options. NEW_FRAME = (1 << 16), // This sample is the last of a running simulation case NEW_SIMULATION = - (1 << 17) | NEW_FRAME // This sample is the first of a new simulation case + (1 << 17), // This sample is the first of a new simulation case + + ALL = -1 }; struct Sample { diff --git a/lib/hooks/frame.cpp b/lib/hooks/frame.cpp index f13b05bbf..02faed7a9 100644 --- a/lib/hooks/frame.cpp +++ b/lib/hooks/frame.cpp @@ -64,14 +64,19 @@ private: bool changed = false; if (!last_smp.get() || - (next_smp->flags & (int)SampleFlags::NEW_SIMULATION) == - (int)SampleFlags::NEW_SIMULATION) { + (next_smp->flags & (int)SampleFlags::NEW_SIMULATION)) { changed = true; } else if (trigger == Trigger::SEQUENCE) { + if (!(next_smp->flags & (int)SampleFlags::HAS_SEQUENCE)) + throw RuntimeError{"Missing sequence number."}; + auto last_interval = (last_smp->sequence + interval - offset) / interval; auto next_interval = (next_smp->sequence + interval - offset) / interval; changed = last_interval != next_interval; - } else + } else { + if (!(next_smp->flags & (int)SampleFlags::HAS_TS_ORIGIN)) + throw RuntimeError{"Missing origin timestamp."}; + switch (unit.value()) { case Unit::HOURS: { auto last_hour = last_smp->ts.origin.tv_sec / 3'600; @@ -156,6 +161,7 @@ private: break; } } + } if (changed) logger->debug("new frame"); diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index 97b41782e..0a3985b91 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -218,7 +218,7 @@ protected: if (!(*d.formatter)) throw RuntimeError("Failed to initialize {} IO", d.dir); - (*d.formatter)->start(dtypes, (int)SampleFlags::HAS_ALL); + (*d.formatter)->start(dtypes, (int)SampleFlags::ALL); } // Initialize hook diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index 54abc41bb..c97120e4e 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -269,7 +269,7 @@ ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) { cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); - fmt->start(signals, (int)SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::ALL); cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt); cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); @@ -370,7 +370,7 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) { cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); - fmt->start(signals, (int)SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::ALL); auto *stream = fopen(fn, "w+"); cr_assert_not_null(stream); From b70704f2d4b5fc3ed66c271a340ca761f21c8074 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 13 Sep 2023 10:25:50 +0200 Subject: [PATCH 069/100] format-json: Include flags in serialization. Include the SampleFlags::NEW_FRAME and NEW_SIMULATION flags in the JSON serialization of samples. Signed-off-by: Philipp Jungkamp --- include/villas/formats/json.hpp | 3 ++ lib/formats/json.cpp | 78 +++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 1183948b1..98509f98c 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -22,6 +22,9 @@ class JsonFormat : public Format { protected: static enum SignalType detect(const json_t *val); + json_t *packFlags(const struct Sample *smp); + int unpackFlags(json_t *json_ts, struct Sample *smp); + json_t *packTimestamps(const struct Sample *smp); int unpackTimestamps(json_t *json_ts, struct Sample *smp); diff --git a/lib/formats/json.cpp b/lib/formats/json.cpp index d67d0475b..795c0c129 100644 --- a/lib/formats/json.cpp +++ b/lib/formats/json.cpp @@ -36,6 +36,56 @@ enum SignalType JsonFormat::detect(const json_t *val) { } } +json_t *JsonFormat::packFlags(const struct Sample *smp) { + json_t *json_flags = json_array(); + + if (flags & (int)SampleFlags::NEW_SIMULATION) { + if (smp->flags & (int)SampleFlags::NEW_SIMULATION) + json_array_append_new(json_flags, json_string("new_simulation")); + } + + if (flags & (int)SampleFlags::NEW_FRAME) { + if (smp->flags & (int)SampleFlags::NEW_FRAME) + json_array_append_new(json_flags, json_string("new_frame")); + } + + if (json_array_size(json_flags) == 0) { + json_decref(json_flags); + return nullptr; + } + + return json_flags; +} + +int JsonFormat::unpackFlags(json_t *json_flags, struct Sample *smp) { + if (!json_flags) + return 0; + + if (!json_is_array(json_flags)) + throw RuntimeError{"The JSON object flags member is not an array."}; + + size_t i; + json_t *json_flag; + json_array_foreach(json_flags, i, json_flag) { + char *flag; + json_error_t err; + if (auto ret = json_unpack_ex(json_flag, &err, 0, "s", &flag)) + return ret; + + if (!strcmp(flag, "new_frame")) + smp->flags |= (int)SampleFlags::NEW_FRAME; + else + smp->flags &= ~(int)SampleFlags::NEW_FRAME; + + if (!strcmp(flag, "new_simulation")) + smp->flags |= (int)SampleFlags::NEW_SIMULATION; + else + smp->flags &= ~(int)SampleFlags::NEW_SIMULATION; + } + + return 0; +} + json_t *JsonFormat::packTimestamps(const struct Sample *smp) { json_t *json_ts = json_object(); @@ -59,6 +109,11 @@ json_t *JsonFormat::packTimestamps(const struct Sample *smp) { json_pack(fmt, smp->ts.received.tv_sec, smp->ts.received.tv_nsec)); } + if (json_object_size(json_ts) == 0) { + json_decref(json_ts); + return nullptr; + } + return json_ts; } @@ -96,7 +151,8 @@ int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) { json_t *json_root; json_error_t err; - json_root = json_pack_ex(&err, 0, "{ s: o }", "ts", packTimestamps(smp)); + json_root = json_pack_ex(&err, 0, "{ s: o*, s: o* }", "ts", + packTimestamps(smp), "flags", packFlags(smp)); if (flags & (int)SampleFlags::HAS_SEQUENCE) { if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { @@ -150,14 +206,15 @@ int JsonFormat::packSamples(json_t **json_smps, int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) { int ret; json_error_t err; - json_t *json_data, *json_value, *json_ts = nullptr; + json_t *json_data, *json_value, *json_ts = nullptr, *json_flags = nullptr; size_t i; int64_t sequence = -1; smp->signals = signals; - ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: I, s: o }", "ts", - &json_ts, "sequence", &sequence, "data", &json_data); + ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: o, s?: I, s: o }", "ts", + &json_ts, "flags", &json_flags, "sequence", &sequence, + "data", &json_data); if (ret) return ret; @@ -170,6 +227,10 @@ int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) { return ret; } + ret = unpackFlags(json_flags, smp); + if (ret) + return ret; + if (!json_is_array(json_data)) return -1; @@ -368,8 +429,9 @@ void JsonFormat::parse(json_t *json) { // Register format static char n[] = "json"; static char d[] = "Javascript Object Notation"; -static FormatPlugin +static FormatPlugin< + JsonFormat, n, d, + (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA | (int)SampleFlags::NEW_FRAME | + (int)SampleFlags::NEW_SIMULATION> p; From c49e339ad13b19dfa64068a0f2c69070740347c8 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 13 Sep 2023 10:27:14 +0200 Subject: [PATCH 070/100] Don't overwrite sample flags during path sample muxing. Signed-off-by: Philipp Jungkamp --- lib/path.cpp | 7 ------- lib/path_source.cpp | 12 ++++++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/path.cpp b/lib/path.cpp index 9b6207d31..8c28a1c75 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -531,15 +531,8 @@ void Path::start() { last_sample->length = signals->size(); last_sample->signals = signals; - last_sample->ts.origin = time_now(); - last_sample->flags = (int)SampleFlags::HAS_TS_ORIGIN; - last_sample->sequence = 0; - last_sample->flags |= (int)SampleFlags::HAS_SEQUENCE; - - if (last_sample->length > 0) - last_sample->flags |= (int)SampleFlags::HAS_DATA; for (size_t i = 0; i < last_sample->length; i++) { auto sig = signals->getByIndex(i); diff --git a/lib/path_source.cpp b/lib/path_source.cpp index e61577e2b..9fa147850 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -96,10 +96,14 @@ int PathSource::read(int i) { goto read_decref_muxed_smps; } + muxed_smps[i]->flags = tomux_smps[i]->flags; + if (path->original_sequence_no) { muxed_smps[i]->sequence = tomux_smps[i]->sequence; - muxed_smps[i]->flags |= - tomux_smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE; + if (tomux_smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE) + muxed_smps[i]->flags |= (int)SampleFlags::HAS_SEQUENCE; + else + muxed_smps[i]->flags &= ~(int)SampleFlags::HAS_SEQUENCE; } else { muxed_smps[i]->sequence = path->last_sequence++; muxed_smps[i]->flags |= (int)SampleFlags::HAS_SEQUENCE; @@ -112,8 +116,6 @@ int PathSource::read(int i) { muxed_smps[i]->length = 0; muxed_smps[i]->ts = tomux_smps[i]->ts; - muxed_smps[i]->flags |= tomux_smps[i]->flags & (int)SampleFlags::HAS_TS; - ret = mappings.remap(muxed_smps[i], tomux_smps[i]); if (ret < 0) { enqueued = ret; @@ -123,6 +125,8 @@ int PathSource::read(int i) { if (muxed_smps[i]->length > 0) muxed_smps[i]->flags |= (int)SampleFlags::HAS_DATA; + else + muxed_smps[i]->flags &= ~(int)SampleFlags::HAS_DATA; } muxed_initialized = tomux; From 54d3f51afbcb2d137d02c0f4905ea545a8ec6064 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 14 Sep 2023 11:36:03 +0200 Subject: [PATCH 071/100] format-villas.human: Add NEW_FRAME flag to format Signed-off-by: Philipp Jungkamp --- lib/formats/villas_human.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/formats/villas_human.cpp b/lib/formats/villas_human.cpp index a06a2d04e..5552d6fa8 100644 --- a/lib/formats/villas_human.cpp +++ b/lib/formats/villas_human.cpp @@ -5,9 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include +#include #include #include #include @@ -41,6 +43,11 @@ size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence); } + if (flags & (int)SampleFlags::NEW_FRAME) { + if (smp->flags & (int)SampleFlags::NEW_FRAME) + off += snprintf(buf + off, len - off, "F"); + } + if (flags & (int)SampleFlags::HAS_DATA) { for (unsigned i = 0; i < smp->length; i++) { auto sig = smp->signals->getByIndex(i); @@ -69,8 +76,8 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, smp->flags = 0; smp->signals = signals; - /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... - * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))? + /* Format: Seconds.NanoSeconds+Offset(SequenceNumber)Flags Value1 Value2 ... + * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))?(F)? * * Please note that only the seconds and at least one value are mandatory */ @@ -117,6 +124,12 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, end++; } + // Optional: NEW_FRAME flag + if (*end == 'F') { + smp->flags |= (int)SampleFlags::NEW_FRAME; + end++; + } + unsigned i; for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { if (*end == delimiter) @@ -189,9 +202,9 @@ void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) { // Register format static char n[] = "villas.human"; static char d[] = "VILLAS human readable format"; -static LineFormatPlugin +static LineFormatPlugin< + VILLASHumanFormat, n, d, + (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA | (int)SampleFlags::NEW_FRAME, + '\n'> p; From 25601efa5411e617b0ade8f367f52a79a5e79818 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 14 Sep 2023 11:38:22 +0200 Subject: [PATCH 072/100] hook-reorder_ts: Add integration test Signed-off-by: Philipp Jungkamp --- lib/hooks/reorder_ts.cpp | 17 ++++++++-- tests/integration/hook-reorder_ts.sh | 49 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100755 tests/integration/hook-reorder_ts.sh diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index 38c43c79f..47203980b 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "villas/exceptions.hpp" #include #include #include @@ -32,6 +33,9 @@ protected: sample_copy(rhs, buffer); } else { buffer = sample_clone(lhs); + if (!buffer) + throw RuntimeError{"Out of memory."}; + sample_copy(lhs, rhs); sample_copy(rhs, buffer); } @@ -80,7 +84,11 @@ public: assert(smp); if (window.empty()) { - window.push_back(sample_clone(smp)); + auto new_smp = sample_clone(smp); + if (!new_smp) + throw RuntimeError{"Out of memory."}; + + window.push_back(new_smp); logger->debug("window.size={}/{}", window.size(), window_size); @@ -104,7 +112,12 @@ public: window.push_back(nullptr); std::copy_backward(std::next(std::begin(window), i + 1), --std::end(window), std::end(window)); - window[i + 1] = sample_clone(smp); + + auto new_smp = sample_clone(smp); + if (!new_smp) + throw RuntimeError{"Out of memory."}; + + window[i + 1] = new_smp; logger->debug("window.size={}/{}", window.size(), window_size); diff --git a/tests/integration/hook-reorder_ts.sh b/tests/integration/hook-reorder_ts.sh new file mode 100755 index 000000000..a62a5da30 --- /dev/null +++ b/tests/integration/hook-reorder_ts.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# Integration test for reorder_ts hook. +# +# Author: Philipp Jungkamp +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < expect.dat < reorder.dat +villas hook drop < reorder.dat > output.dat + +villas compare output.dat expect.dat From 7623af56c7f944f1d6c9037baf0d30d1d91c60f8 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 14 Sep 2023 11:39:21 +0200 Subject: [PATCH 073/100] hook-frame: Add integration test Signed-off-by: Philipp Jungkamp --- tests/integration/hook-frame.sh | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100755 tests/integration/hook-frame.sh diff --git a/tests/integration/hook-frame.sh b/tests/integration/hook-frame.sh new file mode 100755 index 000000000..dce8d18ee --- /dev/null +++ b/tests/integration/hook-frame.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Integration test for frame hook. +# +# Author: Philipp Jungkamp +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < expect.dat < output.dat + +villas compare output.dat expect.dat From f9853f52c7baceecee4921d7703259f47861d071 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 14 Sep 2023 13:13:34 +0200 Subject: [PATCH 074/100] hook-digest: Add integration test Signed-off-by: Philipp Jungkamp --- lib/hooks/digest.cpp | 4 +-- tests/integration/hook-digest.sh | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100755 tests/integration/hook-digest.sh diff --git a/lib/hooks/digest.cpp b/lib/hooks/digest.cpp index 49fa4bc93..4d26197d2 100644 --- a/lib/hooks/digest.cpp +++ b/lib/hooks/digest.cpp @@ -131,8 +131,8 @@ class DigestHook : public Hook { } if (smp->flags & (int)SampleFlags::HAS_DATA) { - if (signals->size() != smp->length) - throw RuntimeError{"Sample length does not match signal list."}; + if (signals->size() < smp->length) + throw RuntimeError{"Sample length longer than signal list."}; for (unsigned int i = 0; i < smp->length; ++i) { auto const signal = signals->getByIndex(i); diff --git a/tests/integration/hook-digest.sh b/tests/integration/hook-digest.sh new file mode 100755 index 000000000..a2bed93cd --- /dev/null +++ b/tests/integration/hook-digest.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Integration test for digest hook. +# +# Author: Philipp Jungkamp +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < expect.dat < expect.digest < frame.dat +villas hook digest -o algorithm=sha256 -o uri=output.digest < frame.dat > output.dat + +villas compare output.dat expect.dat +diff output.digest expect.digest From c863089e4b95f6785d5ebe6ccdf4574578c6a269 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 19 Sep 2023 11:54:37 +0200 Subject: [PATCH 075/100] packaging-nix: Add villas-python package Signed-off-by: Philipp Jungkamp --- packaging/nix/flake.nix | 4 ++++ packaging/nix/python.nix | 23 +++++++++++++++++++++++ python/.envrc | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 packaging/nix/python.nix create mode 100644 python/.envrc diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index dd0830d05..564007e78 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -97,6 +97,10 @@ packagesWith = pkgs: rec { default = villas; + villas-python = pkgs.callPackage ./python.nix { + src = ../../python; + }; + villas-minimal = pkgs.callPackage ./villas.nix { src = ../..; version = "minimal"; diff --git a/packaging/nix/python.nix b/packaging/nix/python.nix new file mode 100644 index 000000000..d1a4dac58 --- /dev/null +++ b/packaging/nix/python.nix @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 +{ + src, + python3Packages, + villas-minimal, +}: +python3Packages.buildPythonPackage { + name = "villas-python"; + src = src; + propagatedBuildInputs = with python3Packages; [ + linuxfd + requests + villas-minimal + ]; + nativeCheckInputs = with python3Packages; [ + black + flake8 + mypy + pytest + types-requests + ]; +} diff --git a/python/.envrc b/python/.envrc new file mode 100644 index 000000000..5a55089c7 --- /dev/null +++ b/python/.envrc @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +export_or_unset() +{ + local var=$1 + + if [ -z "${!var+x}" ]; then + return + fi + + if [ -n "$2" ]; then + export $var="$2" + else + unset $var + fi + +} + +if direnv_version "2.30.0" \ +&& has nix \ +&& nix show-config experimental-features 2>/dev/null | grep -wqF flakes +then + local oldtmp="$TMP" + local oldtemp="$TEMP" + local oldtmpdir="$TMPDIR" + local oldtempdir="$TEMPDIR" + + watch_file ../packaging/nix/*.nix + use flake ../packaging/nix#villas-python + + export_or_unset TMP "$oldtmp" + export_or_unset TEMP "$oldtemp" + export_or_unset TMPDIR "$oldtmpdir" + export_or_unset TEMPDIR "$oldtempdir" +fi From fabedbcc739387398507f40ede8f4790e17eb6a4 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 19 Sep 2023 17:39:30 +0200 Subject: [PATCH 076/100] editorconfig: Cover more files. Signed-off-by: Philipp Jungkamp --- .editorconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 08e375e0b..6e05103d5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,10 +14,14 @@ trim_trailing_whitespace=true # Matches multiple files with brace expansion notation # Set default charset -[{etc,include,lib,plugins,src,tests,tools,common}/**.{c,h,proto,cpp,hpp,h.in,hpp.in}] +[*.{c,h,proto,cpp,hpp,h.in,hpp.in}] indent_style = space indent_size = 2 +[*.py] +indent_style = space +indent_size = 4 + [*.conf] indent_style = tab indent_size = 8 From 44b5a1217138b9d378a1d3c5ac50fac08c44902b Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 19 Sep 2023 12:04:53 +0200 Subject: [PATCH 077/100] python: Rework Python Sample and Format interfaces Signed-off-by: Philipp Jungkamp --- python/examples/Shmem_CIGRE_MV.py | 107 ++++++------- python/pyproject.toml | 43 +++++ python/setup.py | 46 +----- python/villas/__init__.py | 0 python/villas/node/__init__.py | 9 ++ python/villas/node/communicate.py | 85 +++++----- python/villas/node/formats.py | 241 +++++++++++++++++++++++++++++ python/villas/node/node.py | 110 +++++++------ python/villas/node/sample.py | 225 ++++++++++++++++++--------- python/villas/node/test_formats.py | 51 ++++++ python/villas/node/test_sample.py | 170 ++++++++++++++++++++ 11 files changed, 813 insertions(+), 274 deletions(-) create mode 100644 python/pyproject.toml create mode 100644 python/villas/__init__.py create mode 100644 python/villas/node/formats.py create mode 100644 python/villas/node/test_formats.py create mode 100644 python/villas/node/test_sample.py diff --git a/python/examples/Shmem_CIGRE_MV.py b/python/examples/Shmem_CIGRE_MV.py index 1d1640729..fc65c551b 100644 --- a/python/examples/Shmem_CIGRE_MV.py +++ b/python/examples/Shmem_CIGRE_MV.py @@ -1,102 +1,85 @@ +""" +Author: Steffen Vogel +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 import time from villas.node.node import Node as VILLASnode -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - # This could be moved to the DPsim Python code later def get_dpsim_shmem_interface_signals(): - """ It would be nice if the DPsim Shmem interface could - build-up a list of actual signal descriptions - (names, units, etc..) which attributes are exported. - This would eliviate the user from manually configuring - signal mappings """ + """It would be nice if the DPsim Shmem interface could + build-up a list of actual signal descriptions + (names, units, etc..) which attributes are exported. + This would eliviate the user from manually configuring + signal mappings""" signals = [] for i in range(0, 30): - signals.append({ - 'name': f'signal_{i}', - 'type': 'float', - 'unit': 'volts' - }) + signals.append( + { + "name": f"signal_{i}", + "type": "float", + "unit": "volts", + } + ) return signals def get_dpsim_shmem_interface_config(): return { - 'type': 'shmem', - 'in': { - 'name': '/dpsim1-villas', - 'hooks': [ - { - 'type': 'stats' - } - ], - 'signals': get_dpsim_shmem_interface_signals() + "type": "shmem", + "in": { + "name": "/dpsim1-villas", + "hooks": [{"type": "stats"}], + "signals": get_dpsim_shmem_interface_signals(), }, - 'out': { - 'name': '/villas-dpsim1' - } + "out": {"name": "/villas-dpsim1"}, } def get_villas_config(): return { - 'nodes': { - 'broker1': { - 'type': 'mqtt', - 'format': 'json', - 'host': '172.17.0.1', - 'in': { - 'subscribe': '/powerflow-dpsim'}, - 'out': { - 'publish': '/dpsim-powerflow' - } + "nodes": { + "broker1": { + "type": "mqtt", + "format": "json", + "host": "172.17.0.1", + "in": {"subscribe": "/powerflow-dpsim"}, + "out": {"publish": "/dpsim-powerflow"}, }, - 'dpsim1': get_dpsim_shmem_interface_config(), + "dpsim1": get_dpsim_shmem_interface_config(), }, - 'paths': [ + "paths": [ { - 'in': 'dpsim1', - 'out': 'broker1', - - 'hooks': [ - { - 'type': 'limit_rate', - 'rate': 50 - } - ] + "in": "dpsim1", + "out": "broker1", + "hooks": [{"type": "limit_rate", "rate": 50}], } - ] + ], } def main(): - - node = VILLASnode( - config=get_villas_config() - ) + node = VILLASnode(config=get_villas_config()) node.start() # VILLASnode starts running in the background from here.. # Some infos from the running VILLASnode instance queried via its REST API - print('VILLASnode running?: ', node.is_running()) - print('VILLASnode status: ', node.status) - print('VILLASnode nodes: ', node.nodes) - print('VILLASnode paths: ', node.paths) - print('VILLASnode config: ', node.active_config) - print('VILLASnode version: ', node.get_version()) + print("VILLASnode running?: ", node.is_running()) + print("VILLASnode status: ", node.status) + print("VILLASnode nodes: ", node.nodes) + print("VILLASnode paths: ", node.paths) + print("VILLASnode config: ", node.active_config) + print("VILLASnode version: ", node.get_version()) # Load a new config into the running # VILLASnode instance (old config will be replaced) new_config = node.active_config - new_config['paths'].append({ - 'out': 'dpsim1', - 'in': 'broker1' - }) + new_config["paths"].append({"out": "dpsim1", "in": "broker1"}) node.load_config(new_config) @@ -105,5 +88,5 @@ def main(): node.stop() -if __name__ == 'main': +if __name__ == "main": main() diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 000000000..65f4edc34 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +# SPDX-License-Identifier: Apache-2.0 + +[build-system] +requires = ['setuptools>=61.0'] +build-backend = 'setuptools.build_meta' + +[project] +name = 'villas-python' +version = '0.10.3' +description = 'Python support for the VILLASnode simulation-data gateway' +readme = 'README.md' +requires-python = '>=3.10' +keywords = ['simulation', 'power', 'system', 'real-time', 'villas'] +license.text = 'Apache-2.0' +classifiers = [ + 'Development Status :: 4 - Beta', + 'Topic :: Scientific/Engineering', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3', +] +dependencies = ['linuxfd', 'requests'] +optional-dependencies.dev = [ + 'black', + 'flake8', + 'mypy', + 'pytest', + 'types-requests', +] + +[project.urls] +GitHub = 'https://github.com/VILLASframework/node' +Project = 'https://www.fein-aachen.org/en/projects/villas-node' +Homepage = 'https://villas.fein-aachen.org' + +[[project.authors]] +name = 'Steffen Vogel' +email = 'post@steffenvogel.de' + +[[project.authors]] +name = 'Philipp Jungkamp' +email = 'Philipp.Jungkamp@opal-rt.com' diff --git a/python/setup.py b/python/setup.py index d8092dbe6..2d19d0d65 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,42 +1,8 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 +""" +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 -from setuptools import setup, find_namespace_packages -from glob import glob -import sys +from setuptools import setup -with open('README.md') as f: - long_description = f.read() - -setup( - name='villas-node', - version='0.10.3', - author='Steffen Vogel', - author_email='acs-software@eonerc.rwth-aachen.de', - description='Python-support for VILLASnode simulation-data gateway', - license='Apache-2.0', - keywords='simulation power system real-time villas', - url='https://git.rwth-aachen.de/acs/public/villas/VILLASnode', - packages=find_namespace_packages(include=['villas.*']), - long_description=long_description, - long_description_content_type='text/markdown', - classifiers=[ - 'Development Status :: 4 - Beta', - 'Topic :: Scientific/Engineering', - 'License :: OSI Approved :: ' - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 3' - ], - install_requires=[ - 'requests' - ] + [ - 'linuxfd' - ] if sys.platform == 'linux' else [], - setup_requires=[ - 'm2r' - ], - scripts=glob('bin/*') -) +setup() diff --git a/python/villas/__init__.py b/python/villas/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/python/villas/node/__init__.py b/python/villas/node/__init__.py index e69de29bb..6b25e1978 100644 --- a/python/villas/node/__init__.py +++ b/python/villas/node/__init__.py @@ -0,0 +1,9 @@ +""" +Author: Steffen Vogel +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 + +from .node import Node + +__all__ = ["Node"] diff --git a/python/villas/node/communicate.py b/python/villas/node/communicate.py index d78ed5741..f01a05146 100644 --- a/python/villas/node/communicate.py +++ b/python/villas/node/communicate.py @@ -1,86 +1,83 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 +""" +Author: Steffen Vogel +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 -import time import logging import sys -import linuxfd -from villas.node.sample import Sample, Timestamp from threading import Thread +from typing import Callable + +import linuxfd # type: ignore[import] +from villas.node.formats import VillasHuman +from villas.node.sample import Sample logger = logging.getLogger(__name__) +RecvCallback = Callable[[Sample], None] +SendCallback = Callable[[int], Sample] + + class RecvThread(Thread): - - def __init__(self, cb): + def __init__(self, cb: RecvCallback): super().__init__() - self.cb = cb self.daemon = True + self.format = VillasHuman() def run(self): for line in sys.stdin: - if line.startswith('#'): - continue + logger.debug(f"RecvThread: {line}") - logger.debug("RecvThread: {}".format(line)) - - sample = Sample.parse(line) - - self.cb(sample.values) + if (sample := self.format.load_sample(line)) is not None: + self.cb(sample) class SendThread(Thread): - - def __init__(self, cb, rate=None): + def __init__(self, cb: SendCallback, rate: float): super().__init__() - self.cb = cb - self.rate = rate self.daemon = True - + self.format = VillasHuman() + self.rate = rate self.sequence = 0 def run(self): - - if self.rate: - tfd = linuxfd.timerfd() - tfd.settime(1.0, 1.0 / self.rate) - else: - tfd = None + tfd = linuxfd.timerfd() + tfd.settime(1.0, 1.0 / self.rate) while True: - if tfd: - tfd.read() + tfd.read() - values = self.cb() - ts = Timestamp.now(None, self.sequence) + sample = self.cb(self.sequence) + if sample is None: + continue - sample = Sample(ts, values) - - sys.stdout.write(str(sample) + '\n') + sample = self.format.dump_sample(sample) + sys.stdout.write(sample) sys.stdout.flush() - self.sequence += 1 -def communicate(rate, recv_cb=None, send_cb=None, wait=True): - - if recv_cb: +def communicate( + rate: float, + recv_cb: RecvCallback | None = None, + send_cb: SendCallback | None = None, + wait: bool = True, +): + if recv_cb is not None: rt = RecvThread(recv_cb) rt.start() - if send_cb: + if send_cb is not None: st = SendThread(send_cb, rate) st.start() if wait: try: - while True: - time.sleep(1) + rt.join() + st.join() except KeyboardInterrupt: - logger.info('Received Ctrl+C. Stopping send/recv threads') - - # Threads are daemon threads - # and therefore killed with program termination + logger.info("Received Ctrl+C. Stopping send/recv threads") diff --git a/python/villas/node/formats.py b/python/villas/node/formats.py new file mode 100644 index 000000000..eefb3d4ce --- /dev/null +++ b/python/villas/node/formats.py @@ -0,0 +1,241 @@ +""" +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 + +import re +from dataclasses import dataclass, field +from itertools import groupby +from typing import Iterable + +from villas.node.sample import Sample, Timestamp, Signal + + +class SignalList(list[type]): + types = { + "b": bool, + "i": int, + "f": float, + "c": complex, + } + + _type_to_char = {t: c for c, t in types.items()} + + def __init__(self, fmt: str | Sample | Iterable[type] = "64f"): + if isinstance(fmt, Sample): + super().__init__(map(type, fmt.data) if fmt.data else []) + return + elif not isinstance(fmt, str): + super().__init__(fmt) + return + + super().__init__() + regex = f"([{''.join(self.__class__.types.keys())}])" + fields = iter(re.split(regex, fmt)) + while (count_str := next(fields, None)) is not None: + if count_str: + count = int(count_str) + else: + count = 1 + + try: + ty_str = next(fields) + except StopIteration: + if count_str: + raise ValueError("Expected type specifier.") + else: + break + + try: + ty = self.__class__.types[ty_str] + except KeyError: + raise ValueError(f"Unknown type {ty_str}") + + self.extend([ty] * count) + + def __str__(self): + fmt = "" + + for ty, run in groupby(self): + run_length = sum(1 for _ in run) + c = self.__class__._type_to_char[ty] + if run_length > 1: + fmt += f"{run_length}" + fmt += f"{c}" + + return fmt + + def __repr__(self): + return f"{self.__class__.__name__}('{self.__str__()}')" + + +@dataclass(kw_only=True) +class Format: + """ + The base for VILLASnode formats in Python. + """ + + ts_origin: bool = True + ts_received: bool = True + sequence: bool = True + data: bool = True + + def _strip_sample(self, sample: Sample) -> Sample: + if not self.ts_origin: + sample.ts_origin = None + + if not self.ts_received: + sample.ts_received = None + + if not self.sequence: + sample.sequence = None + + if not self.data: + sample.data = [] + + return sample + + +@dataclass +class VillasHuman(Format): + """ + The villas.human format in Python. + """ + + signal_list: SignalList = field(default_factory=SignalList) + separator: str = "\t" + delimiter: str = "\n" + + def load(self, file) -> list[Sample]: + """ + Load samples from a text mode file object. + """ + + return self.loads(file.read()) + + def loads(self, s: str) -> list[Sample]: + """ + Load samples from a string. + """ + + s.strip(self.separator + self.delimiter) + sample_strs = s.split(sep=self.delimiter) + samples = (self.load_sample(sample) for sample in sample_strs) + return [s for s in samples if s is not None] + + def dump(self, samples: Iterable[Sample], file): + """ + Dump samples to a text mode file object. + """ + + return file.write(self.dumps(samples)) + + def dumps(self, samples: Iterable[Sample]) -> str: + """ + Dump samples to a string. + """ + + sample_strs = (self.dump_sample(sample) for sample in iter(samples)) + return "".join(sample_strs) + + def load_sample(self, sample: str) -> Sample | None: + """ + Load a single sample from a string. + """ + + sample = sample.strip(self.delimiter) + + if sample.startswith("#"): + return None + + fields = sample.split(sep=self.separator) + + if not fields[0]: + return None + + m = re.match( + r"(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?" + r"(?:e[+-]?\d+)?)?(?:\((\d+)\))?(F)?", + fields[0], + ) + + if m is None: + raise ValueError(f"Invalid header: {fields[0]}") + + ts_seconds = int(m.group(1)) + ts_nanoseconds = int(m.group(2)) if m.group(2) else 0 + ts_offset = float(m.group(3)) if m.group(3) else None + sequence = int(m.group(4)) if m.group(4) else None + new_frame = bool(m.group(5)) + + ts_origin = Timestamp(ts_seconds, ts_nanoseconds) + if ts_offset is not None: + ts_received_raw = ts_origin.timestamp() + ts_offset + ts_received = Timestamp.fromtimestamp(ts_received_raw) + else: + ts_received = None + + data: list[Signal] = [] + for ty, value in zip(self.signal_list, fields[1:]): + if ty is bool: + data.append(bool(int(value))) + elif ty is int: + data.append(int(value)) + elif ty is float: + data.append(float(value)) + elif ty is complex: + data.append(self._unpack_complex(value)) + + return self._strip_sample( + Sample( + ts_origin=ts_origin, + ts_received=ts_received, + sequence=sequence, + new_frame=new_frame, + data=data, + ) + ) + + def dump_sample(self, smp: Sample) -> str: + """ + Dump a single sample to a string. + """ + + smp = self._strip_sample(smp) + + s = "" + if smp.ts_origin is not None: + s += f"{smp.ts_origin.seconds}" + if smp.ts_origin.nanoseconds != 0: + s += f".{smp.ts_origin.nanoseconds:09}" + if smp.ts_received is not None: + off = smp.ts_received.timestamp() - smp.ts_origin.timestamp() + s += f"+{off}" + if smp.sequence is not None: + s += f"({smp.sequence})" + if smp.new_frame: + s += "F" + + for ty, value in zip(self.signal_list, smp.data): + s += self.separator + assert ty == type(value) + match value: + case bool(): + s += str(int(value)) + case int(): + s += str(value) + case float(): + s += str(value) + case complex(): + s += self._pack_complex(value) + + s += self.delimiter + + return s + + def _unpack_complex(self, s: str) -> complex: + return complex(s.lower().replace("i", "j")) + + def _pack_complex(self, z: complex) -> str: + return f"{z.real}+{z.imag}i" diff --git a/python/villas/node/node.py b/python/villas/node/node.py index f88fef939..2ecce0ad3 100644 --- a/python/villas/node/node.py +++ b/python/villas/node/node.py @@ -1,34 +1,42 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 +""" +Author: Steffen Vogel +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 -import json -import os -import tempfile -import subprocess -import logging -import signal -import requests import datetime +import json +import logging +import os +import signal +import subprocess +from tempfile import NamedTemporaryFile -LOGGER = logging.getLogger('villas.node') +import requests + +LOGGER = logging.getLogger("villas.node") class Node(object): + api_version = "v2" - api_version = 'v2' - - def __init__(self, api_url=None, - log_filename=None, - config_filename=None, config={}, - executable='villas-node', **kwargs): - + def __init__( + self, + api_url=None, + log_filename=None, + config_filename=None, + config={}, + executable="villas-node", + **kwargs, + ): self.api_url = api_url self.log_filename = log_filename self.executable = executable if config_filename and config: - raise RuntimeError('Can\'t provide config_filename and ' - 'config at the same time!') + raise RuntimeError( + "Can't provide config_filename and " "config at the same time!" + ) if config_filename: with open(config_filename) as f: @@ -38,15 +46,14 @@ class Node(object): # Try to deduct api_url from config if self.api_url is None: - port = config.get('http', {}).get('port') + port = config.get("http", {}).get("port") if port is None: port = 80 if os.getuid() == 0 else 8080 - self.api_url = f'http://localhost:{port}' + self.api_url = f"http://localhost:{port}" def start(self): - self.config_file = tempfile.NamedTemporaryFile(mode='w+', - suffix='.json') + self.config_file = NamedTemporaryFile(mode="w+", suffix=".json") json.dump(self.config, self.config_file) @@ -54,16 +61,20 @@ class Node(object): if self.log_filename is None: now = datetime.datetime.now() - self.log_filename = now.strftime( - 'villas-node_%Y-%m-%d_%H-%M-%S.log') + fmt = "villas-node_%Y-%m-%d_%H-%M-%S.log" + self.log_filename = now.strftime(fmt) - self.log = open(self.log_filename, 'w+') + self.log = open(self.log_filename, "w+") - LOGGER.info("Starting VILLASnode instance with config: %s", - self.config_file.name) + LOGGER.info( + f"Starting VILLASnode instance with config: {self.config_file.name}" # noqa: E501 + ) - self.child = subprocess.Popen([self.executable, self.config_file.name], - stdout=self.log, stderr=self.log) + self.child = subprocess.Popen( + [self.executable, self.config_file.name], + stdout=self.log, + stderr=self.log, + ) def pause(self): LOGGER.info("Pausing VILLASnode instance") @@ -82,61 +93,58 @@ class Node(object): def restart(self): LOGGER.info("Restarting VILLASnode instance") - self.request('restart') + self.request("restart") @property def active_config(self): - return self.request('config') + return self.request("config") @property def nodes(self): - return self.request('nodes') + return self.request("nodes") @property def paths(self): - return self.request('paths') + return self.request("paths") @property def status(self): - return self.request('status') + return self.request("status") def load_config(self, i): if type(i) is dict: cfg = i elif type(i) is str: cfg = json.loads(i) - elif hasattr(i, 'read'): # file-like? + elif hasattr(i, "read"): # file-like? cfg = json.load(i) else: raise TypeError() - req = { - 'config': cfg - } + req = {"config": cfg} - self.request('restart', method='POST', json=req) + self.request("restart", method="POST", json=req) - def request(self, action, method='GET', **args): + def request(self, action, method="GET", **args): + if "timeout" not in args: + args["timeout"] = 1 - if 'timeout' not in args: - args['timeout'] = 1 - - r = requests.request(method, - f'{self.api_url}/api/{self.api_version}/{action}', - **args) + r = requests.request( + method, f"{self.api_url}/api/{self.api_version}/{action}", **args + ) r.raise_for_status() return r.json() def get_local_version(self): - ver = subprocess.check_output([self.executable, '-V']) + ver = subprocess.check_output([self.executable, "-V"]) - return ver.decode('ascii').rstrip() + return ver.decode("ascii").rstrip() def get_version(self): - resp = self.request('status') + resp = self.request("status") - return resp['version'] + return resp["version"] def is_running(self): if self.child is None: diff --git a/python/villas/node/sample.py b/python/villas/node/sample.py index 2bbb2f910..1c90b625f 100644 --- a/python/villas/node/sample.py +++ b/python/villas/node/sample.py @@ -1,110 +1,181 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 +""" +Author: Steffen Vogel +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 -import re +import hashlib +from ctypes import c_double, c_float, sizeof +from dataclasses import dataclass, field from datetime import datetime from functools import total_ordering +from sys import byteorder as native +from typing import Iterable + +assert sizeof(c_float) == 4 +assert sizeof(c_double) == 8 + + +Signal = bool | int | float | complex @total_ordering +@dataclass class Timestamp: - """Parsing the VILLASnode human-readable timestamp format""" + """ + A VILLASnode timestamp. Based on the C struct timespec. + """ - def __init__(self, seconds=None, nanoseconds=None, - offset=None, sequence=None): - self.seconds = seconds - self.nanoseconds = nanoseconds - self.offset = offset - self.sequence = sequence + seconds: int + nanoseconds: int = 0 + + def _as_digest_bytes(self): + sec = self.seconds.to_bytes(8, "little") + nsec = self.nanoseconds.to_bytes(8, "little") + return bytes().join([sec, nsec]) @classmethod - def now(cls, offset=None, sequence=None): - n = datetime.utcnow() - - secs = int(n.timestamp()) - nsecs = 1000 * n.microsecond - - return Timestamp(seconds=secs, nanoseconds=nsecs, - offset=offset, sequence=sequence) + def fromdatetime(cls, ts: datetime) -> "Timestamp": + secs = int(ts.timestamp()) + nsecs = int(1000 * ts.microsecond) + return cls(seconds=secs, nanoseconds=nsecs) @classmethod - def parse(cls, ts): - m = re.match(r'(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?' - r'(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts) + def fromtimestamp(cls, ts: float) -> "Timestamp": + secs = int(ts) + nsecs = int(1e9 * (ts - float(secs))) + return cls(seconds=secs, nanoseconds=nsecs) - seconds = int(m.group(1)) # Mandatory - nanoseconds = int(m.group(2)) if m.group(2) else None - offset = float(m.group(3)) if m.group(3) else None - sequence = int(m.group(4)) if m.group(4) else None + def timestamp(self) -> float: + return float(self) - return Timestamp(seconds, nanoseconds, offset, sequence) - - def __str__(self): - str = "%u" % (self.seconds) - - if self.nanoseconds is not None: - str += ".%09u" % self.nanoseconds - if self.offset is not None: - str += "+%u" % self.offset - if self.sequence is not None: - str += "(%u)" % self.sequence - - return str + def datetime(self) -> datetime: + return datetime.fromtimestamp(self.timestamp()) def __float__(self): - sum = float(self.seconds) + return float(self.seconds) + float(self.nanoseconds) * 1e-9 - if self.nanoseconds is not None: - sum += self.nanoseconds * 1e-9 - if self.offset is not None: - sum += self.offset + def _as_ordered_tuple(self): + return ( + self.seconds, + self.nanoseconds, + ) - return sum + def __eq__(self, other: object): + if not isinstance(other, Timestamp): + return False - def __eq__(self, other): - return float(self) == float(other) + return self._as_ordered_tuple() == other._as_ordered_tuple() - def __lt__(self, other): - return float(self) < float(other) + def __lt__(self, other: "Timestamp"): + return self._as_ordered_tuple() < other._as_ordered_tuple() @total_ordering +@dataclass(kw_only=True) class Sample: - """Parsing a VILLASnode sample from a file (not a UDP package!!)""" + """ + A VILLASnode sample. + """ - def __init__(self, ts, values): - self.ts = ts - self.values = values + ts_origin: Timestamp | None = None + ts_received: Timestamp | None = None + sequence: int | None = None + new_frame: bool = False + data: list[Signal] = field(default_factory=list) - @classmethod - def parse(cls, line): - csv = line.split() + def _as_ordered_tuple(self): + return ( + self.ts_origin is not None, + self.ts_origin if self.ts_origin is not None else Timestamp(0), + self.ts_received is not None, + self.ts_received if self.ts_received is not None else Timestamp(0), + self.sequence is not None, + self.sequence if self.sequence is not None else 0, + not self.new_frame, + self.data, + ) - ts = Timestamp.parse(csv[0]) - vs = [] + def __eq__(self, other: object): + if not isinstance(other, Sample): + return False - for value in csv[1:]: - try: - v = float(value) - except ValueError: - value = value.lower() - try: - v = complex(value) - except Exception: - if value.endswith('i'): - v = complex(value.replace('i', 'j')) - else: - raise ValueError() + return self._as_ordered_tuple() == other._as_ordered_tuple() - vs.append(v) + def __lt__(self, other: "Timestamp"): + return self._as_ordered_tuple() < other._as_ordered_tuple() - return Sample(ts, vs) + def _as_digest_bytes(self): + def signal_to_bytes(signal): + match signal: + case bool(): + return signal.to_bytes(1, "little") + case int(): + return signal.to_bytes(8, "little") + case float(): + i = int.from_bytes(bytes(c_double(signal)), native) + return i.to_bytes(8, "little") + case complex(): + f_real = signal.real + f_imag = signal.imag + i_real = int.from_bytes(bytes(c_float(f_real)), native) + i_imag = int.from_bytes(bytes(c_float(f_imag)), native) + real = i_real.to_bytes(4, "little") + imag = i_imag.to_bytes(4, "little") + return bytes().join([real, imag]) - def __str__(self): - return '%s\t%s' % (self.ts, "\t".join(map(str, self.values))) + return bytes().join( + [ + self.ts_origin._as_digest_bytes(), + self.sequence.to_bytes(8, "little"), + ] + + list(map(signal_to_bytes, self.data)) + ) - def __eq__(self, other): - return self.ts == other.ts - def __lt__(self, other): - return self.ts < other.ts +@dataclass +class Frame(list[Sample]): + """ + A frame VILLASnode of sample indicated by the new_frame flag. + """ + + def __init__(self, it: Iterable[Sample]): + super().__init__(it) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + def digest(self, algorithm: str) -> bytes: + """ + A digest for a frame of samples that is comparable to the digest hook. + """ + + hash = hashlib.new(algorithm) + + for sample in self: + hash.update(sample._as_digest_bytes()) + + return hash.digest() + + def group(samples: list[Sample]) -> list["Frame"]: + """ + Group samples into Frames according to their new_frame flag. + """ + + samples.sort() + + if not samples: + return [] + + frames = [] + current_frame = Frame([samples[0]]) + for sample in samples[1:]: + if sample.new_frame: + frames.append(current_frame) + current_frame = Frame([sample]) + else: + current_frame.append(sample) + frames.append(current_frame) + + return frames diff --git a/python/villas/node/test_formats.py b/python/villas/node/test_formats.py new file mode 100644 index 000000000..2b2e9fb5c --- /dev/null +++ b/python/villas/node/test_formats.py @@ -0,0 +1,51 @@ +""" +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 +from villas.node.sample import Sample, Timestamp +from villas.node.formats import SignalList, VillasHuman +from cmath import sqrt + + +def test_signal_list_repr(): + signal_list = SignalList("21fb2ic") + assert signal_list == eval(repr(signal_list)) + + +def test_signal_list(): + signal_list = SignalList("1fb2ic") + assert signal_list == SignalList([float, bool, int, int, complex]) + + +def test_villas_human_repr(): + villas_human = VillasHuman(ts_received=False) + assert villas_human == eval(repr(villas_human)) + + +def test_villas_human(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, False, 42, sqrt(complex(-1))], + ) + + villas_human = VillasHuman(signal_list=SignalList(smp1)) + smp1_str = "123456780+1.0(4)F\t1.0\t2.0\t3.0\t1\t42\t0.0+1.0i\n" + smp2_str = "123456789+1.0(5)\t1.0\t2.0\t3.0\t0\t42\t0.0+1.0i\n" + assert villas_human.dump_sample(smp1) == smp1_str + assert villas_human.dump_sample(smp2) == smp2_str + assert villas_human.dumps([smp1, smp2]) == smp1_str + smp2_str + assert villas_human.load_sample(smp1_str) == smp1 + assert villas_human.load_sample(smp2_str) == smp2 + assert villas_human.loads(smp1_str + smp2_str) == [smp1, smp2] diff --git a/python/villas/node/test_sample.py b/python/villas/node/test_sample.py new file mode 100644 index 000000000..4a723eb44 --- /dev/null +++ b/python/villas/node/test_sample.py @@ -0,0 +1,170 @@ +""" +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 +from villas.node.sample import Sample, Timestamp, Frame +from datetime import datetime +from cmath import sqrt + + +def test_timestamp_repr(): + ts = Timestamp(123456789, 123456789) + assert ts == eval(repr(ts)) + + +def test_timestamp_conversion(): + ts = Timestamp(123456789, 123456789) + + fl = 123456789.123456789 + fl_ts = Timestamp(123456789, 123456791) + assert ts.timestamp() == fl + assert fl_ts == Timestamp.fromtimestamp(fl) + + dt = datetime(1973, 11, 29, 22, 33, 9, 123457) + dt_ts = Timestamp(123456789, 123457000) + assert ts.datetime() == dt + assert dt_ts == Timestamp.fromdatetime(dt) + + +def test_timestamp_ordering(): + ts1 = Timestamp(123456789) + ts2 = Timestamp(123456789, 0) + ts3 = Timestamp(123456789, 123456789) + assert ts1 == ts2 + assert ts2 < ts3 + + +def test_timestamp_as_digest_bytes(): + ts = Timestamp(123456789, 123456789) + digest_bytes = bytes.fromhex("15cd5b070000000015cd5b0700000000") + assert ts._as_digest_bytes() == digest_bytes + + +def test_sample_repr(): + smp = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + assert smp == eval(repr(smp)) + + +def test_sample_ordering(): + smp1 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp3 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456791), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + assert smp1 == smp2 + assert smp2 < smp3 + + +def test_sample_as_digest_bytes(): + smp = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + digest_bytes_hex = "15cd5b070000000000000000000000000400000000000000000000000000f03f00000000000000400000000000000840012a00000000000000000000000000803f" # noqa: E501 + digest_bytes = bytes.fromhex(digest_bytes_hex) + assert smp._as_digest_bytes() == digest_bytes, smp._as_digest_bytes().hex() + + +def test_frame_repr(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + frame = Frame([smp1, smp2]) + assert frame == eval(repr(frame)) + + +def test_frame_group(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp3 = Sample( + ts_origin=Timestamp(123456791), + ts_received=Timestamp(123456793), + sequence=6, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + frames = list(Frame.group([smp1, smp2, smp3])) + assert len(frames) == 2 + assert list(map(len, frames)) == [2, 1] + assert frames == [[smp1, smp2], [smp3]] + + +def test_frame_digest(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + digest = bytes.fromhex( + "a573e3b0953a1e4f69addf631d6229bb714d263b4f362f0847e96c3838c83217" + ) # noqa: E501 + assert Frame([smp1, smp2]).digest("sha256") == digest From 396dd7642eeb33eac92ad040fa4009bed4e73a62 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Wed, 20 Sep 2023 16:17:38 +0200 Subject: [PATCH 078/100] ci: Check Python code with black and mypy Signed-off-by: Philipp Jungkamp --- .gitlab-ci.yml | 12 +++++++----- packaging/docker/Dockerfile.fedora | 13 ++++++++++--- python/setup.py | 8 -------- 3 files changed, 17 insertions(+), 16 deletions(-) delete mode 100644 python/setup.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 457df0b77..88bab1d25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -88,15 +88,17 @@ build:source: # Stage: test -test:flake8: +test:python: stage: test script: - - flake8 --ignore=E501 python/ + - cd python + - /venv/bin/black --check . + - /venv/bin/mypy . + - /venv/bin/flake8 . + - /venv/bin/pytest -v . image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} tags: - docker - needs: - - job: "build:source: [fedora]" test:cppcheck: stage: test @@ -217,7 +219,7 @@ pkg:docker: ARCH: arm64 TRIPLET: aarch64-linux-gnu DOCKER_FILE: packaging/docker/Dockerfile.debian-multiarch - + needs: [] # Stage: deploy diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 2d1ef0c0e..d28802f2c 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -27,7 +27,7 @@ RUN dnf -y install \ openssh-clients \ jq nmap-ncat \ iproute iproute-tc \ - python-pip \ + python python-devel python-pip \ gdb gdb-gdbserver \ cppcheck \ xmlto dblatex rubygem-asciidoctor \ @@ -37,8 +37,7 @@ RUN dnf -y install \ # Tools for debugging, coverage, profiling RUN pip install \ gcovr \ - protobuf \ - flake8 + protobuf # Dependencies RUN dnf -y install \ @@ -79,6 +78,12 @@ RUN ldconfig # Workaround for libnl3's search path for netem distributions RUN ln -s /usr/lib64/tc /usr/lib/tc +COPY ./python /python +RUN python -m venv /venv && \ + source /venv/bin/activate && \ + pip install /python[dev] && \ + rm -r /python + # Expose ports for HTTP and WebSocket frontend EXPOSE 80 EXPOSE 443 @@ -112,6 +117,8 @@ RUN --mount=type=cache,id=${DISTRO}-${FEDORA_VERSION}-${ARCH}-${REF},target=/vil make -j$(nproc) install && \ ldconfig +WORKDIR /villas + ENTRYPOINT ["villas"] LABEL \ diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 2d19d0d65..000000000 --- a/python/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -SPDX-License-Identifier: Apache-2.0 -""" # noqa: E501 - -from setuptools import setup - -setup() From 86bba9c5e8b28d90caad3cd9c529ea42d82ff9ce Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Thu, 21 Sep 2023 13:29:39 +0200 Subject: [PATCH 079/100] python: Always use UTC time when handling Timestamps Signed-off-by: Philipp Jungkamp --- python/villas/node/sample.py | 5 +++-- python/villas/node/test_sample.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/python/villas/node/sample.py b/python/villas/node/sample.py index 1c90b625f..6bb4dc2e4 100644 --- a/python/villas/node/sample.py +++ b/python/villas/node/sample.py @@ -8,7 +8,7 @@ SPDX-License-Identifier: Apache-2.0 import hashlib from ctypes import c_double, c_float, sizeof from dataclasses import dataclass, field -from datetime import datetime +from datetime import datetime, timezone from functools import total_ordering from sys import byteorder as native from typing import Iterable @@ -25,6 +25,7 @@ Signal = bool | int | float | complex class Timestamp: """ A VILLASnode timestamp. Based on the C struct timespec. + These timestamps are always UTC. """ seconds: int @@ -51,7 +52,7 @@ class Timestamp: return float(self) def datetime(self) -> datetime: - return datetime.fromtimestamp(self.timestamp()) + return datetime.fromtimestamp(self.timestamp(), tz=timezone.utc) def __float__(self): return float(self.seconds) + float(self.nanoseconds) * 1e-9 diff --git a/python/villas/node/test_sample.py b/python/villas/node/test_sample.py index 4a723eb44..8e2fbad78 100644 --- a/python/villas/node/test_sample.py +++ b/python/villas/node/test_sample.py @@ -4,7 +4,7 @@ SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH SPDX-License-Identifier: Apache-2.0 """ # noqa: E501 from villas.node.sample import Sample, Timestamp, Frame -from datetime import datetime +from datetime import datetime, timezone from cmath import sqrt @@ -21,7 +21,7 @@ def test_timestamp_conversion(): assert ts.timestamp() == fl assert fl_ts == Timestamp.fromtimestamp(fl) - dt = datetime(1973, 11, 29, 22, 33, 9, 123457) + dt = datetime(1973, 11, 29, 21, 33, 9, 123457, tzinfo=timezone.utc) dt_ts = Timestamp(123456789, 123457000) assert ts.datetime() == dt assert dt_ts == Timestamp.fromdatetime(dt) From 33cd6165df60c2b4e17d29649bd6416af3ff9fd9 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Mon, 25 Sep 2023 12:40:06 +0200 Subject: [PATCH 080/100] Fix fmt 10.0.0 related formatting errors. Signed-off-by: Philipp Jungkamp --- CMakeLists.txt | 1 - common | 2 +- fpga | 2 +- include/villas/node.hpp | 22 ++++--- include/villas/node_compat_type.hpp | 1 - include/villas/nodes/redis.hpp | 19 ++++++ include/villas/nodes/redis_helpers.hpp | 59 +++++++++---------- .../villas/nodes/webrtc/peer_connection.hpp | 28 +++++++++ include/villas/nodes/websocket.hpp | 15 +++-- include/villas/path.hpp | 16 +++-- lib/hooks/limit_rate.cpp | 2 +- lib/nodes/iec60870.cpp | 2 +- lib/nodes/infiniband.cpp | 6 +- lib/nodes/webrtc/peer_connection.cpp | 16 ----- lib/nodes/websocket.cpp | 2 +- 15 files changed, 120 insertions(+), 73 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4d4c7f49..3c64604d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,6 @@ find_package(OpenMP) find_package(Opal) find_package(IBVerbs) find_package(RDMACM) -find_package(spdlog) find_package(Etherlab) find_package(Lua) find_package(LibDataChannel) diff --git a/common b/common index 08fd24b85..785d94cac 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 08fd24b85ec4e5b18f370702eb129b4f1d1e4bca +Subproject commit 785d94caccc1e43853439cb6bd1e1c170fff42a9 diff --git a/fpga b/fpga index 1cac3fafd..4e59f0d04 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 1cac3fafde6ef3098a145f9d5d936a2dc6b7d7c0 +Subproject commit 4e59f0d04bfe5f741b5a1345c858fa0074190f5d diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 73c7dd491..80343e32b 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -7,8 +7,8 @@ #pragma once +#include #include -#include #include #include @@ -25,6 +25,10 @@ #include #include +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +#include +#endif + #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) #define WITH_NETEM #endif // LIBNL3_ROUTE_FOUND @@ -260,9 +264,7 @@ public: void setEnabled(bool en) { enabled = en; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Node &n) { + friend std::ostream &operator<<(std::ostream &os, const Node &n) { os << n.getName(); return os; @@ -317,9 +319,7 @@ public: virtual std::string getType() const { return "node"; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const NodeFactory &f) { + friend std::ostream &operator<<(std::ostream &os, const NodeFactory &f) { os << f.getName(); return os; @@ -366,3 +366,11 @@ public: } // namespace node } // namespace villas + +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +template <> +class fmt::formatter : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index 72877456b..86c47b553 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index ab9b43c4d..33710dcab 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -26,6 +26,25 @@ namespace node { enum class RedisMode { KEY, HASH, CHANNEL }; +inline std::ostream &operator<<(std::ostream &os, const enum villas::node::RedisMode &m) { + switch (m) { + case villas::node::RedisMode::KEY: + os << "key"; + break; + + case villas::node::RedisMode::HASH: + os << "hash"; + break; + + case villas::node::RedisMode::CHANNEL: + os << "channel"; + break; + } + + return os; +} + + class RedisConnection { public: diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index 701bde7ec..292c5f423 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -9,11 +9,14 @@ #include #include -#include +#include #include - #include +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +#include +#endif + namespace std { template @@ -52,7 +55,7 @@ template <> struct hash { namespace sw { namespace redis { -bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { +inline bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { #ifdef REDISPP_WITH_TLS return o1.enabled == o2.enabled && o1.cacert == o2.cacert && o1.cacertdir == o2.cacertdir && o1.cert == o2.cert && @@ -62,7 +65,7 @@ bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { #endif // REDISPP_WITH_TLS } -bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { +inline bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { return o1.type == o2.type && o1.host == o2.host && o1.port == o2.port && o1.path == o2.path && o1.user == o2.user && o1.password == o2.password && o1.db == o2.db && @@ -72,8 +75,8 @@ bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { } #ifdef REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const tls::TlsOptions &t) { +namespace tls { +std::ostream &operator<<(std::ostream &os, const TlsOptions &t) { os << "tls.enabled=" << (t.enabled ? "yes" : "no"); if (t.enabled) { @@ -95,10 +98,10 @@ OStream &operator<<(OStream &os, const tls::TlsOptions &t) { return os; } +} #endif // REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const ConnectionType &t) { +inline std::ostream &operator<<(std::ostream &os, const ConnectionType &t) { switch (t) { case ConnectionType::TCP: os << "tcp"; @@ -112,8 +115,7 @@ OStream &operator<<(OStream &os, const ConnectionType &t) { return os; } -template -OStream &operator<<(OStream &os, const ConnectionOptions &o) { +inline std::ostream &operator<<(std::ostream &os, const ConnectionOptions &o) { os << "type=" << o.type; switch (o.type) { @@ -139,36 +141,31 @@ OStream &operator<<(OStream &os, const ConnectionOptions &o) { } // namespace redis } // namespace sw -template -OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) { - switch (m) { - case villas::node::RedisMode::KEY: - os << "key"; - break; - - case villas::node::RedisMode::HASH: - os << "hash"; - break; - - case villas::node::RedisMode::CHANNEL: - os << "channel"; - break; - } - - return os; -} - namespace villas { namespace node { #ifdef REDISPP_WITH_URI -sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { +inline sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { auto u = sw::redis::Uri{uri}; return u.connection_options(); } #else -sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { +inline sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { return sw::redis::ConnectionOptions{uri}; } #endif } // namespace node } // namespace villas + +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#ifdef REDISPP_WITH_TLS +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif +#endif diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index 26fb62d74..47f246413 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -9,7 +9,9 @@ #pragma once +#include #include +#include #include #include @@ -17,6 +19,32 @@ #include #include +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +#include +#endif + +/* + * libdatachannel defines the operator<< overloads required to format + * rtc::PeerConnection::State and similar in the global namespace. + * But C++ ADL based overload set construction does not find these operators, + * if these are invoked in the spdlog/fmt libraries. + * + * See this issue for a short explaination of ADL errors: + * https://github.com/gabime/spdlog/issues/1227#issuecomment-532009129 + * + * Adding the global ::operator<< overload set to the namespace rtc where + * the data structures are defined, allows ADL to pick these up in spdlog/fmt. + */ +namespace rtc { +using ::operator<<; +} + +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif + namespace villas { namespace node { namespace webrtc { diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index d7f91471e..d3791399e 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include @@ -19,6 +18,10 @@ #include #include +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +#include +#endif + // Forward declarations struct lws; @@ -75,9 +78,7 @@ struct websocket_connection { *send; // A buffer for constructing messages before calling lws_write() } buffers; - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, + friend std::ostream &operator<<(std::ostream &os, const struct websocket_connection &c) { if (c.wsi) { char name[128]; @@ -133,3 +134,9 @@ int websocket_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas + +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 90e06b499..b4fc97b33 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -26,9 +25,12 @@ #include #include #include - #include +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +#include +#endif + // Forward declarations struct pollfd; @@ -99,9 +101,7 @@ public: std::bitset received; // A mask of PathSources for which we already received samples. - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Path &p) { + friend std::ostream &operator<<(std::ostream &os, const Path &p) { if (p.sources.size() > 1) os << "[ "; @@ -185,3 +185,9 @@ public: } // namespace node } // namespace villas + +#ifndef FMT_LEGACY_OSTREAM_FORMATTER +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif diff --git a/lib/hooks/limit_rate.cpp b/lib/hooks/limit_rate.cpp index 80cf00b22..65075e06b 100644 --- a/lib/hooks/limit_rate.cpp +++ b/lib/hooks/limit_rate.cpp @@ -39,7 +39,7 @@ void LimitRateHook::parse(json_t *json) { mode = LIMIT_RATE_LOCAL; else throw ConfigError(json, "node-config-hook-limit_rate-mode", - "Invalid value '{}' for setting 'mode'", mode); + "Invalid value '{}' for setting 'mode'", m); } deadtime = 1.0 / rate; diff --git a/lib/nodes/iec60870.cpp b/lib/nodes/iec60870.cpp index a05ee4890..87f9cbbdc 100644 --- a/lib/nodes/iec60870.cpp +++ b/lib/nodes/iec60870.cpp @@ -576,7 +576,7 @@ bool SlaveNode::onInterrogation(IMasterConnection connection, CS101_ASDU asdu, bool SlaveNode::onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept { - logger->warn("Ignoring ASDU type {}", CS101_ASDU_getTypeID(asdu)); + logger->warn("Ignoring ASDU type {}", (int)CS101_ASDU_getTypeID(asdu)); return true; } diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index 032d7f864..cfbc352c4 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -577,7 +577,7 @@ static void *ib_rdma_cm_event_thread(void *ctx) { break; default: - throw RuntimeError("Unknown event occurred: {}", event->event); + throw RuntimeError("Unknown event occurred: {}", (int)event->event); } rdma_ack_cm_event(event); @@ -836,7 +836,7 @@ int villas::node::ib_read(NodeCompat *n, struct Sample *const smps[], n->logger->debug("Received IBV_WC_WR_FLUSH_ERR (ib_read). Ignore it."); else if (wc[j].status != IBV_WC_SUCCESS) n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[j].status); + (int)wc[j].status); /* 32 byte of meta data is always transferred. We should substract it. * Furthermore, in case of an unreliable connection, a 40 byte @@ -987,7 +987,7 @@ int villas::node::ib_write(NodeCompat *n, struct Sample *const smps[], for (int i = 0; i < ret; i++) { if (wc[i].status != IBV_WC_SUCCESS && wc[i].status != IBV_WC_WR_FLUSH_ERR) n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[i].status); + (int)wc[i].status); // TODO: fix release logic // smps[*release] = (struct Sample *) (wc[i].wr_id); diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index e32e58eef..3a5f3d383 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -24,22 +24,6 @@ using namespace villas; using namespace villas::node; using namespace villas::node::webrtc; -/* - * libdatachannel defines the operator<< overloads required to format - * rtc::PeerConnection::State and similar in the global namespace. - * But C++ ADL based overload set construction does not find these operators, - * if these are invoked in the spdlog/fmt libraries. - * - * See this issue for a short explaination of ADL errors: - * https://github.com/gabime/spdlog/issues/1227#issuecomment-532009129 - * - * Adding the global ::operator<< overload set to the namespace rtc where - * the data structures are defined, allows ADL to pick these up in spdlog/fmt. - */ -namespace rtc { -using ::operator<<; -} - PeerConnection::PeerConnection(const std::string &server, const std::string &session, const std::string &peer, diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index 3520cd8e9..4fa92b851 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -124,7 +124,7 @@ static void websocket_connection_close(struct websocket_connection *c, c->node->logger->debug( "Closing WebSocket connection with {}: status={}, reason={}", - c->toString(), status, reason); + c->toString(), (int)status, reason); c->state = websocket_connection::State::CLOSED; } From b1e9407f8368f6f81c2b5bbf035814df9f5283e2 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Mon, 25 Sep 2023 12:40:55 +0200 Subject: [PATCH 081/100] packaging-nix: Update inputs Signed-off-by: Philipp Jungkamp --- CMakeLists.txt | 6 ----- common | 2 +- fpga | 2 +- include/villas/node.hpp | 6 +---- include/villas/nodes/redis_helpers.hpp | 5 +--- .../villas/nodes/webrtc/peer_connection.hpp | 8 ++---- include/villas/nodes/websocket.hpp | 7 ++--- include/villas/path.hpp | 7 ++--- lib/nodes/webrtc/peer_connection.cpp | 1 - packaging/nix/flake.lock | 26 +++++++++---------- 10 files changed, 23 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c64604d9..a51f53e45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,12 +76,6 @@ find_package(Etherlab) find_package(Lua) find_package(LibDataChannel) -# For compat between libfmt 8 and 9 -add_compile_definitions(FMT_DEPRECATED_OSTREAM) - -# For compat between libfmt 8 and 9 -add_compile_definitions(FMT_DEPRECATED_OSTREAM) - # Check for tools find_program(PASTE NAMES paste) if(NOT PASTE) diff --git a/common b/common index 785d94cac..b33fe9679 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 785d94caccc1e43853439cb6bd1e1c170fff42a9 +Subproject commit b33fe9679c1e1b6c79cd115bfd6b9bb224575068 diff --git a/fpga b/fpga index 4e59f0d04..58482eb95 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 4e59f0d04bfe5f741b5a1345c858fa0074190f5d +Subproject commit 58482eb95fdb8ed713e575b2213022fc06a87ccb diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 80343e32b..c920adc49 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -9,8 +9,8 @@ #include #include +#include #include - #include #include #include @@ -25,10 +25,6 @@ #include #include -#ifndef FMT_LEGACY_OSTREAM_FORMATTER -#include -#endif - #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) #define WITH_NETEM #endif // LIBNL3_ROUTE_FOUND diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index 292c5f423..3cc5b2a39 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -9,14 +9,11 @@ #include #include +#include #include #include #include -#ifndef FMT_LEGACY_OSTREAM_FORMATTER -#include -#endif - namespace std { template diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index 47f246413..26c180971 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -9,20 +9,16 @@ #pragma once -#include #include #include #include - +#include +#include #include #include #include #include -#ifndef FMT_LEGACY_OSTREAM_FORMATTER -#include -#endif - /* * libdatachannel defines the operator<< overloads required to format * rtc::PeerConnection::State and similar in the global namespace. diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index d3791399e..06698353d 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -8,9 +8,10 @@ #pragma once #include - +#include #include #include +#include #include #include #include @@ -18,10 +19,6 @@ #include #include -#ifndef FMT_LEGACY_OSTREAM_FORMATTER -#include -#endif - // Forward declarations struct lws; diff --git a/include/villas/path.hpp b/include/villas/path.hpp index b4fc97b33..81d46c024 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -11,10 +11,11 @@ #include #include +#include #include - #include #include +#include #include #include #include @@ -27,10 +28,6 @@ #include #include -#ifndef FMT_LEGACY_OSTREAM_FORMATTER -#include -#endif - // Forward declarations struct pollfd; diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index 3a5f3d383..edbba8a09 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -13,7 +13,6 @@ #include #include #include - #include #include #include diff --git a/packaging/nix/flake.lock b/packaging/nix/flake.lock index 91713f0fc..a8e9e59c9 100644 --- a/packaging/nix/flake.lock +++ b/packaging/nix/flake.lock @@ -3,11 +3,11 @@ "common": { "flake": false, "locked": { - "lastModified": 1688124353, - "narHash": "sha256-TPupRVaYV/Rxpj2BHjnEeSXZOVRKhnFtG1fdqLxVWcY=", + "lastModified": 1695284846, + "narHash": "sha256-lAHSjPGKr8JMIjsPGVp7W4FQmkL4OzKZ/fzyi8a+3hk=", "owner": "VILLASframework", "repo": "common", - "rev": "120312e938dc298b4dc13792e1acf7510190bbf4", + "rev": "db72389184a5db513c701073d0e02f157ec17ddb", "type": "github" }, "original": { @@ -19,11 +19,11 @@ "ethercat": { "flake": false, "locked": { - "lastModified": 1689851599, - "narHash": "sha256-r829UW4ziY+QUxqjb2j2Bo+xJeUNWn6WiSRK3Gly2Zo=", + "lastModified": 1694079333, + "narHash": "sha256-6F3zBhnU4CFpiO+Cnbd6ecUuiGH/KUntpPfuSYZ+rAI=", "owner": "etherlab.org", "repo": "ethercat", - "rev": "c8a512ac077f2ab51bb072bfbef1a687f9f1c090", + "rev": "722b2d607c4fc004ebf5204aaede0059c02274f4", "type": "gitlab" }, "original": { @@ -36,11 +36,11 @@ "fpga": { "flake": false, "locked": { - "lastModified": 1690302379, - "narHash": "sha256-u2u4CUffhA9jxtuk4HokqlmyDQGNz4+LOEJ5Z9DhedU=", + "lastModified": 1694165718, + "narHash": "sha256-Eymswj0QN1cBxtxtjDiAg4JtxlZB7j9AkW3RwchaNMA=", "ref": "refs/heads/master", - "rev": "1cac3fafde6ef3098a145f9d5d936a2dc6b7d7c0", - "revCount": 532, + "rev": "47553b8c05e7aabdee5f07d0ba985ef1db28dcd4", + "revCount": 534, "submodules": true, "type": "git", "url": "https://github.com/VILLASframework/fpga.git" @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692254348, - "narHash": "sha256-CyRMA7Rap1X65k4p/uoaLXhbnn+PZvwxNHSeLuiQ9ss=", + "lastModified": 1695628330, + "narHash": "sha256-U9ssZ3/Yw3JAq7j0XzCpSbXxtIoC53QmWoXj0wPS47g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5353604b0affde24dcd75e59d0d22342b1758cfb", + "rev": "d35b5bf9c75b72e54dcaf7b24964a794d2ce8edf", "type": "github" }, "original": { From 9adf7931f19dabe697587d27abed1fdfd6fc53d3 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Mon, 25 Sep 2023 17:45:11 +0200 Subject: [PATCH 082/100] src: Suppress cppcheck false positive Signed-off-by: Philipp Jungkamp --- src/villas-pipe.cpp | 6 ++++++ src/villas-signal.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index 14d575e46..ee42a9e7b 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -51,6 +51,9 @@ protected: int count; public: + // TODO: Here seems to be a cppcheck false positive in the CI. + // Try to remove this comment as cppcheck is being updated. + // cppcheck-suppress uninitMemberVar PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) : node(n), formatter(fmt), stop(false), enabled(en), limit(lim), count(0) { @@ -215,6 +218,9 @@ public: class Pipe : public Tool { public: + // TODO: Here seems to be a cppcheck false positive in the CI. + // Try to remove this comment as cppcheck is being updated. + // cppcheck-suppress uninitMemberVar Pipe(int argc, char *argv[]) : Tool(argc, argv, "pipe"), stop(false), formatter(), timeout(0), reverse(false), format("villas.human"), dtypes("64f"), diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index 2794333ce..5543474ae 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -32,6 +32,9 @@ namespace tools { class Signal : public Tool { public: + // TODO: Here seems to be a cppcheck false positive in the CI. + // Try to remove this comment as cppcheck is being updated. + // cppcheck-suppress uninitMemberVar Signal(int argc, char *argv[]) : Tool(argc, argv, "signal"), stop(false), node(), formatter(nullptr), pool(), format("villas.human") { From b90c5d9c77bfce2f204f98c0afcd8b763d64e857 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 26 Sep 2023 17:30:02 +0200 Subject: [PATCH 083/100] Update submodules Signed-off-by: Philipp Jungkamp --- common | 2 +- fpga | 2 +- packaging/nix/flake.lock | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common b/common index b33fe9679..cd74015a0 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit b33fe9679c1e1b6c79cd115bfd6b9bb224575068 +Subproject commit cd74015a05d51a0a198dae0f33e3b441d0f77acf diff --git a/fpga b/fpga index 58482eb95..662b8d626 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 58482eb95fdb8ed713e575b2213022fc06a87ccb +Subproject commit 662b8d626ca963996c1179283f9ff1acfbb14710 diff --git a/packaging/nix/flake.lock b/packaging/nix/flake.lock index a8e9e59c9..e2bece7ac 100644 --- a/packaging/nix/flake.lock +++ b/packaging/nix/flake.lock @@ -3,11 +3,11 @@ "common": { "flake": false, "locked": { - "lastModified": 1695284846, - "narHash": "sha256-lAHSjPGKr8JMIjsPGVp7W4FQmkL4OzKZ/fzyi8a+3hk=", + "lastModified": 1695740398, + "narHash": "sha256-F5ywFXtPx4xyZSKrLJhYp08KWLqocDXb9g2oaTZ+C+M=", "owner": "VILLASframework", "repo": "common", - "rev": "db72389184a5db513c701073d0e02f157ec17ddb", + "rev": "cd74015a05d51a0a198dae0f33e3b441d0f77acf", "type": "github" }, "original": { @@ -36,11 +36,11 @@ "fpga": { "flake": false, "locked": { - "lastModified": 1694165718, - "narHash": "sha256-Eymswj0QN1cBxtxtjDiAg4JtxlZB7j9AkW3RwchaNMA=", + "lastModified": 1695740431, + "narHash": "sha256-4UcupSWLGPRVhFfOWjVobnl9ItQAtTBWruYOSK6OxjA=", "ref": "refs/heads/master", - "rev": "47553b8c05e7aabdee5f07d0ba985ef1db28dcd4", - "revCount": 534, + "rev": "662b8d626ca963996c1179283f9ff1acfbb14710", + "revCount": 535, "submodules": true, "type": "git", "url": "https://github.com/VILLASframework/fpga.git" @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695628330, - "narHash": "sha256-U9ssZ3/Yw3JAq7j0XzCpSbXxtIoC53QmWoXj0wPS47g=", + "lastModified": 1695737284, + "narHash": "sha256-hOMEqtC1s1XW4dlBWlbq4Y7FyFMdQWyYXB4rHFFKNEI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d35b5bf9c75b72e54dcaf7b24964a794d2ce8edf", + "rev": "5f8943db1929bcd4d3ceed9bc12cf70301298cac", "type": "github" }, "original": { From c3d991b23e6baa1089ddcb1baaa03179e05d5113 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 26 Sep 2023 17:28:02 +0200 Subject: [PATCH 084/100] python: Add digest-hook fifo format parsing Signed-off-by: Philipp Jungkamp --- python/villas/node/digest.py | 117 +++++++++++++++++++++++++++++ python/villas/node/formats.py | 2 +- python/villas/node/sample.py | 49 ------------ python/villas/node/test_digest.py | 111 +++++++++++++++++++++++++++ python/villas/node/test_formats.py | 6 +- python/villas/node/test_sample.py | 81 +------------------- 6 files changed, 237 insertions(+), 129 deletions(-) create mode 100644 python/villas/node/digest.py create mode 100644 python/villas/node/test_digest.py diff --git a/python/villas/node/digest.py b/python/villas/node/digest.py new file mode 100644 index 000000000..20c66f65e --- /dev/null +++ b/python/villas/node/digest.py @@ -0,0 +1,117 @@ +""" +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 + +import hashlib +from dataclasses import dataclass +from typing import Iterable + +from villas.node.sample import Sample, Timestamp + + +@dataclass +class Frame(list[Sample]): + """ + A frame VILLASnode of sample indicated by the new_frame flag. + """ + + def __init__(self, it: Iterable[Sample]): + super().__init__(it) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + def _raw_digest(self, algorithm) -> bytes: + hash = hashlib.new(algorithm) + + for sample in self: + hash.update(sample._as_digest_bytes()) + + return hash.digest() + + def digest(self, algorithm: str) -> "Digest": + """ + A digest for a frame of samples that is comparable to the digest hook. + """ + + return Digest.fromframe(self, algorithm) + + def group(samples: list[Sample]) -> list["Frame"]: + """ + Group samples into Frames according to their new_frame flag. + """ + + samples.sort() + + if not samples: + return [] + + frames = [] + current_frame = Frame([samples[0]]) + for sample in samples[1:]: + if sample.new_frame: + frames.append(current_frame) + current_frame = Frame([sample]) + else: + current_frame.append(sample) + frames.append(current_frame) + + return frames + + +@dataclass +class Digest: + first: tuple[Timestamp, int] + last: tuple[Timestamp, int] + algorithm: str + bytes: bytes + + @staticmethod + def fromframe(frame: Frame, algorithm: str) -> "Digest": + first = frame[0] + last = frame[-1] + + def isnone(x): + return x is None + + if any(map(isnone, [first.ts_origin, last.ts_origin])): + raise ValueError("Missing origin timestamp for digest.") + + if any(map(isnone, [first.sequence, last.sequence])): + raise ValueError("Missing sequence number for digest.") + + return Digest( + first=(first.ts_origin, first.sequence), # type: ignore[arg-type] + last=(last.ts_origin, last.sequence), # type: ignore[arg-type] + algorithm=algorithm, + bytes=frame._raw_digest(algorithm), + ) + + @staticmethod + def _parse_timestamp(s: str) -> tuple[Timestamp, int]: + ts, seq = s.split("-") + sec, nsec = ts.split(".") + return Timestamp(seconds=int(sec), nanoseconds=int(nsec)), int(seq) + + @staticmethod + def parse(s: str) -> "Digest": + first, last, algorithm, digest = s.split(" ") + return Digest( + first=Digest._parse_timestamp(first), + last=Digest._parse_timestamp(last), + algorithm=algorithm, + bytes=bytes.fromhex(digest), + ) + + @staticmethod + def _dump_timestamp(timestamp: Timestamp, sequence: int) -> str: + return f"{timestamp.seconds}.{timestamp.nanoseconds}-{sequence}" + + def dump(self) -> str: + first = Digest._dump_timestamp(*self.first) + last = Digest._dump_timestamp(*self.last) + algorithm = self.algorithm + digest = self.bytes.hex().upper() + return f"{first} {last} {algorithm} {digest}" diff --git a/python/villas/node/formats.py b/python/villas/node/formats.py index eefb3d4ce..3371ba8de 100644 --- a/python/villas/node/formats.py +++ b/python/villas/node/formats.py @@ -9,7 +9,7 @@ from dataclasses import dataclass, field from itertools import groupby from typing import Iterable -from villas.node.sample import Sample, Timestamp, Signal +from villas.node.sample import Sample, Signal, Timestamp class SignalList(list[type]): diff --git a/python/villas/node/sample.py b/python/villas/node/sample.py index 6bb4dc2e4..d0cbd519d 100644 --- a/python/villas/node/sample.py +++ b/python/villas/node/sample.py @@ -5,13 +5,11 @@ SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Syst SPDX-License-Identifier: Apache-2.0 """ # noqa: E501 -import hashlib from ctypes import c_double, c_float, sizeof from dataclasses import dataclass, field from datetime import datetime, timezone from functools import total_ordering from sys import byteorder as native -from typing import Iterable assert sizeof(c_float) == 4 assert sizeof(c_double) == 8 @@ -133,50 +131,3 @@ class Sample: ] + list(map(signal_to_bytes, self.data)) ) - - -@dataclass -class Frame(list[Sample]): - """ - A frame VILLASnode of sample indicated by the new_frame flag. - """ - - def __init__(self, it: Iterable[Sample]): - super().__init__(it) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({super().__repr__()})" - - def digest(self, algorithm: str) -> bytes: - """ - A digest for a frame of samples that is comparable to the digest hook. - """ - - hash = hashlib.new(algorithm) - - for sample in self: - hash.update(sample._as_digest_bytes()) - - return hash.digest() - - def group(samples: list[Sample]) -> list["Frame"]: - """ - Group samples into Frames according to their new_frame flag. - """ - - samples.sort() - - if not samples: - return [] - - frames = [] - current_frame = Frame([samples[0]]) - for sample in samples[1:]: - if sample.new_frame: - frames.append(current_frame) - current_frame = Frame([sample]) - else: - current_frame.append(sample) - frames.append(current_frame) - - return frames diff --git a/python/villas/node/test_digest.py b/python/villas/node/test_digest.py new file mode 100644 index 000000000..924564fa4 --- /dev/null +++ b/python/villas/node/test_digest.py @@ -0,0 +1,111 @@ +""" +Author: Philipp Jungkamp +SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH +SPDX-License-Identifier: Apache-2.0 +""" # noqa: E501 + +from cmath import sqrt + +from villas.node.digest import Digest, Frame +from villas.node.sample import Sample, Timestamp + + +def test_frame_repr(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + frame = Frame([smp1, smp2]) + assert frame == eval(repr(frame)) + + +def test_frame_group(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp3 = Sample( + ts_origin=Timestamp(123456791), + ts_received=Timestamp(123456793), + sequence=6, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + frames = list(Frame.group([smp1, smp2, smp3])) + assert len(frames) == 2 + assert list(map(len, frames)) == [2, 1] + assert frames == [[smp1, smp2], [smp3]] + + +def test_digest_fromframe(): + smp1 = Sample( + ts_origin=Timestamp(123456780), + ts_received=Timestamp(123456781), + sequence=4, + new_frame=True, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + smp2 = Sample( + ts_origin=Timestamp(123456789), + ts_received=Timestamp(123456790), + sequence=5, + new_frame=False, + data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], + ) + + algorithm = "sha256" + + digest_hex = ( + "a573e3b0953a1e4f69addf631d6229bb714d263b4f362f0847e96c3838c83217" # noqa: E501 + ) + + digest = Digest( + first=(Timestamp(123456780), 4), + last=(Timestamp(123456789), 5), + algorithm=algorithm, + bytes=bytes.fromhex(digest_hex), + ) + + assert Frame([smp1, smp2]).digest(algorithm) == digest + + +def test_digest(): + digest_str = "1695904705.856457323-0 1695904709.956060462-41 sha256 8E49482DDDAFF6E3B7411D7D20CA338002126FE109EC1BA5932C02FC5E7EFD23" # noqa: E501 + + digest = Digest( + first=(Timestamp(1695904705, 856457323), 0), + last=(Timestamp(1695904709, 956060462), 41), + algorithm="sha256", + bytes=bytes.fromhex( + "8E49482DDDAFF6E3B7411D7D20CA338002126FE109EC1BA5932C02FC5E7EFD23" + ), # noqa: E501 + ) + + assert Digest.parse(digest_str) == digest + assert digest_str == digest.dump() diff --git a/python/villas/node/test_formats.py b/python/villas/node/test_formats.py index 2b2e9fb5c..45b88b629 100644 --- a/python/villas/node/test_formats.py +++ b/python/villas/node/test_formats.py @@ -3,10 +3,12 @@ Author: Philipp Jungkamp SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH SPDX-License-Identifier: Apache-2.0 """ # noqa: E501 -from villas.node.sample import Sample, Timestamp -from villas.node.formats import SignalList, VillasHuman + from cmath import sqrt +from villas.node.formats import SignalList, VillasHuman +from villas.node.sample import Sample, Timestamp + def test_signal_list_repr(): signal_list = SignalList("21fb2ic") diff --git a/python/villas/node/test_sample.py b/python/villas/node/test_sample.py index 8e2fbad78..e2f1dfb86 100644 --- a/python/villas/node/test_sample.py +++ b/python/villas/node/test_sample.py @@ -3,9 +3,11 @@ Author: Philipp Jungkamp SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH SPDX-License-Identifier: Apache-2.0 """ # noqa: E501 -from villas.node.sample import Sample, Timestamp, Frame -from datetime import datetime, timezone + from cmath import sqrt +from datetime import datetime, timezone + +from villas.node.sample import Sample, Timestamp def test_timestamp_repr(): @@ -93,78 +95,3 @@ def test_sample_as_digest_bytes(): digest_bytes_hex = "15cd5b070000000000000000000000000400000000000000000000000000f03f00000000000000400000000000000840012a00000000000000000000000000803f" # noqa: E501 digest_bytes = bytes.fromhex(digest_bytes_hex) assert smp._as_digest_bytes() == digest_bytes, smp._as_digest_bytes().hex() - - -def test_frame_repr(): - smp1 = Sample( - ts_origin=Timestamp(123456780), - ts_received=Timestamp(123456781), - sequence=4, - new_frame=True, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - smp2 = Sample( - ts_origin=Timestamp(123456789), - ts_received=Timestamp(123456790), - sequence=5, - new_frame=False, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - frame = Frame([smp1, smp2]) - assert frame == eval(repr(frame)) - - -def test_frame_group(): - smp1 = Sample( - ts_origin=Timestamp(123456780), - ts_received=Timestamp(123456781), - sequence=4, - new_frame=True, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - smp2 = Sample( - ts_origin=Timestamp(123456789), - ts_received=Timestamp(123456790), - sequence=5, - new_frame=False, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - smp3 = Sample( - ts_origin=Timestamp(123456791), - ts_received=Timestamp(123456793), - sequence=6, - new_frame=True, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - frames = list(Frame.group([smp1, smp2, smp3])) - assert len(frames) == 2 - assert list(map(len, frames)) == [2, 1] - assert frames == [[smp1, smp2], [smp3]] - - -def test_frame_digest(): - smp1 = Sample( - ts_origin=Timestamp(123456780), - ts_received=Timestamp(123456781), - sequence=4, - new_frame=True, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - smp2 = Sample( - ts_origin=Timestamp(123456789), - ts_received=Timestamp(123456790), - sequence=5, - new_frame=False, - data=[1.0, 2.0, 3.0, True, 42, sqrt(complex(-1))], - ) - - digest = bytes.fromhex( - "a573e3b0953a1e4f69addf631d6229bb714d263b4f362f0847e96c3838c83217" - ) # noqa: E501 - assert Frame([smp1, smp2]).digest("sha256") == digest From f09e6e909b5afa22a5d7d395861004c3bbc14fd9 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Tue, 31 Oct 2023 15:53:42 +0100 Subject: [PATCH 085/100] fix possible segfault due to non-functional range check with unsigned int Signed-off-by: Niklas Eiling --- lib/node.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/node.cpp b/lib/node.cpp index 483573e9a..f55789fe0 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -310,16 +310,17 @@ int Node::write(struct Sample *smps[], unsigned cnt) { #ifdef WITH_HOOKS // Run write hooks - cnt = out.hooks.process(smps, cnt); - if (cnt <= 0) - return cnt; + int hook_cnt = out.hooks.process(smps, cnt); + if (hook_cnt <= 0) + return hook_cnt; + cnt = hook_cnt; #endif // WITH_HOOKS vect = getFactory()->getVectorize(); if (!vect) vect = cnt; - while (cnt - nsent > 0) { + while (cnt > static_cast(nsent)) { tosend = MIN(cnt - nsent, vect); sent = _write(&smps[nsent], tosend); if (sent < 0) From 18aa0c8862b60b7f9f1552d14e9733c6e18a429c Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Tue, 12 Dec 2023 14:15:55 +0100 Subject: [PATCH 086/100] rework fpga node type The various changes in fpga require a rewrite of the fpga node type. To allow relative paths for the fpga config file, Config and SuperNode had to be modified so they store the path of the main config file. The syntax of the fpga node type configuration has changed - the example config in etc has been modified accordingly. Signed-off-by: Niklas Eiling --- common | 2 +- etc/examples/nodes/fpga.conf | 41 ++--- fpga | 2 +- include/villas/config_class.hpp | 4 + include/villas/nodes/fpga.hpp | 59 ++++---- include/villas/super_node.hpp | 2 + lib/config.cpp | 3 +- lib/nodes/fpga.cpp | 261 +++++++++++++++----------------- 8 files changed, 176 insertions(+), 198 deletions(-) diff --git a/common b/common index cd74015a0..0cb6cd23c 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit cd74015a05d51a0a198dae0f33e3b441d0f77acf +Subproject commit 0cb6cd23caacdd504753fd7f32e0a606d1b964f3 diff --git a/etc/examples/nodes/fpga.conf b/etc/examples/nodes/fpga.conf index 56a1e1ac3..e7ba7b1a3 100644 --- a/etc/examples/nodes/fpga.conf +++ b/etc/examples/nodes/fpga.conf @@ -7,44 +7,27 @@ logging = { fpgas = { vc707 = { - # Card identification - id = "10ee:7021" - # slot = "88:00.0" - - do_reset = true - - ips = "/global/projects/villas/fpga/software/etc/vc707-xbar-pcie/vc707-xbar-pcie.json" - - paths = ( - { - from = "aurora_8b10b_ch2" - to = "aurora_8b10b_ch3" - - reverse = true - } - ) + interface = "pcie", + id = "10ee:7021", + slot = "0000:88:00.0", + do_reset = true, + ips = "../../../fpga/etc/vc707-xbar-pcie/vc707-xbar-pcie.json", + polling = false, } } nodes = { - dma_0 = { + fpga_0 = { type = "fpga", - fpga = "vc707" - target = "" - - datamover = "dma_0" - use_irqs = false + card = "vc707" + connect = ["0->3", "3->dma", "0<-dma"] } } paths = ( { - in = "dma_0" - - hooks = ( - { - type = "print" - } - ) + in = "fpga_0" + out = "fpga_0" + hooks = ({ type = "print"}) } ) diff --git a/fpga b/fpga index 662b8d626..ac9592299 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 662b8d626ca963996c1179283f9ff1acfbb14710 +Subproject commit ac959229978fa3d433bd982a81c279d35e310245 diff --git a/include/villas/config_class.hpp b/include/villas/config_class.hpp index 60acdc251..a499fcab7 100644 --- a/include/villas/config_class.hpp +++ b/include/villas/config_class.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -32,6 +33,7 @@ protected: Logger logger; std::list includeDirectories; + std::filesystem::path configPath; // Check if file exists on local system. static bool isLocalFile(const std::string &uri) { @@ -87,6 +89,8 @@ public: json_t *load(const std::string &u, bool resolveIncludes = true, bool resolveEnvVars = true); + + std::filesystem::path &getConfigPath() { return configPath; } }; } // namespace node diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 7a25dbf7f..da9bdebd2 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -1,7 +1,9 @@ /* Communicate with VILLASfpga Xilinx FPGA boards. * * Author: Steffen Vogel + * Author: Niklas Eiling * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-FileCopyrightText: 2023 Niklas Eiling * SPDX-License-Identifier: Apache-2.0 */ @@ -20,48 +22,42 @@ namespace villas { namespace node { -#define FPGA_DMA_VLNV -#define FPGA_AURORA_VLNV "acs.eonerc.rwth-aachen.de:user:aurora_axis:" - class FpgaNode : public Node { + enum InterfaceType { PCIE, PLATFORM }; + protected: - int irqFd; - int coalesce; - bool polling; - - std::shared_ptr card; - - std::shared_ptr dma; - std::shared_ptr intf; - - std::unique_ptr blockRx; - std::unique_ptr blockTx; - - // Config only + // Settings std::string cardName; - std::string intfName; - std::string dmaName; + std::list connectStrings; -protected: - virtual int _read(Sample *smps[], unsigned cnt); + // State + std::shared_ptr card; + std::shared_ptr dma; + std::shared_ptr blockRx[2]; + std::shared_ptr blockTx; - virtual int _write(Sample *smps[], unsigned cnt); + // Non-public methods + virtual int _read(Sample *smps[], unsigned cnt) override; + + virtual int _write(Sample *smps[], unsigned cnt) override; public: FpgaNode(const uuid_t &id = {}, const std::string &name = ""); virtual ~FpgaNode(); - virtual int parse(json_t *json); + virtual int prepare() override; - virtual const std::string &getDetails(); + virtual int parse(json_t *json) override; - virtual int check(); + virtual int check() override; - virtual int prepare(); + virtual int start() override; - virtual std::vector getPollFDs(); + virtual std::vector getPollFDs() override; + + virtual const std::string &getDetails() override; }; class FpgaNodeFactory : public NodeFactory { @@ -69,7 +65,8 @@ class FpgaNodeFactory : public NodeFactory { public: using NodeFactory::NodeFactory; - virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + virtual Node *make(const uuid_t &id = {}, + const std::string &nme = "") override { auto *n = new FpgaNode(id, nme); init(n); @@ -77,17 +74,17 @@ public: return n; } - virtual int getFlags() const { + virtual int getFlags() const override { return (int)NodeFactory::Flags::SUPPORTS_READ | (int)NodeFactory::Flags::SUPPORTS_WRITE | (int)NodeFactory::Flags::SUPPORTS_POLL; } - virtual std::string getName() const { return "fpga"; } + virtual std::string getName() const override { return "fpga"; } - virtual std::string getDescription() const { return "VILLASfpga"; } + virtual std::string getDescription() const override { return "VILLASfpga"; } - virtual int start(SuperNode *sn); + virtual int start(SuperNode *sn) override; }; } // namespace node diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index 0bf2d4b60..861825d75 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -141,6 +141,8 @@ public: json_t *getConfig() { return config.root; } + std::filesystem::path &getConfigPath() { return config.getConfigPath(); } + std::string getConfigUri() const { return uri; } int getAffinity() const { return affinity; } diff --git a/lib/config.cpp b/lib/config.cpp index 66acc5205..45de082d2 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -72,13 +72,14 @@ json_t *Config::load(const std::string &u, bool resolveInc, FILE *Config::loadFromStdio() { logger->info("Reading configuration from standard input"); - + configPath = std::filesystem::current_path(); return stdin; } FILE *Config::loadFromLocalFile(const std::string &u) { logger->info("Reading configuration from local file: {}", u); + configPath = u; FILE *f = fopen(u.c_str(), "r"); if (!f) throw RuntimeError("Failed to open configuration from: {}", u); diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index 7f12d1382..bb7e12986 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -1,12 +1,10 @@ /* Communicate with VILLASfpga Xilinx FPGA boards. * - * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * Author: Niklas Eiling + * SPDX-FileCopyrightText: 2023 Niklas Eiling * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include #include @@ -16,16 +14,12 @@ #include #include -#include #include #include #include #include -#include -#include -#include -#include +#include using namespace villas; using namespace villas::node; @@ -33,20 +27,69 @@ using namespace villas::fpga; using namespace villas::utils; // Global state -static std::list> cards; -static std::map dmaMap; +static std::list> cards; -static std::shared_ptr pciDevices; static std::shared_ptr vfioContainer; -using namespace villas; -using namespace villas::node; - FpgaNode::FpgaNode(const uuid_t &id, const std::string &name) - : Node(id, name), irqFd(-1), coalesce(0), polling(true) {} + : Node(id, name), cardName(""), card(), dma(), blockRx(), blockTx() {} FpgaNode::~FpgaNode() {} +int FpgaNode::prepare() { + for (auto &fpgaCard : cards) { + if (fpgaCard->name == cardName) { + card = fpgaCard; + break; + } + } + if (card == nullptr) { + throw ConfigError(config, "node-config-fpga", + "There is no FPGA card with the name: {}", cardName); + } + + std::vector> aurora_channels; + for (int i = 0; i < 4; i++) { + auto name = fmt::format("aurora_8b10b_ch{}", i); + auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); + auto aurora = + std::dynamic_pointer_cast(card->lookupIp(id)); + if (aurora == nullptr) { + logger->error("No Aurora interface found on FPGA"); + return 1; + } + + aurora_channels.push_back(aurora); + } + + dma = std::dynamic_pointer_cast( + card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); + if (dma == nullptr) { + logger->error("No DMA found on FPGA "); + return 1; + } + + // Configure Crossbar switch + for (std::string str : connectStrings) { + const fpga::ConnectString parsedConnectString(str); + parsedConnectString.configCrossBar(dma, aurora_channels); + } + + auto &alloc = HostRam::getAllocator(); + + blockRx[0] = alloc.allocateBlock(0x200 * sizeof(float)); + blockRx[1] = alloc.allocateBlock(0x200 * sizeof(float)); + blockTx = alloc.allocateBlock(0x200 * sizeof(float)); + villas::MemoryAccessor memRx[] = {*(blockRx[0]), *(blockRx[1])}; + villas::MemoryAccessor memTx = *blockTx; + + dma->makeAccesibleFromVA(blockRx[0]); + dma->makeAccesibleFromVA(blockRx[1]); + dma->makeAccesibleFromVA(blockTx); + + return Node::prepare(); +} + int FpgaNode::parse(json_t *json) { int ret = Node::parse(json); if (ret) @@ -54,29 +97,28 @@ int FpgaNode::parse(json_t *json) { json_error_t err; - const char *card = nullptr; - const char *intf = nullptr; - const char *dma = nullptr; - int poll = polling; + const char *jsonCardName = nullptr; + json_t *jsonConnectStrings = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", - "card", &card, "interface", &intf, "dma", &dma, - "coalesce", &coalesce, "polling", &polling); - if (ret) + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o}", "card", &jsonCardName, + "connect", &jsonConnectStrings); + if (ret) { throw ConfigError(json, err, "node-config-fpga", "Failed to parse configuration of node {}", this->getName()); - - if (card) - cardName = card; - - if (intf) - intfName = intf; - - if (dma) - dmaName = dma; - - polling = poll; // cast int to bool + } + cardName = std::string(jsonCardName); + if (jsonConnectStrings != nullptr && json_is_array(jsonConnectStrings)) { + for (size_t i = 0; i < json_array_size(jsonConnectStrings); i++) { + json_t *jsonConnectString = json_array_get(jsonConnectStrings, i); + if (jsonConnectString == nullptr || !json_is_string(jsonConnectString)) { + throw ConfigError(jsonConnectString, "node-config-fpga", + "Failed to parse connect string"); + } + connectStrings.push_back( + std::string(json_string_value(jsonConnectString))); + } + } return 0; } @@ -85,9 +127,13 @@ const std::string &FpgaNode::getDetails() { if (details.empty()) { auto &name = card ? card->name : cardName; - details = - fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", name, - dma->getInstanceName(), polling ? "yes" : "no", coalesce); + const char *const delim = ", "; + + std::ostringstream imploded; + std::copy(connectStrings.begin(), connectStrings.end(), + std::ostream_iterator(imploded, delim)); + + details = fmt::format("fpga={}, connect={}", name, imploded.str()); } return details; @@ -95,136 +141,81 @@ const std::string &FpgaNode::getDetails() { int FpgaNode::check() { return 0; } -int FpgaNode::prepare() { - auto it = cardName.empty() - ? cards.begin() - : std::find_if(cards.begin(), cards.end(), - [this](std::shared_ptr c) { - return c->name == cardName; - }); - - if (it == cards.end()) - throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", - "Invalid FPGA card name: {}", cardName); - - card = *it; - - auto intfCore = intfName.empty() - ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) - : card->lookupIp(intfName); - if (!intfCore) - throw ConfigError(config, "node-config-fpga-interface", - "There is no interface IP with the name: {}", intfName); - - intf = std::dynamic_pointer_cast(intfCore); - if (!intf) - throw RuntimeError("The IP {} is not a interface", *intfCore); - - auto dmaCore = dmaName.empty() ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) - : card->lookupIp(dmaName); - if (!dmaCore) - throw ConfigError(config, "node-config-fpga-dma", - "There is no DMA IP with the name: {}", dmaName); - - dma = std::dynamic_pointer_cast(dmaCore); - if (!dma) - throw RuntimeError("The IP {} is not a DMA controller", *dmaCore); - - int ret = intf->connect(*(dma), true); - if (ret) - throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); - - auto &alloc = HostDmaRam::getAllocator(); - - const std::shared_ptr blockRx = - alloc.allocateBlock(0x100 * sizeof(float)); - const std::shared_ptr blockTx = - alloc.allocateBlock(0x100 * sizeof(float)); - villas::MemoryAccessor memRx = *blockRx; - villas::MemoryAccessor memTx = *blockTx; - - dma->makeAccesibleFromVA(blockRx); - dma->makeAccesibleFromVA(blockTx); - - // Show some debugging infos - auto &mm = MemoryManager::get(); - - dma->dump(); - intf->dump(); - mm.getGraph().dump(); - - return Node::prepare(); +int FpgaNode::start() { + // enque first read + dma->read(*(blockRx[0]), blockRx[0]->getSize()); + return Node::start(); } int FpgaNode::_read(Sample *smps[], unsigned cnt) { + static size_t cur = 0, next = 1; unsigned read; Sample *smp = smps[0]; assert(cnt == 1); - dma->read(*blockRx, blockRx->getSize()); // TODO: calc size - const size_t bytesRead = dma->readComplete().bytes; - read = bytesRead / sizeof(int32_t); + dma->read(*(blockRx[next]), blockRx[next]->getSize()); // TODO: calc size + auto c = dma->readComplete(); + read = c.bytes / sizeof(float); - auto mem = MemoryAccessor(*blockRx); + if (c.interrupts > 1) { + logger->warn("Missed {} interrupts", c.interrupts - 1); + } - for (unsigned i = 0; i < MIN(read, smp->capacity); i++) - smp->data[i].i = mem[i]; + auto mem = MemoryAccessor(*(blockRx[cur])); + + smp->length = 0; + for (unsigned i = 0; i < MIN(read, smp->capacity); i++) { + smp->data[i].f = static_cast(mem[i]); + smp->length++; + } + smp->flags = (int)SampleFlags::HAS_DATA; smp->signals = in.signals; + cur = next; + next = (next + 1) % (sizeof(blockRx) / sizeof(blockRx[0])); - return read; + return 1; } int FpgaNode::_write(Sample *smps[], unsigned cnt) { - int written; + unsigned int written; Sample *smp = smps[0]; - assert(cnt == 1); + assert(cnt == 1 && smps != nullptr && smps[0] != nullptr); - auto mem = MemoryAccessor(*blockTx); + auto mem = MemoryAccessor(*blockTx); - for (unsigned i = 0; i < smps[0]->length; i++) - mem[i] = smps[0]->data[i].i; + for (unsigned i = 0; i < smps[0]->length; i++) { + mem[i] = static_cast(smps[0]->data[i].f); + } - bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); + bool state = dma->write(*blockTx, smp->length * sizeof(float)); if (!state) return -1; - written = 0; // The number of samples written + written = dma->writeComplete().bytes / + sizeof(float); // The number of samples written - return written; + if (written != smp->length) { + logger->warn("Wrote {} samples, but {} were expected", written, + smp->length); + } + + return 1; } std::vector FpgaNode::getPollFDs() { - std::vector fds; - - if (!polling) - fds.push_back(irqFd); - - return fds; + return card->vfioDevice->getEventfdList(); } int FpgaNodeFactory::start(SuperNode *sn) { vfioContainer = std::make_shared(); - pciDevices = std::make_shared(); - // Get the FPGA card plugin - auto pcieCardPlugin = plugin::registry->lookup("pcie"); - if (!pcieCardPlugin) - throw RuntimeError("No FPGA PCIe plugin found"); - - json_t *json_cfg = sn->getConfig(); - json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); - if (!json_fpgas) - throw ConfigError(json_cfg, "node-config-fpgas", - "No section 'fpgas' found in config"); - - // Create all FPGA card instances using the corresponding plugin - auto piceCards = - fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); - - cards.splice(cards.end(), piceCards); + if (cards.empty()) { + std::filesystem::path searchPath = sn->getConfigPath().parent_path(); + createCards(sn->getConfig(), cards, searchPath); + } return NodeFactory::start(sn); } From 97a391c271625509c12d304f49704d2972ee520d Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Fri, 12 Jan 2024 12:05:45 +0100 Subject: [PATCH 087/100] update fpga submodule Signed-off-by: Niklas Eiling --- fpga | 2 +- lib/nodes/fpga.cpp | 27 ++++++++------------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/fpga b/fpga index ac9592299..6c6d30c40 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit ac959229978fa3d433bd982a81c279d35e310245 +Subproject commit 6c6d30c406769969cc91ea44015e55045ea0b94f diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index bb7e12986..db17507b3 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -19,6 +19,7 @@ #include #include +#include #include using namespace villas; @@ -48,31 +49,19 @@ int FpgaNode::prepare() { "There is no FPGA card with the name: {}", cardName); } - std::vector> aurora_channels; - for (int i = 0; i < 4; i++) { - auto name = fmt::format("aurora_8b10b_ch{}", i); - auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); - auto aurora = - std::dynamic_pointer_cast(card->lookupIp(id)); - if (aurora == nullptr) { - logger->error("No Aurora interface found on FPGA"); - return 1; - } + auto axisswitch = std::dynamic_pointer_cast( + card->lookupIp(fpga::Vlnv("xilinx.com:ip:axis_switch:"))); - aurora_channels.push_back(aurora); + for (auto ports : axisswitch->getMasterPorts()) { + logger->info("Port: {}, {}", ports.first, *ports.second); } - - dma = std::dynamic_pointer_cast( - card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); - if (dma == nullptr) { - logger->error("No DMA found on FPGA "); - return 1; + for (auto ports : axisswitch->getSlavePorts()) { + logger->info("Port: {}, {}", ports.first, *ports.second); } - // Configure Crossbar switch for (std::string str : connectStrings) { const fpga::ConnectString parsedConnectString(str); - parsedConnectString.configCrossBar(dma, aurora_channels); + parsedConnectString.configCrossBar(card); } auto &alloc = HostRam::getAllocator(); From 4ca9c88bd0dc6da9edb3d6374f2edd5ce018ff18 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Fri, 26 Jan 2024 13:09:19 +0100 Subject: [PATCH 088/100] fpga: add note about wrong cast Signed-off-by: Niklas Eiling --- fpga | 2 +- lib/nodes/fpga.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fpga b/fpga index 6c6d30c40..b21950751 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 6c6d30c406769969cc91ea44015e55045ea0b94f +Subproject commit b2195075150532dde85daac92f800dd58ec6c668 diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index db17507b3..d85486695 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -155,7 +155,8 @@ int FpgaNode::_read(Sample *smps[], unsigned cnt) { smp->length = 0; for (unsigned i = 0; i < MIN(read, smp->capacity); i++) { - smp->data[i].f = static_cast(mem[i]); + smp->data[i].f = + static_cast(mem[i]); //TODO: This is the wrong cast!!! smp->length++; } smp->flags = (int)SampleFlags::HAS_DATA; From eb450eb65006b570eed180600d7a3b086c5277df Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Wed, 7 Feb 2024 15:17:48 +0100 Subject: [PATCH 089/100] update common and fpga submodules Signed-off-by: Niklas Eiling --- common | 2 +- fpga | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common b/common index 0cb6cd23c..3a66d8ff6 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 0cb6cd23caacdd504753fd7f32e0a606d1b964f3 +Subproject commit 3a66d8ff657c0824138a03df0aca1b16c88d582a diff --git a/fpga b/fpga index b21950751..9138f0c9e 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit b2195075150532dde85daac92f800dd58ec6c668 +Subproject commit 9138f0c9ed19c5b4904505c6988e689be4f79474 From eeb933854cdaba6808af88dfb18223d358450432 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Wed, 7 Feb 2024 18:22:54 +0100 Subject: [PATCH 090/100] update fpga subrepo Signed-off-by: Niklas Eiling --- fpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga b/fpga index 9138f0c9e..d0c1fbb19 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 9138f0c9ed19c5b4904505c6988e689be4f79474 +Subproject commit d0c1fbb192e8df81da5b56a83586c153d0ece2d2 From f699179ef77acdbbb1920526a625ad4dc7ddfce9 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Thu, 8 Feb 2024 09:56:46 +0100 Subject: [PATCH 091/100] add docker tag to reuse step Signed-off-by: Niklas Eiling --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 88bab1d25..6eace4f4a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -171,6 +171,8 @@ test:reuse: image: name: fsfe/reuse:latest entrypoint: [""] + tags: + - docker script: - reuse lint From d544ab70bceaeafb379c18a418ecc7395efa6eb8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 8 Feb 2024 12:25:38 +0100 Subject: [PATCH 092/100] Fix typo in README Signed-off-by: Steffen Vogel --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 238f6f9e8..521b6e80e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ VILLASnode is a client/server application to connect simulation equipment and so - LabView, - and FPGA models -by using protcols such as: +by using protocols such as: - IEEE 802.2 Ethernet / IP / UDP, - ZeroMQ & nanomsg, From 2f15e151b40e51224b24a456de21063d23511347 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 8 Feb 2024 09:35:21 +0100 Subject: [PATCH 093/100] deps: Do now show Git warning about detached HEAD state Signed-off-by: Steffen Vogel --- packaging/deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/deps.sh b/packaging/deps.sh index 44ddebb81..130c96381 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -62,7 +62,7 @@ should_build() { ## Build configuration # Use shallow git clones to speed up downloads -GIT_OPTS+=" --depth=1" +GIT_OPTS+=" --depth=1 --config advice.detachedHead=false" # Install destination PREFIX=${PREFIX:-/usr/local} From 9b3a33f31b45456633a04c0bb94d19add5445f75 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 8 Feb 2024 09:34:41 +0100 Subject: [PATCH 094/100] Remove unused C++20 include which breaks build on C++17 compilers Signed-off-by: Steffen Vogel --- include/villas/nodes/modbus.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index e0f9b61c7..dcee555fc 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include #include From e30e361c3131a5ea5f4567fd652981e6183b55c5 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 13 Feb 2024 13:12:50 +0000 Subject: [PATCH 095/100] devcontainer: Do not use unsupported variable substitution Signed-off-by: Steffen Vogel --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7cdc83470..72b2dd9ef 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ "image": "registry.git.rwth-aachen.de/acs/public/villas/node/dev-vscode", // Uncomment to build the devcontainer locally // "build": { - // "dockerfile": "${workspaceFolder}/packaging/docker/Dockerfile.fedora", + // "dockerfile": "../packaging/docker/Dockerfile.fedora", // "target": "dev-vscode", // "context": ".." // }, From dd72179a35496743ea4e8257f76347254e407ac1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 13 Feb 2024 13:13:06 +0000 Subject: [PATCH 096/100] python: Fix formatting Signed-off-by: Steffen Vogel --- python/examples/Shmem_CIGRE_MV.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/examples/Shmem_CIGRE_MV.py b/python/examples/Shmem_CIGRE_MV.py index fc65c551b..3bfe69c91 100644 --- a/python/examples/Shmem_CIGRE_MV.py +++ b/python/examples/Shmem_CIGRE_MV.py @@ -3,6 +3,7 @@ Author: Steffen Vogel SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University SPDX-License-Identifier: Apache-2.0 """ # noqa: E501 + import time from villas.node.node import Node as VILLASnode From b4fcd0c5664da7738553520b5c9463df9ab3359b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 13 Feb 2024 13:13:21 +0000 Subject: [PATCH 097/100] decvontainer: Fix formatting Signed-off-by: Steffen Vogel --- .devcontainer/devcontainer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 72b2dd9ef..215a9e07b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,8 +13,11 @@ // "context": ".." // }, "remoteUser": "villas", - "runArgs": [ "--privileged", "--security-opt", "seccomp=unconfined"], - + "runArgs": [ + "--privileged", + "--security-opt", + "seccomp=unconfined" + ], "customizations": { "vscode": { "extensions": [ From 0be29ffcab87f3184b77d9ca41b89dae2ae730a2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 13 Feb 2024 13:14:39 +0000 Subject: [PATCH 098/100] python: Pin dependencies Signed-off-by: Steffen Vogel --- python/pyproject.toml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 65f4edc34..24c78d910 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -20,13 +20,16 @@ classifiers = [ 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 3', ] -dependencies = ['linuxfd', 'requests'] +dependencies = [ + 'linuxfd==1.5', + 'requests==2.31.0', +] optional-dependencies.dev = [ - 'black', - 'flake8', - 'mypy', - 'pytest', - 'types-requests', + 'black==24.2.0', + 'flake8==7.0.0', + 'mypy==1.8.0', + 'pytest==8.0.0', + 'types-requests==2.31.0.20240125', ] [project.urls] From c1410ef8a8547bd81f8ebb4b844ec0bd4c040068 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 8 Feb 2024 14:55:05 +0000 Subject: [PATCH 099/100] Fix formatting using clang-format Signed-off-by: Steffen Vogel --- include/villas/node.hpp | 4 ++-- include/villas/nodes/redis.hpp | 4 ++-- include/villas/nodes/redis_helpers.hpp | 13 ++++++++----- include/villas/nodes/rtp.hpp | 2 +- include/villas/nodes/webrtc/peer_connection.hpp | 2 +- include/villas/nodes/websocket.hpp | 4 ++-- include/villas/path.hpp | 7 +++---- include/villas/super_node.hpp | 4 +++- lib/api/response.cpp | 13 +++++++------ lib/hooks/lua.cpp | 2 +- lib/node_compat.cpp | 2 +- lib/nodes/opal.cpp | 2 +- lib/nodes/rtp.cpp | 4 ++-- lib/sample.cpp | 2 +- 14 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/villas/node.hpp b/include/villas/node.hpp index c920adc49..4c54eee06 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include #include #include #include @@ -266,7 +266,7 @@ public: return os; } - json_t *toJson() const; + virtual json_t *toJson() const; static bool isValidName(const std::string &name); diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index 33710dcab..b88872a5d 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -26,7 +26,8 @@ namespace node { enum class RedisMode { KEY, HASH, CHANNEL }; -inline std::ostream &operator<<(std::ostream &os, const enum villas::node::RedisMode &m) { +inline std::ostream &operator<<(std::ostream &os, + const enum villas::node::RedisMode &m) { switch (m) { case villas::node::RedisMode::KEY: os << "key"; @@ -44,7 +45,6 @@ inline std::ostream &operator<<(std::ostream &os, const enum villas::node::Redis return os; } - class RedisConnection { public: diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index 3cc5b2a39..0cef4d2aa 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -8,8 +8,8 @@ #pragma once #include -#include #include +#include #include #include #include @@ -62,7 +62,8 @@ inline bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { #endif // REDISPP_WITH_TLS } -inline bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { +inline bool operator==(const ConnectionOptions &o1, + const ConnectionOptions &o2) { return o1.type == o2.type && o1.host == o2.host && o1.port == o2.port && o1.path == o2.path && o1.user == o2.user && o1.password == o2.password && o1.db == o2.db && @@ -95,7 +96,7 @@ std::ostream &operator<<(std::ostream &os, const TlsOptions &t) { return os; } -} +} // namespace tls #endif // REDISPP_WITH_TLS inline std::ostream &operator<<(std::ostream &os, const ConnectionType &t) { @@ -141,12 +142,14 @@ inline std::ostream &operator<<(std::ostream &os, const ConnectionOptions &o) { namespace villas { namespace node { #ifdef REDISPP_WITH_URI -inline sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { +inline sw::redis::ConnectionOptions +make_redis_connection_options(char const *uri) { auto u = sw::redis::Uri{uri}; return u.connection_options(); } #else -inline sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { +inline sw::redis::ConnectionOptions +make_redis_connection_options(char const *uri) { return sw::redis::ConnectionOptions{uri}; } #endif diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index e5a44745a..919b82ca2 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -21,8 +21,8 @@ #include extern "C" { -#include #include +#include } namespace villas { diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index 26c180971..0d71e5144 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -9,10 +9,10 @@ #pragma once +#include #include #include #include -#include #include #include #include diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index 06698353d..aec7a4bfb 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include #include @@ -76,7 +76,7 @@ struct websocket_connection { } buffers; friend std::ostream &operator<<(std::ostream &os, - const struct websocket_connection &c) { + const struct websocket_connection &c) { if (c.wsi) { char name[128]; diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 81d46c024..d58b9a8da 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -9,14 +9,15 @@ #include +#include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include // Forward declarations struct pollfd; @@ -185,6 +185,5 @@ public: #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index 861825d75..709966938 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -129,7 +129,9 @@ public: const uuid_t &getUuid() const { return uuid; } - struct timespec getStartTime() const { return started; } + struct timespec getStartTime() const { + return started; + } #ifdef WITH_API Api *getApi() { return &api; } diff --git a/lib/api/response.cpp b/lib/api/response.cpp index 62914191e..4bb44e809 100644 --- a/lib/api/response.cpp +++ b/lib/api/response.cpp @@ -13,12 +13,13 @@ using namespace villas::node::api; Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) : session(s), logger(logging.get("api:response")), buffer(b), code(c), - contentType(ct), - headers{{"Server:", HTTP_USER_AGENT}, - {"Access-Control-Allow-Origin:", "*"}, - {"Access-Control-Allow-Methods:", "GET, POST, OPTIONS"}, - {"Access-Control-Allow-Headers:", "Content-Type"}, - {"Access-Control-Max-Age:", "86400"}} {} + contentType(ct), headers{ + {"Server:", HTTP_USER_AGENT}, + {"Access-Control-Allow-Origin:", "*"}, + {"Access-Control-Allow-Methods:", + "GET, POST, OPTIONS"}, + {"Access-Control-Allow-Headers:", "Content-Type"}, + {"Access-Control-Max-Age:", "86400"}} {} int Response::writeBody(struct lws *wsi) { int ret; diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index 6bf5875ae..d9e7c9518 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -10,9 +10,9 @@ #include extern "C" { +#include #include #include -#include }; #include diff --git a/lib/node_compat.cpp b/lib/node_compat.cpp index 589fde594..2537ea145 100644 --- a/lib/node_compat.cpp +++ b/lib/node_compat.cpp @@ -60,7 +60,7 @@ NodeCompat::~NodeCompat() { int ret __attribute__((unused)); ret = _vt->destroy ? _vt->destroy(this) : 0; - delete[] (char *)_vd; + delete[](char *) _vd; } int NodeCompat::prepare() { diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index d0d224ce4..d922ebf0b 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -24,9 +24,9 @@ extern "C" { /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ #define RTLAB -#include #include #include +#include } // Private static storage diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index 27de3c0e7..5722581de 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -15,12 +15,12 @@ #include extern "C" { -#include #include -#include #include #include +#include #include +#include #include #undef ALIGN_MASK } diff --git a/lib/sample.cpp b/lib/sample.cpp index c8d81f9ba..9632c1a85 100644 --- a/lib/sample.cpp +++ b/lib/sample.cpp @@ -76,7 +76,7 @@ void villas::node::sample_free(struct Sample *s) { if (p) pool_put(p, s); else - delete[] (char *)s; + delete[](char *) s; } int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], From 272a3fac369f0afeb42cf44440ff36d0d5c76b39 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 13 Feb 2024 13:46:19 +0000 Subject: [PATCH 100/100] Fix include order Signed-off-by: Steffen Vogel --- lib/nodes/rtp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index 5722581de..17141e4a6 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -15,13 +15,15 @@ #include extern "C" { +// clang-format off +#include #include +#include #include #include -#include #include -#include #include +// clang-format off #undef ALIGN_MASK }