From 870e563568fca1cb1f77915a5389d87154b42372 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 6 Jul 2021 16:27:24 +0200 Subject: [PATCH] hook: add new {Multi,Single}SignalHook sub-classes --- include/villas/hook.hpp | 35 +++++++++++++++ lib/hook.cpp | 99 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 7bcee56d0..1b3036a79 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -168,6 +168,41 @@ public: } }; +class SingleSignalHook : public Hook { + +protected: + unsigned signalIndex; + std::string signalName; + +public: + using Hook::Hook; + + virtual + void parse(json_t *json); + + virtual + void prepare(); +}; + +class MultiSignalHook : public Hook { + +protected: + std::list signalIndices; + std::list signalNames; + +public: + using Hook::Hook; + + virtual + void parse(json_t *json); + + virtual + void prepare(); + + virtual + void check(); +}; + class LimitHook : public Hook { public: diff --git a/lib/hook.cpp b/lib/hook.cpp index 16f02afc7..1ebcd1fda 100644 --- a/lib/hook.cpp +++ b/lib/hook.cpp @@ -106,3 +106,102 @@ void Hook::parse(json_t *json) state = State::PARSED; } + +void SingleSignalHook::parse(json_t *json) +{ + int ret; + + json_error_t err; + json_t *json_signal; + + Hook::parse(json); + + 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 'signals'"); + + signalName = json_string_value(json_signal); +} + + +void SingleSignalHook::prepare() +{ + Hook::prepare(); + + /* Setup mask */ + int index = vlist_lookup_index(&signals, signalName); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); + + signalIndex = (unsigned) index; +} + +/* Multi Signal Hook */ + +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; + + 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"); + + 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'"); + + signalNames.push_back(json_string_value(json_signal)); + } + } + 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(json_string_value(json_signal)); + } + else + throw ConfigError(json, "node-config-hook-signals", "Missing 'signals' setting"); + + + Hook::parse(json); +} + + +void MultiSignalHook::prepare() +{ + /* Setup mask */ + for (const auto &signalName : signalNames) { + int index = vlist_lookup_index(&signals, signalName); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); + + signalIndices.push_back(index); + } + + Hook::prepare(); +} + +void MultiSignalHook::check() +{ + if (signalNames.size() == 0) + throw RuntimeError("At least a single signal must be provided"); + + Hook::check(); +}