diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f4de6fdb6..de4c30102 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -101,9 +101,13 @@ test:cppcheck: --error-exitcode=1 --quiet --inline-suppr - --enable=warning,performance,portability,information,missingInclude + --enable=warning,performance,portability,missingInclude --std=c++11 --suppress=noValidConfiguration + -U '_MSC_VER;_WIN32;_M_ARM' + -U '_MSC_VER;_WIN32;_M_AMD64;_M_X64' + -U '_MSC_FULL_VER;_MSC_VER' + -U '_MSC_BUILD;_MSC_VER' -I include -I common/include src/ lib/ tests/unit/ | tee cppcheck.log @@ -147,9 +151,13 @@ test:integration: paths: - build/tests/integration/ services: - - eclipse-mosquitto - - rabbitmq:3.8 - - redis + - name: eclipse-mosquitto:2.0 + alias: mosquitto + command: [ mosquitto, -c, /mosquitto-no-auth.conf ] + - name: rwthacs/rabbitmq + alias: rabbitmq + - name: redis:6.2 + alias: redis tags: - docker needs: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d00111e6..5f8924276 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Main CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -28,7 +28,7 @@ project(villas-node # Some more project settings set(PROJECT_AUTHOR "Steffen Vogel") -set(PROJECT_COPYRIGHT "2014-2020, Institute for Automation of Complex Power Systems, RWTH Aachen University") +set(PROJECT_COPYRIGHT "2014-2021, Institute for Automation of Complex Power Systems, RWTH Aachen University") set(PROJECT_HOMEPAGE_URL "https://www.fein-aachen.org/projects/villas-node/") # Several CMake settings/defaults @@ -243,8 +243,8 @@ if(WITH_TESTS) endif() configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/include/villas/node/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/include/villas/node/config.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/villas/node/config.hpp.in + ${CMAKE_CURRENT_BINARY_DIR}/include/villas/node/config.hpp ) # Show feature summary diff --git a/README.md b/README.md index 9e4f1897f..69c7e007a 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ User documentation is available here: #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include @@ -71,8 +71,8 @@ protected: { int ret, readcnt, writecnt, avail; - struct shmem_int shm; - struct shmem_conf conf = { + struct ShmemInterface shm; + struct ShmemConfig conf = { .polling = 0, .queuelen = DEFAULT_SHMEM_QUEUELEN, .samplelen = DEFAULT_SHMEM_SAMPLELEN @@ -91,7 +91,7 @@ protected: 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); diff --git a/cmake/FindIBVerbs.cmake b/cmake/FindIBVerbs.cmake index 7c95d2427..7f23b5614 100644 --- a/cmake/FindIBVerbs.cmake +++ b/cmake/FindIBVerbs.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/FindOpal.cmake b/cmake/FindOpal.cmake index 60d023bf8..5700d24e3 100644 --- a/cmake/FindOpal.cmake +++ b/cmake/FindOpal.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/FindRDMACM.cmake b/cmake/FindRDMACM.cmake index 40cc576a4..ee792c14c 100644 --- a/cmake/FindRDMACM.cmake +++ b/cmake/FindRDMACM.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/FindSymbol.cmake b/cmake/FindSymbol.cmake index da933e021..ad7eb40b7 100644 --- a/cmake/FindSymbol.cmake +++ b/cmake/FindSymbol.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/VILLASnodePackaging.cmake b/cmake/VILLASnodePackaging.cmake index 90926e14b..9e212fb56 100644 --- a/cmake/VILLASnodePackaging.cmake +++ b/cmake/VILLASnodePackaging.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/config/Coverage.cmake b/cmake/config/Coverage.cmake index 9dbed7abb..3f7a0b904 100644 --- a/cmake/config/Coverage.cmake +++ b/cmake/config/Coverage.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/config/Debug.cmake b/cmake/config/Debug.cmake index e55eea4b6..3a60bc19f 100644 --- a/cmake/config/Debug.cmake +++ b/cmake/config/Debug.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/config/Profiling.cmake b/cmake/config/Profiling.cmake index 314f69c5b..d3dc0702e 100644 --- a/cmake/config/Profiling.cmake +++ b/cmake/config/Profiling.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/cmake/config/Release.cmake b/cmake/config/Release.cmake index e55eea4b6..3a60bc19f 100644 --- a/cmake/config/Release.cmake +++ b/cmake/config/Release.cmake @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/common b/common index 06bd16a96..851b7a454 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 06bd16a965a494ccfd4d69ab74a5737c8cb1328c +Subproject commit 851b7a454021711af55f253cc05feb972067da74 diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 0ab37e287..241c50403 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/etc/CMakeLists.txt b/etc/CMakeLists.txt index 8aa10c76e..fb83095d6 100644 --- a/etc/CMakeLists.txt +++ b/etc/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/etc/demo.json b/etc/demo.json index f6fd8d62b..368e2c3d3 100644 --- a/etc/demo.json +++ b/etc/demo.json @@ -1,7 +1,7 @@ { "hugepages": 0, "http": { - "htdocs": "/usr/share/villas/node/web" + "port": 80 }, "nodes": { "sig": { diff --git a/etc/eric-lab.conf b/etc/eric-lab.conf index 8e68600f1..994f33cf7 100644 --- a/etc/eric-lab.conf +++ b/etc/eric-lab.conf @@ -21,7 +21,6 @@ logging = { } http = { - htdocs = "/villas/web/" # Root directory of internal webserver port = 80 # Port for HTTP connections } diff --git a/etc/examples/example.conf b/etc/examples/example.conf index a84a30238..c3b708174 100644 --- a/etc/examples/example.conf +++ b/etc/examples/example.conf @@ -9,7 +9,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -33,7 +33,7 @@ @include "global.conf" # An example node. Define multiple nodes in the "nodes" dictionary -@include "nodes/signal_generator.conf" +@include "nodes/socket.conf" # A list of example paths. Define multiple paths by appending them to the "paths" list. -#@include "paths.conf" +@include "paths.conf" diff --git a/etc/examples/global.conf b/etc/examples/global.conf index 15b1c7626..c93d1db78 100644 --- a/etc/examples/global.conf +++ b/etc/examples/global.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -53,6 +53,5 @@ logging = { http = { enabled = true, # Do not listen on port if true - htdocs = "/villas/web/socket/", # Root directory of internal webserver port = 80 # Port for HTTP connections } diff --git a/etc/examples/hooks/limit_value.conf b/etc/examples/hooks/limit_value.conf new file mode 100644 index 000000000..7120894bb --- /dev/null +++ b/etc/examples/hooks/limit_value.conf @@ -0,0 +1,19 @@ +@include "hook-nodes.conf" + +paths = ( + { + in = "signal_node" + out = "file_node" + + hooks = ( + { + type = "limit_value" + + min = -0.5 + max = 0.5 + + signals = [ "sine" ] + } + ) + } +) diff --git a/etc/examples/hooks/print.conf b/etc/examples/hooks/print.conf index a056e6785..c16b5a4a4 100644 --- a/etc/examples/hooks/print.conf +++ b/etc/examples/hooks/print.conf @@ -11,7 +11,7 @@ paths = ( output = "print_output_file.log" format = "villas.human" - prefix = "[file_node] " + # prefix = "[file_node] " # prefix and output are exclusive settings! } ) } diff --git a/etc/examples/nodes/signal.v2.conf b/etc/examples/nodes/signal.v2.conf new file mode 100644 index 000000000..77789dad2 --- /dev/null +++ b/etc/examples/nodes/signal.v2.conf @@ -0,0 +1,30 @@ +nodes = { + signal_node = { + type = "signal.v2", + + rate = 10.0 + realtime = true, # Wait between emitting each sample + limit = 1000, # Only emit 1000 samples, then stop + monitor_missed = true # Count and warn about missed steps + + in = { + signals = ( + { name = "sine1", signal = "sine", amplitude = 123.456, frequency = 10, offset = 1.0 }, + { name = "sine2", signal = "sine", amplitude = 12.456, frequency = 20, offset = 10.0 }, + { name = "sine3", signal = "sine", amplitude = 2, frequency = 1, offset = 100.0 }, + { name = "random1", signal = "random", amplitude = 2, stddev = 2, offset = 13.0 }, + { name = "pulse1", signal = "pulse", frequency = 1.0, pulse_width = 1, pulse_high = 100, pulse_low = 50 } + ) + } + }, + signal_node2 = { + type = "signal.v2", + + in = { + signals = { + count = 8, + signal = "mixed" + } + } + } +} diff --git a/etc/examples/nodes/websocket.conf b/etc/examples/nodes/websocket.conf index 012f2879b..579588941 100644 --- a/etc/examples/nodes/websocket.conf +++ b/etc/examples/nodes/websocket.conf @@ -10,7 +10,6 @@ nodes = { http = { port = 8080 - htdocs = "/villas/contrib/websocket/" ssl_cert = "/etc/ssl/certs/mycert.pem" ssl_private_key= "/etc/ssl/private/mykey.pem" } diff --git a/etc/examples/paths.conf b/etc/examples/paths.conf index 189cd73e1..98a9f7359 100644 --- a/etc/examples/paths.conf +++ b/etc/examples/paths.conf @@ -3,8 +3,8 @@ paths = ( enabled = true, # Enable this path (default: true) reverse = true, # Setup a path in the reverse direction as well (default: false) - in = "acs", # Name of the node we receive messages from (see node dictionary) - out = "sintef", # Name of the node we send messages to. + in = "udp_node", # Name of the node we receive messages from (see node dictionary) + out = "ethernet_node", # Name of the node we send messages to. rate = 10.0 # A rate at which this path will be triggered if no input node receives new data @@ -13,26 +13,6 @@ paths = ( mode = "all", # When this path should be triggered # - "all": After all masked input nodes received new data # - "any": After any of the masked input nodes received new data - mask = [ "acs" ], # A list of input nodes which will trigger the path - }, - { - enabled = false, - reverse = false, - - in = [ # Multiple source nodes are multiplexed - "opal_node.data[0-4]", - "signal_node.data[0-4]" - ], - out = [ # Multiple destination nodes are supported too. - "udp_node", # All destination nodes receive the same sample - "zeromq_node" # Which gets constructed by the 'in' mapping. - ] - }, - { - in = "socket_node", - out = "file_node", # This path includes all available example hooks. - - builtin = false, # By default, all paths will have a few builtin hooks attached to them. - # When collecting statistics or measurements these are undesired. + mask = [ "udp_node" ], # A list of input nodes which will trigger the path } ) diff --git a/etc/gtnet-skt/emulate_gtnet.conf b/etc/gtnet-skt/emulate_gtnet.conf index e4f8d453a..deb718c3b 100644 --- a/etc/gtnet-skt/emulate_gtnet.conf +++ b/etc/gtnet-skt/emulate_gtnet.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/gtnet-skt/test1.conf b/etc/gtnet-skt/test1.conf index f6b7d975a..931904903 100644 --- a/etc/gtnet-skt/test1.conf +++ b/etc/gtnet-skt/test1.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/gtnet-skt/test2.conf b/etc/gtnet-skt/test2.conf index 7fc7251ce..9c934db9d 100644 --- a/etc/gtnet-skt/test2.conf +++ b/etc/gtnet-skt/test2.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/gtnet-skt/test3.conf b/etc/gtnet-skt/test3.conf index cfabce99f..ded3aa2ca 100644 --- a/etc/gtnet-skt/test3.conf +++ b/etc/gtnet-skt/test3.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/gtnet-skt/test4.conf b/etc/gtnet-skt/test4.conf index 883cbd19d..760758475 100644 --- a/etc/gtnet-skt/test4.conf +++ b/etc/gtnet-skt/test4.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/gtnet-skt/test5.conf b/etc/gtnet-skt/test5.conf index b28ba4bc1..a72b85df1 100644 --- a/etc/gtnet-skt/test5.conf +++ b/etc/gtnet-skt/test5.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/js/config.js b/etc/js/config.js index f9fad8c77..b3f97b0d2 100644 --- a/etc/js/config.js +++ b/etc/js/config.js @@ -8,7 +8,7 @@ * villas node <(node /etc/villas/node/js/config.js) * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/js/global.js b/etc/js/global.js index f43fae2be..c4bb5866c 100644 --- a/etc/js/global.js +++ b/etc/js/global.js @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html//Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -59,7 +59,6 @@ module.exports = { http : { enabled : true, // Do not listen on port if true - htdocs : "/villas/web/socket/", // Root directory of internal webserver port : 80 // Port for HTTP connections } -}; \ No newline at end of file +}; diff --git a/etc/loopback.conf b/etc/loopback.conf index 11e2f4e63..5132810a3 100644 --- a/etc/loopback.conf +++ b/etc/loopback.conf @@ -26,7 +26,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/sim-hes-off/rwth.conf b/etc/sim-hes-off/rwth.conf new file mode 100644 index 000000000..2e6e83924 --- /dev/null +++ b/etc/sim-hes-off/rwth.conf @@ -0,0 +1,103 @@ + +nodes = { + rwth-opal = { + type = "socket" + layer = "udp" + + in = { + address = "0.0.0.0:12008" + +# signals = ( +# { name = "Idc1_meas", type = "float", unit = "A" }, +# { name = "Idc2_meas", type = "float", unit = "A" } +# ) + + hooks = ( + "stats" + ) + } + + out = { + address = "134.130.169.81:12008" + } + } + + ntnu-villas = { + type = "socket" + layer = "udp" + + in = { + address = "0.0.0.0:12001" + +# signals = ( +# { name = "P1_ref", type = "float", unit = "W" }, +# { name = "P2_ref", type = "float", unit = "W" }, +# { name = "Udc_meas", type = "float", unit = "V" } +# +# ) + + hooks = ( + "stats" + ) + } + + out = { + address = "10.101.8.4:12001" # todo: update with real IP + } + } + + web-rwth = { + type = "websocket" + + destinations = [ + "https://villas.k8s.eonerc.rwth-aachen.de/ws/relay/sim-hes-off-rwth" + ] + }, + + web-ntnu = { + type = "websocket" + + destinations = [ + "https://villas.k8s.eonerc.rwth-aachen.de/ws/relay/sim-hes-off-ntnu" + ] + }, + + logger = { + type = "file" + format = "csv" + + uri = "opal-rwth.csv" + } +} + +paths = ( + { + in = "rwth-opal", + out = [ +# "ntnu-villas", + "web-rwth" + ], + hooks = ( + { + type = "decimate" + ratio = 100 + }, + { + type = "print" + } + ) + }, + { + enabled = false + + in = [ + "ntnu-villas" + ] + out = [ + "rwth-opal" + # "web-ntnu" + # "logger" + ] + } +) + diff --git a/etc/test.conf b/etc/test.conf new file mode 100644 index 000000000..1e174dc6e --- /dev/null +++ b/etc/test.conf @@ -0,0 +1,19 @@ +nodes = { + signal = { + type = "signal" + + signal = "mixed" + values = 5 + } +} + +paths = ( + { + in = "signal" + hooks = ( + { + type = "print" + } + ) + } +) diff --git a/etc/websocket-client.conf b/etc/websocket-client.conf index bf32bd85f..da6e37fa8 100644 --- a/etc/websocket-client.conf +++ b/etc/websocket-client.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/etc/websocket-demo.conf b/etc/websocket-demo.conf index f2ab40589..a5e8e3090 100644 --- a/etc/websocket-demo.conf +++ b/etc/websocket-demo.conf @@ -5,7 +5,7 @@ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/fpga b/fpga index f1b555475..47a7c0f30 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit f1b5554752353ee044e6139f20ba92bfeaf12c70 +Subproject commit 47a7c0f30ffb6e21422e3a45fd81d86a33716e9f diff --git a/include/villas/api.hpp b/include/villas/api.hpp index 304785af0..520bbe01a 100644 --- a/include/villas/api.hpp +++ b/include/villas/api.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/include/villas/api/node_request.hpp b/include/villas/api/node_request.hpp index 8a97df9f9..8622c5167 100644 --- a/include/villas/api/node_request.hpp +++ b/include/villas/api/node_request.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,11 +25,12 @@ #include -/* Forward declarations */ -struct vnode; - namespace villas { namespace node { + +/* Forward declarations */ +class Node; + namespace api { class NodeRequest : public Request { @@ -37,7 +38,7 @@ class NodeRequest : public Request { public: using Request::Request; - struct vnode *node; + Node *node; virtual void prepare(); diff --git a/include/villas/api/path_request.hpp b/include/villas/api/path_request.hpp index ab0b2a237..50dfa36b2 100644 --- a/include/villas/api/path_request.hpp +++ b/include/villas/api/path_request.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,11 +25,12 @@ #include -/* Forward declarations */ -struct vpath; - namespace villas { namespace node { + +/* Forward declarations */ +class Path; + namespace api { class PathRequest : public Request { @@ -37,7 +38,7 @@ class PathRequest : public Request { public: using Request::Request; - struct vpath *path; + class Path *path; virtual void prepare(); diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index 35d7a3649..fa344961e 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -115,9 +115,6 @@ public: virtual std::string toString(); - - void setLogger(Logger log) - { logger = log; } }; class RequestFactory : public plugin::Plugin { @@ -134,10 +131,18 @@ public: static Request * create(Session *s, const std::string &uri, Session::Method meth, unsigned long ct); + virtual + void init(Request *r) + { + r->logger = getLogger(); + } + virtual std::string getType() const - { return "api:request"; } + { + return "api:request"; + } }; template @@ -157,7 +162,7 @@ public: { auto *r = new T(s); - r->setLogger(getLogger()); + init(r); return r; } diff --git a/include/villas/api/response.hpp b/include/villas/api/response.hpp index 97bcbcc0e..6cae32f3b 100644 --- a/include/villas/api/response.hpp +++ b/include/villas/api/response.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index 1e34f4720..778ba41ef 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -115,7 +115,6 @@ public: static std::string methodToString(Method meth); - }; } /* namespace api */ diff --git a/include/villas/config.hpp b/include/villas/config_class.hpp similarity index 96% rename from include/villas/config.hpp rename to include/villas/config_class.hpp index b96e8436c..8d1e126b4 100644 --- a/include/villas/config.hpp +++ b/include/villas/config_class.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,7 +30,7 @@ #include #include -#include +#include #include #ifdef WITH_CONFIG diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index 3cc784be3..731dbb25b 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -1,7 +1,7 @@ /** Helpers for configuration parsers. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,19 +22,26 @@ #pragma once -#include - -#include -#include - #ifdef WITH_CONFIG #include +#endif + +#include + +#include +#include + +namespace villas { +namespace node { + +#ifdef WITH_CONFIG /** Convert a libconfig object to a jansson object */ -json_t *config_to_json(config_setting_t *json); +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, config_setting_t *parent); +int json_to_config(json_t *json, struct config_setting_t *parent); + #endif /* WITH_CONFIG */ int json_object_extend_str(json_t *orig, const char *str); @@ -47,3 +54,6 @@ void json_object_extend_key_value_token(json_t *obj, const char *key, const char int json_object_extend(json_t *orig, json_t *merge); 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 c88666514..97e0014dc 100644 --- a/include/villas/dumper.hpp +++ b/include/villas/dumper.hpp @@ -2,7 +2,7 @@ * * @file * @author Manuel Pitz - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 3faad9fa7..8969fa392 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,20 +23,31 @@ #pragma once -#include +#include + +#include #include -#include +#include +#include namespace villas { namespace node { +/* 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 */ - bool destroy_signals; + int flags; /**< A set of flags which is automatically used. */ + int real_precision; /**< Number of digits used for floatint point numbers */ Logger logger; @@ -45,7 +56,7 @@ protected: size_t buflen; } in, out; - struct vlist *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); @@ -55,18 +66,21 @@ public: virtual bool isBinaryPayload() - { return false; } + { + return false; + } - struct vlist * getSignals() const - { return signals; } + const SignalList::Ptr getSignals() const + { + return signals; + } int getFlags() const - { return flags; } + { + return flags; + } - void setLogger(Logger log) - { logger = log; } - - void start(struct vlist *sigs, 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 @@ -77,10 +91,10 @@ public: void parse(json_t *json); virtual - int print(FILE *f, const struct sample * const smps[], unsigned cnt); + int print(FILE *f, const struct Sample * const smps[], unsigned cnt); virtual - int scan(FILE *f, struct sample * const smps[], unsigned cnt); + 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. * @@ -94,7 +108,7 @@ public: * @retval <0 Something went wrong. */ virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct sample * const smps[], unsigned cnt) = 0; + 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. * @@ -108,26 +122,26 @@ public: * @retval <0 Something went wrong. */ virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) = 0; + 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 */ - int print(FILE *f, const struct sample *smp) + int print(FILE *f, const struct Sample *smp) { return print(f, &smp, 1); } - int scan(FILE *f, struct sample *smp) + 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) + 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) + int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample *smp) { return sscan(buf, len, rbytes, &smp, 1); } @@ -156,9 +170,17 @@ public: static Format * make(const std::string &format); + virtual + void init(Format *f) + { + f->logger = getLogger(); + } + virtual std::string getType() const - { return "format"; } + { + return "format"; + } }; template @@ -171,20 +193,22 @@ public: { auto *f = new T(flags); - f->setLogger(getLogger()); + init(f); return f; } - /// Get plugin name - virtual std::string - getName() const - { return name; } + virtual + std::string getName() const + { + return name; + } - /// Get plugin description - 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 7a4969a09..04afda612 100644 --- a/include/villas/formats/column.hpp +++ b/include/villas/formats/column.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,17 +27,17 @@ #include -/* Forward declarations. */ -struct sample; - namespace villas { namespace node { +/* 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 */ @@ -48,7 +48,7 @@ public: { } virtual - void header(FILE *f, const struct vlist *sigs); + void header(FILE *f, const SignalList::Ptr sigs); virtual void parse(json_t *json); diff --git a/include/villas/formats/iotagent_ul.hpp b/include/villas/formats/iotagent_ul.hpp index 45ef07b19..731e61e3f 100644 --- a/include/villas/formats/iotagent_ul.hpp +++ b/include/villas/formats/iotagent_ul.hpp @@ -1,7 +1,7 @@ /** UltraLight format for FISMEP project. * * @author Iris Koester - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,19 +24,20 @@ #include -/* Forward declarations */ -struct sample; - namespace villas { namespace node { +/* Forward declarations */ +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); + 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); + int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); public: using Format::Format; diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 5ffda8906..8e8702ca8 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -1,7 +1,7 @@ /** JSON serializtion sample data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,28 +26,28 @@ #include -/* Forward declarations */ -struct sample; - namespace villas { namespace node { +/* Forward declarations */ +struct Sample; + class JsonFormat : public Format { protected: 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); + int packSample(json_t **j, const struct Sample *smp); virtual - int packSamples(json_t **j, const struct sample * const smps[], unsigned cnt); + int packSamples(json_t **j, const struct Sample * const smps[], unsigned cnt); virtual - int unpackSample(json_t *json_smp, struct sample *smp); + int unpackSample(json_t *json_smp, struct Sample *smp); virtual - int unpackSamples(json_t *json_smps, struct sample * const smps[], unsigned cnt); + int unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt); int dump_flags; @@ -58,14 +58,14 @@ public: { } virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt); + 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); + 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); + int print(FILE *f, const struct Sample * const smps[], unsigned cnt); virtual - int scan(FILE *f, struct sample * const smps[], unsigned cnt); + int scan(FILE *f, struct Sample * const smps[], unsigned cnt); virtual void parse(json_t *json); diff --git a/include/villas/formats/json_edgeflex.hpp b/include/villas/formats/json_edgeflex.hpp index 4e5476f15..4066a48e8 100644 --- a/include/villas/formats/json_edgeflex.hpp +++ b/include/villas/formats/json_edgeflex.hpp @@ -1,7 +1,7 @@ /** JSON serializtion for edgeFlex project. * * @author Manuel Pitz - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,9 +31,9 @@ class JsonEdgeflexFormat : public JsonFormat { protected: virtual - int packSample(json_t **j, const struct sample *smp); + int packSample(json_t **j, const struct Sample *smp); virtual - int unpackSample(json_t *json_smp, struct sample *smp); + int unpackSample(json_t *json_smp, struct Sample *smp); public: using JsonFormat::JsonFormat; diff --git a/include/villas/formats/json_kafka.hpp b/include/villas/formats/json_kafka.hpp index 0376dc26a..48c723971 100644 --- a/include/villas/formats/json_kafka.hpp +++ b/include/villas/formats/json_kafka.hpp @@ -1,7 +1,7 @@ /** JSON serializtion for Kafka schema/payloads. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #pragma once -#include +#include #include namespace villas { @@ -32,9 +32,9 @@ class JsonKafkaFormat : public JsonFormat { protected: virtual - int packSample(json_t **j, const struct sample *smp); + int packSample(json_t **j, const struct Sample *smp); virtual - int unpackSample(json_t *json_smp, struct sample *smp); + int unpackSample(json_t *json_smp, struct Sample *smp); const char * villasToKafkaType(enum SignalType vt); diff --git a/include/villas/formats/json_reserve.hpp b/include/villas/formats/json_reserve.hpp index e8a315bb8..3c65b801a 100644 --- a/include/villas/formats/json_reserve.hpp +++ b/include/villas/formats/json_reserve.hpp @@ -1,7 +1,7 @@ /** JSON serializtion for RESERVE project. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,9 +31,9 @@ class JsonReserveFormat : public JsonFormat { protected: virtual - int packSample(json_t **j, const struct sample *smp); + int packSample(json_t **j, const struct Sample *smp); virtual - int unpackSample(json_t *json_smp, struct sample *smp); + int unpackSample(json_t *json_smp, struct Sample *smp); public: using JsonFormat::JsonFormat; diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index ca569d4aa..6be52610e 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,8 +31,8 @@ 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. */ @@ -56,20 +56,20 @@ public: /** Print a header. */ virtual - void header(FILE *f, const struct vlist *sigs) + 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); + 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); + 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); + int scan(FILE *f, struct Sample * const smps[], unsigned cnt); virtual - int print(FILE *f, const struct sample * const smps[], unsigned cnt); + int print(FILE *f, const struct Sample * const smps[], unsigned cnt); virtual void parse(json_t *json); diff --git a/include/villas/formats/msg.hpp b/include/villas/formats/msg.hpp index 28f583a15..73fa4747d 100644 --- a/include/villas/formats/msg.hpp +++ b/include/villas/formats/msg.hpp @@ -1,7 +1,7 @@ /** Message related functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,22 +22,30 @@ #pragma once +#include + +namespace villas { + +/* Forward declarataions */ +struct List; + +namespace node { + /* Forward declaration */ -struct msg; -struct sample; -struct vlist; +struct Message; +struct Sample; /** Convert msg from network to host byteorder */ -void msg_ntoh(struct msg *m); +void msg_ntoh(struct Message *m); /** Convert msg from host to network byteorder */ -void msg_hton(struct msg *m); +void msg_hton(struct Message *m); /** Convert msg header from network to host byteorder */ -void msg_hdr_hton(struct msg *m); +void msg_hdr_hton(struct Message *m); /** Convert msg header from host to network byteorder */ -void msg_hdr_ntoh(struct msg *m); +void msg_hdr_ntoh(struct Message *m); /** Check the consistency of a message. * @@ -47,10 +55,13 @@ void msg_hdr_ntoh(struct msg *m); * @retval 0 The message header is valid. * @retval <0 The message header is invalid. */ -int msg_verify(const struct msg *m); +int msg_verify(const struct Message *m); /** Copy fields from \p msg into \p smp. */ -int msg_to_sample(const struct msg *msg, struct sample *smp, const struct vlist *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 msg *msg, const struct sample *smp, const struct vlist *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 554cfcefb..70144ecad 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -34,24 +34,27 @@ #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 Message) + MSG_DATA_LEN(values)) /** 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. */ -#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, 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; +namespace villas { +namespace node { + /** This message format is used by all clients * * @diafile msg_format.dia **/ -struct msg +struct Message { #if BYTE_ORDER == BIG_ENDIAN unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ @@ -81,3 +84,6 @@ struct msg uint32_t i; /**< Integer values. */ } data[]; } __attribute__((packed)); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index 0c81d491d..58fd6ce97 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,12 +30,12 @@ /* Generated message descriptors by protoc */ #include -/* Forward declarations. */ -struct sample; - namespace villas { namespace node { +/* Forward declarations. */ +struct Sample; + class ProtobufFormat : public BinaryFormat { protected: @@ -45,9 +45,9 @@ public: using BinaryFormat::BinaryFormat; virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt); + 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); + 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 e87f1e23c..b14d39cff 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -33,12 +33,12 @@ #define HAS_128BIT #endif -/* Forward declarations */ -struct sample; - namespace villas { namespace node { +/* Forward declarations */ +struct Sample; + class RawFormat : public BinaryFormat { public: @@ -65,9 +65,9 @@ public: } virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt); + 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); + int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); virtual void parse(json_t *json); diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 80293592c..4b9b9159d 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -36,9 +36,9 @@ public: using Format::Format; virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt); + 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); + 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 b9003ab02..c94c0fef9 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,13 +27,12 @@ #include -/* Forward declarations. */ -struct sample; -struct msg; - namespace villas { namespace node { +/* Forward declarations. */ +struct Sample; + class VillasBinaryFormat : public BinaryFormat { protected: @@ -50,9 +49,9 @@ public: { } virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt); + 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); + int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); virtual void parse(json_t *json); diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index d98aa839f..4550e96f3 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -34,15 +34,15 @@ class VILLASHumanFormat : public LineFormat { protected: virtual - size_t sprintLine(char *buf, size_t len, const struct sample *smp); + 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); + size_t sscanLine(const char *buf, size_t len, struct Sample *smp); public: using LineFormat::LineFormat; virtual - void header(FILE *f, const struct vlist *sigs); + void header(FILE *f, const SignalList::Ptr sigs); }; } /* namespace node */ diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index b43cfb27f..f0280c007 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -6,7 +6,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,23 +27,29 @@ #pragma once -#include -#include +#include +#include +#include #include #include #include -/* Forward declarations */ -struct vpath; -struct vnode; -struct sample; - namespace villas { namespace node { +/* Forward declarations */ +class Node; +class Path; +struct Sample; +class HookFactory; + class Hook { + friend HookFactory; + 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. */ @@ -61,34 +67,32 @@ public: protected: Logger logger; + HookFactory *factory; + 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? */ - struct vpath *path; - struct vnode *node; + Path *path; + Node *node; - struct vlist signals; + SignalList::Ptr signals; json_t *config; /**< A JSON object containing the configuration of the hook. */ public: - Hook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true); + Hook(Path *p, Node *n, int fl, int prio, bool en = true); virtual - ~Hook(); + ~Hook() + { } virtual void parse(json_t *json); - void prepare(struct vlist *sigs); - - void setLogger(Logger log) - { - logger = log; - } + void prepare(SignalList::Ptr sigs); Logger getLogger() { @@ -123,7 +127,11 @@ public: virtual void prepare() - { } + { + assert(state == State::CHECKED); + + state = State::PREPARED; + } /** Called periodically. Period is set by global 'stats' option in the configuration file. */ virtual @@ -141,7 +149,7 @@ public: /** Called whenever a sample is processed. */ virtual - Reason process(struct sample *smp) + Reason process(struct Sample *smp) { return Reason::OK; }; @@ -157,9 +165,9 @@ public: } virtual - struct vlist * getSignals() + SignalList::Ptr getSignals() const { - return &signals; + return signals; } json_t * getConfig() const @@ -167,6 +175,11 @@ public: return config; } + HookFactory * getFactory() const + { + return factory; + } + bool isEnabled() const { return enabled; @@ -180,7 +193,7 @@ protected: std::string signalName; public: - SingleSignalHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + SingleSignalHook(Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), signalIndex(0) { } @@ -214,6 +227,7 @@ public: class LimitHook : public Hook { public: + using Ptr = std::shared_ptr; using Hook::Hook; virtual void setRate(double rate, double maxRate = -1) = 0; @@ -236,18 +250,30 @@ public: class HookFactory : public plugin::Plugin { +protected: + virtual + void init(Hook::Ptr h) + { + h->logger = getLogger(); + h->factory = this; + } + public: using plugin::Plugin::Plugin; - virtual Hook * make(struct vpath *p, struct vnode *n) = 0; - - virtual int getFlags() const = 0; - virtual unsigned getPriority() const = 0; + virtual Hook::Ptr make(Path *p, Node *n) = 0; virtual - std::string - getType() const - { return "hook"; } + int getFlags() const = 0; + + virtual + unsigned getPriority() const = 0; + + virtual + std::string getType() const + { + return "hook"; + } }; template @@ -256,30 +282,38 @@ class HookPlugin : public HookFactory { public: using HookFactory::HookFactory; - virtual Hook * make(struct vpath *p, struct vnode *n) + virtual Hook::Ptr make(Path *p, Node *n) { - auto *h = new T(p, n, getFlags(), getPriority()); + auto h = std::make_shared(p, n, getFlags(), getPriority()); - h->setLogger(getLogger()); + init(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 517b4d157..2281e5f54 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -4,7 +4,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,61 +23,60 @@ * along with this program. If not, see . */ -/** - * @addtogroup hooks User-defined hook functions - * @ingroup path - * @{ - *********************************************************************************/ - #pragma once #include +#include + +namespace villas { +namespace node { + /* Forward declarations */ -struct vlist; -struct sample; -struct vpath; -struct vnode; +class Node; +class Path; +struct Sample; -int hook_list_init(struct vlist *hs) __attribute__ ((warn_unused_result)); +class HookList : public std::list { -int hook_list_destroy(struct vlist *hs) __attribute__ ((warn_unused_result)); +public: + HookList() + { } -/** Parses an object of hooks - * - * Example: - * - * { - * stats = { - * output = "stdout" - * }, - * skip_first = { - * seconds = 10 - * }, - * hooks = [ "print" ] - * } - */ -void hook_list_parse(struct vlist *hs, json_t *json, int mask, struct vpath *p, struct vnode *n); + /** Parses an object of hooks + * + * Example: + * + * { + * stats = { + * output = "stdout" + * }, + * skip_first = { + * seconds = 10 + * }, + * hooks = [ "print" ] + * } + */ + void parse(json_t *json, int mask, Path *p, Node *n); -void hook_list_check(struct vlist *hs); + void check(); -void hook_list_prepare(struct vlist *hs, struct vlist *sigs, int mask, struct vpath *p, struct vnode *n); + void prepare(SignalList::Ptr sigs, int mask, Path *p, Node *n); -int hook_list_prepare_signals(struct vlist *hs, struct vlist *signals); + int process(struct Sample *smps[], unsigned cnt); + void periodic(); + void start(); + void stop(); -int hook_list_add(struct vlist *hs, int mask, struct vpath *p, struct vnode *n); + void dump(villas::Logger logger, std::string subject) const; -int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt); + SignalList::Ptr getSignals() const; -void hook_list_periodic(struct vlist *hs); + /** Get the maximum number of signals which is used by any of the hooks in the list. */ + unsigned getSignalsMaxCount() const; -void hook_list_start(struct vlist *hs); + json_t * toJson() const; +}; -void hook_list_stop(struct vlist *hs); - -struct vlist * hook_list_get_signals(struct vlist *hs); - -/** Get the maximum number of signals which is used by any of the hooks in the list. */ -unsigned hook_list_get_signals_max_cnt(struct vlist *hs); - -json_t * hook_list_to_json(struct vlist *hs); +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/hooks/decimate.hpp b/include/villas/hooks/decimate.hpp index 26f617ce2..304bf98f8 100644 --- a/include/villas/hooks/decimate.hpp +++ b/include/villas/hooks/decimate.hpp @@ -1,7 +1,7 @@ /** Decimate hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,10 +24,6 @@ #include -/** @addtogroup hooks Hook functions - * @{ - */ - namespace villas { namespace node { @@ -40,7 +36,8 @@ protected: public: using LimitHook::LimitHook; - virtual void setRate(double rate, double maxRate = -1) + virtual + void setRate(double rate, double maxRate = -1) { assert(maxRate > 0); @@ -56,16 +53,16 @@ public: ratio = r; } - virtual void start(); + virtual + void start(); - virtual void parse(json_t *json); + virtual + void parse(json_t *json); - virtual Hook::Reason process(sample *smp); + virtual + Hook::Reason process(struct Sample *smp); }; } /* namespace node */ } /* namespace villas */ -/** - * @} - */ diff --git a/include/villas/hooks/limit_rate.hpp b/include/villas/hooks/limit_rate.hpp index 0be8b3391..2eeaaf0db 100644 --- a/include/villas/hooks/limit_rate.hpp +++ b/include/villas/hooks/limit_rate.hpp @@ -1,7 +1,7 @@ /** Rate-limiting hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,10 +24,6 @@ #include -/** @addtogroup hooks Hook functions - * @{ - */ - namespace villas { namespace node { @@ -44,7 +40,7 @@ protected: timespec last; public: - LimitRateHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + LimitRateHook(Path *p, Node *n, int fl, int prio, bool en = true) : LimitHook(p, n, fl, prio, en), mode(LIMIT_RATE_LOCAL), deadtime(0), @@ -58,13 +54,8 @@ public: virtual void parse(json_t *json); - virtual Hook::Reason process(sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; - } /* namespace node */ } /* namespace villas */ - -/** - * @} - */ diff --git a/include/villas/hooks/lua.hpp b/include/villas/hooks/lua.hpp index 5fc73b7c1..4ce20bea7 100644 --- a/include/villas/hooks/lua.hpp +++ b/include/villas/hooks/lua.hpp @@ -36,6 +36,7 @@ namespace node { /* Forward declarations */ class LuaHook; +enum SignalType; class LuaSignalExpression { @@ -54,7 +55,7 @@ public: void parseExpression(const std::string &expr); - void evaluate(union signal_data *data, enum SignalType type); + void evaluate(union SignalData *data, enum SignalType type); }; class LuaHook : public Hook { @@ -68,8 +69,8 @@ protected: std::string script; std::vector expressions; - struct vlist signalsProcessed; /**> Signals as emited by Lua process() function */ - struct vlist 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; @@ -118,7 +119,7 @@ protected: } public: - LuaHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true); + LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); virtual ~LuaHook(); @@ -139,11 +140,9 @@ public: virtual void restart(); /** Called whenever a sample is processed. */ - virtual Reason process(sample *smp); + virtual Reason process(struct Sample *smp); }; } /* namespace node */ } /* namespace villas */ - -/** @} */ diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index 493f521f9..6d39faeb2 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -5,7 +5,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,10 +24,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup kernel Kernel - * @{ - */ - #pragma once #include @@ -42,16 +38,15 @@ #endif /* Forward declarations */ -struct vnode; struct nl_addr; struct rtnl_link; struct rtnl_qdisc; namespace villas { - namespace node { /* Forward declarations */ +class Node; class SuperNode; } @@ -69,7 +64,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; @@ -105,7 +100,7 @@ public: */ static Interface * - getEgress(struct sockaddr *sa, villas::node::SuperNode *sn); + getEgress(struct sockaddr *sa, node::SuperNode *sn); /** Get all IRQs for this interface. * @@ -129,7 +124,7 @@ public: std::string getName() const; - void addNode(struct vnode *n) + void addNode(node::Node *n) { nodes.push_back(n); } @@ -137,5 +132,3 @@ public: } /* namespace kernel */ } /* namespace villas */ - -/** @} */ diff --git a/include/villas/kernel/nl.hpp b/include/villas/kernel/nl.hpp index b33ec1a31..75c91d64b 100644 --- a/include/villas/kernel/nl.hpp +++ b/include/villas/kernel/nl.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,10 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup kernel Kernel - * @{ - */ - #pragma once #include @@ -63,5 +59,3 @@ void shutdown(); } /* namespace nl */ } /* namespace kernel */ } /* namespace villas */ - -/** @} */ diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index c465989bd..c846061e5 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -7,7 +7,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,10 +26,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup kernel Kernel - * @{ - */ - #pragma once #include @@ -83,5 +79,3 @@ int mark(Interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark); } /* namespace tc */ } /* namespace kernel */ } /* namespace villas */ - -/** @} */ diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index 893fe9edb..94331e5c8 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -7,7 +7,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,10 +26,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup kernel Kernel - * @{ - */ - #pragma once #include @@ -81,5 +77,3 @@ int netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json); } /* namespace tc */ } /* namespace kernel */ } /* namespace villas */ - -/** @} */ diff --git a/include/villas/log_opal_sink.hpp b/include/villas/log_opal_sink.hpp index befef0312..bbb19daf8 100644 --- a/include/villas/log_opal_sink.hpp +++ b/include/villas/log_opal_sink.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLAScommon @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/include/villas/mapping.h b/include/villas/mapping.hpp similarity index 58% rename from include/villas/mapping.h rename to include/villas/mapping.hpp index a2bfa1e8b..196842f58 100644 --- a/include/villas/mapping.h +++ b/include/villas/mapping.hpp @@ -1,8 +1,8 @@ -/** Sample value remapping for mux. +/** Sample value remapping for path source muxing. * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,9 +24,10 @@ #pragma once #include +#include -#include #include +#include #include #define RE_MAPPING_INDEX "[a-zA-Z0-9_]+" @@ -39,35 +40,39 @@ #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 "\\])?)" +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; -struct sample; -struct signal; -struct vlist; +class Node; +struct Sample; +class Signal; -enum class MappingType { - UNKNOWN, - DATA, - STATS, - HEADER, - TIMESTAMP -}; +class MappingEntry { -enum class MappingHeaderType { - LENGTH, - SEQUENCE -}; +public: + using Ptr = std::shared_ptr; -enum class MappingTimestampType { - ORIGIN, - RECEIVED -}; + enum class Type { + UNKNOWN, + DATA, + STATS, + HEADER, + TIMESTAMP + }; -struct mapping_entry { - char *node_name; - struct vnode *node; /**< The node to which this mapping refers. */ + enum class HeaderType { + LENGTH, + SEQUENCE + }; - enum MappingType type; /**< The mapping type. Selects one of the union fields below. */ + 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. */ /** The number of values which is covered by this mapping entry. * @@ -79,43 +84,42 @@ struct mapping_entry { union { struct { int offset; - struct signal *signal; + Signal *signal; char *first; char *last; } data; struct { - enum villas::Stats::Metric metric; - enum villas::Stats::Type type; + enum Stats::Metric metric; + enum Stats::Type type; } stats; struct { - enum MappingHeaderType type; + enum HeaderType type; } header; struct { - enum MappingTimestampType type; + enum TimestampType type; } timestamp; }; + + std::string nodeName; /**< Used for between parse and prepare only. */ + + MappingEntry(); + + int prepare(NodeList &nodes); + + int update(struct Sample *remapped, const struct Sample *original) const; + + int parse(json_t *json); + + int parseString(const std::string &str); + + std::string toString(unsigned index) const; + + Signal::Ptr toSignal(unsigned index) const; }; -int mapping_entry_prepare(struct mapping_entry *me, villas::node::NodeList &nodes); - -int mapping_entry_update(const struct mapping_entry *me, struct sample *remapped, const struct sample *original); - -int mapping_entry_init(struct mapping_entry *me); - -int mapping_entry_destroy(struct mapping_entry *me); - -int mapping_entry_parse(struct mapping_entry *me, json_t *json); - -int mapping_entry_parse_str(struct mapping_entry *e, const std::string &str); - -int mapping_entry_to_str(const struct mapping_entry *me, unsigned index, char **str); - -int mapping_list_parse(struct vlist *ml, json_t *json); - -int mapping_list_prepare(struct vlist *ml, villas::node::NodeList &nodes); - -int mapping_list_remap(const struct vlist *ml, struct sample *remapped, const struct sample *original); +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/mapping_list.hpp b/include/villas/mapping_list.hpp new file mode 100644 index 000000000..fe751e427 --- /dev/null +++ b/include/villas/mapping_list.hpp @@ -0,0 +1,47 @@ +#pragma once + +/** Sample value remapping for path source muxing. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include + +#include +#include + +namespace villas { +namespace node { + +class MappingList : public std::list { + +public: + int parse(json_t *json); + + int prepare(NodeList &nodes); + + int remap(struct Sample *remapped, const struct Sample *original) const; + + int update(const MappingEntry::Ptr me, struct Sample *remapped, const struct Sample *original); +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/memory/ib.h b/include/villas/memory/ib.h index 272b35cc4..4e6468e13 100644 --- a/include/villas/memory/ib.h +++ b/include/villas/memory/ib.h @@ -2,7 +2,7 @@ * * @file * @author Dennis Potter - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,11 +23,19 @@ #pragma once -#include +#include -struct memory_ib { +namespace villas { +namespace node { +namespace memory { + +struct IB { struct ibv_pd *pd; - struct memory_type *parent; + struct Type *parent; }; -struct ibv_mr * memory_ib_get_mr(void *ptr); +struct ibv_mr * ib_get_mr(void *ptr); + +} /* namespace memory */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node.h b/include/villas/node.h deleted file mode 100644 index 848f0250e..000000000 --- a/include/villas/node.h +++ /dev/null @@ -1,242 +0,0 @@ -/** Nodes - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -/** - * @addtogroup node Node - * @{ - */ - -#pragma once - -#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 -#endif /* LIBNL3_ROUTE_FOUND */ - -/* Forward declarations */ -#ifdef WITH_NETEM - struct rtnl_qdisc; - struct rtnl_cls; -#endif /* WITH_NETEM */ - -#define RE_NODE_NAME "[a-z0-9_-]{2,32}" - -/* Forward declaration */ -static inline -struct vnode_type * node_type(const struct vnode *n); - -/** The data structure for a node. - * - * Every entity which exchanges messages is represented by a node. - * Nodes can be remote machines and simulators or locally running processes. - */ -struct vnode { - char *name; /**< A short identifier of the node, only used for configuration and logging */ - bool enabled; - - enum State state; - villas::Logger logger; - - char *_name; /**< Singleton: A string used to print to screen. */ - char *_name_long; /**< Singleton: A string used to print to screen. */ - - uuid_t uuid; - - int affinity; /**< CPU Affinity of this node */ - - uint64_t sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */ - - std::shared_ptr stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */ - - struct vnode_direction in, out; - -#ifdef __linux__ - 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 vlist sources; /**< A list of path sources which reference this node (struct vpath_sources). */ - struct vlist destinations; /**< A list of path destinations which reference this node (struct vpath_destinations). */ - - struct vnode_type *_vt; /**< Virtual functions (C++ OOP style) */ - void *_vd; /**< Virtual data (used by struct vnode::_vt functions) */ - - json_t *config; /**< A JSON object containing the configuration of the node. */ - - /** Custom formatter for spdlog */ - template - friend OStream &operator<<(OStream &os, const struct vnode &n) - { - os << n.name << "(" << *node_type(&n) << ")"; - - return os; - } -}; - -/** Initialize node with default values */ -int node_init(struct vnode *n, struct vnode_type *vt) __attribute__ ((warn_unused_result)); - -/** Do initialization after parsing the configuration */ -int node_prepare(struct vnode *n); - -/** 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. - */ -int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid); - -/** Parse an array or single node and checks if they exist in the "nodes" section. - * - * Examples: - * out = [ "sintef", "scedu" ] - * out = "acs" - * - * @param json A JSON array or string. See examples above. - * @param nodes The nodes will be added to this list. - * @param all This list contains all valid nodes. - */ -int node_list_parse(struct vlist *list, json_t *json, villas::node::NodeList &all); - -/** Parse the list of signal definitions. */ -int node_parse_signals(struct vlist *list, json_t *json); - -/** Validate node configuration. */ -int node_check(struct vnode *n); - -/** Start operation of a node. - * - * @see node_type::start - */ -int node_start(struct vnode *n); - -/** Stops operation of a node. - * - * @see node_type::stop - */ -int node_stop(struct vnode *n); - -/** Pauses operation of a node. - * - * @see node_type::stop - */ -int node_pause(struct vnode *n); - -/** Resumes operation of a node. - * - * @see node_type::stop - */ -int node_resume(struct vnode *n); - -/** Restarts operation of a node. - * - * @see node_type::stop - */ -int node_restart(struct vnode *n); - -/** Destroy node by freeing dynamically allocated memory. - * - * @see node_type::destroy - */ -int node_destroy(struct vnode *n) __attribute__ ((warn_unused_result)); - -/** Return a pointer to a string which should be used to print this node. - * - * @see node::_name‚ - * @param n A pointer to the node structure. - */ -const char * node_name_short(struct vnode *n); - -/** Return a pointer to a string which should be used to print this node. */ -char * node_name(struct vnode *n); - -/** Return a pointer to a string which should be used to print this node. - * - * @see node::_name_short - * @see node_type::print - * @param n A pointer to the node structure. - */ -char * node_name_long(struct vnode *n); - -/** Return a list of signals which are sent to this node. - * - * This list is derived from the path which uses the node as destination. - */ -struct vlist * node_output_signals(struct vnode *n); - -struct vlist * node_input_signals(struct vnode *n); - -unsigned node_input_signals_max_cnt(struct vnode *n); - -unsigned node_output_signals_max_cnt(struct vnode *n); - -/** Reverse local and remote socket address. - * - * @see node_type::reverse - */ -int node_reverse(struct vnode *n); - -int node_read(struct vnode *n, struct sample * smps[], unsigned cnt); - -int node_write(struct vnode *n, struct sample * smps[], unsigned cnt); - -int node_poll_fds(struct vnode *n, int fds[]); - -int node_netem_fds(struct vnode *n, int fds[]); - -static inline -struct vnode_type * node_type(const struct vnode *n) -{ - return n->_vt; -} - -struct memory_type * node_memory_type(struct vnode *n); - -bool node_is_valid_name(const char *name); - -bool node_is_enabled(const struct vnode *n); - -json_t * node_to_json(struct vnode *); - -/** @} */ diff --git a/include/villas/node.hpp b/include/villas/node.hpp new file mode 100644 index 000000000..f09c7fd74 --- /dev/null +++ b/include/villas/node.hpp @@ -0,0 +1,484 @@ +/** Nodes + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#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 +#endif /* LIBNL3_ROUTE_FOUND */ + +/* Forward declarations */ +#ifdef WITH_NETEM + struct rtnl_qdisc; + struct rtnl_cls; +#endif /* WITH_NETEM */ + +#define RE_NODE_NAME "[a-z0-9_-]{2,32}" + +namespace villas { +namespace node { + +/* Forward declarations */ +class NodeFactory; +class SuperNode; + +/** 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. + */ +class Node { + + friend NodeFactory; + +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. */ + + 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. */ + +#ifdef __linux__ + 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__ */ + +protected: + enum State state; + + uuid_t uuid; + + bool enabled; + + 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. */ + + 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 */ + + NodeFactory *factory; /**< The factory which created this instance */ + + virtual + int _read(struct Sample * smps[], unsigned cnt) + { + return -1; + } + + virtual + int _write(struct Sample * smps[], unsigned cnt) + { + return -1; + } + +public: + /** Initialize node with default values */ + Node(const std::string &name = ""); + + /** Destroy node by freeing dynamically allocated memory. + * + * @see node_type::destroy + */ + virtual + ~Node(); + + /** Do initialization after parsing the configuration */ + virtual + int prepare(); + + /** 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, const uuid_t sn_uuid); + + /** Validate node configuration. */ + virtual + int check(); + + /** Start operation of a node. + * + * @see node_type::start + */ + virtual + int start(); + + /** Stops operation of a node. + * + * @see node_type::stop + */ + virtual + int stop(); + + /** Pauses operation of a node. + * + * @see node_type::stop + */ + virtual + int pause() + { + return 0; + } + + /** Resumes operation of a node. + * + * @see node_type::stop + */ + virtual + int resume() + { + return 0; + } + + /** Restarts operation of a node. + * + * @see node_type::stop + */ + virtual + int restart(); + + /** Receive multiple messages at once. + * + * This callback is optional. It will only be called if non-null. + * + * Messages are received with a single recvmsg() syscall by + * using gathering techniques (struct iovec). + * The messages will be stored in a circular buffer / array @p m. + * Indexes used to address @p m will wrap around after len messages. + * Some node-types might only support to receive one message at a time. + * + * @param smps An array of pointers to memory blocks where the function should store received samples. + * @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); + + /** Send multiple messages in a single datagram / packet. + * + * This callback is optional. It will only be called if non-null. + * + * Messages are sent with a single sendmsg() syscall by + * using gathering techniques (struct iovec). + * The messages have to be stored in a circular buffer / array m. + * So the indexes will wrap around after len. + * + * @param smps An array of pointers to memory blocks where samples read from. + * @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); + + /** Reverse local and remote socket address. + * + * @see node_type::reverse + */ + virtual + int reverse() + { + return -1; + } + + virtual + std::vector getPollFDs() + { + return {}; + } + + virtual + int getNetemFDs(int fds[]) + { + return 0; + } + + virtual + struct villas::node::memory::Type * getMemoryType() + { + return villas::node::memory::default_type; + } + + villas::node::NodeFactory * getFactory() const + { + return factory; + } + + /** Return a pointer to a string which should be used to print this node. + * + * @see Node::name_short + * @param n A pointer to the node structure. + */ + 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; + } + + const std::string & getNameFull(); + + virtual + const std::string & getDetails() + { + static std::string empty; + return empty; + } + + /** Return a pointer to a string which should be used to print this node. + * + * @see Node::name_long + * @see node_type::print + * @param n A pointer to the node structure. + */ + const std::string & getNameLong(); + + /** 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; + + unsigned getInputSignalsMaxCount() const; + unsigned getOutputSignalsMaxCount() const; + + void swapSignals(); + + json_t * getConfig() + { + return config; + } + + enum State getState() const + { + return state; + } + + void setState(enum State s) + { + state = s; + } + + const uuid_t & getUuid() const + { + return uuid; + } + + std::shared_ptr getStats() + { + return stats; + } + + void setStats(std::shared_ptr sts) + { + stats = sts; + } + + void setEnabled(bool en) + { + enabled = en; + } + + /** Custom formatter for spdlog */ + template + friend OStream &operator<<(OStream &os, const Node &n) + { + os << n.getName(); + + return os; + } + + json_t * toJson() const; + + static + bool isValidName(const std::string &name); + + bool isEnabled() const + { + return enabled; + } +}; + +class NodeFactory : public villas::plugin::Plugin { + + friend Node; + +protected: + virtual + void init(Node *n) + { + n->logger = getLogger(); + n->factory = this; + + instances.push_back(n); + } + + 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) + }; + + NodeList instances; + + NodeFactory() : + Plugin() + { + state = State::INITIALIZED; + } + + virtual + Node * make() = 0; + + static + Node * make(json_t *json, uuid_t uuid); + + static + Node * make(const std::string &type); + + virtual + std::string getType() const + { + return "node"; + } + + /** Custom formatter for spdlog */ + template + friend OStream &operator<<(OStream &os, const NodeFactory &f) + { + os << f.getName(); + + return os; + } + + virtual + int getFlags() const + { + return 0; + } + + virtual + int getVectorize() const + { + return 0; + } + + bool + isInternal() const + { + return getFlags() & (int) Flags::INTERNAL; + } + + virtual + int start(SuperNode *sn); + + virtual + int stop(); + + State getState() const + { + return state; + } +}; + +template +class NodePlugin : public NodeFactory { + +public: + virtual + Node * make() + { + T* n = new T(); + + init(n); + + return n; + } + + virtual + int getFlags() const + { + return flags; + } + + virtual + int getVectorize() const + { + return vectorize; + } + + virtual std::string + getName() const + { + return name; + } + + virtual std::string + getDescription() const + { + return desc; + } +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node/config.h.in b/include/villas/node/config.hpp.in similarity index 95% rename from include/villas/node/config.h.in rename to include/villas/node/config.hpp.in index df4af11cf..7e81a5c88 100644 --- a/include/villas/node/config.h.in +++ b/include/villas/node/config.hpp.in @@ -5,7 +5,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,7 +26,7 @@ #pragma once -#include +#include /** Default number of values in a sample */ #define DEFAULT_SAMPLE_LENGTH 64u diff --git a/include/villas/node/exceptions.hpp b/include/villas/node/exceptions.hpp index 1e7792f03..76133fb01 100644 --- a/include/villas/node/exceptions.hpp +++ b/include/villas/node/exceptions.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,7 +23,7 @@ #pragma once -#include +#include #include #ifdef WITH_CONFIG diff --git a/include/villas/memory.h b/include/villas/node/memory.hpp similarity index 64% rename from include/villas/memory.h rename to include/villas/node/memory.hpp index 58f72571e..4ba1a74eb 100644 --- a/include/villas/memory.h +++ b/include/villas/node/memory.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,29 +23,34 @@ #pragma once +#ifdef IBVERBS_FOUND + #include +#endif /* IBVERBS_FOUND */ + #include #include -#include -#include +#include +#include -/* Forward declarations */ -struct vnode; +namespace villas { +namespace node { +namespace memory { /** Descriptor of a memory block. Associated block always starts at - * &m + sizeof(struct memory_block). */ -struct memory_block { - struct memory_block *prev; - struct memory_block *next; + * &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; }; /** @todo Unused for now */ -struct memory_allocation { - struct memory_type *type; +struct Allocation { + struct Type *type; - struct memory_allocation *parent; + struct Allocation *parent; void *address; size_t alignment; @@ -58,25 +63,29 @@ struct memory_allocation { } ib; #endif struct { - struct memory_block *block; + struct Block *block; } managed; }; }; /** Initilialize memory subsystem */ -int memory_init(int hugepages) __attribute__ ((warn_unused_result)); +int init(int hugepages) __attribute__ ((warn_unused_result)); -int memory_lock(size_t lock); +int lock(size_t lock); /** Allocate \p len bytes memory of type \p m. * * @retval nullptr If allocation failed. * @retval <>0 If allocation was successful. */ -void * memory_alloc(size_t len, struct memory_type *m = memory_default); +void * alloc(size_t len, struct Type *m = default_type); -void * memory_alloc_aligned(size_t len, size_t alignment, struct memory_type *m = memory_default); +void * alloc_aligned(size_t len, size_t alignment, struct Type *m = default_type); -int memory_free(void *ptr); +int free(void *ptr); -struct memory_allocation * memory_get_allocation(void *ptr); +struct Allocation * get_allocation(void *ptr); + +} /* namespace memory */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/memory_type.h b/include/villas/node/memory_type.hpp similarity index 59% rename from include/villas/memory_type.h rename to include/villas/node/memory_type.hpp index a0c96487f..a7d62d43f 100644 --- a/include/villas/memory_type.h +++ b/include/villas/node/memory_type.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,38 +26,48 @@ #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct memory_type; -struct vnode; +class NodeCompat; -typedef struct memory_allocation * (*memory_allocator_t)(size_t len, size_t alignment, struct memory_type *mem); -typedef int (*memory_deallocator_t)(struct memory_allocation * ma, struct memory_type *mem); +namespace memory { -enum class MemoryFlags { +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); + +enum class Flags { MMAP = (1 << 0), DMA = (1 << 1), HUGEPAGE = (1 << 2), HEAP = (1 << 3) }; -struct memory_type { +struct Type { const char *name; int flags; size_t alignment; - memory_allocator_t alloc; - memory_deallocator_t free; + allocator_t alloc; + deallocator_t free; void *_vd; /**< Virtual data for internal state */ }; -extern struct memory_type memory_heap; -extern struct memory_type memory_mmap; -extern struct memory_type memory_mmap_hugetlb; -extern struct memory_type *memory_default; +extern struct Type heap; +extern struct Type mmap; +extern struct Type mmap_hugetlb; +extern struct Type *default_type; -struct memory_type * memory_ib(struct vnode *n, struct memory_type *parent); -struct memory_type * memory_managed(void *ptr, size_t len); +struct Type * ib(NodeCompat *n, struct Type *parent); +struct Type * managed(void *ptr, size_t len); -int memory_mmap_init(int hugepages) __attribute__ ((warn_unused_result)); +int mmap_init(int hugepages) __attribute__ ((warn_unused_result)); + +} /* namespace memory */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp new file mode 100644 index 000000000..8c2dcfc10 --- /dev/null +++ b/include/villas/node_compat.hpp @@ -0,0 +1,221 @@ +/** Node compatability layer for C++ + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +/** + * @addtogroup node Node + * @{ + */ + +#pragma once + +#include + +#include +#include +#include + +namespace villas { +namespace node { + +/* 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) */ + + std::string _details; + + virtual + int _read(struct Sample *smps[], unsigned cnt); + + virtual + int _write(struct Sample *smps[], unsigned cnt); + +public: + NodeCompat *node; + json_t *cfg; + + NodeCompat(struct NodeCompatType *vt); + NodeCompat(const NodeCompat& n); + + NodeCompat& operator=(const NodeCompat& other); + + virtual + ~NodeCompat(); + + template + T * getData() + { + return static_cast(_vd); + } + + virtual + NodeCompatType * getType() const + { + return _vt; + } + + /** Parse node connection details. + + * + * @param cfg 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 *cfg, const uuid_t sn_uuid); + + /** Returns a string with a textual represenation of this node. */ + virtual + const std::string & getDetails(); + + /** 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 prepare(); + + /** Start this node. + + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + virtual + int start(); + + /** Stop this node. + + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + virtual + int stop(); + + /** 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(); + + /** 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(); + + /** Resume this node. + + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + virtual + int resume(); + + /** Reverse source and destination of a node. + + */ + virtual + int reverse(); + + 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. + */ + virtual + int getNetemFDs(int fds[]); + + /** 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; + +public: + NodeCompatFactory(struct NodeCompatType *vt) : + NodeFactory(), + _vt(vt) + { } + + virtual + Node * make(); + + /// Get plugin name + virtual + std::string getName() const + { + return _vt->name; + } + + /// Get plugin description + virtual + std::string getDescription() const + { + return _vt->description; + } + + virtual + int getFlags() const; + + virtual + int getVectorize() const + { + return _vt->vectorize; + } + + virtual + int start(SuperNode *sn); + + virtual + int stop(); +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node_type.h b/include/villas/node_compat_type.hpp similarity index 77% rename from include/villas/node_type.h rename to include/villas/node_compat_type.hpp index 2d89da9f7..9e0739ae5 100644 --- a/include/villas/node_type.h +++ b/include/villas/node_compat_type.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -19,9 +19,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * @addtogroup node Node - * @{ *********************************************************************************/ #pragma once @@ -29,28 +26,21 @@ #include #include -#include #include -#include +#include #include -/* Forward declarations */ -struct vnode; -struct sample; - namespace villas { namespace node { + +/* Forward declarations */ +struct Sample; +class Node; class SuperNode; -} -} -enum class NodeFlags { - PROVIDES_SIGNALS = (1 << 0), - INTERNAL = (1 << 1) -}; +class NodeCompatType { -/** C++ like vtable construct for node_types */ -struct vnode_type { +public: const char *name; const char *description; @@ -59,8 +49,6 @@ struct vnode_type { enum State state; /**< State of this node-type. */ - villas::node::NodeList instances; /**< A list of all existing nodes of this type. */ - size_t size; /**< Size of private data bock. @see node::_vd */ struct { @@ -72,7 +60,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(villas::node::SuperNode *sn); + int (*start)(SuperNode *sn); /** Global de-initialization per node type. * @@ -92,7 +80,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*init)(struct vnode *n); + int (*init)(NodeCompat *n); /** Free memory of an instance of this type. * @@ -100,7 +88,7 @@ struct vnode_type { * * @param n A pointer to the node object. */ - int (*destroy)(struct vnode *n); + int (*destroy)(NodeCompat *n); /** Parse node connection details. * @@ -111,7 +99,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*parse)(struct vnode *n, json_t *json); + int (*parse)(NodeCompat *n, json_t *json); /** Check the current node configuration for plausability and errors. * @@ -121,9 +109,9 @@ struct vnode_type { * @retval 0 Success. Node configuration is good. * @retval <0 Error. The node configuration is bogus. */ - int (*check)(struct vnode *n); + int (*check)(NodeCompat *n); - int (*prepare)(struct vnode *); + int (*prepare)(NodeCompat *n); /** Returns a string with a textual represenation of this node. * @@ -132,7 +120,7 @@ struct vnode_type { * @param n A pointer to the node object. * @return A pointer to a dynamically allocated string. Must be freed(). */ - char * (*print)(struct vnode *n); + char * (*print)(NodeCompat *n); /** Start this node. * @@ -142,7 +130,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(struct vnode *n); + int (*start)(NodeCompat *n); /** Restart this node. * @@ -152,7 +140,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*restart)(struct vnode *n); + int (*restart)(NodeCompat *n); /** Stop this node. * @@ -162,7 +150,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*stop)(struct vnode *n); + int (*stop)(NodeCompat *n); /** Pause this node. * @@ -172,7 +160,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*pause)(struct vnode *n); + int (*pause)(NodeCompat *n); /** Resume this node. * @@ -182,7 +170,7 @@ struct vnode_type { * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*resume)(struct vnode *n); + int (*resume)(NodeCompat *n); /** Receive multiple messages at once. * @@ -200,7 +188,7 @@ struct vnode_type { * @param release The number of samples that should be released after read is called. * @return The number of messages actually received. */ - int (*read)(struct vnode *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. * @@ -217,7 +205,7 @@ struct vnode_type { * @param release The number of samples that should be released after write is called * @return The number of messages actually sent. */ - int (*write)(struct vnode *n, struct sample * const smps[], unsigned cnt); + int (*write)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); /** Reverse source and destination of a node. * @@ -225,7 +213,7 @@ struct vnode_type { * * @param n A pointer to the node object. */ - int (*reverse)(struct vnode *n); + int (*reverse)(NodeCompat *n); /** Get list of file descriptors which can be used by poll/select to detect the availability of new data. * @@ -233,7 +221,7 @@ struct vnode_type { * * @return The number of file descriptors which have been put into \p fds. */ - int (*poll_fds)(struct vnode *n, int fds[]); + int (*poll_fds)(NodeCompat *n, int fds[]); /** Get list of socket file descriptors for configuring network emulation. * @@ -241,38 +229,11 @@ struct vnode_type { * * @return The number of file descriptors which have been put into \p sds. */ - int (*netem_fds)(struct vnode *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)(struct vnode *n, struct memory_type *parent); - - /** Custom formatter for spdlog */ - template - friend OStream &operator<<(OStream &os, const struct vnode_type &vt) - { - return os << vt.name; - } + struct memory::Type * (*memory_type)(NodeCompat *n, struct memory::Type *parent); }; -/** Initialize all registered node type subsystems. - * - * @see node_type::init - */ -int node_type_start(struct vnode_type *vt, villas::node::SuperNode *sn); - -/** De-initialize node type subsystems. - * - * @see node_type::deinit - */ -int node_type_stop(struct vnode_type *vt); - -/** Return a printable representation of the node-type. */ -const char * node_type_name(struct vnode_type *vt); - -struct vnode_type * node_type_lookup(const std::string &name); - -using NodeTypeList = std::list; - -extern NodeTypeList *node_types; - -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node_direction.h b/include/villas/node_direction.h deleted file mode 100644 index 4610d3a14..000000000 --- a/include/villas/node_direction.h +++ /dev/null @@ -1,84 +0,0 @@ -/** Node direction - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -/** - * @addtogroup node Node - * @{ - */ - -#pragma once - -#include - -#include -#include - -/* Forward declarations */ -struct vnode; -struct vpath; - -enum class NodeDir { - IN, /**< VILLASnode is receiving/reading */ - OUT /**< VILLASnode is sending/writing */ -}; - -struct vnode_direction { - enum State state; - enum NodeDir direction; - - /** 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. - */ - struct vpath *path; - - 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) */ - - struct vlist hooks; /**< List of read / write hooks (struct hook). */ - struct vlist signals; /**< Signal description. */ - - json_t *config; /**< A JSON object containing the configuration of the node. */ -}; - -int node_direction_init(struct vnode_direction *nd, enum NodeDir dir, struct vnode *n) __attribute__ ((warn_unused_result)); - -int node_direction_destroy(struct vnode_direction *nd, struct vnode *n) __attribute__ ((warn_unused_result)); - -int node_direction_parse(struct vnode_direction *nd, struct vnode *n, json_t *json); - -void node_direction_check(struct vnode_direction *nd, struct vnode *n); - -int node_direction_prepare(struct vnode_direction *nd, struct vnode *n); - -int node_direction_start(struct vnode_direction *nd, struct vnode *n); - -int node_direction_stop(struct vnode_direction *nd, struct vnode *n); - -struct vlist * node_direction_get_signals(struct vnode_direction *nd); - -unsigned node_direction_get_signals_max_cnt(struct vnode_direction *nd); - -/** @} */ diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp new file mode 100644 index 000000000..0e6f75e4e --- /dev/null +++ b/include/villas/node_direction.hpp @@ -0,0 +1,80 @@ +/** Node direction + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace villas { +namespace node { + +/* Forward declarations */ +class Node; +class Path; + +class NodeDirection { + friend Node; + +public: + enum class Direction { + IN, /**< VILLASnode is receiving/reading */ + OUT /**< VILLASnode is sending/writing */ + } direction; + + /** 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; + + 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. */ + + json_t *config; /**< A JSON object containing the configuration of the node. */ + + NodeDirection(enum NodeDirection::Direction dir, Node *n); + + int parse(json_t *json); + void check(); + int prepare(); + int start(); + int stop(); + + SignalList::Ptr getSignals(int after_hooks = true) const; + + unsigned getSignalsMaxCount() const; +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index 4cee8f92d..de26e25c6 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -24,24 +24,39 @@ #pragma once #include +#include #include #include -/* Forward declarations */ -struct vnode; - namespace villas { namespace node { -class NodeList : public std::list { +/* Forward declarations */ +class Node; + +class NodeList : public std::list { public: /** Lookup a node from the list based on its name */ - struct vnode * lookup(const std::string &name); + Node * lookup(const std::string &name); /** Lookup a node from the list based on its UUID */ - struct vnode * lookup(const uuid_t &uuid); + Node * lookup(const uuid_t &uuid); + + /** Parse an array or single node and checks if they exist in the "nodes" section. + * + * Examples: + * out = [ "sintef", "scedu" ] + * out = "acs" + * + * @param json A JSON array or string. See examples above. + * @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); + + json_t * toJson() const; }; } /* namespace node */ diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index 191c2c091..904ab15fb 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,21 +21,18 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup amqp amqp node type - * @ingroup node - * @{ - */ - #pragma once #include -#include +#include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; struct amqp_ssl_info { int verify_peer; @@ -58,25 +55,26 @@ struct amqp { amqp_connection_state_t producer; amqp_connection_state_t consumer; - villas::node::Format *formatter; + Format *formatter; }; -/** @see node_type::print */ -char * amqp_print(struct vnode *n); +char * amqp_print(NodeCompat *n); -/** @see node_type::parse */ -int amqp_parse(struct vnode *n, json_t *json); +int amqp_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int amqp_start(struct vnode *n); +int amqp_start(NodeCompat *n); -/** @see node_type::stop */ -int amqp_stop(struct vnode *n); +int amqp_init(NodeCompat *n); -/** @see node_type::read */ -int amqp_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int amqp_destroy(NodeCompat *n); -/** @see node_type::write */ -int amqp_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +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_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index c9919a66c..ca24ede52 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -2,7 +2,7 @@ * * @file * @author Niklas Eiling - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,21 +21,18 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup can CAN bus Node Type - * @ingroup node - * @{ - */ - #pragma once #include -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; -union signal_data; +class NodeCompat; +union SignalData; struct can_signal { uint32_t id; @@ -52,42 +49,32 @@ struct can { /* States */ int socket; - union signal_data *sample_buf; + union SignalData *sample_buf; size_t sample_buf_num; struct timespec start_time; }; -/** @see node_type::init */ -int can_init(struct vnode *n); +int can_init(NodeCompat *n); -/** @see node_type::destroy */ -int can_destroy(struct vnode *n); +int can_destroy(NodeCompat *n); -/** @see node_type::parse */ -int can_parse(struct vnode *n, json_t *json); +int can_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * can_print(struct vnode *n); +char * can_print(NodeCompat *n); -/** @see node_type::check */ -int can_check(); +int can_check(NodeCompat *n); -/** @see node_type::prepare */ -int can_prepare(); +int can_prepare(NodeCompat *n); -/** @see node_type::start */ -int can_start(struct vnode *n); +int can_start(NodeCompat *n); -/** @see node_type::stop */ -int can_stop(struct vnode *n); +int can_stop(NodeCompat *n); -/** @see node_type::write */ -int can_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int can_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::read */ -int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::poll_fds */ -int can_poll_fds(struct vnode *n, int fds[]); +int can_poll_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index c0af5a473..d865eaf18 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,21 +21,18 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup comedi Comedi node type - * @ingroup node - * @{ - */ - #pragma once #include -#include -#include +#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; // whether to use read() or mmap() kernel interface #define COMEDI_USE_READ (1) @@ -82,22 +79,19 @@ struct comedi { }; -/** @see node_type::print */ -char * comedi_print(struct vnode *n); +char * comedi_print(NodeCompat *n); -/** @see node_type::parse */ -int comedi_parse(struct vnode *n, json_t *json); +int comedi_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int comedi_start(struct vnode *n); +int comedi_start(NodeCompat *n); -/** @see node_type::stop */ -int comedi_stop(struct vnode *n); +int comedi_stop(NodeCompat *n); -/** @see node_type::read */ -int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int comedi_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::write */ -int comedi_write(struct vnode *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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 447613963..791a69bb3 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -23,25 +23,23 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup ethercats WebSockets node type - * @ingroup node - * @{ - */ - #pragma once #include -#include +#include #include #include #include #include -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; +class SuperNode; /* Include hard-coded Ethercat Bus configuration */ #include @@ -74,45 +72,39 @@ struct ethercat { std::thread thread; /**< Cyclic task thread */ struct Task task; /**< Periodic timer */ - struct pool pool; - struct queue_signalled queue; /**< For samples which are received from WebSockets */ + 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 */ -/** @see node_type::type_start */ -int ethercat_type_start(struct super_node *sn); +int ethercat_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int ethercat_type_stop(); -/** @see node_type::init */ -int ethercat_init(struct vnode *n); +int ethercat_init(NodeCompat *n); -/** @see node_type::destroy */ -int ethercat_destroy(struct vnode *n); +int ethercat_destroy(NodeCompat *n); -/** @see node_type::parse */ -int ethercat_parse(struct vnode *n, json_t *json); +int ethercat_parse(NodeCompat *n, json_t *json); -/** @see node_type::check */ -int ethercat_check(struct vnode *n); +int ethercat_check(NodeCompat *n); -/** @see node_type::prepare */ -int ethercat_prepare(struct vnode *n); +int ethercat_prepare(NodeCompat *n); -/** @see node_type::open */ -int ethercat_start(struct vnode *n); +int ethercat_start(NodeCompat *n); -/** @see node_type::close */ -int ethercat_stop(struct vnode *n); +int ethercat_stop(NodeCompat *n); -/** @see node_type::read */ -int ethercat_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int ethercat_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::write */ -int ethercat_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +char * ethercat_print(NodeCompat *n); -/** @} */ +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 */ diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index ce9d0d5c2..44ac02520 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,20 +21,17 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup example Example node-type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; struct example { /* Settings */ @@ -47,55 +44,39 @@ struct example { struct timespec start_time; }; -/** @see node_vtable::type_start */ -int example_type_start(villas::node::SuperNode *sn); +int example_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int example_type_stop(); -/** @see node_type::init */ -int example_init(struct vnode *n); +int example_init(NodeCompat *n); -/** @see node_type::destroy */ -int example_destroy(struct vnode *n); +int example_destroy(NodeCompat *n); -/** @see node_type::parse */ -int example_parse(struct vnode *n, json_t *json); +int example_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * example_print(struct vnode *n); +char * example_print(NodeCompat *n); -/** @see node_type::check */ -int example_check(); +int example_check(NodeCompat *n); -/** @see node_type::prepare */ -int example_prepare(); +int example_prepare(NodeCompat *n); -/** @see node_type::start */ -int example_start(struct vnode *n); +int example_start(NodeCompat *n); -/** @see node_type::stop */ -int example_stop(struct vnode *n); +int example_stop(NodeCompat *n); -/** @see node_type::pause */ -int example_pause(struct vnode *n); +int example_pause(NodeCompat *n); -/** @see node_type::resume */ -int example_resume(struct vnode *n); +int example_resume(NodeCompat *n); -/** @see node_type::write */ -int example_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int example_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::read */ -int example_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int example_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::reverse */ -int example_reverse(struct vnode *n); +int example_reverse(NodeCompat *n); -/** @see node_type::poll_fds */ -int example_poll_fds(struct vnode *n, int fds[]); +int example_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::netem_fds */ -int example_netem_fds(struct vnode *n, int fds[]); +int example_netem_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/exec.hpp b/include/villas/nodes/exec.hpp index bc3bc91c4..cd9cf4756 100644 --- a/include/villas/nodes/exec.hpp +++ b/include/villas/nodes/exec.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,53 +21,71 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup exec Execute node-type as a sub-process - * @{ - */ - #pragma once +#include #include #include -/* Forward declarations */ -struct vnode; -struct sample; +namespace villas { +namespace node { -/** Node-type for signal generation. - * @see node_type - */ -struct exec { +/* Forward declarations */ +struct Sample; + +class ExecNode : public Node { + +protected: std::unique_ptr proc; + std::unique_ptr formatter; + + FILE *stream_in, *stream_out; bool flush; bool shell; + std::string working_dir; std::string command; + villas::utils::Popen::arg_list arguments; villas::utils::Popen::env_map environment; - villas::node::Format *formatter; + virtual + int _read(struct Sample * smps[], unsigned cnt); + + virtual + int _write(struct Sample * smps[], unsigned cnt); + +public: + ExecNode(const std::string &name = "") : + Node(name), + stream_in(nullptr), + stream_out(nullptr), + flush(true), + shell(false) + { } + + virtual + ~ExecNode(); + + virtual + const std::string & getDetails(); + + virtual + int start(); + + virtual + int stop(); + + virtual + int prepare(); + + virtual + int parse(json_t *json, const uuid_t sn_uuid); + + virtual + std::vector getPollFDs(); }; -/** @see node_type::print */ -char * exec_print(struct vnode *n); - -/** @see node_type::parse */ -int exec_parse(struct vnode *n, json_t *json); - -/** @see node_type::start */ -int exec_open(struct vnode *n); - -/** @see node_type::stop */ -int exec_close(struct vnode *n); - -/** @see node_type::read */ -int exec_read(struct vnode *n, struct sample * const smps[], unsigned cnt); - -/** @see node_type::write */ -int exec_write(struct vnode *n, struct sample * const smps[], unsigned cnt); - -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index a37fd42c9..56ff2f48f 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,12 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup file File-IO node type - * @ingroup node - * @{ - */ - #pragma once #include @@ -34,19 +28,21 @@ #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; #define FILE_MAX_PATHLEN 512 struct file { - villas::node::Format *formatter; + Format *formatter; FILE *stream_in; FILE *stream_out; char *uri_tmpl; /**< Format string for file name. */ char *uri; /**< Real file name. */ - char *mode; /**< File access mode. */ unsigned skip_lines; /**< Skip the first n-th lines/samples of the file. */ int flush; /**< Flush / upload file contents after each write. */ @@ -74,22 +70,23 @@ struct file { struct timespec offset; /**< An offset between the timestamp in the input file and the current time */ }; -/** @see node_type::print */ -char * file_print(struct vnode *n); +char * file_print(NodeCompat *n); -/** @see node_type::parse */ -int file_parse(struct vnode *n, json_t *json); +int file_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int file_start(struct vnode *n); +int file_start(NodeCompat *n); -/** @see node_type::stop */ -int file_stop(struct vnode *n); +int file_stop(NodeCompat *n); -/** @see node_type::read */ -int file_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int file_init(NodeCompat *n); -/** @see node_type::write */ -int file_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +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_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 d3df4c988..c09aa002c 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,43 +21,43 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup fpga BSD fpga Node Type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include -#include +#include #include #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; using namespace villas; #define FPGA_DMA_VLNV #define FPGA_AURORA_VLNV "acs.eonerc.rwth-aachen.de:user:aurora_axis:" -struct fpga { +struct fpga_node { 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; struct { - villas::MemoryAccessor mem; - villas::MemoryBlock block; + struct { + MemoryAccessor i; + MemoryAccessor f; + } accessor; + MemoryBlock::Ptr block; } in, out; // Config only @@ -66,43 +66,27 @@ struct fpga { std::string dmaName; }; -/** @see node_vtable::type_start */ -int fpga_type_start(villas::node::SuperNode *sn); +int fpga_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int fpga_type_stop(); -/** @see node_type::init */ -int fpga_init(struct vnode *n); +int fpga_init(NodeCompat *n); -/** @see node_type::destroy */ -int fpga_destroy(struct vnode *n); +int fpga_destroy(NodeCompat *n); -/** @see node_type::parse */ -int fpga_parse(struct vnode *n, json_t *json); +int fpga_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * fpga_print(struct vnode *n); +char * fpga_print(NodeCompat *n); -/** @see node_type::check */ -int fpga_check(); +int fpga_check(NodeCompat *n); -/** @see node_type::prepare */ -int fpga_prepare(); +int fpga_prepare(NodeCompat *n); -/** @see node_type::start */ -int fpga_start(struct vnode *n); +int fpga_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::stop */ -int fpga_stop(struct vnode *n); +int fpga_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::write */ -int fpga_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int fpga_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::read */ -int fpga_read(struct vnode *n, struct sample * const smps[], unsigned cnt); - -/** @see node_type::poll_fds */ -int fpga_poll_fds(struct vnode *n, int fds[]); - -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index 253c15331..76872f60a 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,12 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup iec61850_sv IEC 61850-9-2 (Sampled Values) node type - * @ingroup node - * @{ - */ - #pragma once #include @@ -41,16 +35,19 @@ #include #include -#include -#include -#include +#include +#include +#include #ifndef CONFIG_GOOSE_DEFAULT_DST_ADDRESS #define CONFIG_GOOSE_DEFAULT_DST_ADDRESS {0x01, 0x0c, 0xcd, 0x01, 0x00, 0x01} #endif +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; enum class IEC61850Type { /* According to IEC 61850-7-2 */ @@ -103,15 +100,13 @@ struct iec61850_receiver { }; }; -/** @see node_type::type_start */ int iec61850_type_start(villas::node::SuperNode *sn); -/** @see node_type::type_stop */ int iec61850_type_stop(); const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); -int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct vlist *node_signals); +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); @@ -123,4 +118,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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index 33edcbbfa..8d5b274e1 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,12 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup iec61850_sv IEC 61850-9-2 (Sampled Values) node type - * @ingroup node - * @{ - */ - #pragma once #include @@ -35,12 +29,15 @@ #include #include -#include -#include +#include +#include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; struct iec61850_sv { char *interface; @@ -53,10 +50,10 @@ struct iec61850_sv { SVSubscriber subscriber; SVReceiver receiver; - struct queue_signalled queue; - struct pool pool; + struct CQueueSignalled queue; + struct Pool pool; - struct vlist signals; /**< Mappings of type struct iec61850_type_descriptor */ + struct List signals; /**< Mappings of type struct iec61850_type_descriptor */ int total_size; } in; @@ -74,36 +71,28 @@ struct iec61850_sv { int smprate; int confrev; - struct vlist signals; /**< Mappings of type struct iec61850_type_descriptor */ + struct List signals; /**< Mappings of type struct iec61850_type_descriptor */ int total_size; } out; }; -/** @see node_type::type_stop */ int iec61850_sv_type_stop(); -/** @see node_type::parse */ -int iec61850_sv_parse(struct vnode *n, json_t *json); +int iec61850_sv_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * iec61850_sv_print(struct vnode *n); +char * iec61850_sv_print(NodeCompat *n); -/** @see node_type::start */ -int iec61850_sv_start(struct vnode *n); +int iec61850_sv_start(NodeCompat *n); -/** @see node_type::stop */ -int iec61850_sv_stop(struct vnode *n); +int iec61850_sv_stop(NodeCompat *n); -/** @see node_type::destroy */ -int iec61850_sv_destroy(struct vnode *n); +int iec61850_sv_destroy(NodeCompat *n); -/** @see node_type::read */ -int iec61850_sv_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::write */ -int iec61850_sv_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::fd */ -int iec61850_sv_fd(struct vnode *n); +int iec61850_sv_poll_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index 90a11395a..0b846b32d 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -2,7 +2,7 @@ * * @file * @author Dennis Potter - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,21 +21,18 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup infiniband infiniband node type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; /* Constants */ #define META_SIZE 24 @@ -111,28 +108,23 @@ struct infiniband { int is_source; }; -/** @see node_type::reverse */ -int ib_reverse(struct vnode *n); +int ib_reverse(NodeCompat *n); -/** @see node_type::print */ -char * ib_print(struct vnode *n); +char * ib_print(NodeCompat *n); -/** @see node_type::parse */ -int ib_parse(struct vnode *n, json_t *json); +int ib_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int ib_start(struct vnode *n); +int ib_check(NodeCompat *n); -/** @see node_type::destroy */ -int ib_destroy(struct vnode *n); +int ib_start(NodeCompat *n); -/** @see node_type::stop */ -int ib_stop(struct vnode *n); +int ib_destroy(NodeCompat *n); -/** @see node_type::read */ -int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int ib_stop(NodeCompat *n); -/** @see node_type::write */ -int ib_write(struct vnode *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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/influxdb.hpp b/include/villas/nodes/influxdb.hpp index cc8a7149f..61582c75f 100644 --- a/include/villas/nodes/influxdb.hpp +++ b/include/villas/nodes/influxdb.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,46 +21,36 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup influxdb InfluxDB node-type - * @{ - */ - #pragma once -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; -struct sample; +class NodeCompat; +struct Sample; -/** Node-type for signal generation. - * @see node_type - */ struct influxdb { char *host; char *port; char *key; - struct vlist fields; + struct List fields; int sd; }; -/** @see node_type::print */ -char * influxdb_print(struct vnode *n); +char * influxdb_print(NodeCompat *n); -/** @see node_type::parse */ -int influxdb_parse(struct vnode *n, json_t *json); +int influxdb_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int influxdb_open(struct vnode *n); +int influxdb_open(NodeCompat *n); -/** @see node_type::stop */ -int influxdb_close(struct vnode *n); +int influxdb_close(NodeCompat *n); -/** @see node_type::write */ -int influxdb_write(struct vnode *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 894e36e22..7948f7e52 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -21,26 +21,23 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup kafka kafka node type - * @ingroup node - * @{ - */ - #pragma once #include -#include +#include #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; struct kafka { - struct queue_signalled 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. */ @@ -69,40 +66,34 @@ struct kafka { char *password; /**< SSL certificate. */ } sasl; - villas::node::Format *formatter; + Format *formatter; }; -/** @see node_type::reverse */ -int kafka_reverse(struct vnode *n); +int kafka_reverse(NodeCompat *n); -/** @see node_type::print */ -char * kafka_print(struct vnode *n); +char * kafka_print(NodeCompat *n); -/** @see node_type::prepare */ -int kafka_prepare(struct vnode *n); +int kafka_init(NodeCompat *n); -/** @see node_type::parse */ -int kafka_parse(struct vnode *n, json_t *json); +int kafka_prepare(NodeCompat *n); -/** @see node_type::start */ -int kafka_start(struct vnode *n); +int kafka_parse(NodeCompat *n, json_t *json); -/** @see node_type::destroy */ -int kafka_destroy(struct vnode *n); +int kafka_start(NodeCompat *n); -/** @see node_type::stop */ -int kafka_stop(struct vnode *n); +int kafka_destroy(NodeCompat *n); -/** @see node_type::type_start */ -int kafka_type_start(villas::node::SuperNode *sn); +int kafka_stop(NodeCompat *n); + +int kafka_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int kafka_type_stop(); -/** @see node_type::read */ -int kafka_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int kafka_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::write */ -int kafka_write(struct vnode *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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/loopback.hpp b/include/villas/nodes/loopback.hpp index 90a56d98e..9733230dc 100644 --- a/include/villas/nodes/loopback.hpp +++ b/include/villas/nodes/loopback.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,46 +21,49 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup loopback Loopback connections - * @{ - */ - #pragma once +#include + #include -#include -/* Forward declarations */ -struct vnode; -struct sample; +namespace villas { +namespace node { -/** Node-type for signal generation. - * @see node_type - */ -struct loopback { +class LoopbackNode : public Node { + +protected: int queuelen; + struct CQueueSignalled queue; enum QueueSignalledMode mode; - struct queue_signalled queue; + + virtual + int _write(struct Sample * smps[], unsigned cnt); + + virtual + int _read(struct Sample * smps[], unsigned cnt); + +public: + LoopbackNode(const std::string &name = ""); + + virtual + ~LoopbackNode(); + + virtual + int prepare(); + + virtual + int stop(); + + virtual + std::vector getPollFDs(); + + virtual + const std::string & getDetails(); + + virtual + int parse(json_t *json); }; -/** @see node_type::print */ -char * loopback_print(struct vnode *n); - -/** @see node_type::parse */ -int loopback_parse(struct vnode *n, json_t *json); - -/** @see node_type::start */ -int loopback_open(struct vnode *n); - -/** @see node_type::stop */ -int loopback_close(struct vnode *n); - -/** @see node_type::read */ -int loopback_read(struct vnode *n, struct sample * const smps[], unsigned cnt); - -/** @see node_type::write */ -int loopback_write(struct vnode *n, struct sample * const smps[], unsigned cnt); - -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index 844087314..a19dbbe1c 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -1,8 +1,8 @@ -/** Node-type for internal loopback connections. +/** Node type: internal loopback * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,46 +21,74 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup loopback Loopback connections - * @{ - */ - #pragma once +#include #include -#include -/* Forward declarations */ -struct vnode; -struct sample; +namespace villas { +namespace node { -/** Node-type for signal generation. - * @see node_type - */ -struct loopback_internal { - int queuelen; - struct queue_signalled queue; +class InternalLoopbackNode : public Node { - struct vnode *source; +protected: + unsigned queuelen; + struct CQueueSignalled queue; + + Node *source; + + virtual + int _write(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); + + virtual + ~InternalLoopbackNode(); + + virtual + std::vector getPollFDs(); + + virtual + int stop(); }; -/** @see node_type::print */ -char * loopback_internal_print(struct vnode *n); +class InternalLoopbackNodeFactory : public NodeFactory { -/** @see node_type::start */ -int loopback_internal_start(struct vnode *n); +public: + using NodeFactory::NodeFactory; -/** @see node_type::stop */ -int loopback_internal_stop(struct vnode *n); + virtual + Node * make() + { + return nullptr; + } -/** @see node_type::read */ -int loopback_internal_read(struct vnode *n, struct sample * const smps[], unsigned cnt); + 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; + } -/** @see node_type::write */ -int loopback_internal_write(struct vnode *n, struct sample * const smps[], unsigned cnt); + virtual + std::string getName() const + { + return "loopback.internal"; + } -struct vnode * loopback_internal_create(struct vnode *orig); + virtual + std::string getDescription() const + { + return "internal loopback node"; + } +}; -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 261e35f9f..add269db9 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,27 +21,26 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup mqtt mqtt node type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include #include #include /* Forward declarations */ -struct vnode; struct mosquitto; +namespace villas { +namespace node { + +/* Forward declarations */ +class NodeCompat; + struct mqtt { struct mosquitto *client; - struct queue_signalled queue; - struct pool pool; + 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. */ @@ -66,40 +65,36 @@ struct mqtt { } ssl; - villas::node::Format *formatter; + Format *formatter; }; -/** @see node_type::reverse */ -int mqtt_reverse(struct vnode *n); +int mqtt_reverse(NodeCompat *n); -/** @see node_type::print */ -char * mqtt_print(struct vnode *n); +char * mqtt_print(NodeCompat *n); -/** @see node_type::prepare */ -int mqtt_prepare(struct vnode *n); +int mqtt_prepare(NodeCompat *n); -/** @see node_type::parse */ -int mqtt_parse(struct vnode *n, json_t *json); +int mqtt_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int mqtt_start(struct vnode *n); +int mqtt_check(NodeCompat *n); -/** @see node_type::destroy */ -int mqtt_destroy(struct vnode *n); +int mqtt_start(NodeCompat *n); -/** @see node_type::stop */ -int mqtt_stop(struct vnode *n); +int mqtt_init(NodeCompat *n); -/** @see node_type::type_start */ -int mqtt_type_start(villas::node::SuperNode *sn); +int mqtt_destroy(NodeCompat *n); + +int mqtt_stop(NodeCompat *n); + +int mqtt_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int mqtt_type_stop(); -/** @see node_type::read */ -int mqtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int mqtt_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::write */ -int mqtt_write(struct vnode *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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index 66815542d..74c883c8b 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,19 +21,16 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup nanomsg nanomsg node type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; /** The maximum length of a packet which contains stuct msg. */ #define NANOMSG_MAX_PACKET_LEN 1500 @@ -41,28 +38,35 @@ struct vnode; struct nanomsg { struct { int socket; - struct vlist endpoints; + struct List endpoints; } in, out; - villas::node::Format *formatter; + Format *formatter; }; -/** @see node_type::print */ -char * nanomsg_print(struct vnode *n); +char * nanomsg_print(NodeCompat *n); -/** @see node_type::parse */ -int nanomsg_parse(struct vnode *n, json_t *json); +int nanomsg_init(NodeCompat *n); -/** @see node_type::start */ -int nanomsg_start(struct vnode *n); +int nanomsg_destroy(NodeCompat *n); -/** @see node_type::stop */ -int nanomsg_stop(struct vnode *n); +int nanomsg_parse(NodeCompat *n, json_t *json); -/** @see node_type::read */ -int nanomsg_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int nanomsg_start(NodeCompat *n); -/** @see node_type::write */ -int nanomsg_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int nanomsg_stop(NodeCompat *n); -/** @} */ +int nanomsg_type_stop(); + +int nanomsg_reverse(NodeCompat *n); + +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_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 d8e00a706..e21825a0c 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -8,7 +8,7 @@ * @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-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,22 +27,19 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup ngsi FIRWARE NGSI 9/10 RESTful HTTP API - * @ingroup node - * @{ - */ - #pragma once #include #include -#include +#include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; struct ngsi { const char *endpoint; /**< The NGSI context broker endpoint URL. */ @@ -63,41 +60,34 @@ struct ngsi { struct { CURL *curl; /**< libcurl: handle */ - struct vlist signals; /**< A mapping between indices of the VILLASnode samples and the attributes in ngsi::context */ + struct List signals; /**< A mapping between indices of the VILLASnode samples and the attributes in ngsi::context */ } in, out; }; -/** Initialize global NGSI settings and maps shared memory regions. - * - * @see node_type::type_start - */ -int ngsi_type_start(villas::node::SuperNode *sn); -/** Free global NGSI settings and unmaps shared memory regions. - * - * @see node_type::type_stop - */ +int ngsi_type_start(SuperNode *sn); + int ngsi_type_stop(); -/** @see node_type::parse */ -int ngsi_parse(struct vnode *n, json_t *json); +int ngsi_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * ngsi_print(struct vnode *n); +char * ngsi_print(NodeCompat *n); -/** @see node_type::start */ -int ngsi_start(struct vnode *n); +int ngsi_init(NodeCompat *n); -/** @see node_type::stop */ -int ngsi_stop(struct vnode *n); +int ngsi_destroy(NodeCompat *n); -/** @see node_type::reverse */ -int ngsi_reverse(struct vnode *n); +int ngsi_start(NodeCompat *n); -/** @see node_type::read */ -int ngsi_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int ngsi_stop(NodeCompat *n); -/** @see node_type::write */ -int ngsi_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int ngsi_reverse(NodeCompat *n); -/** @} */ +int ngsi_read(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[]); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index b3cc838e8..2fdc1b635 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,20 +21,17 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup opal OPAL-RT Async Process node type - * @{ - */ - #pragma once #include -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; extern "C" { #include @@ -52,39 +49,23 @@ struct opal { Opal_RecvAsyncParam recvParams; }; -/** Initialize global OPAL settings and maps shared memory regions. - * - * @see node_type::type_start - */ -int opal_type_start(villas::node::SuperNode *sn); +int opal_type_start(SuperNode *sn); int opal_register_region(int argc, char *argv[]); -/** Free global OPAL settings and unmaps shared memory regions. - * - * @see node_type::type_stop - */ int opal_type_stop(); -/** @see node_type::parse */ -int opal_parse(struct vnode *n, json_t *json); +int opal_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * opal_print(struct vnode *n); +char * opal_print(NodeCompat *n); -/** Print global settings of the OPAL node type. */ -int opal_print_global(); +int opal_start(NodeCompat *n); -/** @see node_type::start */ -int opal_start(struct vnode *n); +int opal_stop(NodeCompat *n); -/** @see node_type::stop */ -int opal_stop(struct vnode *n); +int opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::read */ -int opal_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::write */ -int opal_write(struct vnode *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 7aa801c3b..9364bb18e 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -21,12 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup redis BSD redis Node Type - * @ingroup node - * @{ - */ - #pragma once #include @@ -35,14 +29,17 @@ #include -#include -#include -#include +#include +#include +#include #include #include -#include +#include #include +namespace villas { +namespace node { + enum class RedisMode { KEY, HASH, @@ -68,7 +65,7 @@ protected: void loop(); - std::unordered_multimap subscriberMap; + std::unordered_multimap subscriberMap; sw::redis::Subscriber subscriber; @@ -84,8 +81,8 @@ public: void start(); void stop(); - void subscribe(struct vnode *n, const std::string &channel); - void unsubscribe(struct vnode *n, const std::string &channel); + void subscribe(NodeCompat *n, const std::string &channel); + void unsubscribe(NodeCompat *n, const std::string &channel); }; struct redis { @@ -102,55 +99,41 @@ struct redis { struct Task task; /**< Timer for periodic events. */ double rate; /**< Rate for polling key updates if keyspace notifications are disabled. */ - villas::node::Format *formatter; + Format *formatter; - struct pool pool; - struct queue_signalled queue; + struct Pool pool; + struct CQueueSignalled queue; }; -/** @see node_type::init */ -int redis_init(struct vnode *n); +int redis_init(NodeCompat *n); -/** @see node_type::destroy */ -int redis_destroy(struct vnode *n); +int redis_destroy(NodeCompat *n); -/** @see node_type::parse */ -int redis_parse(struct vnode *n, json_t *json); +int redis_parse(NodeCompat *n, json_t *json); -/** @see node_type::print */ -char * redis_print(struct vnode *n); +char * redis_print(NodeCompat *n); -/** @see node_type::check */ -int redis_check(); +int redis_check(NodeCompat *n); -/** @see node_type::prepare */ -int redis_prepare(); +int redis_prepare(NodeCompat *n); -/** @see node_type::start */ -int redis_start(struct vnode *n); +int redis_start(NodeCompat *n); -/** @see node_type::stop */ -int redis_stop(struct vnode *n); +int redis_stop(NodeCompat *n); -/** @see node_type::pause */ -int redis_pause(struct vnode *n); +int redis_pause(NodeCompat *n); -/** @see node_type::resume */ -int redis_resume(struct vnode *n); +int redis_resume(NodeCompat *n); -/** @see node_type::write */ -int redis_write(struct vnode *n, struct sample *smps[], unsigned cnt, unsigned *release); +int redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::read */ -int redis_read(struct vnode *n, struct sample *smps[], unsigned cnt, unsigned *release); +int redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::reverse */ -int redis_reverse(struct vnode *n); +int redis_reverse(NodeCompat *n); -/** @see node_type::poll_fds */ -int redis_poll_fds(struct vnode *n, int fds[]); +int redis_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::netem_fds */ -int redis_netem_fds(struct vnode *n, int fds[]); +int redis_netem_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index c53e9afcd..2b9f979f3 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -21,12 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup redis BSD redis Node Type - * @ingroup node - * @{ - */ - #pragma once #include @@ -34,7 +28,7 @@ #include #include -#include +#include namespace std { @@ -191,23 +185,21 @@ OStream &operator<<(OStream &os, const ConnectionOptions &o) } /* namespace sw */ template -OStream &operator<<(OStream &os, const enum RedisMode &m) +OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) { switch (m) { - case RedisMode::KEY: + case villas::node::RedisMode::KEY: os << "key"; break; - case RedisMode::HASH: + case villas::node::RedisMode::HASH: os << "hash"; break; - case RedisMode::CHANNEL: + case villas::node::RedisMode::CHANNEL: os << "channel"; break; } return os; } - -/** @} */ diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index 976b68033..29ac1e380 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -3,7 +3,7 @@ * @file * @author Steffen Vogel * @author Marvin Klimke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,19 +22,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup rtp rtp node type - * @ingroup node - * @{ - */ - #pragma once #include #include -#include +#include #include #include #include @@ -42,14 +36,18 @@ #include #include -/* Forward declarations */ -struct vnode; - extern "C" { #include #include } +namespace villas { +namespace node { + +/* Forward declarations */ +class NodeCompat; +class SuperNode; + /** The maximum length of a packet which contains rtp data. */ #define RTP_INITIAL_BUFFER_LEN 1500 #define RTP_PACKET_TYPE 21 @@ -68,7 +66,7 @@ struct rtp { struct sa saddr_rtcp; /**< Local/Remote address of the RTCP socket */ } in, out; - villas::node::Format *formatter; + Format *formatter; struct { int enabled; @@ -82,41 +80,49 @@ struct rtp { enum RTPHookType rate_hook_type; - villas::node::LimitHook *rate_hook; - villas::dsp::PID rate_pid; + LimitHook::Ptr rate_hook; + dsp::PID rate_pid; /* PID parameters for rate controller */ double Kp, Ki, Kd; double rate_min; double rate; - double rate_last; double rate_source; /**< Sample rate of source */ std::ofstream *log; char *log_filename; } aimd; /** AIMD state */ - struct queue_signalled recv_queue; + struct CQueueSignalled recv_queue; struct mbuf *send_mb; }; -/** @see node_type::print */ -char * rtp_print(struct vnode *n); +char * rtp_print(NodeCompat *n); -/** @see node_type::parse */ -int rtp_parse(struct vnode *n, json_t *json); +int rtp_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int rtp_start(struct vnode *n); +int rtp_init(NodeCompat *n); -/** @see node_type::stop */ -int rtp_stop(struct vnode *n); +int rtp_destroy(NodeCompat *n); -/** @see node_type::read */ -int rtp_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int rtp_reverse(NodeCompat *n); -/** @see node_type::write */ -int rtp_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int rtp_type_start(SuperNode *sn); -/** @} */ +int rtp_type_stop(); + +int rtp_start(NodeCompat *n); + +int rtp_stop(NodeCompat *n); + +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_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 3175f0332..bf06fbf3e 100644 --- a/include/villas/nodes/shmem.hpp +++ b/include/villas/nodes/shmem.hpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,50 +21,43 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup shmem_node Shared memory node type - * @{ - */ - #pragma once -#include -#include +#include +#include #include -#include -#include +#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; -/** Node-type for shared memory communication. - * @see node_type - */ 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 shmem_conf conf; /**< Interface configuration struct. */ + struct ShmemConfig conf; /**< Interface configuration struct. */ char **exec; /**< External program to execute on start. */ - struct shmem_int intf; /**< Shmem interface */ + struct ShmemInterface intf; /**< Shmem interface */ }; -/** @see node_type::print */ -char * shmem_print(struct vnode *n); +char * shmem_print(NodeCompat *n); -/** @see node_type::parse */ -int shmem_parse(struct vnode *n, json_t *json); +int shmem_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int shmem_start(struct vnode *n); +int shmem_start(NodeCompat *n); -/** @see node_type::stop */ -int shmem_stop(struct vnode *n); +int shmem_stop(NodeCompat *n); -/** @see node_type::read */ -int shmem_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int shmem_init(NodeCompat *n); -/** @see node_type::write */ -int shmem_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int shmem_prepare(NodeCompat *n); -/** @} */ +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 */ diff --git a/include/villas/nodes/signal.hpp b/include/villas/nodes/signal.hpp new file mode 100644 index 000000000..939e6a729 --- /dev/null +++ b/include/villas/nodes/signal.hpp @@ -0,0 +1,122 @@ +/** Node-type for signal generation. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace villas { +namespace node { + +/* Forward declarations */ +struct Sample; + +class SignalNodeSignal { + +public: + enum class Type { + RANDOM, + SINE, + SQUARE, + TRIANGLE, + RAMP, + COUNTER, + CONSTANT, + PULSE, + MIXED + }; + + 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. */ + +public: + SignalNodeSignal(json_t *json); + + int parse(json_t *json); + + static + enum Type lookupType(const std::string &type); + + static + std::string typeToString(enum Type type); + + void start(); + + void read(unsigned c, double t, double rate, SignalData *d); + + Signal::Ptr toSignal(Signal::Ptr tpl) const; +}; + +class SignalNode : public Node { + +protected: + std::vector signals; + + 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. */ + + struct timespec started; /**< Point in time when this node was started. */ + unsigned missed_steps; /**< Total number of missed steps. */ + +public: + SignalNode(const std::string &name = ""); + + virtual + const std::string & getDetails(); + + virtual + int parse(json_t *json, const uuid_t sn_uuid); + + virtual + int start(); + + virtual + int stop(); + + virtual + int prepare(); + + virtual + int _read(struct Sample *smps[], unsigned cnt); + + virtual + std::vector getPollFDs(); +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/signal_generator.hpp b/include/villas/nodes/signal_old.hpp similarity index 76% rename from include/villas/nodes/signal_generator.hpp rename to include/villas/nodes/signal_old.hpp index d66b7ea12..19bf883cb 100644 --- a/include/villas/nodes/signal_generator.hpp +++ b/include/villas/nodes/signal_old.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,25 +21,19 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup signal_generator Signal generation node-type- - * @{ - */ - #pragma once -#include +#include #include -/* Forward declarations */ -struct vnode; -struct sample; +namespace villas { +namespace node { -/** Node-type for signal generation. - * @see node_type - */ -struct signal_generator { +/* Forward declarations */ +class NodeCompat; +struct Sample; + +struct signal_node { struct Task task; /**< Timer for periodic events. */ int rt; /**< Real-time mode? */ @@ -76,19 +70,23 @@ struct signal_generator { unsigned missed_steps; /**< Total number of missed steps. */ }; -/** @see node_type::print */ -char * signal_generator_print(struct vnode *n); +char * signal_node_print(NodeCompat *n); -/** @see node_type::parse */ -int signal_generator_parse(struct vnode *n, json_t *json); +int signal_node_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int signal_generator_start(struct vnode *n); +int signal_node_start(NodeCompat *n); -/** @see node_type::stop */ -int signal_generator_stop(struct vnode *n); +int signal_node_stop(NodeCompat *n); -/** @see node_type::read */ -int signal_generator_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int signal_node_init(NodeCompat *n); -/** @} */ +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_poll_fds(NodeCompat *n, int fds[]); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index c3a1dd5b9..e21d01369 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,31 +21,28 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup socket BSD Socket Node Type - * @ingroup node - * @{ - */ - #pragma once -#include -#include +#include +#include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; /** The maximum length of a packet which contains stuct msg. */ #define SOCKET_INITIAL_BUFFER_LEN (64*1024) -struct socket { +struct Socket { 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 */ - villas::node::Format *formatter; + Format *formatter; /* Multicast options */ struct multicast { @@ -63,28 +60,31 @@ struct socket { }; -/** @see node_vtable::type_start */ -int socket_type_start(villas::node::SuperNode *sn); +int socket_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int socket_type_stop(); -/** @see node_type::start */ -int socket_start(struct vnode *n); +int socket_init(NodeCompat *n); -/** @see node_type::stop */ -int socket_stop(struct vnode *n); +int socket_destroy(NodeCompat *n); -/** @see node_type::write */ -int socket_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int socket_start(NodeCompat *n); -/** @see node_type::read */ -int socket_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int socket_check(NodeCompat *n); -/** @see node_type::parse */ -int socket_parse(struct vnode *n, json_t *json); +int socket_stop(NodeCompat *n); -/** @see node_type::print */ -char * socket_print(struct vnode *n); +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_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + +int socket_parse(NodeCompat *n, json_t *json); + +char * socket_print(NodeCompat *n); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/stats.hpp b/include/villas/nodes/stats.hpp index 00d6b2264..be94e7099 100644 --- a/include/villas/nodes/stats.hpp +++ b/include/villas/nodes/stats.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,25 +21,22 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup stats Sending stats - * @{ - */ - #pragma once #include #include #include -#include +#include + +namespace villas { +namespace node { /* Forward declarations */ -struct vnode; +class NodeCompat; struct stats_node_signal { - struct vnode *node; + Node *node; char *node_str; enum villas::Stats::Metric metric; @@ -51,27 +48,34 @@ struct stats_node { struct Task task; - struct vlist signals; /** List of type struct stats_node_signal */ + struct List signals; /** List of type struct stats_node_signal */ }; -/** @see node_type::print */ -int stats_node_type_start(villas::node::SuperNode *sn); +int stats_node_type_start(SuperNode *sn); -/** @see node_type::print */ -char *stats_node_print(struct vnode *n); +int stats_node_init(NodeCompat *n); -/** @see node_type::parse */ -int stats_node_parse(struct vnode *n, json_t *json); +int stats_node_destroy(NodeCompat *n); + +char *stats_node_print(NodeCompat *n); + +int stats_node_parse(NodeCompat *n, json_t *json); + +int stats_node_prepare(NodeCompat *n); + +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_parse_signal(struct stats_node_signal *s, json_t *json); -/** @see node_type::start */ -int stats_node_start(struct vnode *n); +int stats_node_signal_destroy(struct stats_node_signal *s); -/** @see node_type::stop */ -int stats_node_stop(struct vnode *n); +int stats_node_signal_parse(struct stats_node_signal *s, json_t *json); -/** @see node_type::read */ -int stats_node_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int stats_node_poll_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index 1a9187c83..1038c7278 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,22 +21,19 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup temper BSD temper Node Type - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include -#include +#include #include #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; +class NodeCompat; class TEMPerDevice : public villas::usb::Device { @@ -67,7 +64,7 @@ public: virtual bool hasHumiditySensor() const { return false; }; - void read(struct sample *smp); + void read(struct Sample *smp); }; class TEMPer1Device : public TEMPerDevice { @@ -129,55 +126,41 @@ struct temper { TEMPerDevice *device; }; -/** @see node_vtable::type_start */ -int temper_type_start(villas::node::SuperNode *sn); +int temper_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int temper_type_stop(); -/** @see node_type::init */ -int temper_init(struct vnode *n); +int temper_init(NodeCompat *n); -/** @see node_type::destroy */ -int temper_destroy(struct vnode *n); +int temper_prepare(NodeCompat *n); -/** @see node_type::parse */ -int temper_parse(struct vnode *n, json_t *json); +int temper_destroy(NodeCompat *n); -/** @see node_type::print */ -char * temper_print(struct vnode *n); +int temper_parse(NodeCompat *n, json_t *json); + +char * temper_print(NodeCompat *n); -/** @see node_type::check */ int temper_check(); -/** @see node_type::prepare */ int temper_prepare(); -/** @see node_type::start */ -int temper_start(struct vnode *n); +int temper_start(NodeCompat *n); -/** @see node_type::stop */ -int temper_stop(struct vnode *n); +int temper_stop(NodeCompat *n); -/** @see node_type::pause */ -int temper_pause(struct vnode *n); +int temper_pause(NodeCompat *n); -/** @see node_type::resume */ -int temper_resume(struct vnode *n); +int temper_resume(NodeCompat *n); -/** @see node_type::write */ -int temper_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int temper_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::read */ -int temper_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); -/** @see node_type::reverse */ -int temper_reverse(struct vnode *n); +int temper_reverse(NodeCompat *n); -/** @see node_type::poll_fds */ -int temper_poll_fds(struct vnode *n, int fds[]); +int temper_poll_fds(NodeCompat *n, int fds[]); -/** @see node_type::netem_fds */ -int temper_netem_fds(struct vnode *n, int fds[]); +int temper_netem_fds(NodeCompat *n, int fds[]); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/test_rtt.hpp b/include/villas/nodes/test_rtt.hpp index 3b45af42a..e2ab75303 100644 --- a/include/villas/nodes/test_rtt.hpp +++ b/include/villas/nodes/test_rtt.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,22 +21,20 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup test-rtt Node-type for testing Round-trip Time. - * @ingroup node - * @{ - */ - #pragma once -#include +#include #include #include +namespace villas { +namespace node { + /* Forward declarations */ +class NodeCompat; +struct Sample; + struct test_rtt; -struct vnode; -struct sample; struct test_rtt_case { double rate; @@ -46,12 +44,12 @@ struct test_rtt_case { char *filename; char *filename_formatted; - struct vnode *node; + NodeCompat *node; }; struct test_rtt { struct Task task; /**< The periodic task for test_rtt_read() */ - villas::node::Format *formatter;/**< The format of the output file */ + Format *formatter;/**< The format of the output file */ FILE *stream; double cooldown; /**< Number of seconds to wait beween tests. */ @@ -59,28 +57,31 @@ struct test_rtt { int current; /**< Index of current test in test_rtt::cases */ int counter; - struct vlist 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. */ }; -/** @see node_type::print */ -char * test_rtt_print(struct vnode *n); +char * test_rtt_print(NodeCompat *n); -/** @see node_type::parse */ -int test_rtt_parse(struct vnode *n, json_t *json); +int test_rtt_parse(NodeCompat *n, json_t *json); -/** @see node_type::start */ -int test_rtt_start(struct vnode *n); +int test_rtt_prepare(NodeCompat *n); -/** @see node_type::stop */ -int test_rtt_stop(struct vnode *n); +int test_rtt_init(NodeCompat *n); -/** @see node_type::read */ -int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int test_rtt_destroy(NodeCompat *n); -/** @see node_type::write */ -int test_rtt_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +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_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + +int test_rtt_poll_fds(NodeCompat *n, int fds[]); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/nodes/uldaq.hpp b/include/villas/nodes/uldaq.hpp index d0586ccd2..09d15ec11 100644 --- a/include/villas/nodes/uldaq.hpp +++ b/include/villas/nodes/uldaq.hpp @@ -3,7 +3,7 @@ * @file * @author Manuel Pitz * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,24 +22,21 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @ingroup node - * @addtogroup uldaq Read USB analog to digital converters - * @{ - */ - #pragma once #include #include -#include +#include #include #define ULDAQ_MAX_DEV_COUNT 100 #define ULDAQ_MAX_RANGE_COUNT 8 +namespace villas { +namespace node { + struct uldaq { const char *device_id; @@ -71,4 +68,24 @@ struct uldaq { } out; }; -/** @} */ +int uldaq_type_start(SuperNode *sn); + +int uldaq_init(NodeCompat *n); + +int uldaq_destroy(NodeCompat *n); + +int uldaq_parse(NodeCompat *n, json_t *json); + +char * uldaq_print(NodeCompat *n); + +int uldaq_check(NodeCompat *n); + +int uldaq_start(NodeCompat *n); + +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/websocket.hpp b/include/villas/nodes/websocket.hpp index 45eb48ee1..da048795a 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,37 +21,35 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup websockets WebSockets node type - * @ingroup node - * @{ - */ - #pragma once #include -#include +#include #include #include #include #include -#include - -/* Forward declarations */ -struct vnode; - -#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) +#include +#include /* Forward declaration */ struct lws; +namespace villas { +namespace node { + +/* Forward declarations */ +class NodeCompat; + +#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) + /** Internal data per websocket node */ struct websocket { - struct vlist 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). */ - struct pool pool; - struct queue_signalled queue; /**< For samples which are received from WebSockets */ + struct Pool pool; + struct CQueueSignalled queue; /**< For samples which are received from WebSockets */ }; struct websocket_destination { @@ -77,9 +75,9 @@ struct websocket_connection { } mode; struct lws *wsi; - struct vnode *node; - villas::node::Format *formatter; - struct queue queue; /**< For samples which are sent to the Websocket */ + NodeCompat *node; + Format *formatter; + struct CQueue queue; /**< For samples which are sent to the Websocket */ struct websocket_destination *destination; @@ -114,25 +112,25 @@ struct websocket_connection { int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); -/** @see node_type::type_start */ -int websocket_type_start(villas::node::SuperNode *sn); +int websocket_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int websocket_type_stop(); -/** @see node_type::start */ -int websocket_start(struct vnode *n); +int websocket_parse(NodeCompat *n, json_t *j); -/** @see node_type::stop */ -int websocket_stop(struct vnode *n); +char * websocket_print(NodeCompat *n); -/** @see node_type::stop */ -int websocket_destroy(struct vnode *n); +int websocket_start(NodeCompat *n); -/** @see node_type::read */ -int websocket_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int websocket_stop(NodeCompat *n); -/** @see node_type::write */ -int websocket_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +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_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 7b124ecd5..83fd0474c 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,33 +21,30 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup zeromq ZeroMQ node type - * @ingroup node - * @{ - */ - #pragma once #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 #endif +namespace villas { +namespace node { + /* Forward declarations */ -struct vnode; -struct sample; +class NodeCompat; +struct Sample; struct zeromq { int ipv6; - villas::node::Format *formatter; + Format *formatter; struct Curve { int enabled; @@ -67,34 +64,39 @@ struct zeromq { struct Dir { void *socket; /**< ZeroMQ socket. */ void *mon_socket; - struct vlist endpoints; + struct List endpoints; char *filter; int bind, pending; } in, out; }; -/** @see node_type::print */ -char * zeromq_print(struct vnode *n); +char * zeromq_print(NodeCompat *n); -/** @see node_type::parse */ -int zeromq_parse(struct vnode *n, json_t *json); +int zeromq_parse(NodeCompat *n, json_t *json); -/** @see node_type::type_start */ -int zeromq_type_start(villas::node::SuperNode *sn); +int zeromq_type_start(SuperNode *sn); -/** @see node_type::type_stop */ int zeromq_type_stop(); -/** @see node_type::start */ -int zeromq_start(struct vnode *n); +int zeromq_init(NodeCompat *n); -/** @see node_type::stop */ -int zeromq_stop(struct vnode *n); +int zeromq_destroy(NodeCompat *n); -/** @see node_type::read */ -int zeromq_read(struct vnode *n, struct sample * const smps[], unsigned cnt); +int zeromq_check(NodeCompat *n); -/** @see node_type::write */ -int zeromq_write(struct vnode *n, struct sample * const smps[], unsigned cnt); +int zeromq_start(NodeCompat *n); -/** @} */ +int zeromq_stop(NodeCompat *n); + +int zeromq_reverse(NodeCompat *n); + +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_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/path.h b/include/villas/path.h deleted file mode 100644 index f1dd4a928..000000000 --- a/include/villas/path.h +++ /dev/null @@ -1,195 +0,0 @@ -/** Message paths - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -/** A path connects one input node to multiple output nodes (1-to-n). - * - * @addtogroup path Path - * @{ - */ - -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Forward declarations */ -struct vnode; - -/** The register mode determines under which condition the path is triggered. */ -enum class PathMode { - ANY, /**< The path is triggered whenever one of the sources receives samples. */ - ALL /**< The path is triggered only after all sources have received at least 1 sample. */ -}; - -/** The datastructure for a path. */ -struct vpath { - enum State state; /**< Path state. */ - - enum PathMode mode; /**< Determines when this path is triggered. */ - - uuid_t uuid; - - struct { - int nfds; - struct pollfd *pfds; - } reader; - - struct pool pool; - struct sample *last_sample; - int last_sequence; - - struct vlist sources; /**< List of all incoming nodes (struct vpath_source). */ - struct vlist destinations; /**< List of all outgoing nodes (struct vpath_destination). */ - struct vlist mappings; /**< List of all input mappings (struct mapping_entry). */ - struct vlist hooks; /**< List of processing hooks (struct hook). */ - struct vlist signals; /**< List of signals which this path creates (struct signal). */ - - struct Task timeout; - - double rate; /**< A timeout for */ - int enabled; /**< Is this path enabled? */ - int muxed; /**< Is this path muxed? */ - int affinity; /**< Thread affinity. */ - int poll; /**< Weather or not to use poll(2). */ - int reverse; /**< This path has a matching reverse path. */ - int 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. */ - - villas::Logger logger; - - std::list mask_list; - - std::bitset mask; /**< A mask of path_sources which are enabled for poll(). */ - std::bitset received; /**< A mask of path_sources for which we already received samples. */ - - /** Custom formatter for spdlog */ - template - friend OStream &operator<<(OStream &os, const struct vpath &p) - { - os << "["; - - for (size_t i = 0; i < vlist_length(&p.sources); i++) { - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p.sources, i); - - os << " " << node_name_short(ps->node); - } - - os << " ] " CLR_MAG("=>") " ["; - - for (size_t i = 0; i < vlist_length(&p.destinations); i++) { - struct vpath_destination *pd = (struct vpath_destination *) vlist_at(&p.destinations, i); - - os << " " << node_name_short(pd->node); - } - - os << " ]"; - - return os; - } -}; - -/** Initialize internal data structures. */ -int path_init(struct vpath *p) __attribute__ ((warn_unused_result)); - -int path_prepare(struct vpath *p, villas::node::NodeList &nodes); - -/** Check if path configuration is proper. */ -void path_check(struct vpath *p); - -/** Start a path. - * - * Start a new pthread for receiving/sending messages over this path. - * - * @param p A pointer to the path structure. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int path_start(struct vpath *p); - -/** Stop a path. - * - * @param p A pointer to the path structure. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int path_stop(struct vpath *p); - -/** Destroy path by freeing dynamically allocated memory. - * - * @param i A pointer to the path structure. - */ -int path_destroy(struct vpath *p) __attribute__ ((warn_unused_result)); - -/** Get a list of signals which is emitted by the path. */ -struct vlist * path_output_signals(struct vpath *p); - -unsigned path_output_signals_max_cnt(struct vpath *p); - -/** Reverse a path */ -int path_reverse(struct vpath *p, struct vpath *r); - -/** 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 - * @param nodes A linked list of all existing nodes - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int path_parse(struct vpath *p, json_t *json, villas::node::NodeList &nodes, const uuid_t sn_uuid); - -void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList &nodes); - -bool path_is_simple(const struct vpath *p); - -bool path_is_muxed(const struct vpath *p); - -bool path_is_enabled(const struct vpath *p); - -bool path_is_reversed(const struct vpath *p); - -json_t * path_to_json(struct vpath *p); - -/** @} */ diff --git a/include/villas/path.hpp b/include/villas/path.hpp new file mode 100644 index 000000000..64ad69ffb --- /dev/null +++ b/include/villas/path.hpp @@ -0,0 +1,203 @@ +/** Message paths + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Forward declarations */ +struct pollfd; + +namespace villas { +namespace node { + +/* Forward declarations */ +class Node; + +/** The datastructure for a path. */ +class Path { + friend PathSource; + friend SecondaryPathSource; + friend PathDestination; + +protected: + void * runSingle(); + void * runPoll(); + + static + void * runWrapper(void *arg); + + void startPoll(); + + static int id; + +public: + 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. */ + + uuid_t uuid; + + std::vector pfds; + + 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. */ + + 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 */ + + 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. */ + + /** 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() << " "; + + if (p.sources.size() > 1) + os << "] "; + + os << CLR_MAG("=>"); + + if (p.destinations.size() > 1) + os << " ["; + + for (auto pd : p.destinations) + os << " " << pd->getNode()->getNameShort(); + + if (p.destinations.size() > 1) + os << " ]"; + + return os; + } + + Path(); + ~Path(); + + void prepare(NodeList &nodes); + + /** Check if path configuration is proper. */ + void check(); + + /** Check prepared path. */ + void checkPrepared(); + + /** Start a path. + * + * Start a new pthread for receiving/sending messages over this path. + */ + void start(); + + /** Stop a path. */ + void stop(); + + /** 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. + * + * @param json A JSON object containing the configuration of the path. + * @param p Pointer to the allocated memory for this path + * @param nodes A linked list of all existing nodes + * @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 parseMask(json_t *json_mask, NodeList &nodes); + + bool isSimple() const; + bool isMuxed() const; + + bool isEnabled() const + { + return enabled; + } + + bool isReversed() const + { + return reversed; + } + + State getState() const + { + return state; + } + + json_t * toJson() const; +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/path_destination.h b/include/villas/path_destination.hpp similarity index 55% rename from include/villas/path_destination.h rename to include/villas/path_destination.hpp index b5aca6b82..200984d4e 100644 --- a/include/villas/path_destination.h +++ b/include/villas/path_destination.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,36 +21,54 @@ * along with this program. If not, see . *********************************************************************************/ -/** A path connects one input node to multiple output nodes (1-to-n). - * - * @addtogroup path Path - * @{ - */ - #pragma once +#include + #include +namespace villas { +namespace node { + /* Forward declarations */ -struct vpath; -struct sample; +class Node; +class Path; +struct Sample; +class PathDestination; -struct vpath_destination { - struct vnode *node; +class PathDestination { + friend Path; - struct queue queue; +public: + using Ptr = std::shared_ptr; + +protected: + Node *node; + Path *path; + + struct CQueue queue; + +public: + PathDestination(Path *p, Node *n); + + ~PathDestination(); + + int prepare(int queuelen); + + void check(); + + static + void enqueueAll(class Path *p, const struct Sample * const smps[], unsigned cnt); + + void write(); + + Node * getNode() const + { + return node; + } }; -int path_destination_init(struct vpath_destination *pd, struct vnode *n) __attribute__ ((warn_unused_result)); +using PathDestinationList = std::vector; -int path_destination_destroy(struct vpath_destination *pd) __attribute__ ((warn_unused_result)); - -int path_destination_prepare(struct vpath_destination *pd, int queuelen); - -void path_destination_check(struct vpath_destination *pd); - -void path_destination_enqueue(struct vpath *p, const struct sample * const smps[], unsigned cnt); - -void path_destination_write(struct vpath_destination *pd, struct vpath *p); - -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 31bec2522..f2d5a83d7 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -24,21 +24,24 @@ #pragma once #include +#include #include #include -/* Forward declarations */ -struct vpath; - namespace villas { namespace node { -class PathList : public std::list { +/* Forward declarations */ +class Path; + +class PathList : public std::list { public: /** Lookup a path from the list based on its UUID */ - struct vpath * lookup(const uuid_t &uuid); + Path * lookup(const uuid_t &uuid) const; + + json_t * toJson() const; }; } /* namespace node */ diff --git a/include/villas/path_source.h b/include/villas/path_source.h deleted file mode 100644 index c3cc237da..000000000 --- a/include/villas/path_source.h +++ /dev/null @@ -1,66 +0,0 @@ -/** Message source - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -/** A path connects one input node to multiple output nodes (1-to-n). - * - * @addtogroup path Path - * @{ - */ - -#pragma once - -#include -#include - -/* Forward declarations */ -struct vpath; -struct sample; - -enum PathSourceType { - MASTER, - SECONDARY -}; - -struct vpath_source { - struct vnode *node; - - bool masked; - - enum PathSourceType type; - - struct pool pool; - struct vlist mappings; /**< List of mappings (struct mapping_entry). */ - struct vlist secondaries; /**< List of secondary path sources (struct path_sourced). */ -}; - -int path_source_init_master(struct vpath_source *ps, struct vnode *n) __attribute__ ((warn_unused_result)); - -int path_source_init_secondary(struct vpath_source *ps, struct vnode *n) __attribute__ ((warn_unused_result)); - -int path_source_destroy(struct vpath_source *ps) __attribute__ ((warn_unused_result)); - -void path_source_check(struct vpath_source *ps); - -int path_source_read(struct vpath_source *ps, struct vpath *p, int i); - -/** @} */ diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp new file mode 100644 index 000000000..85515cf46 --- /dev/null +++ b/include/villas/path_source.hpp @@ -0,0 +1,119 @@ +/** Message source + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include +#include + +#include +#include + +namespace villas { +namespace node { + +/* Forward declarations */ +struct Sample; +class Node; +class Path; + +class PathSource { + friend Path; + +public: + using Ptr = std::shared_ptr; + +protected: + Node *node; + Path *path; + + bool masked; + + struct Pool pool; + + MappingList mappings; /**< List of mappings (struct MappingEntry). */ + +public: + PathSource(Path *p, Node *n); + virtual ~PathSource(); + + void check(); + + int read(int i); + + virtual + void writeToSecondaries(struct Sample *smps[], unsigned cnt) + { } + + Node * getNode() const + { + return node; + } + + Path * getPath() const + { + return path; + } +}; + +using PathSourceList = std::vector; + +class SecondaryPathSource : public PathSource { + +protected: + PathSource::Ptr master; + +public: + using Ptr = std::shared_ptr; + + SecondaryPathSource(Path *p, Node *n, NodeList &nodes, PathSource::Ptr master); +}; + +using SecondaryPathSourceList = std::vector; + +class MasterPathSource : public PathSource { + +protected: + SecondaryPathSourceList secondaries; /**< List of secondary path sources (PathSource). */ + +public: + MasterPathSource(Path *p, Node *n); + + void addSecondary(SecondaryPathSource::Ptr ps) + { + secondaries.push_back(ps); + } + + SecondaryPathSourceList getSecondaries() + { + return secondaries; + } + + virtual + void writeToSecondaries(struct Sample *smps[], unsigned cnt); +}; + + + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/pool.h b/include/villas/pool.hpp similarity index 79% rename from include/villas/pool.h rename to include/villas/pool.hpp index 09c426571..7fb4b5bbe 100644 --- a/include/villas/pool.h +++ b/include/villas/pool.hpp @@ -4,7 +4,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,10 +30,13 @@ #include #include -#include +#include + +namespace villas { +namespace node { /** A thread-safe memory pool */ -struct pool { +struct Pool { enum State state; off_t buffer_off; /**< Offset from the struct address to the underlying memory area */ @@ -42,7 +45,7 @@ struct pool { size_t blocksz; /**< Length of a block in bytes */ size_t alignment; /**< Alignment of a block in bytes */ - struct queue 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 INLINE static inline __attribute__((unused)) @@ -57,10 +60,10 @@ 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) __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. * @@ -68,26 +71,29 @@ int pool_destroy(struct pool *p) __attribute__ ((warn_unused_result)); * This number can be smaller than the requested \p cnt blocks * in case the pool currently holds less than \p cnt blocks. */ -INLINE ssize_t pool_get_many(struct pool *p, void *blocks[], size_t cnt) +INLINE ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt) { return queue_pull_many(&p->queue, blocks, cnt); } /** Push \p cnt values which are giving by the array values to the stack. */ -INLINE ssize_t pool_put_many(struct pool *p, void *blocks[], size_t cnt) +INLINE ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt) { return queue_push_many(&p->queue, blocks, cnt); } /** Get a free memory block from pool. */ -INLINE void * pool_get(struct pool *p) +INLINE void * pool_get(struct Pool *p) { void *ptr; return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; } /** Release a memory block back to the pool. */ -INLINE int pool_put(struct pool *p, void *buf) +INLINE int pool_put(struct Pool *p, void *buf) { return queue_push(&p->queue, buf); } + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/queue.h b/include/villas/queue.h index e70a46145..a1512ffe4 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 - * @copyright 2014-2020, Steffen Vogel + * @copyright 2014-2021, Steffen Vogel * @license BSD 2-Clause License * * All rights reserved. @@ -40,24 +40,27 @@ #include #include -#include -#include +#include +#include + +namespace villas { +namespace node { typedef char cacheline_pad_t[CACHELINE_SIZE]; -struct queue_cell { +struct CQueue_cell { std::atomic sequence; off_t data_off; /**< Pointer relative to the queue struct */ }; /** A lock-free multiple-producer, multiple-consumer (MPMC) queue. */ -struct queue { +struct CQueue { std::atomic state; cacheline_pad_t _pad0; /**< Shared area: all threads read */ size_t buffer_mask; - off_t buffer_off; /**< Relative pointer to struct queue_cell[] */ + off_t buffer_off; /**< Relative pointer to struct CQueue_cell[] */ cacheline_pad_t _pad1; /**< Producer area: only producers read & write */ @@ -71,28 +74,28 @@ struct queue { }; /** Initialize MPMC queue */ -int queue_init(struct queue *q, size_t size, struct memory_type *mem = memory_default) __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 queue *q) __attribute__ ((warn_unused_result)); +int queue_destroy(struct CQueue *q) __attribute__ ((warn_unused_result)); /** Return estimation of current queue usage. * * Note: This is only an estimation and not accurate as long other * threads are performing operations. */ -size_t queue_available(struct queue *q); +size_t queue_available(struct CQueue *q); -int queue_push(struct queue *q, void *ptr); +int queue_push(struct CQueue *q, void *ptr); -int queue_pull(struct queue *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. * * @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 queue *q, void *ptr[], size_t cnt); +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. * @@ -100,7 +103,7 @@ int queue_push_many(struct queue *q, void *ptr[], size_t cnt); * This number can be smaller than \p cnt in case the queue contained less than * \p cnt elements. */ -int queue_pull_many(struct queue *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 * the queue is empty) to fail. @@ -108,4 +111,7 @@ int queue_pull_many(struct queue *q, void *ptr[], size_t cnt); * @return 0 on success. * @return -1 on failure. */ -int queue_close(struct queue *q); +int queue_close(struct CQueue *q); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index 108c0d921..0966d6269 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index 810cf0a42..2f9ea76d7 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,6 +26,10 @@ #include #include +#include + +namespace villas { +namespace node { enum class QueueSignalledMode { AUTO, /**< We will choose the best method available on the platform */ @@ -43,8 +47,8 @@ enum class QueueSignalledFlags { }; /** Wrapper around queue that uses POSIX CV's for signalling writes. */ -struct queue_signalled { - struct queue queue; /**< Actual underlying queue. */ +struct CQueueSignalled { + struct CQueue queue; /**< Actual underlying queue. */ enum QueueSignalledMode mode; enum QueueSignalledFlags flags; @@ -64,19 +68,22 @@ struct queue_signalled { #define queue_signalled_available(q) queue_available(&((q)->queue)) -int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem = memory_default, 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 queue_signalled *qs) __attribute__ ((warn_unused_result)); +int queue_signalled_destroy(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); -int queue_signalled_push(struct queue_signalled *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 queue_signalled *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 queue_signalled *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 queue_signalled *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 queue_signalled *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 queue_signalled *qs); +int queue_signalled_fd(struct CQueueSignalled *qs); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/queue_signalled.hpp b/include/villas/queue_signalled.hpp index c4a17b104..80a11af02 100644 --- a/include/villas/queue_signalled.hpp +++ b/include/villas/queue_signalled.hpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/include/villas/sample.h b/include/villas/sample.hpp similarity index 61% rename from include/villas/sample.h rename to include/villas/sample.hpp index d04684a05..ab54fbd5b 100644 --- a/include/villas/sample.h +++ b/include/villas/sample.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,13 +31,11 @@ #include #include -#include - -/* Forward declarations */ -struct pool; +#include +#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)) @@ -46,7 +44,13 @@ struct pool; #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 { + +/* Forward declarations */ +struct Pool; /** Parts of a sample that can be serialized / de-serialized by the IO formats */ enum class SampleFlags { @@ -63,16 +67,16 @@ enum class SampleFlags { 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. */ +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. */ - struct vlist *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 { @@ -82,58 +86,63 @@ struct sample { /** 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. + * 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. * Use the SAMPLE_LENGTH() macro to calculate the required size. * * Metadata describing the details of signal values (such as name, unit, data type and more) - * are stored in the struct sample::signals list. Each entry in this list corresponedents - * to an entry in the struct sample::data array. + * are stored in the struct Sample::signals list. Each entry in this list corresponedents + * to an entry in the struct Sample::data array. */ - union signal_data 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); -struct sample * sample_clone(struct sample *smp); +int sample_init(struct Sample *s); -void sample_free(struct sample *s); +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. * 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); +int sample_alloc_many(struct Pool *p, struct Sample *smps[], int cnt); /** Release an array of samples back to their pools */ -void sample_free_many(struct sample *smps[], int cnt); +void sample_free_many(struct Sample *smps[], int cnt); /** Increase reference count of sample */ -int sample_incref(struct sample *s); +int sample_incref(struct Sample *s); /** Decrease reference count and release memory if last reference was held. */ -int sample_decref(struct sample *s); +int sample_decref(struct Sample *s); -int sample_copy(struct sample *dst, const struct sample *src); +int sample_copy(struct Sample *dst, const struct Sample *src); /** Dump all details about a sample to debug log */ -void sample_dump(villas::Logger logger, struct sample *s); +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_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); +enum SignalType sample_format(const struct Sample *s, unsigned idx); -void sample_data_insert(struct sample *smp, const union signal_data *src, size_t offset, size_t len); -void sample_data_remove(struct sample *smp, 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 */ +} /* namespace villas */ diff --git a/include/villas/shmem.h b/include/villas/shmem.hpp similarity index 83% rename from include/villas/shmem.h rename to include/villas/shmem.hpp index 2bb36715f..498aa0abd 100644 --- a/include/villas/shmem.h +++ b/include/villas/shmem.hpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,35 +21,32 @@ * along with this program. If not, see . *********************************************************************************/ -/** Interface to the shared memory node for external programs. - * - * @addtogroup shmem Shared memory interface - * @{ - */ - #pragma once -#include +#include #include #include -#include +#include #define DEFAULT_SHMEM_QUEUELEN 512u #define DEFAULT_SHMEM_SAMPLELEN 64u +namespace villas { +namespace node { + /** Struct containing all parameters that need to be known when creating a new * shared memory object. */ -struct shmem_conf { +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 */ }; /** The structure that actually resides in the shared memory. */ -struct shmem_shared { +struct ShmemShared { int polling; /**< Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. */ - struct queue_signalled queue; /**< Queue for samples passed in both directions. */ - struct pool pool; /**< Pool for the samples in the queues. */ + 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. */ @@ -57,11 +54,11 @@ 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 shmem_shared *shared; /**< Actually shared datastructure */ + struct ShmemShared *shared; /**< Actually shared datastructure */ }; /** Main structure representing the shared memory interface. */ -struct shmem_int { +struct ShmemInterface { struct shmem_dir read, write; std::atomic readers, writers, closed; }; @@ -77,7 +74,7 @@ struct shmem_int { * @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 shmem_int* shm, struct shmem_conf* 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. * @@ -85,7 +82,7 @@ int shmem_int_open(const char* wname, const char* rname, struct shmem_int* shm, * @retval 0 Closing successfull. * @retval <0 An error occurred; errno is set appropiately. */ -int shmem_int_close(struct shmem_int *shm); +int shmem_int_close(struct ShmemInterface *shm); /** Read samples from the interface. * @@ -96,7 +93,7 @@ int shmem_int_close(struct shmem_int *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 shmem_int *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. * @@ -106,7 +103,7 @@ int shmem_int_read(struct shmem_int *shm, struct sample * const smps[], unsigned * @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 shmem_int *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. * @@ -116,11 +113,12 @@ int shmem_int_write(struct shmem_int *shm, const struct sample * const smps[], u * @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 shmem_int *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 - * per struct sample. */ + * per struct Sample. */ size_t shmem_total_size(int queuelen, int samplelen); -/** @} */ +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/signal.h b/include/villas/signal.h deleted file mode 100644 index 405ecc94f..000000000 --- a/include/villas/signal.h +++ /dev/null @@ -1,87 +0,0 @@ -/** Signal meta data. - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#pragma once - -#include - -#include - -#include -#include -#include - -/* "I" defined by complex.h collides with a define in OpenSSL */ -#undef I - -/* Forward declarations */ -struct mapping_entry; - -/** Signal descriptor. - * - * This data structure contains meta data about samples values in struct sample::data - */ -struct signal { - char *name; /**< The name of the signal. */ - char *unit; /**< The unit of the signal. */ - - union signal_data init; /**< The initial value of the signal. */ - - int enabled; - - std::atomic refcnt; /**< Reference counter. */ - - enum SignalType type; -}; - -/** Initialize a signal with default values. */ -int signal_init(struct signal *s) __attribute__ ((warn_unused_result)); - -/** Destroy a signal and release memory. */ -int signal_destroy(struct signal *s) __attribute__ ((warn_unused_result)); - -/** Allocate memory for a new signal, and initialize it with provided values. */ -struct signal * signal_create(const char *name, const char *unit, enum SignalType fmt) __attribute__ ((warn_unused_result)); - -/** Destroy and release memory of signal. */ -int signal_free(struct signal *s) __attribute__ ((warn_unused_result)); - -/** Increase reference counter. */ -int signal_incref(struct signal *s); - -/** Decrease reference counter. */ -int signal_decref(struct signal *s); - -/** Copy a signal. */ -struct signal * signal_copy(struct signal *s); - -/** Parse signal description. */ -int signal_parse(struct signal *s, json_t *json); - -char * signal_print(const struct signal *s, const union signal_data *d = nullptr); - -/** Initialize signal from a mapping_entry. */ -int signal_init_from_mapping(struct signal *s, const struct mapping_entry *me, unsigned index); - -/** Produce JSON representation of signal. */ -json_t * signal_to_json(struct signal *s); diff --git a/include/villas/signal.hpp b/include/villas/signal.hpp new file mode 100644 index 000000000..aa22e1c34 --- /dev/null +++ b/include/villas/signal.hpp @@ -0,0 +1,69 @@ +/** Signal meta data. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include + +#include + +#include +#include + +/* "I" defined by complex.h collides with a define in OpenSSL */ +#undef I + +namespace villas { +namespace node { + +/** Signal descriptor. + * + * This data structure contains meta data about samples values in struct Sample::data + */ +class Signal { + +public: + using Ptr = std::shared_ptr; + + 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; + + /** 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); + + std::string toString(const union SignalData *d = nullptr) const; + + /** Produce JSON representation of signal. */ + json_t * toJson() const; + + bool isNext(const Signal &sig); +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/signal_data.h b/include/villas/signal_data.hpp similarity index 61% rename from include/villas/signal_data.h rename to include/villas/signal_data.hpp index 5b4ea6a12..75197852c 100644 --- a/include/villas/signal_data.h +++ b/include/villas/signal_data.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,26 +27,30 @@ #include #include +#include #include +namespace villas { +namespace node { + /** A signal value. * * Data is in host endianess! */ -union signal_data { +union SignalData { double f; /**< Floating point values. */ int64_t i; /**< Integer values. */ bool b; /**< Boolean values. */ std::complex z; /**< Complex values. */ - signal_data() : + SignalData() : i(0) { } - static union signal_data nan() + static union SignalData nan() { - union signal_data d; + union SignalData d; d.f = std::numeric_limits::quiet_NaN(); @@ -57,18 +61,24 @@ union signal_data { { return f == std::numeric_limits::quiet_NaN(); } + + /** Convert signal data from one description/format to another. */ + void cast(enum SignalType type, enum SignalType to); + + /** 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; + + int parseString(enum SignalType type, const char *ptr, char **end); + + int parseJson(enum SignalType type, json_t *json); + + json_t * toJson(enum SignalType type) const; + + std::string toString(enum SignalType type, int precision = 5) const; }; -/** Convert signal data from one description/format to another. */ -void signal_data_cast(union signal_data *data, enum SignalType from, enum SignalType to); - -/** Print value of a signal to a character buffer. */ -int signal_data_print_str(const union signal_data *data, enum SignalType type, char *buf, size_t len, int precision = 5); - -int signal_data_parse_str(union signal_data *data, enum SignalType type, const char *ptr, char **end); - -int signal_data_parse_json(union signal_data *data, enum SignalType type, json_t *json); - -json_t * signal_data_to_json(const union signal_data *data, enum SignalType type); - -void signal_data_set(union signal_data *data, enum SignalType type, double val); +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/signal_list.h b/include/villas/signal_list.hpp similarity index 55% rename from include/villas/signal_list.h rename to include/villas/signal_list.hpp index 1843a0b07..8d4ddb4ee 100644 --- a/include/villas/signal_list.h +++ b/include/villas/signal_list.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,28 +23,40 @@ #pragma once +#include +#include + #include #include -#include +#include -/* Forward declarations */ -struct vlist; +namespace villas { +namespace node { -int signal_list_init(struct vlist *list) __attribute__ ((warn_unused_result)); +class SignalList : public std::vector { -int signal_list_destroy(struct vlist *list) __attribute__ ((warn_unused_result)); +public: + using Ptr = std::shared_ptr; -int signal_list_clear(struct vlist *list); + SignalList() + { } -int signal_list_parse(struct vlist *list, json_t *json); + SignalList(unsigned len, enum SignalType fmt); + SignalList(const char *dt); -int signal_list_generate(struct vlist *list, unsigned len, enum SignalType fmt); + int parse(json_t *json); -int signal_list_generate2(struct vlist *list, const char *dt); + Ptr clone(); -void signal_list_dump(villas::Logger logger, const struct vlist *list, const union signal_data *data = nullptr, unsigned len = 0); + void dump(villas::Logger logger, const union SignalData *data = nullptr, unsigned len = 0) const; -int signal_list_copy(struct vlist *dst, const struct vlist *src); + json_t * toJson() const; -json_t * signal_list_to_json(struct vlist *list); + int getIndexByName(const std::string &name); + Signal::Ptr getByName(const std::string &name); + Signal::Ptr getByIndex(unsigned idx); +}; + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/signal_type.h b/include/villas/signal_type.hpp similarity index 64% rename from include/villas/signal_type.h rename to include/villas/signal_type.hpp index 909399c04..9d0b0abcf 100644 --- a/include/villas/signal_type.h +++ b/include/villas/signal_type.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,18 +23,26 @@ #pragma once +#include + +namespace villas { +namespace node { + enum class SignalType { INVALID = 0, /**< Signal type is invalid. */ - FLOAT = 1, /**< See signal_data::f */ - INTEGER = 2, /**< See signal_data::i */ - BOOLEAN = 3, /**< See signal_data::b */ - COMPLEX = 4 /**< See signal_data::z */ + FLOAT = 1, /**< See SignalData::f */ + INTEGER = 2, /**< See SignalData::i */ + BOOLEAN = 3, /**< See SignalData::b */ + COMPLEX = 4 /**< See SignalData::z */ }; -enum SignalType signal_type_from_str(const char *str); +enum SignalType signalTypeFromString(const std::string &str); -enum SignalType signal_type_from_fmtstr(char c); +enum SignalType signalTypeFromFormatString(char c); -const char * signal_type_to_str(enum SignalType fmt); +std::string signalTypeToString(enum SignalType fmt); -enum SignalType signal_type_detect(const char *val); +enum SignalType signalTypeDetect(const std::string &val); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/socket_addr.h b/include/villas/socket_addr.hpp similarity index 93% rename from include/villas/socket_addr.h rename to include/villas/socket_addr.hpp index bee5e444c..8931d2574 100644 --- a/include/villas/socket_addr.h +++ b/include/villas/socket_addr.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,7 +28,7 @@ #include #include -#include +#include #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) #define WITH_SOCKET_LAYER_ETH @@ -37,13 +37,6 @@ #include #endif /* LIBNL3_ROUTE_FOUND */ -enum class SocketLayer { - ETH, - IP, - UDP, - UNIX -}; - union sockaddr_union { struct sockaddr sa; struct sockaddr_storage ss; @@ -55,6 +48,16 @@ union sockaddr_union { #endif }; +namespace villas { +namespace node { + +enum class SocketLayer { + ETH, + IP, + UDP, + UNIX +}; + /** Generate printable socket address depending on the address family * * A IPv4 address is formatted as dotted decimals followed by the port/protocol number @@ -82,3 +85,6 @@ char * socket_print_addr(struct sockaddr *saddr); 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); + +} /* namespace node */ +} /* namespace villas */ diff --git a/include/villas/stats.hpp b/include/villas/stats.hpp index 6a3154f61..679541c32 100644 --- a/include/villas/stats.hpp +++ b/include/villas/stats.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -33,18 +33,23 @@ #include #include #include -#include +#include #include -/* Forward declarations */ -struct sample; -struct vnode; - namespace villas { +namespace node { + +/* Forward declarations */ +struct Sample; +class Node; + +} class Stats { public: + using Ptr = std::shared_ptr; + enum class Format { HUMAN, JSON, @@ -89,7 +94,7 @@ protected: struct TypeDescription { const char *name; - enum SignalType signal_type; + enum node::SignalType signal_type; }; static std::shared_ptr table; @@ -120,13 +125,13 @@ public: static void printHeader(enum Format fmt); - void printPeriodic(FILE *f, enum Format fmt, struct vnode *p) const; + void printPeriodic(FILE *f, enum Format fmt, node::Node *n) const; void print(FILE *f, enum Format fmt, int verbose) const; - union signal_data getValue(enum Metric sm, enum Type st) const; + union node::SignalData getValue(enum Metric sm, enum Type st) const; - const villas::Hist & getHistogram(enum Metric sm) const; + const Hist & getHistogram(enum Metric sm) const; static std::unordered_map metrics; static std::unordered_map types; diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index 3c8932428..cabb068ab 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,7 +23,7 @@ #pragma once -#include +#include #ifdef WITH_GRAPHVIZ extern "C" { @@ -36,20 +36,20 @@ extern "C" { #include #include #include -#include -#include +#include +#include #include #include #include #include #include -/* Forward declarations */ -struct vnode; - namespace villas { namespace node { +/* Forward declarations */ +class Node; + /** Global configuration */ class SuperNode { @@ -136,7 +136,7 @@ public: state = st; } - struct vnode * getNode(const std::string &name) + Node * getNode(const std::string &name) { return nodes.lookup(name); } diff --git a/include/villas/web.hpp b/include/villas/web.hpp index 2de77e3f7..2dbd2ffb8 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -52,7 +52,6 @@ protected: 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 htdocs; /**< The root directory for files served via HTTP. */ 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. */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5f722e574..767371da5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -47,13 +47,14 @@ set(LIB_SRC dumper.cpp format.cpp mapping.cpp + mapping_list.cpp memory.cpp memory/heap.cpp memory/managed.cpp memory/mmap.cpp node_direction.cpp - node_type.cpp node.cpp + node_compat.cpp node_list.cpp path_destination.cpp path_source.cpp diff --git a/lib/api.cpp b/lib/api.cpp index bca1e68e1..828db44d2 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -1,7 +1,7 @@ /** REST-API-releated functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include #include using namespace villas; diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index cf63aab73..25a0d6302 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -2,7 +2,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/lib/api/node_request.cpp b/lib/api/node_request.cpp index 3fc5c98b6..3a3a66634 100644 --- a/lib/api/node_request.cpp +++ b/lib/api/node_request.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,8 +25,7 @@ using namespace villas::node::api; -void -NodeRequest::prepare() +void NodeRequest::prepare() { int ret; diff --git a/lib/api/path_request.cpp b/lib/api/path_request.cpp index 92299e349..bfeab18eb 100644 --- a/lib/api/path_request.cpp +++ b/lib/api/path_request.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,12 +22,11 @@ *********************************************************************************/ #include -#include +#include using namespace villas::node::api; -void -PathRequest::prepare() +void PathRequest::prepare() { int ret; uuid_t uuid; diff --git a/lib/api/request.cpp b/lib/api/request.cpp index 81124152f..a8625182d 100644 --- a/lib/api/request.cpp +++ b/lib/api/request.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index b7cec57ae..94095b736 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -1,7 +1,7 @@ /** The "capabiltities" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index 64948ecb3..17488c413 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -1,7 +1,7 @@ /** The "config" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/api/requests/graph.cpp b/lib/api/requests/graph.cpp index 97416945d..f530b7b1c 100644 --- a/lib/api/requests/graph.cpp +++ b/lib/api/requests/graph.cpp @@ -1,7 +1,7 @@ /** The "stats" API request. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ extern "C" { #include } -#include +#include #include #include diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index 30741eee7..d01cc08b8 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -1,7 +1,7 @@ /** The API ressource for start/stop/pause/resume nodes. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include @@ -34,7 +34,7 @@ namespace villas { namespace node { namespace api { -template +template class NodeActionRequest : public NodeRequest { public: @@ -48,7 +48,11 @@ public: if (body != nullptr) throw BadRequest("Node endpoints do not accept any body data"); - A(node); + int ret = (node->*func)(); + if (ret) + throw BadRequest("Failed to execute action", "{ s: d }", + "ret", ret + ); return new Response(session, HTTP_STATUS_OK); } @@ -59,27 +63,27 @@ public: static char n1[] = "node/start"; static char r1[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/start"; static char d1[] = "start a node"; -static RequestPlugin, n1, r1, d1> p1; +static RequestPlugin, n1, r1, d1> p1; static char n2[] = "node/stop"; static char r2[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/stop"; static char d2[] = "stop a node"; -static RequestPlugin, n2, r2, d2> p2; +static RequestPlugin, n2, r2, d2> p2; static char n3[] = "node/pause"; static char r3[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/pause"; static char d3[] = "pause a node"; -static RequestPlugin, n3, r3, d3> p3; +static RequestPlugin, n3, r3, d3> p3; static char n4[] = "node/resume"; static char r4[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/resume"; static char d4[] = "resume a node"; -static RequestPlugin, n4, r4, d4> p4; +static RequestPlugin, n4, r4, d4> p4; static char n5[] = "node/restart"; static char r5[] = "/node/(" RE_NODE_NAME "|" RE_UUID ")/restart"; static char d5[] = "restart a node"; -static RequestPlugin, n5, r5, d5> p5; +static RequestPlugin, n5, r5, d5> p5; } /* namespace api */ diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 8b97390bc..4bc0e4480 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -1,7 +1,7 @@ /** The "file" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -45,14 +46,15 @@ public: if (body != nullptr) throw BadRequest("File endpoint does not accept any body data"); - struct vnode_type *vt = node_type_lookup("file"); + NodeFactory *nf = plugin::Registry::lookup("file"); - if (node_type(node) != vt) + if (node->getFactory() != nf) throw BadRequest("This node is not a file node", "{ s: s }", - "type", node_type(node) + "type", node->getFactory()->getName() ); - struct file *f = (struct file *) node->_vd; + auto *nc = dynamic_cast(node); + auto *f = nc->getData(); if (matches[2] == "rewind") rewind(f->stream_in); diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index 9c4bae571..03cf2877d 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -1,7 +1,7 @@ /** The "node" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ public: if (body != nullptr) throw BadRequest("Nodes endpoint does not accept any body data"); - return new JsonResponse(session, HTTP_STATUS_OK, node_to_json(node)); + return new JsonResponse(session, HTTP_STATUS_OK, node->toJson()); } }; diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index b52c90882..da640faa6 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -1,7 +1,7 @@ /** The API ressource for querying statistics. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include @@ -48,10 +48,10 @@ public: if (body != nullptr) throw BadRequest("Stats endpoint does not accept any body data"); - if (node->stats == nullptr) + if (node->getStats() == nullptr) throw BadRequest("The statistics collection for this node is not enabled"); - return new JsonResponse(session, HTTP_STATUS_OK, node->stats->toJson()); + return new JsonResponse(session, HTTP_STATUS_OK, node->getStats()->toJson()); } }; diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index 284ebee2b..c6b6dc461 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -1,7 +1,7 @@ /** The API ressource for resetting statistics. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include @@ -48,10 +48,10 @@ public: if (body != nullptr) throw BadRequest("Stats endpoint does not accept any body data"); - if (node->stats == nullptr) + if (node->getStats() == nullptr) throw BadRequest("The statistics collection for this node is not enabled"); - node->stats->reset(); + node->getStats()->reset(); return new Response(session, HTTP_STATUS_OK); } diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index 29d8b76c2..e605018b9 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -1,7 +1,7 @@ /** The "nodes" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -48,10 +48,7 @@ public: if (body != nullptr) throw BadRequest("Nodes endpoint does not accept any body data"); - json_t *json_nodes = json_array(); - - for (auto *n : session->getSuperNode()->getNodes()) - json_array_append_new(json_nodes, node_to_json(n)); + json_t *json_nodes = session->getSuperNode()->getNodes().toJson(); return new JsonResponse(session, HTTP_STATUS_OK, json_nodes); } diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 92f42d07a..6c69ebf88 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -1,7 +1,7 @@ /** The API ressource for start/stop/pause/resume paths. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include @@ -34,7 +34,7 @@ namespace villas { namespace node { namespace api { -template +template class PathActionRequest : public PathRequest { public: @@ -48,7 +48,7 @@ public: if (body != nullptr) throw BadRequest("Path endpoints do not accept any body data"); - A(path); + (path->*func)(); return new Response(session, HTTP_STATUS_OK); } @@ -59,12 +59,12 @@ public: static char n1[] = "path/start"; static char r1[] = "/path/(" RE_UUID ")/start"; static char d1[] = "start a path"; -static RequestPlugin, n1, r1, d1> p1; +static RequestPlugin, n1, r1, d1> p1; static char n2[] = "path/stop"; static char r2[] = "/path/(" RE_UUID ")/stop"; static char d2[] = "stop a path"; -static RequestPlugin, n2, r2, d2> p2; +static RequestPlugin, n2, r2, d2> p2; } /* namespace api */ diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index 1f9217a76..a74b656db 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -1,7 +1,7 @@ /** The "path" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ public: if (body != nullptr) throw BadRequest("Endpoint does not accept any body data"); - return new JsonResponse(session, HTTP_STATUS_OK, path_to_json(path)); + return new JsonResponse(session, HTTP_STATUS_OK, path->toJson()); } }; diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index 3bf442d5e..df08bf5f7 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -1,7 +1,7 @@ /** The "paths" API ressource. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,9 +23,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -49,10 +47,7 @@ public: if (body != nullptr) throw BadRequest("Paths endpoint does not accept any body data"); - json_t *json_paths = json_array(); - - for (auto *p : session->getSuperNode()->getPaths()) - json_array_append_new(json_paths, path_to_json(p)); + json_t *json_paths = session->getSuperNode()->getPaths().toJson(); return new JsonResponse(session, HTTP_STATUS_OK, json_paths); } diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 7d0e0218a..92563da71 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -1,7 +1,7 @@ /** The "restart" API request. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index 13ac22f16..57131cffe 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -1,7 +1,7 @@ /** The "shutdown" API request. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index 5d6591d3e..c72287517 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -1,7 +1,7 @@ /** The "status" API request. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/lib/api/response.cpp b/lib/api/response.cpp index c464ab59d..2a8dc83ac 100644 --- a/lib/api/response.cpp +++ b/lib/api/response.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,6 +23,7 @@ #include #include +#include using namespace villas::node::api; @@ -41,8 +42,7 @@ Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) : } { } -int -Response::writeBody(struct lws *wsi) +int Response::writeBody(struct lws *wsi) { int ret; @@ -53,8 +53,7 @@ Response::writeBody(struct lws *wsi) return 1; } -int -Response::writeHeaders(struct lws *wsi) +int Response::writeHeaders(struct lws *wsi) { int ret; uint8_t headerBuffer[2048], *p = headerBuffer, *end = &headerBuffer[sizeof(headerBuffer) - 1]; @@ -94,8 +93,7 @@ JsonResponse::~JsonResponse() json_decref(response); } -void -JsonResponse::encodeBody() +void JsonResponse::encodeBody() { buffer.encode(response, JSON_INDENT(4)); } diff --git a/lib/api/session.cpp b/lib/api/session.cpp index 69ea4a215..1981619cc 100644 --- a/lib/api/session.cpp +++ b/lib/api/session.cpp @@ -1,7 +1,7 @@ /** API session. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -178,9 +178,11 @@ void Session::bodyComplete() int Session::writeable() { + if (!response) + return 0; + if (!headersSent) { - if (response) - response->writeHeaders(wsi); + response->writeHeaders(wsi); /* Now wait, until we can send the body */ headersSent = true; diff --git a/lib/capabilities.cpp b/lib/capabilities.cpp index fe2f92e4e..09561bb21 100644 --- a/lib/capabilities.cpp +++ b/lib/capabilities.cpp @@ -38,34 +38,32 @@ json_t * villas::node::getCapabilities() 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); + } -#if 0 /* @todo Port to C++ */ - for (auto f : NodeFactory::lookup()) { - json_name = json_string(f->getName().c_str()); + for (auto f : plugin::Registry::lookup()) { + if (f->isInternal()) + continue; - json_array_append_new(json_nodes, json_name); - } -#else - for (auto *vt : *node_types) - json_array_append_new(json_nodes, json_string(vt->name)); -#endif + json_name = json_string(f->getName().c_str()); + + json_array_append_new(json_nodes, json_name); + } return json_pack("{ s: o, s: o, s: o, s: o }", "hooks", json_hooks, diff --git a/lib/config.cpp b/lib/config.cpp index c08f30694..2e5bd23c1 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -2,7 +2,7 @@ /** Configuration file parsing. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,10 +31,10 @@ #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -59,19 +59,24 @@ Config::Config(const std::string &u) : Config::~Config() { - if (root) - json_decref(root); + json_decref(root); } json_t * Config::load(std::FILE *f, bool resolveInc, bool resolveEnvVars) { json_t *root = decode(f); - if (resolveInc) + if (resolveInc) { + json_t *root_old = root; root = expandIncludes(root); + json_decref(root_old); + } - if (resolveEnvVars) + if (resolveEnvVars) { + json_t *root_old = root; root = expandEnvVars(root); + json_decref(root_old); + } return root; } @@ -139,10 +144,7 @@ std::list Config::getIncludeDirectories(FILE *f) const std::list dirs; - dir = getcwd(buf, sizeof(buf)); - if (dir != nullptr) - dirs.push_back(dir); - + // Adding directory of base configuration file fd = fileno(f); if (fd < 0) throw SystemError("Failed to get file descriptor"); @@ -158,6 +160,11 @@ std::list Config::getIncludeDirectories(FILE *f) const } } + // Adding current working directory + dir = getcwd(buf, sizeof(buf)); + if (dir != nullptr) + dirs.push_back(dir); + return dirs; } @@ -255,7 +262,7 @@ json_t * Config::libconfigDecode(FILE *f) /* Setup libconfig include path. */ #if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) - config_set_hook (&cfg, this); + config_set_hook(&cfg, this); config_set_include_func(&cfg, includeFuncStub); #else @@ -323,7 +330,7 @@ json_t * Config::walkStrings(json_t *root, str_walk_fcn_t cb) return new_root; default: - return root; + return json_incref(root); }; } @@ -346,7 +353,7 @@ json_t * Config::expandIncludes(json_t *in) static const std::string kw = "@include "; if (text.find(kw) != 0) - return str; + return json_incref(str); else { std::string pattern = text.substr(kw.size()); diff --git a/lib/config_helper.cpp b/lib/config_helper.cpp index 75b81f026..f6630f14d 100644 --- a/lib/config_helper.cpp +++ b/lib/config_helper.cpp @@ -1,7 +1,7 @@ /** Helpers for configuration parsers. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,13 +25,14 @@ #include -#include +#include #include #include #ifdef WITH_CONFIG -static int json_to_config_type(int type) +static +int json_to_config_type(int type) { switch (type) { case JSON_OBJECT: @@ -58,7 +59,7 @@ static int json_to_config_type(int type) return -1; } -json_t * config_to_json(config_setting_t *cfg) +json_t * villas::node::config_to_json(config_setting_t *cfg) { switch (config_setting_type(cfg)) { case CONFIG_TYPE_INT: @@ -80,8 +81,10 @@ json_t * config_to_json(config_setting_t *cfg) case CONFIG_TYPE_LIST: { json_t *json = json_array(); - for (int i = 0; i < config_setting_length(cfg); i++) - json_array_append_new(json, config_to_json(config_setting_get_elem(cfg, i))); + 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; } @@ -90,9 +93,10 @@ json_t * config_to_json(config_setting_t *cfg) 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(config_setting_get_elem(cfg, i)), - config_to_json(config_setting_get_elem(cfg, i)) + config_setting_name(elm), + config_to_json(elm) ); } @@ -104,7 +108,7 @@ json_t * config_to_json(config_setting_t *cfg) } } -int json_to_config(json_t *json, config_setting_t *parent) +int villas::node::json_to_config(json_t *json, config_setting_t *parent) { config_setting_t *cfg; int ret, type; @@ -168,7 +172,7 @@ int json_to_config(json_t *json, config_setting_t *parent) } #endif /* WITH_CONFIG */ -void json_object_extend_key_value_token(json_t *obj, const char *key, const char *value) +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 = ","; @@ -185,7 +189,7 @@ void json_object_extend_key_value_token(json_t *obj, const char *key, const char free(str); } -void json_object_extend_key_value(json_t *obj, const char *key, const char *value) +void villas::node::json_object_extend_key_value(json_t *obj, const char *key, const char *value) { char *end, *cpy, *key1, *key2, *lasts; @@ -268,7 +272,7 @@ success: json_object_set(subobj, key1, add); } -json_t * json_load_cli(int argc, const char *argv[]) +json_t * villas::node::json_load_cli(int argc, const char *argv[]) { const char *opt; const char *key = nullptr; @@ -319,7 +323,7 @@ json_t * json_load_cli(int argc, const char *argv[]) return json; } -int json_object_extend(json_t *obj, json_t *merge) +int villas::node::json_object_extend(json_t *obj, json_t *merge) { const char *key; int ret; @@ -342,7 +346,7 @@ int json_object_extend(json_t *obj, json_t *merge) return 0; } -int json_object_extend_str(json_t *obj, const char *str) +int villas::node::json_object_extend_str(json_t *obj, const char *str) { char *key, *value, *cpy, *lasts; diff --git a/lib/dumper.cpp b/lib/dumper.cpp index c2eeca0fc..4edd2227e 100644 --- a/lib/dumper.cpp +++ b/lib/dumper.cpp @@ -1,7 +1,7 @@ /** Dump fields and values in a socket to plot them with villasDump.py. * * @author Manuel Pitz - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/format.cpp b/lib/format.cpp index 27f4522f1..62631c653 100644 --- a/lib/format.cpp +++ b/lib/format.cpp @@ -1,7 +1,7 @@ /** Reading and writing simulation samples in various formats. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,7 +28,7 @@ #include #include -#include +#include #include using namespace villas; @@ -38,8 +38,6 @@ using namespace villas::utils; Format * FormatFactory::make(json_t *json) { std::string type; - - FormatFactory *ff; Format *f; if (json_is_string(json)) { @@ -52,11 +50,10 @@ Format * FormatFactory::make(json_t *json) type = json_string_value(json_type); - ff = plugin::Registry::lookup(type); - if (!ff) - throw ConfigError(json, "Unknown format: {}", type); + f = FormatFactory::make(type); + if (!f) + return nullptr; - f = ff->make(); f->parse(json); return f; @@ -77,7 +74,6 @@ Format * FormatFactory::make(const std::string &format) Format::Format(int fl) : flags(fl), real_precision(17), - destroy_signals(false), signals(nullptr) { in.buflen = @@ -96,12 +92,9 @@ Format::~Format() delete[] in.buffer; delete[] out.buffer; - - if (signals && destroy_signals) - ret = vlist_destroy(signals, (dtor_cb_t) signal_decref, false); } -void Format::start(struct vlist *sigs, int fl) +void Format::start(SignalList::Ptr sigs, int fl) { flags &= fl; @@ -112,28 +105,16 @@ void Format::start(struct vlist *sigs, int fl) void Format::start(const std::string &dtypes, int fl) { - int ret; - flags |= fl; - signals = new struct vlist; + signals = std::make_shared(dtypes.c_str()); if (!signals) throw MemoryAllocationError(); - ret = vlist_init(signals); - if (ret) - throw RuntimeError("Failed to initialize list"); - - ret = signal_list_generate2(signals, dtypes.c_str()); - if (ret) - throw RuntimeError("Failed to generate signal list"); - - destroy_signals = true; - start(); } -int Format::print(FILE *f, const struct sample * const smps[], unsigned cnt) +int Format::print(FILE *f, const struct Sample * const smps[], unsigned cnt) { int ret; size_t wbytes; @@ -145,7 +126,7 @@ int Format::print(FILE *f, const struct sample * const smps[], unsigned cnt) return ret; } -int Format::scan(FILE *f, struct sample * const smps[], unsigned cnt) +int Format::scan(FILE *f, struct Sample * const smps[], unsigned cnt) { size_t bytes, rbytes; diff --git a/lib/formats/CMakeLists.txt b/lib/formats/CMakeLists.txt index 8b973764b..052d6fb94 100644 --- a/lib/formats/CMakeLists.txt +++ b/lib/formats/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/lib/formats/column.cpp b/lib/formats/column.cpp index a5baa8e04..060ac6fb1 100644 --- a/lib/formats/column.cpp +++ b/lib/formats/column.cpp @@ -1,7 +1,7 @@ /** Comma-separated values. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,18 +25,17 @@ #include #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 ColumnLineFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) { size_t off = 0; - struct signal *sig; 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, @@ -55,12 +54,12 @@ size_t ColumnLineFormat::sprintLine(char *buf, size_t len, const struct sample * off += snprintf(buf + off, len - off, "%cnan", separator); for (unsigned i = 0; i < smp->length; i++) { - sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) break; off += snprintf(buf + off, len - off, "%c", separator); - off += signal_data_print_str(&smp->data[i], sig->type, buf + off, len - off, real_precision); + off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); } off += snprintf(buf + off, len - off, "%c", delimiter); @@ -68,7 +67,7 @@ size_t ColumnLineFormat::sprintLine(char *buf, size_t len, const struct sample * return off; } -size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct sample *smp) +size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) { int ret; unsigned i = 0; @@ -114,11 +113,11 @@ size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct sample *s if (*end == delimiter) goto out; - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) goto out; - ret = signal_data_parse_str(&smp->data[i], sig->type, ptr, &end); + ret = smp->data[i].parseString(sig->type, ptr, &end); if (ret || end == ptr) /* There are no valid values anymore. */ goto out; } @@ -133,7 +132,7 @@ out: if (*end == delimiter) return end - buf; } -void ColumnLineFormat::header(FILE *f, const struct vlist *sigs) +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) @@ -152,20 +151,20 @@ void ColumnLineFormat::header(FILE *f, const struct vlist *sigs) fprintf(f, "sequence%c", separator); if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < vlist_length(sigs); i++) { - struct signal *sig = (struct signal *) vlist_at_safe(sigs, i); + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); if (!sig) break; - if (sig->name) - fprintf(f, "%s", sig->name); + if (!sig->name.empty()) + fprintf(f, "%s", sig->name.c_str()); else fprintf(f, "signal%u", i); - if (sig->unit) - fprintf(f, "[%s]", sig->unit); + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); - if (i + 1 < vlist_length(sigs)) + if (i + 1 < sigs->size()) fprintf(f, "%c", separator); } } diff --git a/lib/formats/iotagent_ul.cpp b/lib/formats/iotagent_ul.cpp index 826fb1551..6653e44e3 100644 --- a/lib/formats/iotagent_ul.cpp +++ b/lib/formats/iotagent_ul.cpp @@ -3,7 +3,7 @@ * See: https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html * * @author Iris Koester - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,33 +24,30 @@ #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) +int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { size_t printed = 0; - struct signal *sig; - const struct sample *smp = smps[0]; + const struct Sample *smp = smps[0]; for (unsigned i = 0; (i < smp->length) && (printed < len); i++) { - sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) return -1; - if (sig->name) - printed += snprintf(buf + printed, len - printed, "%s|%f|", sig->name, 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 { - char name[32]; - snprintf(name, 32, "signal_%u", i); - printed += snprintf(buf + printed, len - printed, "%s|%f|", name, smp->data[i].f); + printed += snprintf(buf + printed, len - printed, "signal_%u|%f|", i, smp->data[i].f); } } @@ -60,7 +57,7 @@ int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, cons return 0; } -int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) { return -1; } diff --git a/lib/formats/json.cpp b/lib/formats/json.cpp index fee1998cd..4b0c34d8f 100644 --- a/lib/formats/json.cpp +++ b/lib/formats/json.cpp @@ -1,7 +1,7 @@ /** JSON serializtion of sample data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,9 +20,9 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include -#include +#include #include #include @@ -52,7 +52,7 @@ enum SignalType JsonFormat::detect(const json_t *val) } } -json_t * JsonFormat::packTimestamps(const struct sample *smp) +json_t * JsonFormat::packTimestamps(const struct Sample *smp) { json_t *json_ts = json_object(); @@ -75,7 +75,7 @@ json_t * JsonFormat::packTimestamps(const struct sample *smp) return json_ts; } -int JsonFormat::unpackTimestamps(json_t *json_ts, struct sample *smp) +int JsonFormat::unpackTimestamps(json_t *json_ts, struct Sample *smp) { int ret; json_error_t err; @@ -106,7 +106,7 @@ int JsonFormat::unpackTimestamps(json_t *json_ts, struct sample *smp) return 0; } -int JsonFormat::packSample(json_t **json_smp, const struct sample *smp) +int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) { json_t *json_root; json_error_t err; @@ -125,11 +125,11 @@ int JsonFormat::packSample(json_t **json_smp, const struct sample *smp) json_t *json_data = json_array(); for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) return -1; - json_t *json_value = signal_data_to_json(&smp->data[i], sig->type); + json_t *json_value = smp->data[i].toJson(sig->type); json_array_append_new(json_data, json_value); } @@ -142,7 +142,7 @@ int JsonFormat::packSample(json_t **json_smp, const struct sample *smp) return 0; } -int JsonFormat::packSamples(json_t **json_smps, const struct sample * const smps[], unsigned cnt) +int JsonFormat::packSamples(json_t **json_smps, const struct Sample * const smps[], unsigned cnt) { int ret; json_t *json_root = json_array(); @@ -162,7 +162,7 @@ int JsonFormat::packSamples(json_t **json_smps, const struct sample * const smps return cnt; } -int JsonFormat::unpackSample(json_t *json_smp, struct sample *smp) +int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) { int ret; json_error_t err; @@ -200,16 +200,16 @@ int JsonFormat::unpackSample(json_t *json_smp, struct sample *smp) if (i >= smp->capacity) break; - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i); + 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 {}).", - signal_type_to_str(fmt), signal_type_to_str(sig->type), sig->name, i); + signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); - ret = signal_data_parse_json(&smp->data[i], sig->type, json_value); + ret = smp->data[i].parseJson(sig->type, json_value); if (ret) return -3; @@ -222,7 +222,7 @@ int JsonFormat::unpackSample(json_t *json_smp, struct sample *smp) return 0; } -int JsonFormat::unpackSamples(json_t *json_smps, struct sample * const smps[], unsigned cnt) +int JsonFormat::unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt) { int ret; json_t *json_smp; @@ -243,7 +243,7 @@ int JsonFormat::unpackSamples(json_t *json_smps, struct sample * const smps[], u return i; } -int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sample * const smps[], unsigned cnt) +int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { int ret; json_t *json; @@ -263,7 +263,7 @@ int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sampl return ret; } -int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) { int ret; json_t *json; @@ -286,7 +286,7 @@ int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample return ret; } -int JsonFormat::print(FILE *f, const struct sample * const smps[], unsigned cnt) +int JsonFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) { int ret; unsigned i; @@ -309,7 +309,7 @@ int JsonFormat::print(FILE *f, const struct sample * const smps[], unsigned cnt) return i; } -int JsonFormat::scan(FILE *f, struct sample * const smps[], unsigned cnt) +int JsonFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) { int ret; unsigned i; diff --git a/lib/formats/json_edgeflex.cpp b/lib/formats/json_edgeflex.cpp index bd42676bf..3ff89492f 100644 --- a/lib/formats/json_edgeflex.cpp +++ b/lib/formats/json_edgeflex.cpp @@ -1,7 +1,7 @@ /** JSON serializtion for edgeFlex project. * * @author Manuel Pitz - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,12 +22,12 @@ #include -#include +#include #include using namespace villas::node; -int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct sample *smp) +int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct Sample *smp) { json_t *json_data, *json_value; json_t *json_created = nullptr; @@ -35,16 +35,15 @@ int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct sample *smp) if (smp->length < 1) return -1; - json_data = json_object(); for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) return -1; - json_value = signal_data_to_json(&smp->data[i], sig->type); - json_object_set(json_data, sig->name, 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); @@ -55,9 +54,9 @@ int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct sample *smp) return 0; } -int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct sample *smp) +int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) { - int ret, idx; + int ret; const char *key; json_t *json_value, *json_created = nullptr; json_int_t created = -1; @@ -72,26 +71,20 @@ int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct sample *smp) if (!strcmp(key, "created")) json_created = json_incref(json_value); else { - struct signal *sig; - - sig = vlist_lookup_name(signals, key); - if (sig) { - if (!sig->enabled) - continue; - - idx = vlist_index(signals, sig); - } - 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); if (idx < (int) smp->capacity) { - ret = signal_data_parse_json(&smp->data[idx], sig->type, json_value); + ret = smp->data[idx].parseJson(sig->type, json_value); if (ret) return ret; } diff --git a/lib/formats/json_kafka.cpp b/lib/formats/json_kafka.cpp index 295a111f7..a94ad526d 100644 --- a/lib/formats/json_kafka.cpp +++ b/lib/formats/json_kafka.cpp @@ -1,7 +1,7 @@ /** JSON serializtion for Kafka schema/payloads. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,7 +20,7 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include #include #include @@ -47,7 +47,7 @@ const char * JsonKafkaFormat::villasToKafkaType(enum SignalType vt) } } -int JsonKafkaFormat::packSample(json_t **json_smp, const struct sample *smp) +int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) { json_t *json_payload, *json_fields, *json_field, *json_value; @@ -80,9 +80,9 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct sample *smp) } /* Include sample data */ - for (size_t i = 0; i < MIN(smp->length, vlist_length(smp->signals)); i++) { - struct signal *sig = (struct signal *) vlist_at(smp->signals, i); - const union signal_data *data = &smp->data[i]; + 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), @@ -90,10 +90,10 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct sample *smp) "field", sig->name ); - json_value = signal_data_to_json(data, sig->type); + json_value = data->toJson(sig->type); json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, sig->name, json_value); + json_object_set_new(json_payload, sig->name.c_str(), json_value); } json_object_set_new(json_schema, "fields", json_fields); @@ -102,14 +102,14 @@ int JsonKafkaFormat::packSample(json_t **json_smp, const struct sample *smp) *json_smp = json_pack("{ s: o, s: o }", "schema", json_schema, "payload", json_payload - );; + ); if (*json_smp == nullptr) return -1; return 0; } -int JsonKafkaFormat::unpackSample(json_t *json_smp, struct sample *smp) +int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) { json_t *json_payload, *json_value; @@ -139,14 +139,14 @@ int JsonKafkaFormat::unpackSample(json_t *json_smp, struct sample *smp) } /* Unpack signal data */ - for (size_t i = 0; i < vlist_length(signals); i++) { - struct signal *sig = (struct signal *) vlist_at(signals, i); + for (size_t i = 0; i < signals->size(); i++) { + auto sig = signals->getByIndex(i); - json_value = json_object_get(json_payload, sig->name); + json_value = json_object_get(json_payload, sig->name.c_str()); if (!json_value) continue; - signal_data_parse_json(&smp->data[i], sig->type, json_value); + smp->data[i].parseJson(sig->type, json_value); smp->length++; } diff --git a/lib/formats/json_reserve.cpp b/lib/formats/json_reserve.cpp index e6f0ac240..148440e97 100644 --- a/lib/formats/json_reserve.cpp +++ b/lib/formats/json_reserve.cpp @@ -1,7 +1,7 @@ /** JSON serializtion for RESERVE project. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,14 +22,14 @@ #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) +int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) { json_error_t err; json_t *json_root; @@ -49,12 +49,12 @@ int JsonReserveFormat::packSample(json_t **json_smp, const struct sample *smp) json_data = json_array(); for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) return -1; - if (sig->name) - json_name = json_string(sig->name); + if (!sig->name.empty()) + json_name = json_string(sig->name.c_str()); else { char name[32]; snprintf(name, 32, "signal%u", i); @@ -62,8 +62,8 @@ int JsonReserveFormat::packSample(json_t **json_smp, const struct sample *smp) json_name = json_string(name); } - if (sig->unit) - json_unit = json_string(sig->unit); + if (!sig->unit.empty()) + json_unit = json_string(sig->unit.c_str()); else json_unit = nullptr; @@ -114,7 +114,7 @@ int JsonReserveFormat::packSample(json_t **json_smp, const struct sample *smp) return 0; } -int JsonReserveFormat::unpackSample(json_t *json_smp, struct sample *smp) +int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) { int ret, idx; double created = -1; @@ -180,15 +180,9 @@ int JsonReserveFormat::unpackSample(json_t *json_smp, struct sample *smp) if (ret) return -1; - struct signal *sig; - - sig = vlist_lookup_name(signals, name); - if (sig) { - if (!sig->enabled) - continue; - - idx = vlist_index(signals, sig); - } + auto sig = signals->getByName(name); + if (sig) + idx = signals->getIndexByName(name); else { ret = sscanf(name, "signal_%d", &idx); if (ret != 1) diff --git a/lib/formats/line.cpp b/lib/formats/line.cpp index 1437b54dd..4f684ce21 100644 --- a/lib/formats/line.cpp +++ b/lib/formats/line.cpp @@ -1,7 +1,7 @@ /** Line-based formats * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,7 +26,7 @@ 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) +int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { unsigned i; size_t off = 0; @@ -40,7 +40,7 @@ int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sampl return i; } -int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) { unsigned i; size_t off = 0; @@ -77,7 +77,7 @@ int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample return i; } -int LineFormat::print(FILE *f, const struct sample * const smps[], unsigned cnt) +int LineFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) { int ret; unsigned i; @@ -98,7 +98,7 @@ int LineFormat::print(FILE *f, const struct sample * const smps[], unsigned cnt) return i; } -int LineFormat::scan(FILE *f, struct sample * const smps[], unsigned cnt) +int LineFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) { int ret; unsigned i; diff --git a/lib/formats/msg.cpp b/lib/formats/msg.cpp index debe96370..b0250595c 100644 --- a/lib/formats/msg.cpp +++ b/lib/formats/msg.cpp @@ -1,7 +1,7 @@ /** Message related functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,12 +24,15 @@ #include #include -#include -#include +#include +#include #include -#include +#include -void msg_ntoh(struct msg *m) +using namespace villas; +using namespace villas::node; + +void villas::node::msg_ntoh(struct Message *m) { msg_hdr_ntoh(m); @@ -37,7 +40,7 @@ void msg_ntoh(struct msg *m) m->data[i].i = ntohl(m->data[i].i); } -void msg_hton(struct msg *m) +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); @@ -45,7 +48,7 @@ void msg_hton(struct msg *m) msg_hdr_hton(m); } -void msg_hdr_hton(struct msg *m) +void villas::node::msg_hdr_hton(struct Message *m) { m->length = htons(m->length); m->sequence = htonl(m->sequence); @@ -53,7 +56,7 @@ void msg_hdr_hton(struct msg *m) m->ts.nsec = htonl(m->ts.nsec); } -void msg_hdr_ntoh(struct msg *m) +void villas::node::msg_hdr_ntoh(struct Message *m) { m->length = ntohs(m->length); m->sequence = ntohl(m->sequence); @@ -61,7 +64,7 @@ void msg_hdr_ntoh(struct msg *m) m->ts.nsec = ntohl(m->ts.nsec); } -int msg_verify(const struct msg *m) +int villas::node::msg_verify(const struct Message *m) { if (m->version != MSG_VERSION) return -1; @@ -73,7 +76,7 @@ int msg_verify(const struct msg *m) return 0; } -int msg_to_sample(const struct msg *msg, struct sample *smp, const struct vlist *sigs, uint8_t *source_index) +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; @@ -83,8 +86,8 @@ int msg_to_sample(const struct msg *msg, struct sample *smp, const struct vlist return ret; unsigned len = MIN(msg->length, smp->capacity); - for (i = 0; i < MIN(len, vlist_length(sigs)); i++) { - struct signal *sig = (struct signal *) vlist_at_safe(sigs, i); + for (i = 0; i < MIN(len, sigs->size()); i++) { + auto sig = sigs->getByIndex(i); if (!sig) return -1; @@ -113,7 +116,7 @@ int msg_to_sample(const struct msg *msg, struct sample *smp, const struct vlist return 0; } -int msg_from_sample(struct msg *msg_in, const struct sample *smp, const struct vlist *sigs, uint8_t source_index) +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; @@ -125,7 +128,7 @@ int msg_from_sample(struct msg *msg_in, const struct sample *smp, const struct v msg_in->ts.nsec = smp->ts.origin.tv_nsec; for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at_safe(sigs, i); + auto sig = sigs->getByIndex(i); if (!sig) return -1; diff --git a/lib/formats/protobuf.cpp b/lib/formats/protobuf.cpp index 860c2461e..ea1cefdf7 100644 --- a/lib/formats/protobuf.cpp +++ b/lib/formats/protobuf.cpp @@ -1,7 +1,7 @@ /** Protobuf IO format * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,8 +20,8 @@ * along with this program. If not, see . *********************************************************************************/ -#include -#include +#include +#include #include #include #include @@ -49,7 +49,7 @@ enum SignalType ProtobufFormat::detect(const Villas__Node__Value *val) } } -int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sample * const smps[], unsigned cnt) +int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { unsigned psz; @@ -71,7 +71,7 @@ int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct s 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; @@ -157,7 +157,7 @@ out: return -1; } -int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +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; @@ -167,7 +167,7 @@ int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sa return -1; for (i = 0; i < MIN(pb_msg->n_samples, cnt); i++) { - struct sample *smp = smps[i]; + struct Sample *smp = smps[i]; Villas__Node__Sample *pb_smp = pb_msg->samples[i]; smp->flags = 0; @@ -192,13 +192,13 @@ int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sa enum SignalType fmt = detect(pb_val); - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, j); + 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 {}).", - signal_type_to_str(fmt), signal_type_to_str(sig->type), sig->name, i); + signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); switch (sig->type) { case SignalType::FLOAT: diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index f5fa82cb9..aaf1da5bf 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -1,7 +1,7 @@ /** RAW IO format * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,7 +20,7 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include #include #include @@ -53,7 +53,7 @@ using namespace villas::node; /** 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) +int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { int o = 0; size_t nlen; @@ -72,7 +72,7 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sample #endif for (unsigned i = 0; i < cnt; i++) { - const struct sample *smp = smps[i]; + const struct Sample *smp = smps[i]; /* First three values are sequence, seconds and nano-seconds timestamps * @@ -121,7 +121,7 @@ int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sample for (unsigned j = 0; j < smp->length; j++) { enum SignalType fmt = sample_format(smp, j); - const union signal_data *data = &smp->data[j]; + const union SignalData *data = &smp->data[j]; /* Check length */ nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); @@ -247,7 +247,7 @@ out: if (wbytes) return cnt; } -int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned 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 */ @@ -264,7 +264,7 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample /* 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); @@ -327,7 +327,7 @@ int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample unsigned i; for (i = 0; i < smp->capacity && o < nlen; i++) { enum SignalType fmt = sample_format(smp, i); - union signal_data *data = &smp->data[i]; + union SignalData *data = &smp->data[i]; switch (fmt) { case SignalType::FLOAT: diff --git a/lib/formats/value.cpp b/lib/formats/value.cpp index a6721535c..3be17d7b6 100644 --- a/lib/formats/value.cpp +++ b/lib/formats/value.cpp @@ -21,17 +21,16 @@ *********************************************************************************/ #include -#include -#include +#include +#include using namespace villas::node; -int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct sample * const smps[], unsigned cnt) +int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) { unsigned i; size_t off = 0; - struct signal *sig; - const struct sample *smp = smps[0]; + const struct Sample *smp = smps[0]; assert(cnt == 1); assert(smp->length <= 1); @@ -39,11 +38,11 @@ int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct samp buf[0] = '\0'; for (i = 0; i < smp->length; i++) { - sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) return -1; - off += signal_data_print_str(&smp->data[i], sig->type, buf, len, real_precision); + off += smp->data[i].printString(sig->type, buf, len, real_precision); off += snprintf(buf + off, len - off, "\n"); } @@ -53,10 +52,10 @@ int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct samp return i; } -int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +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]; + struct Sample *smp = smps[0]; const char *ptr = buf; char *end; @@ -66,11 +65,11 @@ int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sampl printf("Reading: %s", buf); if (smp->capacity >= 1) { - struct signal *sig = (struct signal *) vlist_at_safe(signals, i); + auto sig = signals->getByIndex(i); if (!sig) return -1; - ret = signal_data_parse_str(&smp->data[i], sig->type, ptr, &end); + ret = smp->data[i].parseString(sig->type, ptr, &end); if (ret || end == ptr) /* There are no valid values anymore. */ goto out; diff --git a/lib/formats/villas.proto b/lib/formats/villas.proto index 4e5a3d2b3..086228b2c 100644 --- a/lib/formats/villas.proto +++ b/lib/formats/villas.proto @@ -2,7 +2,7 @@ /// /// @file /// @author Steffen Vogel -/// @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +/// @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC /// @license GNU General Public License (version 3) /// /// VILLASnode diff --git a/lib/formats/villas_binary.cpp b/lib/formats/villas_binary.cpp index 49cd93feb..1dfd23aba 100644 --- a/lib/formats/villas_binary.cpp +++ b/lib/formats/villas_binary.cpp @@ -1,7 +1,7 @@ /** Message related functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,22 +26,22 @@ #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 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 msg *msg = (struct msg *) ptr; - const struct sample *smp = smps[i]; + struct Message *msg = (struct Message *) ptr; + const struct Sample *smp = smps[i]; if (ptr + MSG_LEN(smp->length) > buf + len) break; @@ -65,7 +65,7 @@ int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, const stru return i; } -int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct sample * const smps[], unsigned cnt) +int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) { int ret, values; unsigned i, j; @@ -76,8 +76,8 @@ int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struc return -1; /* Packet size is invalid: Must be multiple of 4 bytes */ for (i = 0, j = 0; i < cnt; i++) { - struct msg *msg = (struct msg *) ptr; - struct sample *smp = smps[j]; + struct Message *msg = (struct Message *) ptr; + struct Sample *smp = smps[j]; smp->signals = signals; @@ -86,7 +86,7 @@ int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struc break; /* Check if header is still in buffer bounaries */ - if (ptr + sizeof(struct msg) > buf + len) + if (ptr + sizeof(struct Message) > buf + len) return -2; /* Invalid msg received */ values = web ? msg->length : ntohs(msg->length); diff --git a/lib/formats/villas_human.cpp b/lib/formats/villas_human.cpp index de0aab0b5..a22d33862 100644 --- a/lib/formats/villas_human.cpp +++ b/lib/formats/villas_human.cpp @@ -1,7 +1,7 @@ /** The internal datastructure for a sample of simulation data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,17 +24,16 @@ #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 VILLASHumanFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) { size_t off = 0; - struct signal *sig; if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { @@ -57,12 +56,12 @@ size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, const struct sample if (flags & (int) SampleFlags::HAS_DATA) { for (unsigned i = 0; i < smp->length; i++) { - sig = (struct signal *) vlist_at_safe(smp->signals, i); + auto sig = smp->signals->getByIndex(i); if (!sig) break; off += snprintf(buf + off, len - off, "\t"); - off += signal_data_print_str(&smp->data[i], sig->type, buf + off, len - off, real_precision); + off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); } } @@ -71,7 +70,7 @@ size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, const struct sample return off; } -size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct sample *smp) +size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) { int ret; char *end; @@ -136,11 +135,11 @@ size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct sample * if (*end == delimiter) goto out; - struct signal *sig = (struct signal *) vlist_at_safe(signals, i); + auto sig = signals->getByIndex(i); if (!sig) goto out; - ret = signal_data_parse_str(&smp->data[i], sig->type, ptr, &end); + ret = smp->data[i].parseString(sig->type, ptr, &end); if (ret || end == ptr) /* There are no valid values anymore. */ goto out; } @@ -162,7 +161,7 @@ out: if (*end == delimiter) return end - buf; } -void VILLASHumanFormat::header(FILE *f, const struct vlist *sigs) +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) @@ -180,18 +179,18 @@ void VILLASHumanFormat::header(FILE *f, const struct vlist *sigs) fprintf(f, "(sequence)"); if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < vlist_length(sigs); i++) { - struct signal *sig = (struct signal *) vlist_at_safe(sigs, i); + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); if (!sig) break; - if (sig->name) - fprintf(f, "\t%s", sig->name); + if (!sig->name.empty()) + fprintf(f, "\t%s", sig->name.c_str()); else fprintf(f, "\tsignal%u", i); - if (sig->unit) - fprintf(f, "[%s]", sig->unit); + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); } } diff --git a/lib/hook.cpp b/lib/hook.cpp index 7072a9b91..fe2856c9a 100644 --- a/lib/hook.cpp +++ b/lib/hook.cpp @@ -1,7 +1,7 @@ /** Hook-releated functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,13 +23,13 @@ #include #include -#include -#include +#include +#include #include #include -#include +#include #include -#include +#include const char *hook_reasons[] = { "ok", "error", "skip-sample", "stop-processing" @@ -38,42 +38,25 @@ const char *hook_reasons[] = { using namespace villas; using namespace villas::node; -Hook::Hook(struct vpath *p, struct vnode *n, int fl, int prio, bool en) : +Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) : logger(logging.get("hook")), - state(State::INITIALIZED), + 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) { - int ret; - - ret = signal_list_init(&signals); - if (ret) - throw RuntimeError("Failed to initialize signal list"); - - /* We dont need to parse builtin hooks. */ - state = flags & (int) Hook::Flags::BUILTIN ? State::CHECKED : State::INITIALIZED; -} - -Hook::~Hook() -{ - int ret __attribute__((unused)); - - ret = signal_list_destroy(&signals); -} - -void Hook::prepare(struct vlist *sigs) -{ - int ret; - assert(state == State::CHECKED); - ret = signal_list_copy(&signals, sigs); - if (ret) - throw RuntimeError("Failed to copy signal list"); + signals = sigs->clone(); prepare(); @@ -124,7 +107,7 @@ void SingleSignalHook::parse(json_t *json) 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'"); + throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signal'"); signalName = json_string_value(json_signal); } @@ -135,7 +118,7 @@ void SingleSignalHook::prepare() Hook::prepare(); /* Setup mask */ - int index = vlist_lookup_index(&signals, signalName); + int index = signals->getIndexByName(signalName.c_str()); if (index < 0) throw RuntimeError("Failed to find signal {}", signalName); @@ -193,7 +176,7 @@ void MultiSignalHook::prepare() Hook::prepare(); for (const auto &signalName : signalNames) { - int index = vlist_lookup_index(&signals, signalName); + int index = signals->getIndexByName(signalName.c_str()); if (index < 0) throw RuntimeError("Failed to find signal {}", signalName); diff --git a/lib/hook_list.cpp b/lib/hook_list.cpp index cca317e7c..f1929e947 100644 --- a/lib/hook_list.cpp +++ b/lib/hook_list.cpp @@ -1,7 +1,7 @@ /** Hook-releated functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,43 +23,14 @@ #include #include #include -#include +#include #include -#include +#include using namespace villas; using namespace villas::node; -int hook_list_init(struct vlist *hs) -{ - int ret; - - ret = vlist_init(hs); - if (ret) - return ret; - - return 0; -} - -static int hook_destroy(Hook *h) -{ - delete h; - - return 0; -} - -int hook_list_destroy(struct vlist *hs) -{ - int ret; - - ret = vlist_destroy(hs, (dtor_cb_t) hook_destroy, false); - if (ret) - return ret; - - return 0; -} - -void hook_list_parse(struct vlist *hs, json_t *json, int mask, struct vpath *o, struct vnode *n) +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"); @@ -69,7 +40,7 @@ void hook_list_parse(struct vlist *hs, json_t *json, int mask, struct vpath *o, json_array_foreach(json, i, json_hook) { int ret; const char *type; - Hook *h; + Hook::Ptr h; json_error_t err; json_t *json_config; @@ -100,33 +71,18 @@ void hook_list_parse(struct vlist *hs, json_t *json, int mask, struct vpath *o, h = hf->make(o, n); h->parse(json_config); - vlist_push(hs, h); + push_back(h); } } -static int hook_cmp_priority(const Hook *a, const Hook *b) +void HookList::check() { - return a->getPriority() - b->getPriority(); -} - -static int hook_is_enabled(const Hook *h) -{ - return h->isEnabled() ? 0 : -1; -} - -void hook_list_check(struct vlist *hs) -{ - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); - + for (auto h : *this) h->check(); - } } -void hook_list_prepare(struct vlist *hs, vlist *sigs, int m, struct vpath *p, struct vnode *n) +void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) { - assert(hs->state == State::INITIALIZED); - if (!m) goto skip_add; @@ -134,44 +90,41 @@ void hook_list_prepare(struct vlist *hs, vlist *sigs, int m, struct vpath *p, st for (auto f : plugin::Registry::lookup()) { if ((f->getFlags() & m) == m) { auto h = f->make(p, n); - - vlist_push(hs, h); + push_back(h); } } skip_add: /* Remove filters which are not enabled */ - vlist_filter(hs, (dtor_cb_t) hook_is_enabled); + remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); /* We sort the hooks according to their priority */ - vlist_sort(hs, (cmp_cb_t) hook_cmp_priority); - - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); + 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); sigs = h->getSignals(); auto logger = h->getLogger(); - logger->debug("Signal list after hook #{}:", i); - signal_list_dump(logger, sigs); + logger->debug("Signal list after hook #{}:", i++); + sigs->dump(logger); } } -int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt) +int HookList::process(struct Sample * smps[], unsigned cnt) { unsigned current, processed = 0; - if (vlist_length(hs) == 0) + if (size() == 0) return cnt; for (current = 0; current < cnt; current++) { - struct sample *smp = smps[current]; - - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); + struct Sample *smp = smps[current]; + for (auto h : *this) { auto ret = h->process(smp); smp->signals = h->getSignals(); switch (ret) { @@ -197,51 +150,39 @@ skip: {} return processed; } -void hook_list_periodic(struct vlist *hs) +void HookList::periodic() { - for (size_t j = 0; j < vlist_length(hs); j++) { - Hook *h = (Hook *) vlist_at(hs, j); - + for (auto h : *this) h->periodic(); - } } -void hook_list_start(struct vlist *hs) +void HookList::start() { - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); - + for (auto h : *this) h->start(); - } } -void hook_list_stop(struct vlist *hs) +void HookList::stop() { - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); - + for (auto h : *this) h->stop(); - } } -struct vlist * hook_list_get_signals(struct vlist *hs) +SignalList::Ptr HookList::getSignals() const { - Hook *h = (Hook *) vlist_last(hs); + auto h = back(); if (!h) return nullptr; return h->getSignals(); } -unsigned hook_list_get_signals_max_cnt(struct vlist *hs) +unsigned HookList::getSignalsMaxCount() const { unsigned max_cnt = 0; - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); - - struct vlist *sigs = h->getSignals(); - unsigned sigs_cnt = vlist_length(sigs); + for (auto h : *this) { + unsigned sigs_cnt = h->getSignals()->size(); if (sigs_cnt > max_cnt) max_cnt = sigs_cnt; @@ -250,15 +191,21 @@ unsigned hook_list_get_signals_max_cnt(struct vlist *hs) return max_cnt; } -json_t * hook_list_to_json(struct vlist *hs) +json_t * HookList::toJson() const { json_t *json_hooks = json_array(); - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at_safe(hs, i); - + for (auto h : *this) json_array_append(json_hooks, h->getConfig()); - } return json_hooks; } + +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()); +} diff --git a/lib/hooks/CMakeLists.txt b/lib/hooks/CMakeLists.txt index 81a119618..ff83826bd 100644 --- a/lib/hooks/CMakeLists.txt +++ b/lib/hooks/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/lib/hooks/average.cpp b/lib/hooks/average.cpp index be58f2b80..48f65e368 100644 --- a/lib/hooks/average.cpp +++ b/lib/hooks/average.cpp @@ -1,7 +1,7 @@ /** Average hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,17 +20,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -41,28 +37,23 @@ protected: unsigned offset; public: - AverageHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + AverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : MultiSignalHook(p, n, fl, prio, en), offset(0) { } virtual void prepare() { - int ret; - struct signal *avg_sig; - assert(state == State::CHECKED); MultiSignalHook::prepare(); /* Add averaged signal */ - avg_sig = signal_create("average", nullptr, SignalType::FLOAT); + auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); if (!avg_sig) throw RuntimeError("Failed to create new signal"); - ret = vlist_insert(&signals, offset, avg_sig); - if (ret) - throw RuntimeError("Failed to intialize list"); + signals->insert(signals->begin() + offset, avg_sig); state = State::PREPARED; } @@ -85,7 +76,7 @@ public: state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { double avg, sum = 0; int n = 0; @@ -116,7 +107,7 @@ public: if (offset >= smp->length) return Reason::ERROR; - sample_data_insert(smp, (union signal_data *) &avg, offset, 1); + sample_data_insert(smp, (union SignalData *) &avg, offset, 1); return Reason::OK; } @@ -129,5 +120,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,14 +21,10 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include +#include namespace villas { namespace node { @@ -41,30 +37,25 @@ protected: std::string new_unit; public: - CastHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + 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() { - struct signal *orig_sig, *new_sig; - assert(state == State::CHECKED); MultiSignalHook::prepare(); for (auto index : signalIndices) { - orig_sig = (struct signal *) vlist_at_safe(&signals, index); + 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; - new_sig = signal_create(name.c_str(), unit.c_str(), type); - - vlist_set(&signals, index, new_sig); - signal_decref(orig_sig); + (*signals)[index] = std::make_shared(name, unit, type); } state = State::PREPARED; @@ -93,7 +84,7 @@ public: throw ConfigError(json, err, "node-config-hook-cast"); if (type) { - new_type = signal_type_from_str(type); + new_type = signalTypeFromString(type); if (new_type == SignalType::INVALID) throw RuntimeError("Invalid signal type: {}", type); } @@ -110,15 +101,15 @@ public: state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); for (auto index : signalIndices) { - struct signal *orig_sig = (struct signal *) vlist_at(smp->signals, index); - struct signal *new_sig = (struct signal *) vlist_at(&signals, index); + auto orig_sig = smp->signals->getByIndex(index); + auto new_sig = signals->getByIndex(index); - signal_data_cast(&smp->data[index], orig_sig->type, new_sig->type); + smp->data[index].cast(orig_sig->type, new_sig->type); } return Reason::OK; @@ -133,5 +124,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,10 +20,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include namespace villas { @@ -56,7 +52,7 @@ void DecimateHook::parse(json_t *json) state = State::PARSED; } -Hook::Reason DecimateHook::process(sample *smp) +Hook::Reason DecimateHook::process(struct Sample *smp) { assert(state == State::STARTED); @@ -73,5 +69,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,17 +20,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include -#include +#include #include #include @@ -117,7 +113,7 @@ protected: public: - DPHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + DPHook(Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), signal_name(nullptr), signal_index(0), @@ -224,17 +220,14 @@ public: virtual void prepare() { - int ret; - assert(state == State::CHECKED); char *new_sig_name; - struct signal *orig_sig, *new_sig; assert(state != State::STARTED); if (signal_name) { - signal_index = vlist_lookup_index(&signals, signal_name); + signal_index = signals->getIndexByName(signal_name); if (signal_index < 0) throw RuntimeError("Failed to find signal: {}", signal_name); } @@ -242,60 +235,48 @@ public: if (inverse) { /* Remove complex-valued coefficient signals */ for (int i = 0; i < fharmonics_len; i++) { - orig_sig = (struct signal *) vlist_at_safe(&signals, signal_index + i); + auto orig_sig = signals->getByIndex(signal_index + i); if (!orig_sig) - throw RuntimeError("Failed to find signal");; + throw RuntimeError("Failed to find signal"); if (orig_sig->type != SignalType::COMPLEX) - throw RuntimeError("Signal is not complex");; + throw RuntimeError("Signal is not complex"); - ret = vlist_remove(&signals, signal_index + i); - if (ret) - throw RuntimeError("Failed to remove signal from list");; - - signal_decref(orig_sig); + signals->erase(signals->begin() + signal_index + i); } /* Add new real-valued reconstructed signals */ - new_sig = signal_create("dp", "idp", SignalType::FLOAT); + auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); if (!new_sig) - throw RuntimeError("Failed to create signal");; + throw RuntimeError("Failed to create signal"); - ret = vlist_insert(&signals, offset, new_sig); - if (ret) - throw RuntimeError("Failed to insert signal into list");; + signals->insert(signals->begin() + offset, new_sig); } else { - orig_sig = (struct signal *) vlist_at_safe(&signals, signal_index); + auto orig_sig = signals->getByIndex(signal_index); if (!orig_sig) - throw RuntimeError("Failed to find signal");; + throw RuntimeError("Failed to find signal"); if (orig_sig->type != SignalType::FLOAT) - throw RuntimeError("Signal is not float");; + throw RuntimeError("Signal is not float"); - ret = vlist_remove(&signals, signal_index); - if (ret) - throw RuntimeError("Failed to remove signal from list");; + 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); - new_sig = signal_create(new_sig_name, orig_sig->unit, SignalType::COMPLEX); + auto new_sig = std::make_shared(new_sig_name, orig_sig->unit, SignalType::COMPLEX); if (!new_sig) - throw RuntimeError("Failed to create new signal");; + throw RuntimeError("Failed to create new signal"); - ret = vlist_insert(&signals, offset + i, new_sig); - if (ret) - throw RuntimeError("Failed to insert signal into list");; + signals->insert(signals->begin() + offset, new_sig); } - - signal_decref(orig_sig); } state = State::PREPARED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { if (signal_index >= smp->length) return Hook::Reason::ERROR; @@ -307,7 +288,7 @@ public: istep(coeffs, &signal); sample_data_remove(smp, signal_index, fharmonics_len); - sample_data_insert(smp, (union signal_data *) &signal, offset, 1); + sample_data_insert(smp, (union SignalData *) &signal, offset, 1); } else { double signal = smp->data[signal_index].f; @@ -316,7 +297,7 @@ public: step(&signal, coeffs); sample_data_remove(smp, signal_index, 1); - sample_data_insert(smp, (union signal_data *) coeffs, offset, fharmonics_len); + sample_data_insert(smp, (union SignalData *) coeffs, offset, fharmonics_len); } time += timestep; @@ -333,5 +314,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,15 +20,10 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include -#include +#include namespace villas { namespace node { @@ -36,7 +31,7 @@ namespace node { class DropHook : public Hook { protected: - sample *prev; + struct Sample *prev; public: using Hook::Hook; @@ -60,7 +55,7 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { int dist; @@ -102,5 +97,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,13 +21,8 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include -#include +#include namespace villas { namespace node { @@ -37,7 +32,7 @@ class DumpHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -54,5 +49,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,15 +20,11 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -40,7 +36,7 @@ protected: double energy; - sample *last; + struct Sample *last; public: using Hook::Hook; @@ -96,7 +92,7 @@ public: logger->info("Energy: {}", energy); } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { double P, P_last, dt; @@ -130,5 +126,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,16 +21,12 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include -#include -#include +#include +#include +#include namespace villas { namespace node { @@ -40,7 +36,7 @@ class FixHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -73,5 +69,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,18 +20,14 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include -#include -#include -#include +#include +#include +#include namespace villas { namespace node { @@ -56,7 +52,7 @@ protected: timespec startTime; public: - GateHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + 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), @@ -109,14 +105,14 @@ public: SingleSignalHook::prepare(); /* Check if signal type is float */ - auto sig = (struct signal *) vlist_at(&signals, signalIndex); + auto sig = signals->getByIndex(signalIndex); if (sig->type != SignalType::FLOAT) throw RuntimeError("Gate signal must be of type float"); state = State::PREPARED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -176,5 +172,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,17 +20,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include -#include -#include +#include +#include #include #define GPS_NTP_DELAY_WIN_SIZE 16 @@ -52,7 +48,7 @@ protected: public: - JitterCalcHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + 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), @@ -71,7 +67,7 @@ public: * 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(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -118,5 +114,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,14 +20,10 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include -#include +#include +#include #include namespace villas { @@ -68,7 +64,7 @@ void LimitRateHook::parse(json_t *json) state = State::PARSED; } -Hook::Reason LimitRateHook::process(sample *smp) +Hook::Reason LimitRateHook::process(struct Sample *smp) { assert(state == State::STARTED); @@ -102,5 +98,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,18 +20,14 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -44,34 +40,13 @@ protected: float min, max; public: - LimitValueHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + 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 prepare() - { - int ret; - struct signal *avg_sig; - - assert(state == State::CHECKED); - - MultiSignalHook::prepare(); - - /* Add averaged signal */ - avg_sig = signal_create("average", nullptr, SignalType::FLOAT); - if (!avg_sig) - throw RuntimeError("Failed to create new signal"); - - ret = vlist_insert(&signals, offset, avg_sig); - if (ret) - throw RuntimeError("Failed to intialize list"); - - state = State::PREPARED; - } - virtual void parse(json_t *json) { int ret; @@ -91,7 +66,7 @@ public: state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -125,11 +100,9 @@ public: }; /* Register hook */ -static char n[] = "average"; -static char d[] = "Calculate average over some signals"; +static char n[] = "limit_value"; +static char d[] = "Limit signal values"; static HookPlugin p; } /* namespace node */ } /* namespace villas */ - -/** @} */ diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index c6dfc3b77..90219635c 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -2,7 +2,7 @@ /** Lua expressions hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,10 +21,6 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include @@ -37,14 +33,15 @@ extern "C" { #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include using namespace villas; +using namespace villas::node; class LuaError : public RuntimeError { @@ -96,8 +93,8 @@ public: } }; -static void -lua_pushtimespec(lua_State *L, struct timespec *ts) +static +void lua_pushtimespec(lua_State *L, struct timespec *ts) { lua_createtable(L, 2, 0); @@ -108,8 +105,8 @@ lua_pushtimespec(lua_State *L, struct timespec *ts) lua_rawseti(L, -2, 1); } -static void -lua_totimespec(lua_State *L, struct timespec *ts) +static +void lua_totimespec(lua_State *L, struct timespec *ts) { lua_rawgeti(L, -1, 0); ts->tv_sec = lua_tonumber(L, -1); @@ -120,8 +117,33 @@ lua_totimespec(lua_State *L, struct timespec *ts) lua_pop(L, 2); } -static void -lua_tosignaldata(lua_State *L, union signal_data *data, enum SignalType targetType, int idx = -1) +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::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 */ + } + + return true; +} + +static +void lua_tosignaldata(lua_State *L, union SignalData *data, enum SignalType targetType, int idx = -1) { int luaType; enum SignalType type; @@ -142,11 +164,11 @@ lua_tosignaldata(lua_State *L, union signal_data *data, enum SignalType targetTy return; } - signal_data_cast(data, type, targetType); + data->cast(type, targetType); } -static void -lua_tosample(lua_State *L, struct sample *smp, struct vlist *signals, bool use_names = true, int idx = -1) +static +void lua_tosample(lua_State *L, struct Sample *smp, SignalList::Ptr signals, bool use_names = true, int idx = -1) { int ret; @@ -180,19 +202,22 @@ lua_tosample(lua_State *L, struct sample *smp, struct vlist *signals, bool use_n lua_getfield(L, idx, "data"); ret = lua_type(L, -1); if (ret != LUA_TNIL) { - for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at(signals, i); - + int i = 0; + for (auto sig : *signals) { if (use_names) - lua_getfield(L, -1, sig->name); + 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; lua_pop(L, 1); + i++; + smp->length++; } if (smp->length > 0) @@ -201,8 +226,8 @@ lua_tosample(lua_State *L, struct sample *smp, struct vlist *signals, bool use_n lua_pop(L, 1); } -static void -lua_pushsample(lua_State *L, struct sample *smp, bool use_names = true) +static +void lua_pushsample(lua_State *L, struct Sample *smp, bool use_names = true) { lua_createtable(L, 0, 5); @@ -228,30 +253,15 @@ lua_pushsample(lua_State *L, struct sample *smp, bool use_names = true) lua_createtable(L, smp->length, 0); for (unsigned i = 0; i < smp->length; i++) { - struct signal *sig = (struct signal *) vlist_at(smp->signals, i); - union signal_data *data = &smp->data[i]; + const auto sig = smp->signals->getByIndex(i); + const auto *data = &smp->data[i]; - switch (sig->type) { - case SignalType::FLOAT: - lua_pushnumber(L, data->f); - break; - - case SignalType::INTEGER: - lua_pushinteger(L, data->i); - break; - - case SignalType::BOOLEAN: - lua_pushboolean(L, data->b); - break; - - case SignalType::COMPLEX: - case SignalType::INVALID: - default: - continue; /* we skip unknown types. Lua will see a nil value in the table */ - } + auto pushed = lua_pushsignaldata(L, data, sig); + if (!pushed) + continue; if (use_names) - lua_setfield(L, -2, sig->name); + lua_setfield(L, -2, sig->name.c_str()); else lua_rawseti(L, -2, i); } @@ -260,8 +270,8 @@ lua_pushsample(lua_State *L, struct sample *smp, bool use_names = true) } } -static void -lua_pushjson(lua_State *L, json_t *json) +static +void lua_pushjson(lua_State *L, json_t *json) { size_t i; const char *key; @@ -274,7 +284,7 @@ lua_pushjson(lua_State *L, json_t *json) lua_pushjson(L, json_value); lua_setfield(L, -2, key); } - break;; + break; case JSON_ARRAY: lua_newtable(L); @@ -304,7 +314,8 @@ lua_pushjson(lua_State *L, json_t *json) } } -static json_t * lua_tojson(lua_State *L, int index = -1) +static +json_t * lua_tojson(lua_State *L, int index = -1) { double n; const char *s; @@ -381,7 +392,6 @@ static json_t * lua_tojson(lua_State *L, int index = -1) namespace villas { namespace node { - LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) : cookie(0), L(l) @@ -403,14 +413,12 @@ LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) : expression = expr; } -void -LuaSignalExpression::prepare() +void LuaSignalExpression::prepare() { parseExpression(expression); } -void -LuaSignalExpression::parseExpression(const std::string &expr) +void LuaSignalExpression::parseExpression(const std::string &expr) { /* Release previous expression */ if (cookie) @@ -425,8 +433,7 @@ LuaSignalExpression::parseExpression(const std::string &expr) cookie = luaL_ref(L, LUA_REGISTRYINDEX); } -void -LuaSignalExpression::evaluate(union signal_data *data, enum SignalType type) +void LuaSignalExpression::evaluate(union SignalData *data, enum SignalType type) { int err; @@ -443,41 +450,29 @@ LuaSignalExpression::evaluate(union signal_data *data, enum SignalType type) lua_pop(L, 1); } -LuaHook::LuaHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en) : +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) -{ - int ret; - ret = signal_list_init(&signalsProcessed); - if (ret) - throw RuntimeError("Failed to initialize signal list"); - - ret = signal_list_init(&signalsExpressions); - if (ret) - throw RuntimeError("Failed to initialize signal list"); -} + hasExpressions(false), + needsLocking(false), + functions({0}) +{ } LuaHook::~LuaHook() { - int ret __attribute__((unused)); - lua_close(L); - - ret = signal_list_destroy(&signalsProcessed); - ret = signal_list_destroy(&signalsExpressions); } -void -LuaHook::parseExpressions(json_t *json_sigs) +void LuaHook::parseExpressions(json_t *json_sigs) { int ret; size_t i; json_t *json_sig; - signal_list_clear(&signalsExpressions); - ret = signal_list_parse(&signalsExpressions, json_sigs); + 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"); @@ -487,8 +482,7 @@ LuaHook::parseExpressions(json_t *json_sigs) hasExpressions = true; } -void -LuaHook::parse(json_t *json) +void LuaHook::parse(json_t *json) { int ret; const char *script_str = nullptr; @@ -519,8 +513,7 @@ LuaHook::parse(json_t *json) state = State::PARSED; } -void -LuaHook::lookupFunctions() +void LuaHook::lookupFunctions() { int ret; @@ -548,8 +541,7 @@ LuaHook::lookupFunctions() } } -void -LuaHook::loadScript() +void LuaHook::loadScript() { int ret; @@ -565,43 +557,37 @@ LuaHook::loadScript() throw LuaError(L, ret); } -int -LuaHook::luaRegisterApiHandler(lua_State *L) +int LuaHook::luaRegisterApiHandler(lua_State *L) { // register_api_handler(path_regex) return 0; } -int -LuaHook::luaInfo(lua_State *L) +int LuaHook::luaInfo(lua_State *L) { logger->info(luaL_checkstring(L, 1)); return 0; } -int -LuaHook::luaWarn(lua_State *L) +int LuaHook::luaWarn(lua_State *L) { logger->warn(luaL_checkstring(L, 1)); return 0; } -int -LuaHook::luaError(lua_State *L) +int LuaHook::luaError(lua_State *L) { logger->error(luaL_checkstring(L, 1)); return 0; } -int -LuaHook::luaDebug(lua_State *L) +int LuaHook::luaDebug(lua_State *L) { logger->debug(luaL_checkstring(L, 1)); return 0; } -void -LuaHook::setupEnvironment() +void LuaHook::setupEnvironment() { lua_pushlightuserdata(L, this); lua_rawseti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); @@ -614,8 +600,7 @@ LuaHook::setupEnvironment() lua_register(L, "register_api_handler", &dispatch<&LuaHook::luaRegisterApiHandler>); } -void -LuaHook::prepare() +void LuaHook::prepare() { /* Load Lua standard libraries */ luaL_openlibs(L); @@ -637,7 +622,7 @@ LuaHook::prepare() if (functions.process) { /* We currently do not support the alteration of * signal metadata in process() */ - signal_list_copy(&signalsProcessed, &signals); + signalsProcessed = signals; } /* Prepare Lua expressions */ @@ -645,8 +630,7 @@ LuaHook::prepare() for (auto &expr : expressions) expr.prepare(); - signal_list_clear(&signals); - signal_list_copy(&signals, &signalsExpressions); + signals = signalsExpressions; } if (!functions.process && !hasExpressions) @@ -666,8 +650,7 @@ LuaHook::prepare() } } -void -LuaHook::start() +void LuaHook::start() { assert(state == State::PREPARED); @@ -686,8 +669,7 @@ LuaHook::start() state = State::STARTED; } -void -LuaHook::stop() +void LuaHook::stop() { assert(state == State::STARTED); @@ -706,8 +688,7 @@ LuaHook::stop() state = State::STOPPED; } -void -LuaHook::restart() +void LuaHook::restart() { auto lockScope = needsLocking ? std::unique_lock(mutex) @@ -726,8 +707,7 @@ LuaHook::restart() Hook::restart(); } -void -LuaHook::periodic() +void LuaHook::periodic() { assert(state == State::STARTED); @@ -744,8 +724,7 @@ LuaHook::periodic() } } -Hook::Reason -LuaHook::process(sample *smp) +Hook::Reason LuaHook::process(struct Sample *smp) { if (!functions.process && !hasExpressions) return Reason::OK; @@ -779,7 +758,7 @@ LuaHook::process(sample *smp) lua_pop(L, 1); - lua_tosample(L, smp, &signalsProcessed, useNames); + lua_tosample(L, smp, signalsProcessed, useNames); } else reason = Reason::OK; @@ -790,7 +769,9 @@ LuaHook::process(sample *smp) lua_setglobal(L, "smp"); for (unsigned i = 0; i < expressions.size(); i++) { - auto *sig = (struct signal *) vlist_at(&signalsExpressions, i); + auto sig = signalsExpressions->getByIndex(i); + if (!sig) + continue; expressions[i].evaluate(&smp->data[i], sig->type); } @@ -803,10 +784,8 @@ LuaHook::process(sample *smp) /* Register hook */ static char n[] = "lua"; -static char d[] = "Implement hook in Lua"; +static char d[] = "Implement hook functions or expressions in Lua"; static HookPlugin p; } /* namespace node */ } /* namespace villas */ - -/** @} */ diff --git a/lib/hooks/ma.cpp b/lib/hooks/ma.cpp index 5a13c910e..1ae12b20e 100644 --- a/lib/hooks/ma.cpp +++ b/lib/hooks/ma.cpp @@ -21,12 +21,8 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include +#include namespace villas { namespace node { @@ -41,11 +37,11 @@ protected: uint64_t smpMemoryPosition; public: - MovingAverageHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + MovingAverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : MultiSignalHook(p, n, fl, prio, en), smpMemory(), accumulator(0.0), - windowSize(0), + windowSize(10), smpMemoryPosition(0) { } @@ -56,7 +52,7 @@ public: /* Add signals */ for (auto index : signalIndices) { - auto *origSig = (struct signal *) vlist_at(&signals, index); + auto origSig = signals->getByIndex(index); /* Check that signal has float type */ if (origSig->type != SignalType::FLOAT) @@ -91,7 +87,7 @@ public: } virtual - Hook::Reason process(struct sample *smp) + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -127,5 +123,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,21 +20,16 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include #include -#include +#include #include #include -#include -#include +#include /* Uncomment to enable dumper of memory windows */ //#define DFT_MEM_DUMP @@ -127,7 +122,7 @@ protected: double angleUnitFactor; public: - PmuDftHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + PmuDftHook(Path *p, Node *n, int fl, int prio, bool en = true) : MultiSignalHook(p, n, fl, prio, en), windowType(WindowType::NONE), paddingType(PaddingType::ZERO), @@ -179,31 +174,30 @@ public: dumperEnable = logger->level() <= SPDLOG_LEVEL_DEBUG; - signal_list_clear(&signals); + signals->clear(); for (unsigned i = 0; i < signalIndices.size(); i++) { - struct signal *freqSig; - struct signal *amplSig; - struct signal *phaseSig; - struct signal *rocofSig; - /* Add signals */ - std::stringstream ss_freq, ss_ampl, ss_phase, ss_rocof; - ss_freq << "frequency" << (channelNameEnable)?signalNames[i]:""; - freqSig = signal_create(ss_freq.str().c_str(), "Hz", SignalType::FLOAT); - ss_ampl << "amplitude" << (channelNameEnable)?signalNames[i]:""; - amplSig = signal_create(ss_ampl.str().c_str(), "V", SignalType::FLOAT); - ss_phase << "phase" << (channelNameEnable)?signalNames[i]:""; - phaseSig = signal_create(ss_phase.str().c_str(), "rad", SignalType::FLOAT); - ss_rocof << "rocof" << (channelNameEnable)?signalNames[i]:""; - rocofSig = signal_create(ss_rocof.str().c_str(), "Hz/s", SignalType::FLOAT); + auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); + auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); + auto phaseSig = std::make_shared("phase", "rad", SignalType::FLOAT); + auto rocofSig = std::make_shared("rocof", "Hz/s", SignalType::FLOAT); if (!freqSig || !amplSig || !phaseSig || !rocofSig) throw RuntimeError("Failed to create new signals"); - vlist_push(&signals, freqSig); - vlist_push(&signals, amplSig); - vlist_push(&signals, phaseSig); - vlist_push(&signals, rocofSig); + if (channelNameEnable) { + auto suffix = fmt::format("_{}", signalNames[i]); + + 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); } /* Initialize sample memory */ @@ -335,7 +329,7 @@ public: state = State::CHECKED; } - virtual Hook::Reason process(struct sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -468,7 +462,7 @@ public: double tmpSmpWindow[windowSize]; for (unsigned i = 0; i< windowSize; i++) - tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * filterWindowCoefficents[i];; + tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * filterWindowCoefficents[i]; #ifdef DFT_MEM_DUMP if (dumperEnable) @@ -568,5 +562,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,16 +20,12 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -62,7 +58,7 @@ protected: std::vector filterWindow; public: - PpsTsHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + PpsTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : SingleSignalHook(p, n, fl, prio, en), mode(Mode::SIMPLE), lastSequence(0), @@ -118,7 +114,7 @@ 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: @@ -132,7 +128,7 @@ public: } } - villas::node::Hook::Reason processSimple(struct sample *smp) + villas::node::Hook::Reason processSimple(struct Sample *smp) { assert(state == State::STARTED); @@ -168,7 +164,7 @@ public: return Hook::Reason::OK; } - villas::node::Hook::Reason processHorizon(struct sample *smp) + villas::node::Hook::Reason processHorizon(struct Sample *smp) { assert(state == State::STARTED); @@ -238,5 +234,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,17 +20,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include +#include #include -#include -#include +#include +#include #include namespace villas { @@ -39,97 +35,108 @@ namespace node { class PrintHook : public Hook { protected: - Format *formatter; - FILE *stream; + Format::Ptr formatter; std::string prefix; - std::string uri; + std::string output_path; + + FILE *output; public: - PrintHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + PrintHook(Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), - formatter(nullptr), - stream(nullptr) + output(nullptr) { } - virtual ~PrintHook() + virtual + void start() { - if (formatter) - delete formatter; - } + 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"); + } - formatter->start(&signals); - - stream = !uri.empty() ? fopen(uri.c_str(), "a+") : stdout; - if (!stream) - throw SystemError("Failed to open IO"); + formatter->start(signals); state = State::STARTED; } - virtual void stop() - { - assert(state == State::STARTED); - - if (stream != stdout) - fclose(stream); - - state = State::STOPPED; + virtual + void stop() { + if (output) + fclose(output); } - virtual void parse(json_t *json) + virtual + void parse(json_t *json) { - const char *p = nullptr, *u = nullptr; + const char *p = nullptr; + const char *o = nullptr; int ret; json_error_t err; json_t *json_format = nullptr; - assert(state != State::STARTED); + assert(state == State::INITIALIZED || + state == State::CHECKED || + state == State::PARSED); Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o }", - "output", &u, + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: s }", "prefix", &p, - "format", &json_format + "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) prefix = p; - if (u) - uri = u; + if (o) + output_path = o; /* Format */ - formatter = json_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"); state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); - if (stream == stdout) { - if (!prefix.empty()) - std::cout << prefix.c_str(); - else if (node) - std::cout << "Node " << *node << ": "; - else if (path) - std::cout << "Path " << *path << ": "; - } + if (!output) { + char buf[1024]; + size_t wbytes; - formatter->print(stream, smp); + formatter->sprint(buf, sizeof(buf), &wbytes, smp); + + if (wbytes > 0 && buf[wbytes-1] == '\n') + buf[wbytes-1] = 0; + + if (node) + logger->info("{}{} {}", prefix, *node, buf); + else if (path) + logger->info("{}{} {}", prefix, *path, buf); + } + else + formatter->print(output, smp); return Reason::OK; } @@ -137,11 +144,9 @@ public: /* Register hook */ static char n[] = "print"; -static char d[] = "Print the message to stdout"; +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 1c29cc038..98d5e905d 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -1,7 +1,7 @@ /** Path restart hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,15 +20,11 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -36,7 +32,7 @@ namespace node { class RestartHook : public Hook { protected: - sample *prev; + struct Sample *prev; public: using Hook::Hook; @@ -60,7 +56,7 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -73,17 +69,11 @@ public: smp->flags |= (int) SampleFlags::IS_FIRST; /* Restart hooks */ - for (size_t i = 0; i < vlist_length(&node->in.hooks); i++) { - Hook *k = (Hook *) vlist_at(&node->in.hooks, i); - + for (auto k : node->in.hooks) k->restart(); - } - - for (size_t i = 0; i < vlist_length(&node->out.hooks); i++) { - Hook *k = (Hook *) vlist_at(&node->out.hooks, i); + for (auto k : node->out.hooks) k->restart(); - } } } @@ -104,5 +94,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,12 +20,8 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include +#include namespace villas { namespace node { @@ -40,7 +36,7 @@ protected: uint64_t smpMemoryPosition; public: - RMSHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + RMSHook(Path *p, Node *n, int fl, int prio, bool en = true) : MultiSignalHook(p, n, fl, prio, en), smpMemory(), windowSize(0), @@ -54,7 +50,7 @@ public: /* Add signals */ for (auto index : signalIndices) { - auto *origSig = (struct signal *) vlist_at(&signals, index); + auto origSig = signals->getByIndex(index); /* Check that signal has float type */ if (origSig->type != SignalType::FLOAT) @@ -91,7 +87,7 @@ public: } virtual - Hook::Reason process(struct sample *smp) + Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -129,5 +125,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,14 +20,10 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include +#include namespace villas { namespace node { @@ -39,7 +35,7 @@ protected: double offset; public: - ScaleHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + ScaleHook(Path *p, Node *n, int fl, int prio, bool en = true) : MultiSignalHook(p, n, fl, prio, en), scale(1.0), offset(0.0) @@ -64,7 +60,7 @@ 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); @@ -101,5 +97,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,12 +20,8 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include +#include namespace villas { namespace node { @@ -57,7 +53,7 @@ public: state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -74,5 +70,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,15 +20,11 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -43,7 +39,7 @@ protected: } mode; public: - ShiftTimestampHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + ShiftTimestampHook(Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), mode(SHIFT_ORIGIN) { } @@ -80,7 +76,7 @@ public: state = State::PARSED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { timespec *ts; @@ -99,7 +95,7 @@ public: return Hook::Reason::ERROR; } - *ts = time_add(ts, &offset);; + *ts = time_add(ts, &offset); return Reason::OK; } @@ -112,5 +108,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,13 +20,9 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include -#include +#include +#include namespace villas { namespace node { @@ -102,7 +98,7 @@ public: skip_state = SkipState::STARTED; } - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -147,5 +143,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,18 +20,14 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include #include #include #include #include -#include -#include +#include +#include namespace villas { namespace node { @@ -44,7 +40,7 @@ protected: StatsHook *parent; public: - StatsWriteHook(StatsHook *pa, struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + StatsWriteHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), parent(pa) { @@ -52,18 +48,18 @@ public: 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; public: - StatsReadHook(StatsHook *pa, struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + StatsReadHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), last(nullptr), parent(pa) @@ -91,7 +87,7 @@ public: state = State::STOPPED; } - virtual Hook::Reason process(sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; class StatsHook : public Hook { @@ -100,8 +96,8 @@ class StatsHook : public Hook { friend StatsWriteHook; protected: - StatsReadHook *readHook; - StatsWriteHook *writeHook; + std::shared_ptr readHook; + std::shared_ptr writeHook; enum Stats::Format format; int verbose; @@ -115,7 +111,7 @@ protected: public: - StatsHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) : + StatsHook(Path *p, Node *n, int fl, int prio, bool en = true) : Hook(p, n, fl, prio, en), format(Stats::Format::HUMAN), verbose(0), @@ -124,16 +120,16 @@ public: output(nullptr), uri() { - readHook = new StatsReadHook(this, p, n, fl, prio, en); - writeHook = new StatsWriteHook(this, p, n, fl, prio, en); + 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(); /* Add child hooks */ if (node) { - vlist_push(&node->in.hooks, (void *) readHook); - vlist_push(&node->out.hooks, (void *) writeHook); + node->in.hooks.push_back(readHook); + node->out.hooks.push_back(writeHook); } } @@ -172,7 +168,7 @@ public: stats->reset(); } - virtual Hook::Reason process(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) @@ -230,17 +226,14 @@ public: stats = std::make_shared(buckets, warmup); - /* Register statistic object to node. - * - * This allows the node code to update statistics. */ if (node) - node->stats = stats; + node->setStats(stats); state = State::PREPARED; } }; -Hook::Reason StatsWriteHook::process(struct sample *smp) +Hook::Reason StatsWriteHook::process(struct Sample *smp) { timespec now = time_now(); @@ -249,7 +242,7 @@ Hook::Reason StatsWriteHook::process(struct sample *smp) return Reason::OK; } -Hook::Reason StatsReadHook::process(struct sample *smp) +Hook::Reason StatsReadHook::process(struct Sample *smp) { if (last) { if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_RECEIVED) @@ -288,5 +281,3 @@ static HookPlugin p; } /* namespace node */ } /* namespace villas */ -/** @} */ - diff --git a/lib/hooks/ts.cpp b/lib/hooks/ts.cpp index 9182db715..aed5b8629 100644 --- a/lib/hooks/ts.cpp +++ b/lib/hooks/ts.cpp @@ -1,7 +1,7 @@ /** Timestamp hook. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,13 +20,9 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup hooks Hook functions - * @{ - */ - #include -#include -#include +#include +#include namespace villas { namespace node { @@ -36,7 +32,7 @@ class TsHook : public Hook { public: using Hook::Hook; - virtual Hook::Reason process(sample *smp) + virtual Hook::Reason process(struct Sample *smp) { assert(state == State::STARTED); @@ -53,5 +49,3 @@ static HookPlugin - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,7 +26,7 @@ #include -#include +#include #include #include #include diff --git a/lib/kernel/nl.cpp b/lib/kernel/nl.cpp index 8ec80e17f..122585c25 100644 --- a/lib/kernel/nl.cpp +++ b/lib/kernel/nl.cpp @@ -3,7 +3,7 @@ * VILLASnode uses libnl3 to talk to the Linux kernel to gather networking related information * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/kernel/tc.cpp b/lib/kernel/tc.cpp index 1359f3e65..1f9777525 100644 --- a/lib/kernel/tc.cpp +++ b/lib/kernel/tc.cpp @@ -3,7 +3,7 @@ * VILLASnode uses these functions to setup the network emulation feature. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/lib/kernel/tc_netem.cpp b/lib/kernel/tc_netem.cpp index 4f093ab32..717d380c2 100644 --- a/lib/kernel/tc_netem.cpp +++ b/lib/kernel/tc_netem.cpp @@ -3,7 +3,7 @@ * VILLASnode uses these functions to setup the network emulation feature. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -86,7 +86,7 @@ static int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) 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); diff --git a/lib/mapping.cpp b/lib/mapping.cpp index 73b8991a4..1923d8e4d 100644 --- a/lib/mapping.cpp +++ b/lib/mapping.cpp @@ -1,7 +1,7 @@ /** Sample value remapping for mux. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,19 +23,19 @@ #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 mapping_entry_parse_str(struct mapping_entry *me, const std::string &str) +int MappingEntry::parseString(const std::string &str) { std::smatch mr; std::regex re(RE_MAPPING); @@ -44,65 +44,65 @@ int mapping_entry_parse_str(struct mapping_entry *me, const std::string &str) goto invalid_format; if (mr[1].matched) - me->node_name = strdup(mr.str(1).c_str()); + nodeName = mr.str(1); if (mr[9].matched) - me->node_name = strdup(mr.str(9).c_str()); + nodeName = mr.str(9); if (mr[6].matched) { - me->data.first = strdup(mr.str(6).c_str()); - me->data.last = mr[7].matched + data.first = strdup(mr.str(6).c_str()); + data.last = mr[7].matched ? strdup(mr.str(7).c_str()) : nullptr; - me->type = MappingType::DATA; + type = Type::DATA; } else if (mr[10].matched) { - me->data.first = strdup(mr.str(10).c_str()); - me->data.last = mr[11].matched + data.first = strdup(mr.str(10).c_str()); + data.last = mr[11].matched ? strdup(mr.str(11).c_str()) : nullptr; - me->type = MappingType::DATA; + type = Type::DATA; } else if (mr[8].matched) { - me->data.first = strdup(mr.str(8).c_str()); - me->data.last = nullptr; + data.first = strdup(mr.str(8).c_str()); + data.last = nullptr; - me->type = MappingType::DATA; + type = Type::DATA; } else if (mr[2].matched) { - me->stats.type = Stats::lookupType(mr.str(3)); - me->stats.metric = Stats::lookupMetric(mr.str(2)); + stats.type = Stats::lookupType(mr.str(3)); + stats.metric = Stats::lookupMetric(mr.str(2)); - me->type = MappingType::STATS; + type = Type::STATS; } else if (mr[5].matched) { if (mr.str(5) == "origin") - me->timestamp.type = MappingTimestampType::ORIGIN; + timestamp.type = TimestampType::ORIGIN; else if (mr.str(5) == "received") - me->timestamp.type = MappingTimestampType::RECEIVED; + timestamp.type = TimestampType::RECEIVED; else goto invalid_format; - me->type = MappingType::TIMESTAMP; + type = Type::TIMESTAMP; } else if (mr[4].matched) { if (mr.str(4) == "sequence") - me->header.type = MappingHeaderType::SEQUENCE; + header.type = HeaderType::SEQUENCE; else if (mr.str(4) == "length") - me->header.type = MappingHeaderType::LENGTH; + header.type = HeaderType::LENGTH; else goto invalid_format; - me->type = MappingType::HEADER; + type = Type::HEADER; } /* Only node name given.. We map all data */ - else if (me->node_name) { - me->data.first = nullptr; - me->data.last = nullptr; + else if (!nodeName.empty()) { + data.first = nullptr; + data.last = nullptr; - me->type = MappingType::DATA; + type = Type::DATA; } return 0; @@ -112,25 +112,15 @@ invalid_format: throw RuntimeError("Failed to parse mapping expression: {}", str); } -int mapping_entry_init(struct mapping_entry *me) -{ - me->type = MappingType::UNKNOWN; +MappingEntry::MappingEntry() : + node(nullptr), + type(Type::UNKNOWN), + length(0), + offset(0), + nodeName() +{ } - me->node = nullptr; - me->node_name = nullptr; - - return 0; -} - -int mapping_entry_destroy(struct mapping_entry *me) -{ - if (me->node_name) - free(me->node_name); - - return 0; -} - -int mapping_entry_parse(struct mapping_entry *me, json_t *json) +int MappingEntry::parse(json_t *json) { const char *str; @@ -138,88 +128,48 @@ int mapping_entry_parse(struct mapping_entry *me, json_t *json) if (!str) return -1; - return mapping_entry_parse_str(me, str); + return parseString(str); } -int mapping_list_parse(struct vlist *ml, json_t *json) +int MappingEntry::update(struct Sample *remapped, const struct Sample *original) const { - int ret; + unsigned len = length; - 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 + if (offset + len > remapped->capacity) return -1; - json_array_foreach(json_mapping, i, json_entry) { - auto *me = new struct mapping_entry; - if (!me) - throw MemoryAllocationError(); - - ret = mapping_entry_init(me); - if (ret) - goto out; - - ret = mapping_entry_parse(me, json_entry); - if (ret) - goto out; - - vlist_push(ml, me); - } - - ret = 0; - -out: json_decref(json_mapping); - - return ret; -} - -int mapping_update(const struct mapping_entry *me, struct sample *remapped, const struct sample *original) -{ - unsigned len = me->length; - - if (me->offset + len > remapped->capacity) - return -1; - - switch (me->type) { - case MappingType::STATS: - remapped->data[me->offset] = me->node->stats->getValue(me->stats.metric, me->stats.type); + switch (type) { + case Type::STATS: + remapped->data[offset] = node->getStats()->getValue(stats.metric, stats.type); break; - case MappingType::TIMESTAMP: { + case Type::TIMESTAMP: { const struct timespec *ts; - switch (me->timestamp.type) { - case MappingTimestampType::RECEIVED: + switch (timestamp.type) { + case TimestampType::RECEIVED: ts = &original->ts.received; break; - case MappingTimestampType::ORIGIN: + case TimestampType::ORIGIN: ts = &original->ts.origin; break; default: return -1; } - remapped->data[me->offset + 0].i = ts->tv_sec; - remapped->data[me->offset + 1].i = ts->tv_nsec; + remapped->data[offset + 0].i = ts->tv_sec; + remapped->data[offset + 1].i = ts->tv_nsec; break; } - case MappingType::HEADER: - switch (me->header.type) { - case MappingHeaderType::LENGTH: - remapped->data[me->offset].i = original->length; + case Type::HEADER: + switch (header.type) { + case HeaderType::LENGTH: + remapped->data[offset].i = original->length; break; - case MappingHeaderType::SEQUENCE: - remapped->data[me->offset].i = original->sequence; + case HeaderType::SEQUENCE: + remapped->data[offset].i = original->sequence; break; default: @@ -227,10 +177,10 @@ int mapping_update(const struct mapping_entry *me, struct sample *remapped, cons } break; - case MappingType::DATA: - for (unsigned j = me->data.offset, - i = me->offset; - j < MIN(original->length, (unsigned) (me->data.offset + me->length)); + case Type::DATA: + for (unsigned j = data.offset, + i = offset; + j < MIN(original->length, (unsigned) (data.offset + length)); j++, i++) { @@ -240,72 +190,57 @@ int mapping_update(const struct mapping_entry *me, struct sample *remapped, cons remapped->data[i] = original->data[j]; } - len = MIN((unsigned) me->length, original->length - me->data.offset); + len = MIN((unsigned) length, original->length - data.offset); break; - case MappingType::UNKNOWN: + case Type::UNKNOWN: return -1; } - if (me->offset + len > remapped->length) - remapped->length = me->offset + len; + if (offset + len > remapped->length) + remapped->length = offset + len; return 0; } -int mapping_list_remap(const struct vlist *ml, struct sample *remapped, const struct sample *original) +int MappingEntry::prepare(NodeList &nodes) { - int ret; - - for (size_t i = 0; i < vlist_length(ml); i++) { - struct mapping_entry *me = (struct mapping_entry *) vlist_at(ml, i); - - ret = mapping_update(me, remapped, original); - if (ret) - return ret; + if (!nodeName.empty() && node == nullptr) { + node = nodes.lookup(nodeName); + if (!node) + throw RuntimeError("Invalid node name in mapping: {}", nodeName); } - return 0; -} - -int mapping_entry_prepare(struct mapping_entry *me, NodeList &nodes) -{ - if (me->node_name && me->node == nullptr) { - me->node = nodes.lookup(me->node_name); - if (!me->node) - throw RuntimeError("Invalid node name in mapping: {}", me->node_name); - } - - if (me->type == MappingType::DATA) { + if (type == Type::DATA) { int first = -1, last = -1; - if (me->data.first) { - if (me->node) - first = vlist_lookup_index(node_input_signals(me->node), me->data.first); + if (data.first) { + if (node) + first = node->getInputSignals()->getIndexByName(data.first); if (first < 0) { char *endptr; - first = strtoul(me->data.first, &endptr, 10); - if (endptr != me->data.first + strlen(me->data.first)) - throw RuntimeError("Failed to parse data index in mapping: {}", me->data.first); + 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 */ - me->data.offset = 0; - me->length = -1; + data.offset = 0; + length = -1; goto end; } - if (me->data.last) { - if (me->node) - last = vlist_lookup_index(node_input_signals(me->node), me->data.last); + if (data.last) { + if (node) + last = node->getInputSignals()->getIndexByName(data.last); if (last < 0) { char *endptr; - last = strtoul(me->data.last, &endptr, 10); - if (endptr != me->data.last + strlen(me->data.last)) - throw RuntimeError("Failed to parse data index in mapping: {}", me->data.last); + 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 @@ -314,102 +249,123 @@ int mapping_entry_prepare(struct mapping_entry *me, NodeList &nodes) if (last < first) throw RuntimeError("Invalid data range indices for mapping: {} < {}", last, first); - me->data.offset = first; - me->length = last - first + 1; + data.offset = first; + length = last - first + 1; + } + else { + length = 1; } end: - if (me->length < 0) { - struct vlist *sigs = node_input_signals(me->node); - - me->length = vlist_length(sigs); - } + if (length < 0) + length = node->getInputSignals()->size(); return 0; } -int mapping_list_prepare(struct vlist *ml, NodeList &nodes) +std::string MappingEntry::toString(unsigned index) const { - int ret; + assert(length == 0 || (int) index < length); - for (size_t i = 0, off = 0; i < vlist_length(ml); i++) { - struct mapping_entry *me = (struct mapping_entry *) vlist_at(ml, i); + std::stringstream ss; - ret = mapping_entry_prepare(me, nodes); - if (ret) - return ret; + if (node) + ss << node->getNameShort() << "."; - me->offset = off; - off += me->length; - } - - return 0; -} - -int mapping_entry_to_str(const struct mapping_entry *me, unsigned index, char **str) -{ - const char *type; - - assert(me->length == 0 || (int) index < me->length); - - if (me->node) - strcatf(str, "%s.", node_name_short(me->node)); - - switch (me->type) { - case MappingType::STATS: - strcatf(str, "stats.%s.%s", - Stats::metrics[me->stats.metric].name, - Stats::types[me->stats.type].name - ); + switch (type) { + case Type::STATS: + ss << "stats."; + ss << Stats::metrics[stats.metric].name << "."; + ss << Stats::types[stats.type].name; break; - case MappingType::HEADER: - switch (me->header.type) { - case MappingHeaderType::LENGTH: - type = "length"; + case Type::HEADER: + ss << "hdr."; + switch (header.type) { + case HeaderType::LENGTH: + ss << "length"; break; - case MappingHeaderType::SEQUENCE: - type = "sequence"; + case HeaderType::SEQUENCE: + ss << "sequence"; break; - default: - type = nullptr; + default: {} + } + break; + + case Type::TIMESTAMP: + ss << "ts."; + switch (timestamp.type) { + case TimestampType::ORIGIN: + ss << "origin."; + break; + + case TimestampType::RECEIVED: + ss << "received."; + break; + + default: {} } - strcatf(str, "hdr.%s", type); + ss << (index == 0 ? "sec" : "nsec"); break; - case MappingType::TIMESTAMP: - switch (me->timestamp.type) { - case MappingTimestampType::ORIGIN: - type = "origin"; - break; + case Type::DATA: + if (node && index < node->getInputSignals()->size()) { + auto s = node->getInputSignals()->getByIndex(index); - case MappingTimestampType::RECEIVED: - type = "received"; - break; - - default: - type = nullptr; - } - - strcatf(str, "ts.%s.%s", type, index == 0 ? "sec" : "nsec"); - break; - - case MappingType::DATA: - if (me->node && index < vlist_length(node_input_signals(me->node))) { - struct signal *s = (struct signal *) vlist_at(node_input_signals(me->node), index); - - strcatf(str, "data[%s]", s->name); + ss << "data[" << s->name << "]"; } else - strcatf(str, "data[%u]", index); + ss << "data[" << index << "]"; break; - case MappingType::UNKNOWN: - return -1; + case Type::UNKNOWN: + return ""; } - return 0; + return ss.str(); +} + + +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); + + 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::DATA: { + auto sig = std::make_shared(data.signal->name, data.signal->unit, data.signal->type); + + sig->init = data.signal->init; + + return sig; + } + + case MappingEntry::Type::UNKNOWN: + break; + } + + return std::shared_ptr(); } diff --git a/lib/mapping_list.cpp b/lib/mapping_list.cpp new file mode 100644 index 000000000..85b4467e6 --- /dev/null +++ b/lib/mapping_list.cpp @@ -0,0 +1,94 @@ +/** Sample value remapping for path source muxing. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include + +using namespace villas; +using namespace villas::node; + +int MappingList::parse(json_t *json) +{ + int ret; + + 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; + + 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; + + push_back(me); + } + + ret = 0; + +out: json_decref(json_mapping); + + return 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; + } + + return 0; +} + +int MappingList::prepare(NodeList &nodes) +{ + int ret; + + unsigned off = 0; + for (auto me : *this) { + ret = me->prepare(nodes); + if (ret) + return ret; + + me->offset = off; + off += me->length; + } + + return 0; +} diff --git a/lib/memory.cpp b/lib/memory.cpp index de5362f53..066d4afc5 100644 --- a/lib/memory.cpp +++ b/lib/memory.cpp @@ -1,7 +1,7 @@ /** Memory allocators. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -32,16 +32,18 @@ #include #include -#include +#include #include #include using namespace villas; +using namespace villas::node; +using namespace villas::node::memory; -static std::unordered_map allocations; +static std::unordered_map allocations; static Logger logger; -int memory_init(int hugepages) +int villas::node::memory::init(int hugepages) { int ret; @@ -49,20 +51,20 @@ int memory_init(int hugepages) logger->info("Initialize memory sub-system: #hugepages={}", hugepages); - ret = memory_mmap_init(hugepages); + ret = mmap_init(hugepages); if (ret < 0) return ret; - size_t lock = kernel::getHugePageSize() * hugepages; + size_t lock_sz = kernel::getHugePageSize() * hugepages; - ret = memory_lock(lock); + ret = lock(lock_sz); if (ret) return ret; return 0; } -int memory_lock(size_t lock) +int villas::node::memory::lock(size_t sz) { int ret; @@ -80,19 +82,19 @@ int memory_lock(size_t lock) if (ret) return ret; - if (l.rlim_cur < lock) { - if (l.rlim_max < lock) { + 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 {}", lock); + logger->warn(" $ ulimit -Hl {}", sz); return 0; } - l.rlim_max = lock; + l.rlim_max = sz; } - l.rlim_cur = lock; + l.rlim_cur = sz; ret = setrlimit(RLIMIT_MEMLOCK, &l); if (ret) @@ -114,14 +116,14 @@ int memory_lock(size_t lock) return 0; } -void * memory_alloc(size_t len, struct memory_type *m) +void * villas::node::memory::alloc(size_t len, struct Type *m) { - return memory_alloc_aligned(len, sizeof(void *), m); + return alloc_aligned(len, sizeof(void *), m); } -void * memory_alloc_aligned(size_t len, size_t alignment, struct memory_type *m) +void * villas::node::memory::alloc_aligned(size_t len, size_t alignment, struct Type *m) { - struct memory_allocation *ma = m->alloc(len, alignment, 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; @@ -134,12 +136,12 @@ void * memory_alloc_aligned(size_t len, size_t alignment, struct memory_type *m) return ma->address; } -int memory_free(void *ptr) +int villas::node::memory::free(void *ptr) { int ret; /* Find corresponding memory allocation entry */ - struct memory_allocation *ma = allocations[ptr]; + struct Allocation *ma = allocations[ptr]; if (!ma) return -1; @@ -160,9 +162,9 @@ int memory_free(void *ptr) return 0; } -struct memory_allocation * memory_get_allocation(void *ptr) +struct Allocation * villas::node::memory::get_allocation(void *ptr) { return allocations[ptr]; } -struct memory_type *memory_default = nullptr; +struct Type *villas::node::memory::default_type = nullptr; diff --git a/lib/memory/heap.cpp b/lib/memory/heap.cpp index 2f929cc92..c82913b05 100644 --- a/lib/memory/heap.cpp +++ b/lib/memory/heap.cpp @@ -1,7 +1,7 @@ /** Heap memory allocator. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,17 +23,20 @@ #include #include -#include +#include #include using namespace villas; +using namespace villas::node; using namespace villas::utils; +using namespace villas::node::memory; -static struct memory_allocation * memory_heap_alloc(size_t len, size_t alignment, struct memory_type *m) +static +struct Allocation * heap_alloc(size_t len, size_t alignment, struct Type *m) { int ret; - auto *ma = new struct memory_allocation; + auto *ma = new struct Allocation; if (!ma) throw MemoryAllocationError(); @@ -53,18 +56,19 @@ static struct memory_allocation * memory_heap_alloc(size_t len, size_t alignment return ma; } -static int memory_heap_free(struct memory_allocation *ma, struct memory_type *m) +static +int heap_free(struct Allocation *ma, struct Type *m) { - free(ma->address); + ::free(ma->address); return 0; } /* List of available memory types */ -struct memory_type memory_heap = { +struct Type villas::node::memory::heap = { .name = "heap", - .flags = (int) MemoryFlags::HEAP, + .flags = (int) Flags::HEAP, .alignment = 1, - .alloc = memory_heap_alloc, - .free = memory_heap_free + .alloc = heap_alloc, + .free = heap_free }; diff --git a/lib/memory/ib.cpp b/lib/memory/ib.cpp index 54007c003..57c280a18 100644 --- a/lib/memory/ib.cpp +++ b/lib/memory/ib.cpp @@ -1,7 +1,7 @@ /** Infiniband memory allocator. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,33 +20,33 @@ * along with this program. If not, see . *********************************************************************************/ -#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 * memory_ib_get_mr(void *ptr) +struct ibv_mr * villas::node::memory::ib_get_mr(void *ptr) { - struct memory_allocation *ma; - struct ibv_mr *mr; + auto *ma = get_allocation(ptr); - ma = memory_get_allocation(ptr); - mr = ma->ib.mr; - - return mr; + return ma->ib.mr; } -static struct memory_allocation * memory_ib_alloc(size_t len, size_t alignment, struct memory_type *m) +static +struct Allocation * ib_alloc(size_t len, size_t alignment, struct Type *m) { - struct memory_ib *mi = (struct memory_ib *) m->_vd; + auto *mi = (struct IB *) m->_vd; - auto *ma = new struct memory_allocation; + auto *ma = new struct Allocation; if (!ma) throw MemoryAllocationError(); @@ -72,10 +72,11 @@ static struct memory_allocation * memory_ib_alloc(size_t len, size_t alignment, return ma; } -static int memory_ib_free(struct memory_allocation *ma, struct memory_type *m) +static +int ib_free(struct Allocation *ma, struct Type *m) { int ret; - struct memory_ib *mi = (struct memory_ib *) m->_vd; + auto *mi = (struct IB *) m->_vd; ibv_dereg_mr(ma->ib.mr); @@ -86,20 +87,20 @@ static int memory_ib_free(struct memory_allocation *ma, struct memory_type *m) return 0; } -struct memory_type * memory_ib(struct vnode *n, struct memory_type *parent) +struct Type * villas::node::memory::ib(NodeCompat *n, struct Type *parent) { - struct infiniband *i = (struct infiniband *) n->_vd; - struct memory_type *mt = (struct memory_type *) malloc(sizeof(struct memory_type)); + auto *i = n->getData(); + auto *mt = (struct Type *) malloc(sizeof(struct Type)); mt->name = "ib"; mt->flags = 0; - mt->alloc = memory_ib_alloc; - mt->free = memory_ib_free; + mt->alloc = ib_alloc; + mt->free = ib_free; mt->alignment = 1; - mt->_vd = malloc(sizeof(struct memory_ib)); + mt->_vd = malloc(sizeof(struct IB)); - struct memory_ib *mi = (struct memory_ib *) mt->_vd; + auto *mi = (struct memory::IB *) mt->_vd; mi->pd = i->ctx.pd; mi->parent = parent; diff --git a/lib/memory/managed.cpp b/lib/memory/managed.cpp index 290b8f2c7..a69de0b6a 100644 --- a/lib/memory/managed.cpp +++ b/lib/memory/managed.cpp @@ -1,7 +1,7 @@ /** Managed memory allocator. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,25 +30,28 @@ #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 memory_allocation * memory_managed_alloc(size_t len, size_t alignment, struct memory_type *m) +static +struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) { /* Simple first-fit allocation */ - struct memory_block *first = (struct memory_block *) m->_vd; - struct memory_block *block; + struct Block *first = (struct Block *) m->_vd; + struct Block *block; for (block = first; block != nullptr; block = block->next) { if (block->used) continue; - char* cptr = (char *) block + sizeof(struct memory_block); + char* cptr = (char *) block + sizeof(struct Block); size_t avail = block->length; uintptr_t uptr = (uintptr_t) cptr; @@ -66,13 +69,13 @@ static struct memory_allocation * memory_managed_alloc(size_t len, size_t alignm } if (avail >= len) { - if (gap > sizeof(struct memory_block)) { + 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 memory_block); - struct memory_block *newblock = (struct memory_block *) (cptr - sizeof(struct memory_block)); + 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; @@ -86,9 +89,9 @@ static struct memory_allocation * memory_managed_alloc(size_t len, size_t alignm block->length = len + gap; } - if (avail > len + sizeof(struct memory_block)) { + if (avail > len + sizeof(struct Block)) { /* Imperfect fit, so create another block for the remaining part */ - struct memory_block *newblock = (struct memory_block *) (cptr + len); + struct Block *newblock = (struct Block *) (cptr + len); newblock->prev = block; newblock->next = block->next; block->next = newblock; @@ -97,18 +100,18 @@ static struct memory_allocation * memory_managed_alloc(size_t len, size_t alignm newblock->next->prev = newblock; newblock->used = false; - newblock->length = avail - len - sizeof(struct memory_block); + newblock->length = avail - len - sizeof(struct Block); } else { /* If this block was larger than the requested length, but only - * by less than sizeof(struct memory_block), we may have wasted + * by less than sizeof(struct Block), we may have wasted * memory by previous assignments to block->length. */ block->length = avail; } block->used = true; - auto *ma = new struct memory_allocation; + auto *ma = new struct Allocation; if (!ma) throw MemoryAllocationError(); @@ -126,27 +129,28 @@ static struct memory_allocation * memory_managed_alloc(size_t len, size_t alignm return nullptr; } -static int memory_managed_free(struct memory_allocation *ma, struct memory_type *m) +static +int managed_free(struct Allocation *ma, struct Type *m) { - struct memory_block *block = ma->managed.block; + 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 memory_block); + 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 memory_block); + 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 memory_block); + block->length += block->next->length + sizeof(struct Block); block->next = block->next->next; if (block->next) block->next->prev = block; @@ -159,34 +163,34 @@ static int memory_managed_free(struct memory_allocation *ma, struct memory_type return 0; } -struct memory_type * memory_managed(void *ptr, size_t len) +struct Type * villas::node::memory::managed(void *ptr, size_t len) { - struct memory_type *mt = (struct memory_type *) ptr; - struct memory_block *mb; + struct Type *mt = (struct Type *) ptr; + struct Block *mb; char *cptr = (char *) ptr; - if (len < sizeof(struct memory_type) + sizeof(struct memory_block)) { + if (len < sizeof(struct Type) + sizeof(struct Block)) { auto logger = logging.get("memory:managed"); logger->info("Passed region is too small"); return nullptr; } - /* Initialize memory_type */ + /* Initialize type */ mt->name = "managed"; mt->flags = 0; - mt->alloc = memory_managed_alloc; - mt->free = memory_managed_free; + mt->alloc = managed_alloc; + mt->free = managed_free; mt->alignment = 1; - cptr += ALIGN(sizeof(struct memory_type), sizeof(void *)); + cptr += ALIGN(sizeof(struct Type), sizeof(void *)); /* Initialize first free memory block */ - mb = (struct memory_block *) cptr; + mb = (struct Block *) cptr; mb->prev = nullptr; mb->next = nullptr; mb->used = false; - cptr += ALIGN(sizeof(struct memory_block), sizeof(void *)); + cptr += ALIGN(sizeof(struct Block), sizeof(void *)); mb->length = len - (cptr - (char *) ptr); diff --git a/lib/memory/mmap.cpp b/lib/memory/mmap.cpp index f62792827..dab89b6ee 100644 --- a/lib/memory/mmap.cpp +++ b/lib/memory/mmap.cpp @@ -1,7 +1,7 @@ /** mmap memory allocator. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -35,21 +35,27 @@ #endif /* __MACH__ */ #include -#include +#include #include #include #include #include using namespace villas; -using namespace villas; +using namespace villas::node; using namespace villas::utils; +using namespace villas::node::memory; -static size_t pgsz = -1; -static size_t hugepgsz = -1; -static Logger logger; +static +size_t pgsz = -1; -int memory_mmap_init(int hugepages) +static +size_t hugepgsz = -1; + +static +Logger logger; + +int villas::node::memory::mmap_init(int hugepages) { logger = logging.get("memory:mmap"); @@ -60,14 +66,14 @@ int memory_mmap_init(int hugepages) if (hugepages == 0) { logger->warn("Hugepage allocator disabled."); - memory_default = &memory_mmap; + default_type = &mmap; return 0; } if (!utils::isPrivileged()) { logger->warn("Running in an unprivileged environment. Hugepages are not used!"); - memory_default = &memory_mmap; + default_type = &mmap; return 0; } @@ -94,27 +100,28 @@ int memory_mmap_init(int hugepages) logger->debug("Increased number of reserved hugepages from {} to {}", pagecnt, hugepages); } - memory_default = &memory_mmap_hugetlb; + default_type = &mmap_hugetlb; #else logger->debug("Hugepages not supported on this system. Falling back to standard mmap() allocator."); - memory_default = &memory_mmap; + default_type = &mmap; #endif return 0; } /** Allocate memory backed by mmaps with malloc() like interface */ -static struct memory_allocation * memory_mmap_alloc(size_t len, size_t alignment, struct memory_type *m) +static +struct Allocation * mmap_alloc(size_t len, size_t alignment, struct Type *m) { int flags, fd; size_t sz; - auto *ma = new struct memory_allocation; + auto *ma = new struct Allocation; if (!ma) throw MemoryAllocationError(); - if (m->flags & (int) MemoryFlags::HUGEPAGE) { + if (m->flags & (int) Flags::HUGEPAGE) { #ifdef __linux__ flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB; #else @@ -143,7 +150,7 @@ static struct memory_allocation * memory_mmap_alloc(size_t len, size_t alignment ma->alignment = ALIGN(alignment, sz); ma->type = m; - ma->address = mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); + ma->address = ::mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); if (ma->address == MAP_FAILED) { delete ma; return nullptr; @@ -152,7 +159,8 @@ static struct memory_allocation * memory_mmap_alloc(size_t len, size_t alignment return ma; } -static int memory_mmap_free(struct memory_allocation *ma, struct memory_type *m) +static +int mmap_free(struct Allocation *ma, struct Type *m) { int ret; @@ -163,18 +171,18 @@ static int memory_mmap_free(struct memory_allocation *ma, struct memory_type *m) return 0; } -struct memory_type memory_mmap = { +struct Type memory::mmap = { .name = "mmap", - .flags = (int) MemoryFlags::MMAP, + .flags = (int) Flags::MMAP, .alignment = 12, /* 4k page */ - .alloc = memory_mmap_alloc, - .free = memory_mmap_free + .alloc = mmap_alloc, + .free = mmap_free }; -struct memory_type memory_mmap_hugetlb = { +struct Type memory::mmap_hugetlb = { .name = "mmap_hugetlb", - .flags = (int) MemoryFlags::MMAP | (int) MemoryFlags::HUGEPAGE, + .flags = (int) Flags::MMAP | (int) Flags::HUGEPAGE, .alignment = 21, /* 2 MiB hugepage */ - .alloc = memory_mmap_alloc, - .free = memory_mmap_free + .alloc = mmap_alloc, + .free = mmap_free }; diff --git a/lib/node.cpp b/lib/node.cpp index d30ba5c6a..5d14b4bb8 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -1,7 +1,7 @@ /** Nodes. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,20 +25,25 @@ #include #include -#include +#ifdef __linux__ + #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 @@ -51,95 +56,67 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -int node_init(struct vnode *n, struct vnode_type *vt) -{ - int ret; - - n->_vt = vt; - n->_vd = new char[vt->size]; - if (!n->_vd) - throw MemoryAllocationError(); - - memset(n->_vd, 0, vt->size); - - using stats_ptr = std::shared_ptr; - - new (&n->stats) stats_ptr(); - new (&n->logger) Logger(); - - n->logger = logging.get(fmt::format("node:{}", *vt)); - - uuid_clear(n->uuid); - - n->name = nullptr; - n->_name = nullptr; - n->_name_long = nullptr; - n->enabled = true; - n->affinity = -1; /* all cores */ - +Node::Node(const std::string &n) : + logger(logging.get("node")), + sequence_init(0), + sequence(0), + in(NodeDirection::Direction::IN, this), + out(NodeDirection::Direction::OUT, this), #ifdef __linux__ - n->fwmark = -1; + fwmark(-1), #endif /* __linux__ */ - #ifdef WITH_NETEM - n->tc_qdisc = nullptr; - n->tc_classifier = nullptr; + tc_qdisc(nullptr), + tc_classifier(nullptr), +#endif /* WITH_NETEM */ + state(State::INITIALIZED), + enabled(true), + config(nullptr), + name_short(n), + name_long(), + affinity(-1), /* all cores */ + loopback_count(0), + factory(nullptr) +{ + uuid_clear(uuid); + + name_long = fmt::format(CLR_RED("{}"), n); +} + +Node::~Node() +{ +#ifdef WITH_NETEM + rtnl_qdisc_put(tc_qdisc); + rtnl_cls_put(tc_classifier); #endif /* WITH_NETEM */ - /* Default values */ - ret = node_direction_init(&n->in, NodeDir::IN, n); - if (ret) - return ret; - - ret = node_direction_init(&n->out, NodeDir::OUT, n); - if (ret) - return ret; - - ret = vlist_init(&n->sources); - if (ret) - return ret; - - ret = vlist_init(&n->destinations); - if (ret) - return ret; - - ret = vt->init ? vt->init(n) : 0; - if (ret) - return ret; - - n->state = State::INITIALIZED; - - vt->instances.push_back(n); - - return 0; + factory->instances.remove(this); } -int node_prepare(struct vnode *n) +int Node::prepare() { int ret; - assert(n->state == State::CHECKED); - - ret = node_type(n)->prepare ? node_type(n)->prepare(n) : 0; + ret = in.prepare(); if (ret) return ret; - ret = node_direction_prepare(&n->in, n); + ret = out.prepare(); if (ret) return ret; - ret = node_direction_prepare(&n->out, n); - if (ret) - return ret; - - n->state = State::PREPARED; + state = State::PREPARED; return 0; } -int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) +int Node::parse(json_t *json, const uuid_t sn_uuid) { - int ret, enabled = n->enabled; + assert(state == State::INITIALIZED || + state == State::PARSED || + state == State::CHECKED); + + int ret, en = enabled, init_seq = -1; json_error_t err; json_t *json_netem = nullptr; @@ -147,42 +124,50 @@ int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) const char *uuid_str = nullptr; const char *name_str = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: b }", + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: b, s?: i }", "name", &name_str, "uuid", &uuid_str, - "enabled", &enabled + "enabled", &en, + "initial_sequenceno", &init_seq ); if (ret) return ret; + if (init_seq >= 0) + sequence_init = init_seq; + if (name_str) - n->logger = logging.get(fmt::format("node:{}", name_str)); + logger = logging.get(fmt::format("node:{}", name_str)); #ifdef __linux__ ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", "out", "netem", &json_netem, - "fwmark", &n->fwmark + "fwmark", &fwmark ); if (ret) return ret; #endif /* __linux__ */ - n->enabled = enabled; + enabled = en; - if (name_str) - n->name = strdup(name_str); - else - n->name = strdup(""); + if (name_str) { + name_short = std::string(name_str); + name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_str, factory->getName()); + } + else if (name_short.empty()) { + name_short = ""; + name_long = CLR_RED(""); + } if (uuid_str) { - ret = uuid_parse(uuid_str, n->uuid); + ret = uuid_parse(uuid_str, uuid); if (ret) throw ConfigError(json, "node-config-node-uuid", "Failed to parse UUID: {}", uuid_str); } else /* Generate UUID from hashed config including node name */ - uuid::generateFromJson(n->uuid, json, sn_uuid); + uuid::generateFromJson(uuid, json, sn_uuid); if (json_netem) { #ifdef WITH_NETEM @@ -193,18 +178,18 @@ int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) return ret; if (enabled) - kernel::tc::netem_parse(&n->tc_qdisc, json_netem); + kernel::tc::netem_parse(&tc_qdisc, json_netem); else - n->tc_qdisc = nullptr; + tc_qdisc = nullptr; #endif /* WITH_NETEM */ } struct { const char *str; - struct vnode_direction *dir; + struct NodeDirection *dir; } dirs[] = { - { "in", &n->in }, - { "out", &n->out } + { "in", &in }, + { "out", &out } }; const char *fields[] = { "signals", "builtin", "vectorize", "hooks" }; @@ -213,8 +198,10 @@ int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) json_t *json_dir = json_object_get(json, dirs[j].str); /* Skip if direction is unused */ - if (!json_dir) + if (!json_dir) { json_dir = json_pack("{ s: b }", "enabled", 0); + // json_object_set_new(json, dirs[j].str, json_dir); + } /* Copy missing fields from main node config to direction config */ for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { @@ -225,510 +212,358 @@ int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) json_object_set(json_dir, fields[i], json_field_node); } - ret = node_direction_parse(dirs[j].dir, n, json_dir); + ret = dirs[j].dir->parse(json_dir); if (ret) return ret; } - ret = node_type(n)->parse ? node_type(n)->parse(n, json) : 0; - if (ret) - return ret; - - n->config = json; - n->state = State::PARSED; + config = json; return 0; } -int node_check(struct vnode *n) +int Node::check() { - int ret; - assert(n->state != State::DESTROYED); + assert(state == State::CHECKED || + state == State::PARSED || + state == State::INITIALIZED); - node_direction_check(&n->in, n); - node_direction_check(&n->out, n); + in.check(); + out.check(); - ret = node_type(n)->check ? node_type(n)->check(n) : 0; - if (ret) - return ret; - - n->state = State::CHECKED; + state = State::CHECKED; return 0; } -int node_start(struct vnode *n) +int Node::start() { int ret; - assert(n->state == State::PREPARED); - assert(node_type(n)->state == State::STARTED); + assert(state == State::PREPARED); - n->logger->info("Starting node {}", node_name_long(n)); + logger->info("Starting node {}", getNameFull()); - ret = node_direction_start(&n->in, n); + ret = in.start(); if (ret) return ret; - ret = node_direction_start(&n->out, n); - if (ret) - return ret; - - ret = node_type(n)->start ? node_type(n)->start(n) : 0; + ret = out.start(); if (ret) return ret; #ifdef __linux__ /* Set fwmark for outgoing packets if netem is enabled for this node */ - if (n->fwmark >= 0) { + if (fwmark >= 0) { int fds[16]; - int num_sds = node_netem_fds(n, fds); + int num_sds = getNetemFDs(fds); for (int i = 0; i < num_sds; i++) { int fd = fds[i]; - ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &n->fwmark, sizeof(n->fwmark)); + ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); if (ret) throw RuntimeError("Failed to set FW mark for outgoing packets"); else - n->logger->debug("Set FW mark for socket (sd={}) to {}", fd, n->fwmark); + logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); } } #endif /* __linux__ */ - n->state = State::STARTED; - n->sequence = 0; + state = State::STARTED; + sequence = sequence_init; return 0; } -int node_stop(struct vnode *n) +int Node::stop() { int ret; - if (n->state != State::STOPPING && n->state != State::STARTED && n->state != State::CONNECTED && n->state != State::PENDING_CONNECT) + if (state != State::STOPPING && state != State::STARTED && state != State::CONNECTED && state != State::PENDING_CONNECT) return 0; - n->logger->info("Stopping node"); + logger->info("Stopping node"); - ret = node_direction_stop(&n->in, n); + ret = in.stop(); if (ret) return ret; - ret = node_direction_stop(&n->out, n); + ret = out.stop(); if (ret) return ret; - ret = node_type(n)->stop ? node_type(n)->stop(n) : 0; - - if (ret == 0) - n->state = State::STOPPED; - - return ret; -} - -int node_pause(struct vnode *n) -{ - int ret; - - if (n->state != State::STARTED) - return -1; - - n->logger->info("Pausing node"); - - ret = node_type(n)->pause ? node_type(n)->pause(n) : 0; - - if (ret == 0) - n->state = State::PAUSED; - - return ret; -} - -int node_resume(struct vnode *n) -{ - int ret; - - if (n->state != State::PAUSED) - return -1; - - n->logger->info("Resuming node"); - - ret = node_type(n)->resume ? node_type(n)->resume(n) : 0; - - if (ret == 0) - n->state = State::STARTED; - - return ret; -} - -int node_restart(struct vnode *n) -{ - int ret; - - if (n->state != State::STARTED) - return -1; - - n->logger->info("Restarting node"); - - if (node_type(n)->restart) - ret = node_type(n)->restart(n); - else { - ret = node_type(n)->stop ? node_type(n)->stop(n) : 0; - if (ret) - return ret; - - ret = node_type(n)->start ? node_type(n)->start(n) : 0; - if (ret) - return ret; - } - return 0; } -int node_destroy(struct vnode *n) +int Node::restart() { int ret; - assert(n->state != State::DESTROYED && n->state != State::STARTED); - ret = node_direction_destroy(&n->in, n); + assert(state == State::STARTED); + + logger->info("Restarting node"); + + ret = stop(); if (ret) return ret; - ret = node_direction_destroy(&n->out, n); + ret = start(); if (ret) return ret; - ret = vlist_destroy(&n->sources); - if (ret) - return ret; - - ret = vlist_destroy(&n->destinations); - if (ret) - return ret; - - if (node_type(n)->destroy) { - ret = (int) node_type(n)->destroy(n); - if (ret) - return ret; - } - - node_type(n)->instances.remove(n); - - if (n->_vd) - delete[] (char *) n->_vd; - - if (n->_name) - free(n->_name); - - if (n->_name_long) - free(n->_name_long); - - if (n->name) - free(n->name); - -#ifdef WITH_NETEM - rtnl_qdisc_put(n->tc_qdisc); - rtnl_cls_put(n->tc_classifier); -#endif /* WITH_NETEM */ - - using stats_ptr = std::shared_ptr; - - n->stats.~stats_ptr(); - - n->state = State::DESTROYED; - return 0; } -int node_read(struct vnode *n, struct sample * smps[], unsigned cnt) +int Node::read(struct Sample * smps[], unsigned cnt) { int toread, readd, nread = 0; unsigned vect; - assert(node_type(n)->read); - - if (n->state == State::PAUSED || n->state == State::PENDING_CONNECT) + if (state == State::PAUSED || state == State::PENDING_CONNECT) return 0; - else if (n->state != State::STARTED && n->state != State::CONNECTED) + else if (state != State::STARTED && state != State::CONNECTED) return -1; - vect = node_type(n)->vectorize; + vect = factory->getVectorize(); if (!vect) vect = cnt; while (cnt - nread > 0) { toread = MIN(cnt - nread, vect); - readd = node_type(n)->read(n, &smps[nread], toread); + readd = _read(&smps[nread], toread); if (readd < 0) return readd; nread += readd; } - #ifdef WITH_HOOKS /* Run read hooks */ - int rread = hook_list_process(&n->in.hooks, smps, nread); + int rread = in.hooks.process(smps, nread); if (rread < 0) return rread; int skipped = nread - rread; if (skipped > 0) { - if (n->stats != nullptr) - n->stats->update(Stats::Metric::SMPS_SKIPPED, skipped); + if (stats != nullptr) + stats->update(Stats::Metric::SMPS_SKIPPED, skipped); - n->logger->debug("Received {} samples of which {} have been skipped", nread, skipped); + logger->debug("Received {} samples of which {} have been skipped", nread, skipped); } else - n->logger->debug( "Received {} samples", nread); + logger->debug( "Received {} samples", nread); return rread; #else - n->logger->debug("Received {} samples", nread); + logger->debug("Received {} samples", nread); return nread; #endif /* WITH_HOOKS */ } -int node_write(struct vnode *n, struct sample * smps[], unsigned cnt) +int Node::write(struct Sample * smps[], unsigned cnt) { int tosend, sent, nsent = 0; unsigned vect; - assert(node_type(n)->write); - - if (n->state == State::PAUSED || n->state == State::PENDING_CONNECT) + if (state == State::PAUSED || state == State::PENDING_CONNECT) return 0; - else if (n->state != State::STARTED && n->state != State::CONNECTED) + else if (state != State::STARTED && state != State::CONNECTED) return -1; #ifdef WITH_HOOKS /* Run write hooks */ - cnt = hook_list_process(&n->out.hooks, smps, cnt); + cnt = out.hooks.process(smps, cnt); if (cnt <= 0) return cnt; #endif /* WITH_HOOKS */ - vect = node_type(n)->vectorize; + vect = getFactory()->getVectorize(); if (!vect) vect = cnt; while (cnt - nsent > 0) { tosend = MIN(cnt - nsent, vect); - sent = node_type(n)->write(n, &smps[nsent], tosend); + sent = _write(&smps[nsent], tosend); if (sent < 0) return sent; nsent += sent; - n->logger->debug("Sent {} samples", sent); + logger->debug("Sent {} samples", sent); } return nsent; } -char * node_name(struct vnode *n) +const std::string & Node::getNameFull() { - if (!n->_name) - strcatf(&n->_name, CLR_RED("%s") "(" CLR_YEL("%s") ")", n->name, node_type_name(node_type(n))); + if (name_full.empty()) { + char uuid_str[37]; + uuid_unparse(uuid, uuid_str); - return n->_name; -} - -char * node_name_long(struct vnode *n) -{ - if (!n->_name_long) { - char uuid[37]; - uuid_unparse(n->uuid, uuid); - - strcatf(&n->_name_long, "%s: uuid=%s, #in.signals=%zu(%zu), #out.signals=%zu(%zu), #in.hooks=%zu, #out.hooks=%zu, in.vectorize=%d, out.vectorize=%d", - node_name(n), uuid, - vlist_length(&n->in.signals), - node_input_signals(n) ? vlist_length(node_input_signals(n)) : 0, - vlist_length(&n->out.signals), - node_output_signals(n) ? vlist_length(node_output_signals(n)) : 0, - vlist_length(&n->in.hooks), vlist_length(&n->out.hooks), - n->in.vectorize, n->out.vectorize + name_full = fmt::format("{}: uuid={}, #in.signals={}/{}, #in.hooks={}, #out.hooks={}, in.vectorize={}, out.vectorize={}", + getName(), uuid_str, + getInputSignals(false)->size(), + getInputSignals(true)->size(), + in.hooks.size(), out.hooks.size(), + in.vectorize, out.vectorize ); #ifdef WITH_NETEM - strcatf(&n->_name_long, ", out.netem=%s", n->tc_qdisc ? "yes" : "no"); + name_full += fmt::format(", out.netem={}", tc_qdisc ? "yes" : "no"); - if (n->tc_qdisc) - strcatf(&n->_name_long, ", fwmark=%d", n->fwmark); + if (tc_qdisc) + name_full += fmt::format(", fwmark={}", fwmark); #endif /* WITH_NETEM */ - if (n->out.path) { - auto pn = fmt::format("{}", *n->out.path); - strcatf(&n->_name_long, ", out.path=%s", pn.c_str()); + 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); } - if (node_type(n)->print) { - struct vnode_type *vt = node_type(n); - - /* Append node-type specific details */ - char *name_long = vt->print(n); - strcatf(&n->_name_long, ", %s", name_long); - free(name_long); - } + /* Append node-type specific details */ + auto details = getDetails(); + if (!details.empty()) + name_full += fmt::format(", {}", details); } - return n->_name_long; + return name_full; } -const char * node_name_short(struct vnode *n) +SignalList::Ptr Node::getInputSignals(bool after_hooks) const { - return n->name; + return in.getSignals(after_hooks); } -int node_reverse(struct vnode *n) +SignalList::Ptr Node::getOutputSignals(bool after_hooks) const { - return node_type(n)->reverse ? node_type(n)->reverse(n) : -1; + if (out.path) + return out.path->getOutputSignals(); + + return nullptr; } -int node_poll_fds(struct vnode *n, int fds[]) +unsigned Node::getInputSignalsMaxCount() const { - return node_type(n)->poll_fds ? node_type(n)->poll_fds(n, fds) : -1; + return in.getSignalsMaxCount(); } -int node_netem_fds(struct vnode *n, int fds[]) +unsigned Node::getOutputSignalsMaxCount() const { - return node_type(n)->netem_fds ? node_type(n)->netem_fds(n, fds) : -1; -} - -struct memory_type * node_memory_type(struct vnode *n) -{ - return node_type(n)->memory_type ? node_type(n)->memory_type(n, memory_default) : memory_default; -} - -int node_list_parse(struct vlist *list, json_t *json, NodeList &all) -{ - struct vnode *node; - const char *str; - char *allstr = nullptr; - - size_t index; - json_t *elm; - - 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; - - vlist_push(list, node); - break; - - 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; - - vlist_push(list, node); - } - break; - - default: - goto invalid; - } - - 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"); - - return -1; - -invalid2: - for (auto *n : all) - strcatf(&allstr, " %s", node_name_short(n)); - - throw RuntimeError("Unknown node {}. Choose of one of: {}", str, allstr); + if (out.path) + return out.path->getOutputSignalsMaxCount(); return 0; } -bool node_is_valid_name(const char *name) +bool Node::isValidName(const std::string &name) { std::regex re(RE_NODE_NAME); return std::regex_match(name, re); } -bool node_is_enabled(const struct vnode *n) +json_t * Node::toJson() const { - return n->enabled; -} - -struct vlist * node_input_signals(struct vnode *n) -{ - return node_direction_get_signals(&n->in); -} - -struct vlist * node_output_signals(struct vnode *n) -{ - if (n->out.path) - return path_output_signals(n->out.path); - - return nullptr; -} - -unsigned node_input_signals_max_cnt(struct vnode *n) -{ - return node_direction_get_signals_max_cnt(&n->in); -} - -unsigned node_output_signals_max_cnt(struct vnode *n) -{ - if (n->out.path) - return path_output_signals_max_cnt(n->out.path); - - return 0; -} - -json_t * node_to_json(struct vnode *n) -{ - struct vlist *output_signals; - json_t *json_node; json_t *json_signals_in = nullptr; json_t *json_signals_out = nullptr; - char uuid[37]; - uuid_unparse(n->uuid, uuid); + char uuid_str[37]; + uuid_unparse(uuid, uuid_str); - json_signals_in = signal_list_to_json(&n->in.signals); + json_signals_in = getInputSignals()->toJson(); - output_signals = node_output_signals(n); + auto output_signals = getOutputSignals(); if (output_signals) - json_signals_out = signal_list_to_json(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", node_name_short(n), - "uuid", uuid, - "state", stateToString(n->state).c_str(), - "affinity", n->affinity, + "name", getNameShort().c_str(), + "uuid", uuid_str, + "state", stateToString(state).c_str(), + "affinity", affinity, "in", - "vectorize", n->in.vectorize, + "vectorize", in.vectorize, "signals", json_signals_in, "out", - "vectorize", n->out.vectorize, + "vectorize", out.vectorize, "signals", json_signals_out ); - if (n->stats) - json_object_set_new(json_node, "stats", n->stats->toJson()); + if (stats) + json_object_set_new(json_node, "stats", stats->toJson()); /* Add all additional fields of node here. * This can be used for metadata */ - json_object_update(json_node, n->config); + json_object_update(json_node, config); return json_node; } + +void Node::swapSignals() { + SWAP(in.signals, out.signals); +} + +Node * NodeFactory::make(json_t *json, uuid_t uuid) +{ + int ret; + std::string type; + Node *n; + + if (json_is_string(json)) { + type = json_string_value(json); + + return NodeFactory::make(type); + } + else if (json_is_object(json)) { + json_t *json_type = json_object_get(json, "type"); + + type = json_string_value(json_type); + + n = NodeFactory::make(type); + if (!n) + return nullptr; + + ret = n->parse(json, uuid); + if (ret) { + delete n; + return nullptr; + } + + return n; + } + else + throw ConfigError(json, "node-config-node", "Invalid node config"); +} + +Node * NodeFactory::make(const std::string &type) +{ + NodeFactory *nf = plugin::Registry::lookup(type); + if (!nf) + throw RuntimeError("Unknown node-type: {}", type); + + return nf->make(); +} + +int NodeFactory::start(SuperNode *sn) +{ + getLogger()->info("Initialized node type which is used by {} nodes", instances.size()); + + state = State::STARTED; + + return 0; +} + +int NodeFactory::stop() +{ + getLogger()->info("De-initialized node type"); + + state = State::STOPPED; + + return 0; +} diff --git a/lib/node_compat.cpp b/lib/node_compat.cpp new file mode 100644 index 000000000..c1f81431a --- /dev/null +++ b/lib/node_compat.cpp @@ -0,0 +1,331 @@ +/** Legacy nodes. + * + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include +#include + +using namespace villas; +using namespace villas::node; + +NodeCompat::NodeCompat(struct NodeCompatType *vt) : + Node(), + _vt(vt) +{ + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); + + memset(_vd, 0, _vt->size); + + 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(); + + memcpy(_vd, n._vd, _vt->size); + + 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; + + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); + + memcpy(_vd, n._vd, _vt->size); + } + + return *this; +} + +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; + + delete[] (char *) _vd; +} + +int NodeCompat::prepare() +{ + assert(state == State::CHECKED); + + int ret = _vt->prepare + ? _vt->prepare(this) + : 0; + if (ret) + return ret; + + return Node::prepare(); +} + +int NodeCompat::parse(json_t *cfg, const uuid_t sn_uuid) +{ + int ret = Node::parse(cfg, sn_uuid); + if (ret) + return ret; + + ret = _vt->parse + ? _vt->parse(this, cfg) + : 0; + if (!ret) + state = State::PARSED; + + 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; + + return ret; +} + +int NodeCompat::pause() +{ + int ret; + + if (state != State::STARTED) + return -1; + + logger->info("Pausing node"); + + ret = _vt->pause + ? _vt->pause(this) + : 0; + if (!ret) + state = State::PAUSED; + + return ret; +} + +int NodeCompat::resume() +{ + int ret; + + if (state != State::PAUSED) + return -1; + + logger->info("Resuming node"); + + ret = _vt->resume + ? _vt->resume(this) + : 0; + if (!ret) + state = State::STARTED; + + return ret; +} + +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::_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; +} + +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 {}; +} + +int NodeCompat::getNetemFDs(int fds[]) +{ + return _vt->netem_fds + ? _vt->netem_fds(this, fds) + : -1; +} + +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::stop() +{ + assert(state == State::STARTED || + state == State::PAUSED || + state == State::STOPPING); + + int ret = Node::stop(); + if (ret) + return ret; + + ret = _vt->stop + ? _vt->stop(this) : + 0; + if (!ret) + state = State::STOPPED; + + return ret; +} + +const std::string & NodeCompat::getDetails() +{ + if (_vt->print && _details.empty()) { + auto *d = _vt->print(this); + _details = std::string(d); + free(d); + } + + return _details; +} + +Node * NodeCompatFactory::make() +{ + auto *n = new NodeCompat(_vt); + + init(n); + + return n; +} + +int NodeCompatFactory::start(SuperNode *sn) +{ + assert(state == State::INITIALIZED); + + int ret = _vt->type.start + ? _vt->type.start(sn) + : 0; + if (ret) + return ret; + + return NodeFactory::start(sn); +} + +int NodeCompatFactory::stop() +{ + assert(state == State::STARTED); + + int ret = _vt->type.stop + ? _vt->type.stop() + : 0; + if (ret) + return ret; + + 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; +} diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index 48b78ad95..973a0f2ad 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -2,7 +2,7 @@ /** Node direction * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,211 +21,179 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include #include #include -#include +#include #include -#include +#include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int node_direction_prepare(struct vnode_direction *nd, struct vnode *n) -{ - assert(nd->state == State::CHECKED); +NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) : + direction(dir), + path(nullptr), + node(n), + enabled(1), + builtin(1), + vectorize(1), + config(nullptr) +{ } -#ifdef WITH_HOOKS - int t = nd->direction == NodeDir::OUT ? (int) Hook::Flags::NODE_WRITE : (int) Hook::Flags::NODE_READ; - int m = nd->builtin ? t | (int) Hook::Flags::BUILTIN : 0; - - hook_list_prepare(&nd->hooks, &nd->signals, m, nullptr, n); -#endif /* WITH_HOOKS */ - - nd->state = State::PREPARED; - - return 0; -} - -int node_direction_init(struct vnode_direction *nd, enum NodeDir dir, struct vnode *n) +int NodeDirection::parse(json_t *json) { int ret; - nd->direction = dir; - nd->enabled = 1; - nd->vectorize = 1; - nd->builtin = 1; - nd->path = nullptr; - -#ifdef WITH_HOOKS - ret = hook_list_init(&nd->hooks); - if (ret) - return ret; -#endif /* WITH_HOOKS */ - - ret = signal_list_init(&nd->signals); - if (ret) - return ret; - - nd->state = State::INITIALIZED; - - return 0; -} - -int node_direction_destroy(struct vnode_direction *nd, struct vnode *n) -{ - int ret = 0; - - assert(nd->state != State::DESTROYED && nd->state != State::STARTED); - -#ifdef WITH_HOOKS - ret = hook_list_destroy(&nd->hooks); - if (ret) - return ret; -#endif /* WITH_HOOKS */ - - ret = signal_list_destroy(&nd->signals); - if (ret) - return ret; - - nd->state = State::DESTROYED; - - return 0; -} - -int node_direction_parse(struct vnode_direction *nd, struct vnode *n, json_t *json) -{ - int ret; - - assert(nd->state == State::INITIALIZED); - json_error_t err; json_t *json_hooks = nullptr; json_t *json_signals = nullptr; - nd->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", &nd->vectorize, - "builtin", &nd->builtin, - "enabled", &nd->enabled + "vectorize", &vectorize, + "builtin", &builtin, + "enabled", &enabled ); if (ret) throw ConfigError(json, err, "node-config-node-in"); - if (node_type(n)->flags & (int) NodeFlags::PROVIDES_SIGNALS) { + 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_array(json_signals)) { - ret = signal_list_parse(&nd->signals, json_signals); + 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; + + 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_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; + + asprintf(&name_new, "%s%d", name, i); + + json_string_set(json_name, name_new); + } + + 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 = signal_list_generate2(&nd->signals, dt); - if (ret) + signals = std::make_shared(dt); + if (signals) return ret; } else { - int count = DEFAULT_SAMPLE_LENGTH; - const char *type_str = "float"; - - if (json_is_object(json_signals)) { - ret = json_unpack_ex(json_signals, &err, 0, "{ s: i, s: s }", - "count", &count, - "type", &type_str - ); - if (ret) - throw ConfigError(json_signals, "node-config-node-signals", "Invalid signal definition"); - } - - enum SignalType type = signal_type_from_str(type_str); - if (type == SignalType::INVALID) - throw ConfigError(json_signals, "node-config-node-signals", "Invalid signal type {}", type_str); - - ret = signal_list_generate(&nd->signals, count, type); - if (ret) + signals = std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); + if (signals) return ret; } #ifdef WITH_HOOKS if (json_hooks) { - int m = nd->direction == NodeDir::OUT ? (int) Hook::Flags::NODE_WRITE : (int) Hook::Flags::NODE_READ; + int m = direction == NodeDirection::Direction::OUT + ? (int) Hook::Flags::NODE_WRITE + : (int) Hook::Flags::NODE_READ; - hook_list_parse(&nd->hooks, json_hooks, m, nullptr, n); + hooks.parse(json_hooks, m, nullptr, node); } #endif /* WITH_HOOKS */ - nd->state = State::PARSED; + return 0; +} + +void NodeDirection::check() +{ + if (vectorize <= 0) + throw RuntimeError("Invalid setting 'vectorize' with value {}. Must be natural number!", vectorize); + +#ifdef WITH_HOOKS + hooks.check(); +#endif /* WITH_HOOKS */ +} + +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; + + hooks.prepare(signals, m, nullptr, node); +#endif /* WITH_HOOKS */ return 0; } -void node_direction_check(struct vnode_direction *nd, struct vnode *n) +int NodeDirection::start() { - assert(n->state != State::DESTROYED); - - if (nd->vectorize <= 0) - throw RuntimeError("Invalid setting 'vectorize' with value {}. Must be natural number!", nd->vectorize); - #ifdef WITH_HOOKS - hook_list_check(&nd->hooks); + hooks.start(); #endif /* WITH_HOOKS */ - nd->state = State::CHECKED; -} - -int node_direction_start(struct vnode_direction *nd, struct vnode *n) -{ - assert(nd->state == State::PREPARED); - -#ifdef WITH_HOOKS - hook_list_start(&nd->hooks); -#endif /* WITH_HOOKS */ - - nd->state = State::STARTED; - return 0; } -int node_direction_stop(struct vnode_direction *nd, struct vnode *n) +int NodeDirection::stop() { - assert(nd->state == State::STARTED); - #ifdef WITH_HOOKS - hook_list_stop(&nd->hooks); + hooks.stop(); #endif /* WITH_HOOKS */ - nd->state = State::STOPPED; - return 0; } -struct vlist * node_direction_get_signals(struct vnode_direction *nd) -{ - assert(nd->state == State::PREPARED); - -#ifdef WITH_HOOKS - if (vlist_length(&nd->hooks) > 0) - return hook_list_get_signals(&nd->hooks); -#endif /* WITH_HOOKS */ - - return &nd->signals; -} - -unsigned node_direction_get_signals_max_cnt(struct vnode_direction *nd) +SignalList::Ptr NodeDirection::getSignals(int after_hooks) const { #ifdef WITH_HOOKS - if (vlist_length(&nd->hooks) > 0) - return MAX(vlist_length(&nd->signals), hook_list_get_signals_max_cnt(&nd->hooks)); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif /* WITH_HOOKS */ - return vlist_length(&nd->signals); + return signals; +} + +unsigned NodeDirection::getSignalsMaxCount() const +{ +#ifdef WITH_HOOKS + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); +#endif /* WITH_HOOKS */ + + return signals->size(); } diff --git a/lib/node_list.cpp b/lib/node_list.cpp index 55f3fca38..3397e88f2 100644 --- a/lib/node_list.cpp +++ b/lib/node_list.cpp @@ -21,26 +21,93 @@ */ #include -#include +#include +#include +using namespace villas; using namespace villas::node; -struct vnode * NodeList::lookup(const uuid_t &uuid) +Node * NodeList::lookup(const uuid_t &uuid) { for (auto *n : *this) { - if (!uuid_compare(uuid, n->uuid)) + if (!uuid_compare(uuid, n->getUuid())) return n; } return nullptr; } -struct vnode * NodeList::lookup(const std::string &name) +Node * NodeList::lookup(const std::string &name) { for (auto *n : *this) { - if (name == n->name) + if (name == n->getNameShort()) return n; } return nullptr; } + +int NodeList::parse(json_t *json, NodeList &all) +{ + Node *node; + const char *str; + + size_t index; + json_t *elm; + + 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; + + push_back(node); + break; + + 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; + + push_back(node); + } + break; + + default: + goto invalid; + } + + 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"); + + return -1; + +invalid2: + std::stringstream allss; + for (auto *n : all) + allss << " " << n->getNameShort(); + + throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str()); + + return 0; +} + +json_t * NodeList::toJson() const +{ + json_t *json_nodes = json_array(); + + for (const auto *n : *this) + json_array_append_new(json_nodes, n->toJson()); + + return json_nodes; +} diff --git a/lib/node_type.cpp b/lib/node_type.cpp deleted file mode 100644 index e6c79fc5f..000000000 --- a/lib/node_type.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/** Nodes. - * - * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASnode - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -using namespace villas; - -/** Global list of all known plugins */ -std::list *node_types = nullptr; - -int node_type_start(struct vnode_type *vt, villas::node::SuperNode *sn) -{ - int ret; - - if (vt->state == State::STARTED) - return 0; - - auto logger = logging.get(fmt::format("node:{}", *vt)); - logger->info("Initializing node type which is used by {} nodes", vt->instances.size()); - - ret = vt->type.start ? vt->type.start(sn) : 0; - if (ret == 0) - vt->state = State::STARTED; - - return ret; -} - -int node_type_stop(struct vnode_type *vt) -{ - int ret; - - if (vt->state != State::STARTED) - return 0; - - auto logger = logging.get(fmt::format("node:{}", *vt)); - logger->info("De-initializing node type"); - - ret = vt->type.stop ? vt->type.stop() : 0; - if (ret == 0) - vt->state = State::STOPPED; - - return ret; -} - -const char * node_type_name(struct vnode_type *vt) -{ - return vt->name; -} - -struct vnode_type * node_type_lookup(const std::string &name) -{ - for (auto *vt : *node_types) { - if (name == vt->name) - return vt; - } - - return nullptr; -} diff --git a/lib/nodes/CMakeLists.txt b/lib/nodes/CMakeLists.txt index 77c603b67..3acc9b6a8 100644 --- a/lib/nodes/CMakeLists.txt +++ b/lib/nodes/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -37,7 +37,7 @@ if(WITH_NODE_STATS) endif() if(WITH_NODE_SIGNAL) - list(APPEND NODE_SRC signal_generator.cpp) + list(APPEND NODE_SRC signal.cpp signal_v1.cpp) endif() if(WITH_NODE_LOOPBACK) diff --git a/lib/nodes/amqp.cpp b/lib/nodes/amqp.cpp index 415099d75..06e8627e7 100644 --- a/lib/nodes/amqp.cpp +++ b/lib/nodes/amqp.cpp @@ -1,7 +1,7 @@ /** Node type: nanomsg * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -34,7 +34,8 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static void amqp_default_ssl_info(struct amqp_ssl_info *s) +static +void amqp_default_ssl_info(struct amqp_ssl_info *s) { s->verify_peer = 1; s->verify_hostname = 1; @@ -43,7 +44,8 @@ static void amqp_default_ssl_info(struct amqp_ssl_info *s) s->ca_cert = nullptr; } -static amqp_bytes_t amqp_bytes_strdup(const char *str) +static +amqp_bytes_t amqp_bytes_strdup(const char *str) { size_t len = strlen(str) + 1; amqp_bytes_t buf = amqp_bytes_malloc(len); @@ -53,7 +55,8 @@ static amqp_bytes_t amqp_bytes_strdup(const char *str) return buf; } -static amqp_connection_state_t amqp_connect(struct amqp_connection_info *ci, struct amqp_ssl_info *ssl) +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; @@ -62,63 +65,97 @@ static amqp_connection_state_t amqp_connect(struct amqp_connection_info *ci, str conn = amqp_new_connection(); if (!conn) - return nullptr; + throw MemoryAllocationError(); if (ci->ssl) { sock = amqp_ssl_socket_new(conn); if (!sock) - return nullptr; + throw MemoryAllocationError(); amqp_ssl_socket_set_verify_peer(sock, ssl->verify_peer); amqp_ssl_socket_set_verify_hostname(sock, ssl->verify_hostname); - if (ssl->ca_cert) - amqp_ssl_socket_set_cacert(sock, ssl->ca_cert); + 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) - amqp_ssl_socket_set_key(sock, ssl->client_cert, ssl->client_key); + 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) - return nullptr; + throw MemoryAllocationError(); } ret = amqp_socket_open(sock, ci->host, ci->port); - if (ret != AMQP_STATUS_OK) + 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) + 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) + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to open channel"); return nullptr; + } return conn; } -static int amqp_close(amqp_connection_state_t conn) +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) + 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) + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to close connection"); return -1; + }; return 0; } -int amqp_parse(struct vnode *n, json_t *json) +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); + + a->formatter = nullptr; + + return 0; +} + +int villas::node::amqp_parse(NodeCompat *n, json_t *json) { int ret; - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); int port = 5672; const char *uri = nullptr; @@ -133,10 +170,6 @@ int amqp_parse(struct vnode *n, json_t *json) json_t *json_ssl = nullptr; json_t *json_format = nullptr; - /* Default values */ - amqp_default_ssl_info(&a->ssl_info); - amqp_default_connection_info(&a->connection_info); - 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, @@ -158,7 +191,7 @@ int amqp_parse(struct vnode *n, json_t *json) if (uri) a->uri = strdup(uri); else - a->uri = strf("amqp://%s:%s@%s:%d/%s", username, password, host, port, vhost); + 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) @@ -190,6 +223,8 @@ int amqp_parse(struct vnode *n, json_t *json) } /* Format */ + if (a->formatter) + delete a->formatter; a->formatter = json_format ? FormatFactory::make(json_format) : FormatFactory::make("json"); @@ -199,9 +234,9 @@ int amqp_parse(struct vnode *n, json_t *json) return 0; } -char * amqp_print(struct vnode *n) +char * villas::node::amqp_print(NodeCompat *n) { - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); char *buf = nullptr; @@ -235,23 +270,23 @@ char * amqp_print(struct vnode *n) return buf; } -int amqp_start(struct vnode *n) +int villas::node::amqp_start(NodeCompat *n) { - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); amqp_bytes_t queue; amqp_rpc_reply_t rep; amqp_queue_declare_ok_t *r; - a->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + a->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); /* Connect producer */ - a->producer = amqp_connect(&a->connection_info, &a->ssl_info); + a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); if (!a->producer) return -1; /* Connect consumer */ - a->consumer = amqp_connect(&a->connection_info, &a->ssl_info); + a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); if (!a->consumer) return -1; @@ -288,28 +323,26 @@ int amqp_start(struct vnode *n) return 0; } -int amqp_stop(struct vnode *n) +int villas::node::amqp_stop(NodeCompat *n) { int ret; - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); - ret = amqp_close(a->consumer); + ret = amqp_close(n, a->consumer); if (ret) return ret; - ret = amqp_close(a->producer); + ret = amqp_close(n, a->producer); if (ret) return ret; - delete a->formatter; - return 0; } -int amqp_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); amqp_envelope_t env; amqp_rpc_reply_t rep; @@ -324,10 +357,10 @@ int amqp_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return ret; } -int amqp_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); char data[1500]; size_t wbytes; @@ -352,9 +385,9 @@ int amqp_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int amqp_poll_fds(struct vnode *n, int fds[]) +int villas::node::amqp_poll_fds(NodeCompat *n, int fds[]) { - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); amqp_socket_t *sock = amqp_get_socket(a->consumer); @@ -363,9 +396,9 @@ int amqp_poll_fds(struct vnode *n, int fds[]) return 1; } -int amqp_destroy(struct vnode *n) +int villas::node::amqp_destroy(NodeCompat *n) { - struct amqp *a = (struct amqp *) n->_vd; + auto *a = n->getData(); if (a->uri) free(a->uri); @@ -385,10 +418,13 @@ int amqp_destroy(struct vnode *n) if (a->consumer) amqp_destroy_connection(a->consumer); + if (a->formatter) + delete a->formatter; + return 0; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -396,6 +432,7 @@ static void register_plugin() { 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; @@ -405,8 +442,5 @@ static void register_plugin() { p.write = amqp_write; p.poll_fds = amqp_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/can.cpp b/lib/nodes/can.cpp index 2232b16e5..bcdbd3b6f 100644 --- a/lib/nodes/can.cpp +++ b/lib/nodes/can.cpp @@ -1,7 +1,7 @@ /** Node-type: CAN bus * * @author Niklas Eiling - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -34,24 +34,23 @@ #include #include -#include +#include #include #include -#include -#include +#include +#include #include - -/* Forward declarations */ -static struct vnode_type p; - using namespace villas; using namespace villas::node; using namespace villas::utils; -int can_init(struct vnode *n) +/* Forward declarations */ +static NodeCompatType p; + +int villas::node::can_init(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); c->interface_name = nullptr; c->socket = 0; @@ -63,11 +62,9 @@ int can_init(struct vnode *n) return 0; } -int can_destroy(struct vnode *n) +int villas::node::can_destroy(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; - - free(c->interface_name); + auto *c = n->getData(); if (c->socket != 0) close(c->socket); @@ -83,13 +80,13 @@ int can_destroy(struct vnode *n) return 0; } -static int can_parse_signal(json_t *json, struct vlist *node_signals, struct can_signal *can_signals, size_t signal_index) +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; - struct signal* sig = nullptr; int ret = 1; json_error_t err; @@ -108,8 +105,8 @@ static int can_parse_signal(json_t *json, struct vlist *node_signals, struct can 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); - sig = (struct signal*)vlist_at(node_signals, signal_index); - if ((!name && !sig->name) || (name && strcmp(name, sig->name) == 0)) { + 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; @@ -122,10 +119,10 @@ static int can_parse_signal(json_t *json, struct vlist *node_signals, struct can out: return ret; } -int can_parse(struct vnode *n, json_t *json) +int villas::node::can_parse(NodeCompat *n, json_t *json) { int ret = 1; - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); size_t i; json_t *json_in_signals; json_t *json_out_signals; @@ -159,13 +156,13 @@ int can_parse(struct vnode *n, json_t *json) throw MemoryAllocationError(); json_array_foreach(json_in_signals, i, json_signal) { - ret = can_parse_signal(json_signal, &n->in.signals, c->in, i); + 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); + ret = can_parse_signal(json_signal, n->out.signals, c->out, i); if (ret) throw RuntimeError("at signal {}.", i); } @@ -175,16 +172,16 @@ int can_parse(struct vnode *n, json_t *json) return ret; } -char * can_print(struct vnode *n) +char * villas::node::can_print(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); return strf("interface_name={}", c->interface_name); } -int can_check(struct vnode *n) +int villas::node::can_check(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; + 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!"); @@ -192,22 +189,22 @@ int can_check(struct vnode *n) return 0; } -int can_prepare(struct vnode *n) +int villas::node::can_prepare(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); - c->sample_buf = (union signal_data*) calloc(vlist_length(&n->in.signals), sizeof(union signal_data)); + c->sample_buf = (union SignalData*) calloc(n->getInputSignals(false)->size(), sizeof(union SignalData)); return (c->sample_buf != 0 ? 0 : 1); } -int can_start(struct vnode *n) +int villas::node::can_start(NodeCompat *n) { int ret = 1; struct sockaddr_can addr = {0}; struct ifreq ifr; - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); c->start_time = time_now(); c->socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); @@ -230,9 +227,9 @@ int can_start(struct vnode *n) return 0; } -int can_stop(struct vnode *n) +int villas::node::can_stop(NodeCompat *n) { - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); if (c->socket != 0) { close(c->socket); @@ -242,7 +239,8 @@ int can_stop(struct vnode *n) return 0; } -static int can_convert_to_raw(const union signal_data *sig, const struct signal *from, void *to, int size) +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!"); @@ -305,12 +303,13 @@ static int can_convert_to_raw(const union signal_data *sig, const struct signal } fail: - throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", signal_type_to_str(from->type), to, size); + throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", signalTypeToString(from->type), to, size); return 1; } -int can_conv_from_raw(union signal_data* sig, void* from, int size, struct signal *to) +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!"); @@ -370,12 +369,12 @@ int can_conv_from_raw(union signal_data* sig, void* from, int size, struct signa goto fail; } fail: - throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", signal_type_to_str(to->type), from, size); + throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", signalTypeToString(to->type), from, size); return 1; } -int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret = 0; int nbytes; @@ -384,7 +383,7 @@ int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt) struct timeval tv; bool found_id = false; - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); assert(cnt >= 1 && smps[0]->capacity >= 1); @@ -406,12 +405,12 @@ int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt) smps[nread]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; } - for (size_t i=0; i < vlist_length(&(n->in.signals)); i++) { + 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, - (struct signal*) vlist_at(&n->in.signals, i)) != 0) { + n->getInputSignals(false)->getByIndex(i)) != 0) { goto out; } @@ -426,9 +425,9 @@ int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt) 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 == vlist_length(&n->in.signals)) { + 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 signal_data)); + 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; @@ -439,26 +438,26 @@ int can_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } out: /* Set signals, because other VILLASnode parts expect us to */ - smps[nread]->signals = &n->in.signals; + smps[nread]->signals = n->getInputSignals(false); return ret; } -int can_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +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 */ - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); assert(cnt >= 1 && smps[0]->capacity >= 1); - frame = (struct can_frame*) calloc(sizeof(struct can_frame), vlist_length(&(n->out.signals))); + frame = (struct can_frame*) calloc(sizeof(struct can_frame), n->getOutputSignals()->size()); for (nwrite=0; nwrite < cnt; nwrite++) { - for (size_t i=0; i < vlist_length(&(n->out.signals)); i++) { + for (size_t i=0; i < n->getOutputSignals()->size(); i++) { if (c->out[i].offset != 0) /* frame is shared */ continue; @@ -467,14 +466,14 @@ int can_write(struct vnode *n, struct sample * const smps[], unsigned cnt) can_convert_to_raw( &smps[nwrite]->data[i], - (struct signal*)vlist_at(&(n->out.signals), i), + n->getOutputSignals()->getByIndex(i), &frame[fsize].data, c->out[i].size); fsize++; } - for (size_t i=0; i < vlist_length(&(n->out.signals)); i++) { + for (size_t i=0; i < n->getOutputSignals(false)->size(); i++) { if (c->out[i].offset == 0) { /* frame already stored */ continue; } @@ -486,7 +485,7 @@ int can_write(struct vnode *n, struct sample * const smps[], unsigned cnt) frame[j].can_dlc += c->out[i].size; can_convert_to_raw( &smps[nwrite]->data[i], - (struct signal*)vlist_at(&(n->out.signals), i), + n->getOutputSignals(false)->getByIndex(i), (uint8_t*)&frame[j].data + c->out[i].offset, c->out[i].size); break; @@ -513,9 +512,9 @@ int can_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return nwrite; } -int can_poll_fds(struct vnode *n, int fds[]) +int villas::node::can_poll_fds(NodeCompat *n, int fds[]) { - struct can *c = (struct can *) n->_vd; + auto *c = n->getData(); fds[0] = c->socket; @@ -527,6 +526,7 @@ 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; @@ -540,8 +540,5 @@ static void register_plugin() { p.write = can_write; p.poll_fds = can_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index 865521c0a..17370b2a6 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -2,7 +2,7 @@ * * @author Steffen Vogel * @author Daniel Krebs - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,8 @@ using namespace villas::utils; 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) +static +int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t *json) { int ret; @@ -100,9 +101,10 @@ static int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, return 0; } -static int comedi_start_common(struct vnode *n) +static +int comedi_start_common(NodeCompat *n) { - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction* directions[2] = { &c->in, &c->out }; comedi_set_global_oor_behavior(COMEDI_OOR_NAN); @@ -159,10 +161,11 @@ static int comedi_start_common(struct vnode *n) return 0; } -static int comedi_start_in(struct vnode *n) +static +int comedi_start_in(NodeCompat *n) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->in; /* Try to find first analog input subdevice if not specified in config */ @@ -249,10 +252,11 @@ static int comedi_start_in(struct vnode *n) return 0; } -static int comedi_start_out(struct vnode *n) +static +int comedi_start_out(NodeCompat *n) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->out; /* Try to find first analog output subdevice if not specified in config */ @@ -358,10 +362,11 @@ static int comedi_start_out(struct vnode *n) return 0; } -static int comedi_stop_in(struct vnode *n) +static +int comedi_stop_in(NodeCompat *n) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->in; comedi_cancel(c->dev, d->subdevice); @@ -373,10 +378,11 @@ static int comedi_stop_in(struct vnode *n) return 0; } -static int comedi_stop_out(struct vnode *n) +static +int comedi_stop_out(NodeCompat *n) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->out; comedi_cancel(c->dev, d->subdevice); @@ -388,10 +394,10 @@ static int comedi_stop_out(struct vnode *n) return 0; } -int comedi_parse(struct vnode *n, json_t *json) +int villas::node::comedi_parse(NodeCompat *n, json_t *json) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); const char *device; @@ -432,9 +438,9 @@ int comedi_parse(struct vnode *n, json_t *json) return 0; } -char * comedi_print(struct vnode *n) +char * villas::node::comedi_print(NodeCompat *n) { - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); char *buf = nullptr; @@ -446,9 +452,9 @@ char * comedi_print(struct vnode *n) return buf; } -int comedi_start(struct vnode *n) +int villas::node::comedi_start(NodeCompat *n) { - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); c->dev = comedi_open(c->device); if (!c->dev) @@ -491,10 +497,10 @@ int comedi_start(struct vnode *n) return 0; } -int comedi_stop(struct vnode *n) +int villas::node::comedi_stop(NodeCompat *n) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); if (c->in.enabled) comedi_stop_in(n); @@ -511,10 +517,10 @@ int comedi_stop(struct vnode *n) #if COMEDI_USE_READ -int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->in; const size_t villas_sample_size = d->chanlist_len * d->sample_size; @@ -569,7 +575,7 @@ int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) for (size_t i = 0; i < cnt; i++) { d->counter++; - smps[i]->signals = &n->in.signals; + 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; @@ -623,10 +629,10 @@ int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) #else -int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->in; const size_t villas_sample_size = d->chanlist_len * d->sample_size; @@ -801,10 +807,10 @@ int comedi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) #endif -int comedi_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); struct comedi_direction *d = &c->out; if (!d->enabled) { @@ -859,7 +865,7 @@ int comedi_write(struct vnode *n, struct sample * const smps[], unsigned cnt) size_t villas_samples_written = 0; while (villas_samples_written < cnt) { - const struct sample *sample = smps[villas_samples_written]; + 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); @@ -921,6 +927,7 @@ int comedi_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return villas_samples_written; } +static char* comedi_cmd_trigger_src(unsigned int src, char *buf) { buf[0] = 0; @@ -942,6 +949,7 @@ char* comedi_cmd_trigger_src(unsigned int src, char *buf) return buf; } +static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) { char buf[256]; @@ -965,16 +973,16 @@ void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) logger->debug("stop: {:-8s} {}", src, cmd->stop_arg); } -int comedi_poll_fds(struct vnode *n, int fds[]) +int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) { - struct comedi *c = (struct comedi *) n->_vd; + auto *c = n->getData(); fds[0] = comedi_fileno(c->dev); return 0; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -990,8 +998,5 @@ static void register_plugin() { p.write = comedi_write; p.poll_fds = comedi_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index 491d36bc6..b8e2edd2b 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -27,14 +27,14 @@ #include #include #include -#include +#include #include using namespace villas; using namespace villas::node; /* Forward declartions */ -static struct vnode_type p; +static NodeCompatType p; /* Constants */ #define NSEC_PER_SEC (1000000000) @@ -59,11 +59,12 @@ struct coupler { .sc = nullptr }; -static void ethercat_cyclic_task(struct vnode *n) +static +void ethercat_cyclic_task(NodeCompat *n) { int ret; - struct sample *smp; - struct ethercat *w = (struct ethercat *) n->_vd; + struct Sample *smp; + auto *w = n->getData(); while (true) { w->task.wait(); @@ -81,7 +82,7 @@ static void ethercat_cyclic_task(struct vnode *n) smp->length = MIN(w->in.num_channels, smp->capacity); smp->flags = (int) SampleFlags::HAS_DATA; - smp->signals = &n->in.signals; + smp->signals = n->getInputSignals(false); /* Read process data */ for (unsigned i = 0; i < smp->length; i++) { @@ -111,7 +112,7 @@ static void ethercat_cyclic_task(struct vnode *n) } } -int ethercat_type_start(villas::node::SuperNode *sn) +int villas::node::ethercat_type_start(villas::node::SuperNode *sn) { int ret; json_error_t err; @@ -143,7 +144,7 @@ int ethercat_type_start(villas::node::SuperNode *sn) return 0; } -int ethercat_type_stop() +int villas::node::ethercat_type_stop() { auto logger = logging.get("node:ethercat"); @@ -154,9 +155,9 @@ int ethercat_type_stop() return 0; } -int ethercat_parse(struct vnode *n, json_t *json) +int villas::node::ethercat_parse(NodeCompat *n, json_t *json) { - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); int ret; json_error_t err; @@ -182,9 +183,9 @@ int ethercat_parse(struct vnode *n, json_t *json) return 0; } -char * ethercat_print(struct vnode *n) +char * villas::node::ethercat_print(NodeCompat *n) { - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); std::stringstream ss; ss << "alias=" << alias; @@ -194,9 +195,9 @@ char * ethercat_print(struct vnode *n) return strdup(ss.str().c_str()); } -int ethercat_check(struct vnode *n) +int villas::node::ethercat_check(NodeCompat *n) { - struct ethercat *w = (struct ethercat *) n->_vd; + 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 || @@ -211,9 +212,18 @@ int ethercat_check(struct vnode *n) return 0; } -int ethercat_prepare(struct vnode *n) +int villas::node::ethercat_prepare(NodeCompat *n) { - struct ethercat *w = (struct ethercat *) n->_vd; + 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 = 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) @@ -267,10 +277,10 @@ int ethercat_prepare(struct vnode *n) return 0; } -int ethercat_start(struct vnode *n) +int villas::node::ethercat_start(NodeCompat *n) { int ret; - struct ethercat *w = (struct ethercat *) n->_vd; + 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); @@ -312,21 +322,26 @@ int ethercat_start(struct vnode *n) return 0; } -int ethercat_stop(struct vnode *n) +int villas::node::ethercat_stop(NodeCompat *n) { - struct ethercat *w = (struct ethercat *) n->_vd; + int ret; + auto *w = n->getData(); w->thread.join(); + ret = queue_signalled_close(&w->queue); + if (ret) + return ret; + return 0; } -int ethercat_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); int avail; - struct sample *cpys[cnt]; + struct Sample *cpys[cnt]; avail = queue_signalled_pull_many(&w->queue, (void **) cpys, cnt); if (avail < 0) @@ -338,28 +353,27 @@ int ethercat_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return avail; } -int ethercat_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); if (cnt < 1) return cnt; - struct sample *smp = smps[0]; + struct Sample *smp = smps[0]; sample_incref(smp); - struct sample *old = w->send.exchange(smp); + struct Sample *old = w->send.exchange(smp); if (old) sample_decref(old); return 1; } -int ethercat_init(struct vnode *n) +int villas::node::ethercat_init(NodeCompat *n) { - int ret; - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); /* Default values */ w->rate = 1000; @@ -385,25 +399,17 @@ int ethercat_init(struct vnode *n) w->domain_regs = nullptr; /* Placement new for C++ objects */ - new (&w->send) std::atomic(); + new (&w->send) std::atomic(); new (&w->thread) std::thread(); new (&w->task) Task(CLOCK_REALTIME); - ret = pool_init(&w->pool, DEFAULT_ETHERCAT_QUEUE_LENGTH, SAMPLE_LENGTH(vlist_length(&n->in.signals))); - if (ret) - return ret; - - ret = queue_signalled_init(&w->queue, DEFAULT_ETHERCAT_QUEUE_LENGTH); - if (ret) - return ret; - return 0; } -int ethercat_destroy(struct vnode *n) +int villas::node::ethercat_destroy(NodeCompat *n) { int ret; - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); if (w->domain_regs) delete[] w->domain_regs; @@ -429,9 +435,9 @@ int ethercat_destroy(struct vnode *n) return 0; } -int ethercat_poll_fds(struct vnode *n, int *fds) +int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) { - struct ethercat *w = (struct ethercat *) n->_vd; + auto *w = n->getData(); fds[0] = queue_signalled_fd(&w->queue); @@ -458,9 +464,6 @@ static void register_plugin() { p.write = ethercat_write; p.poll_fds = ethercat_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/example.cpp b/lib/nodes/example.cpp index b738457ce..7998b6002 100644 --- a/lib/nodes/example.cpp +++ b/lib/nodes/example.cpp @@ -1,7 +1,7 @@ /** An example get started with new implementations of new node-types * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,38 +20,38 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include #include -#include +#include #include #include #include -/* Forward declartions */ -static struct vnode_type p; - using namespace villas; using namespace villas::node; using namespace villas::utils; -int example_type_start(villas::node::SuperNode *sn) +/* Forward declartions */ +static NodeCompatType p; + +int villas::node::example_type_start(villas::node::SuperNode *sn) { /* TODO: Add implementation here */ return 0; } -int example_type_stop() +int villas::node::example_type_stop() { /* TODO: Add implementation here */ return 0; } -int example_init(struct vnode *n) +int villas::node::example_init(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ @@ -61,22 +61,19 @@ int example_init(struct vnode *n) return 0; } -int example_destroy(struct vnode *n) +int villas::node::example_destroy(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + // auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ - if (s->setting2) - free(s->setting2); - return 0; } -int example_parse(struct vnode *n, json_t *json) +int villas::node::example_parse(NodeCompat *n, json_t *json) { int ret; - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); json_error_t err; @@ -92,18 +89,18 @@ int example_parse(struct vnode *n, json_t *json) return 0; } -char * example_print(struct vnode *n) +char * villas::node::example_print(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ return strf("setting1=%d, setting2=%s", s->setting1, s->setting2); } -int example_check(struct vnode *n) +int villas::node::example_check(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ @@ -116,9 +113,9 @@ int example_check(struct vnode *n) return 0; } -int example_prepare(struct vnode *n) +int villas::node::example_prepare(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ @@ -130,9 +127,9 @@ int example_prepare(struct vnode *n) return 0; } -int example_start(struct vnode *n) +int villas::node::example_start(NodeCompat *n) { - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); /* TODO: Add implementation here. The following is just an example */ @@ -141,37 +138,37 @@ int example_start(struct vnode *n) return 0; } -int example_stop(struct vnode *n) +int villas::node::example_stop(NodeCompat *n) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ return 0; } -int example_pause(struct vnode *n) +int villas::node::example_pause(NodeCompat *n) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ return 0; } -int example_resume(struct vnode *n) +int villas::node::example_resume(NodeCompat *n) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ return 0; } -int example_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::example_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int read; - struct example *s = (struct example *) n->_vd; + auto *s = n->getData(); struct timespec now; /* TODO: Add implementation here. The following is just an example */ @@ -182,20 +179,20 @@ int example_read(struct vnode *n, struct sample * const smps[], unsigned cnt) smps[0]->data[0].f = time_delta(&now, &s->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 = &n->in.signals; + smps[0]->signals = n->getInputSignals(false); read = 1; /* The number of samples read */ return read; } -int example_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::example_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int written; - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ @@ -204,27 +201,27 @@ int example_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return written; } -int example_reverse(struct vnode *n) +int villas::node::example_reverse(NodeCompat *n) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ return 0; } -int example_poll_fds(struct vnode *n, int fds[]) +int villas::node::example_poll_fds(NodeCompat *n, int fds[]) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ return 0; /* The number of file descriptors which have been set in fds */ } -int example_netem_fds(struct vnode *n, int fds[]) +int villas::node::example_netem_fds(NodeCompat *n, int fds[]) { - //struct example *s = (struct example *) n->_vd; + //auto *s = n->getData(); /* TODO: Add implementation here. */ @@ -255,8 +252,5 @@ static void register_plugin() { p.poll_fds = example_poll_fds; p.netem_fds = example_netem_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index d1d3d48a7..cb354457e 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -1,7 +1,7 @@ /** Node-type for subprocess node-types. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,56 +21,67 @@ *********************************************************************************/ #include +#include -#include -#include +#include #include #include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int exec_parse(struct vnode *n, json_t *json) +ExecNode::~ExecNode() { - struct exec *e = (struct exec *) n->_vd; + if (stream_in) + fclose(stream_in); + + if (stream_out) + fclose(stream_out); +} + +int ExecNode::parse(json_t *json, const uuid_t sn_uuid) +{ + int ret = Node::parse(json, sn_uuid); + if (ret) + return ret; json_error_t err; - int ret, flush = 1; + int f = 1, s = -1; json_t *json_exec; json_t *json_env = nullptr; json_t *json_format = nullptr; const char *wd = nullptr; - int shell = -1; 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", &flush, + "flush", &f, "environment", &json_env, - "shell", &shell, + "shell", &s, "working_directory", &wd ); if (ret) throw ConfigError(json, err, "node-config-node-exec"); - e->flush = flush; - e->shell = shell < 0 ? json_is_string(json_exec) : shell; + flush = f != 0; + shell = s < 0 ? json_is_string(json_exec) : s != 0; - e->arguments.clear(); - e->environment.clear(); + arguments.clear(); + environment.clear(); if (json_is_string(json_exec)) { - if (shell == 0) + if (!shell) throw ConfigError(json_exec, "node-config-node-exec-shell", "The exec setting must be an array if shell mode is disabled."); - e->command = json_string_value(json_exec); + command = json_string_value(json_exec); } else if (json_is_array(json_exec)) { - if (shell == 1) + 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) @@ -83,9 +94,9 @@ int exec_parse(struct vnode *n, json_t *json) throw ConfigError(json_arg, "node-config-node-exec-exec", "All arguments must be of string type"); if (i == 0) - e->command = json_string_value(json_arg); + command = json_string_value(json_arg); - e->arguments.push_back(json_string_value(json_arg)); + arguments.push_back(json_string_value(json_arg)); } } @@ -98,172 +109,118 @@ int exec_parse(struct vnode *n, json_t *json) if (!json_is_string(json_value)) throw ConfigError(json_value, "node-config-node-exec-environment", "Environment variables must be of string type"); - e->environment[key] = json_string_value(json_value); + environment[key] = json_string_value(json_value); } } /* Format */ - e->formatter = json_format + auto *fmt = json_format ? FormatFactory::make(json_format) : FormatFactory::make("villas.human"); - if (!e->formatter) + + formatter = Format::Ptr(fmt); + if (!formatter) throw ConfigError(json_format, "node-config-node-exec-format", "Invalid format configuration"); - // if (!(e->format->flags & (int) Flags::NEWLINES)) - // throw ConfigError(json_format, "node-config-node-exec-format", "Only line-delimited formats are currently supported"); + state = State::PARSED; return 0; } -int exec_prepare(struct vnode *n) +int ExecNode::prepare() { - struct exec *e = (struct exec *) n->_vd; + assert(state == State::CHECKED); /* Initialize IO */ - e->formatter->start(&n->in.signals); + formatter->start(getInputSignals(false)); + return Node::prepare(); +} + +int ExecNode::start() +{ /* Start subprocess */ - e->proc = std::make_unique(e->command, e->arguments, e->environment, e->working_dir, e->shell); - n->logger->debug("Started sub-process with pid={}", e->proc->getPid()); + 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_out = fdopen(proc->getFdOut(), "w"); + if (!stream_out) + return -1; + + int ret = Node::start(); + if (!ret) + state = State::STARTED; return 0; } -int exec_init(struct vnode *n) +int ExecNode::stop() { - struct exec *e = (struct exec *) n->_vd; - - new (&e->proc) std::unique_ptr(); - new (&e->working_dir) std::string(); - new (&e->command) std::string(); - new (&e->arguments) Popen::arg_list(); - new (&e->environment) Popen::env_map(); - - return 0; -} - -int exec_destroy(struct vnode *n) -{ - struct exec *e = (struct exec *) n->_vd; - - delete e->formatter; - - using uptr = std::unique_ptr; - using str = std::string; - using al = Popen::arg_list; - using em = Popen::env_map; - - e->proc.~uptr(); - e->working_dir.~str(); - e->command.~str(); - e->arguments.~al(); - e->environment.~em(); - - return 0; -} - -int exec_stop(struct vnode *n) -{ - struct exec *e = (struct exec *) n->_vd; + int ret = Node::stop(); + if (ret) + return ret; /* Stop subprocess */ - n->logger->debug("Killing sub-process with pid={}", e->proc->getPid()); - e->proc->kill(SIGINT); + logger->debug("Killing sub-process with pid={}", proc->getPid()); + proc->kill(SIGINT); - n->logger->debug("Waiting for sub-process with pid={} to terminate", e->proc->getPid()); - e->proc->close(); + logger->debug("Waiting for sub-process with pid={} to terminate", proc->getPid()); + proc->close(); /** @todo Check exit code of subprocess? */ return 0; } -int exec_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int ExecNode::_read(struct Sample * smps[], unsigned cnt) { - struct exec *e = (struct exec *) n->_vd; - - size_t rbytes; - int avail; - std::string line; - - std::getline(e->proc->cin(), line); - - avail = e->formatter->sscan(line.c_str(), line.length(), &rbytes, smps, cnt); - if (rbytes - 1 != line.length()) - return -1; - - return avail; + return formatter->scan(stream_in, smps, cnt); } -int exec_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int ExecNode::_write(struct Sample * smps[], unsigned cnt) { - struct exec *e = (struct exec *) n->_vd; - - size_t wbytes; int ret; - char *line = new char[1024]; - if (!line) - throw MemoryAllocationError(); - ret = e->formatter->sprint(line, 1024, &wbytes, smps, cnt); + ret = formatter->print(stream_out, smps, cnt); if (ret < 0) return ret; - e->proc->cout() << line; - - if (e->flush) - e->proc->cout().flush(); - - delete[] line; + if (flush) + fflush(stream_out); return cnt; } -char * exec_print(struct vnode *n) +const std::string & ExecNode::getDetails() { - struct exec *e = (struct exec *) n->_vd; - char *buf = nullptr; + std::string wd = working_dir; + if (wd.empty()) { + char buf[128]; + wd = getcwd(buf, sizeof(buf)); + } - strcatf(&buf, "exec=%s, shell=%s, flush=%s, #environment=%zu, #arguments=%zu, working_dir=%s", - e->command.c_str(), - e->shell ? "yes" : "no", - e->flush ? "yes" : "no", - e->environment.size(), - e->arguments.size(), - e->working_dir.c_str() - ); + if (details.empty()) { + details = fmt::format("exec={}, shell={}, flush={}, #environment={}, #arguments={}, working_dir={}", + command, + shell ? "yes" : "no", + flush ? "yes" : "no", + environment.size(), + arguments.size(), + wd + ); + } - return buf; + return details; } -int exec_poll_fds(struct vnode *n, int fds[]) +std::vector ExecNode::getPollFDs() { - struct exec *e = (struct exec *) n->_vd; - - fds[0] = e->proc->getFd(); - - return 1; + return { proc->getFdIn() }; } -static struct vnode_type p; - -__attribute__((constructor(110))) -static void register_plugin() { - p.name = "exec"; - p.description = "run subprocesses with stdin/stdout communication"; - p.vectorize = 0; - p.size = sizeof(struct exec); - p.parse = exec_parse; - p.print = exec_print; - p.prepare = exec_prepare; - p.init = exec_init; - p.destroy = exec_destroy; - p.stop = exec_stop; - p.read = exec_read; - p.write = exec_write; - p.poll_fds = exec_poll_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); -} +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 4f67b2a98..28214fc50 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -1,7 +1,7 @@ /** Node type: File * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,10 +27,10 @@ #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -39,7 +39,8 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static char * file_format_name(const char *format, struct timespec *ts) +static +char * file_format_name(const char *format, struct timespec *ts) { struct tm tm; char *buf = new char[FILE_MAX_PATHLEN]; @@ -54,7 +55,8 @@ static char * file_format_name(const char *format, struct timespec *ts) return buf; } -static struct timespec file_calc_offset(const struct timespec *first, const struct timespec *epoch, enum file::EpochMode mode) +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(); @@ -81,9 +83,9 @@ static struct timespec file_calc_offset(const struct timespec *first, const stru } } -int file_parse(struct vnode *n, json_t *json) +int villas::node::file_parse(NodeCompat *n, json_t *json) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); int ret; json_error_t err; @@ -115,6 +117,8 @@ int file_parse(struct vnode *n, json_t *json) 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"); @@ -147,14 +151,12 @@ int file_parse(struct vnode *n, json_t *json) throw RuntimeError("Invalid value '{}' for setting 'epoch'", epoch); } - n->_vd = f; - return 0; } -char * file_print(struct vnode *n) +char * villas::node::file_print(NodeCompat *n) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); char *buf = nullptr; const char *epoch_str = nullptr; @@ -236,14 +238,17 @@ char * file_print(struct vnode *n) return buf; } -int file_start(struct vnode *n) +int villas::node::file_start(NodeCompat *n) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); struct timespec now = time_now(); int ret; /* Prepare file name */ + if (f->uri) + delete[] f->uri; + f->uri = file_format_name(f->uri_tmpl, &now); /* Check if directory exists */ @@ -269,10 +274,10 @@ int file_start(struct vnode *n) free(cpy); - f->formatter->start(&n->in.signals); + f->formatter->start(n->getInputSignals(false)); /* Open file */ - f->stream_out = fopen(f->uri, "a+"); + f->stream_out = fopen(f->uri, "w+"); if (!f->stream_out) return -1; @@ -303,7 +308,7 @@ int file_start(struct vnode *n) n->logger->warn("Empty file"); } else { - struct sample smp; + struct Sample smp; smp.capacity = 0; @@ -320,7 +325,7 @@ int file_start(struct vnode *n) rewind(f->stream_in); /* Fast-forward */ - struct sample *smp = sample_alloc_mem(vlist_length(&n->in.signals)); + 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); @@ -329,24 +334,21 @@ int file_start(struct vnode *n) return 0; } -int file_stop(struct vnode *n) +int villas::node::file_stop(NodeCompat *n) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); f->task.stop(); fclose(f->stream_in); fclose(f->stream_out); - delete f->formatter; - delete f->uri; - return 0; } -int file_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); int ret; uint64_t steps; @@ -374,7 +376,7 @@ retry: ret = f->formatter->scan(f->stream_in, smps, cnt); case file::EOFBehaviour::STOP: n->logger->info("Reached end-of-file."); - n->state = State::STOPPING; + n->setState(State::STOPPING); return -1; @@ -412,10 +414,10 @@ retry: ret = f->formatter->scan(f->stream_in, smps, cnt); return cnt; } -int file_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); assert(cnt == 1); @@ -429,9 +431,9 @@ int file_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int file_poll_fds(struct vnode *n, int fds[]) +int villas::node::file_poll_fds(NodeCompat *n, int fds[]) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); if (f->rate) { fds[0] = f->task.getFD(); @@ -447,9 +449,9 @@ int file_poll_fds(struct vnode *n, int fds[]) return -1; /** @todo not supported yet */ } -int file_init(struct vnode *n) +int villas::node::file_init(NodeCompat *n) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); new (&f->task) Task(CLOCK_REALTIME); @@ -462,19 +464,27 @@ int file_init(struct vnode *n) f->buffer_size_out = 0; f->skip_lines = 0; + f->formatter = nullptr; + return 0; } -int file_destroy(struct vnode *n) +int villas::node::file_destroy(NodeCompat *n) { - struct file *f = (struct file *) n->_vd; + auto *f = n->getData(); f->task.~Task(); + if (f->uri) + delete[] f->uri; + + if (f->formatter) + delete f->formatter; + return 0; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -492,8 +502,5 @@ static void register_plugin() { p.write = file_write; p.poll_fds = file_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index b3fcc3c82..e721ebb82 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -1,7 +1,7 @@ /** Communicate with VILLASfpga Xilinx FPGA boards * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,45 +27,36 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include #include #include #include -/* Forward declartions */ -static struct vnode_type p; - using namespace villas; using namespace villas::node; using namespace villas::utils; +/* Forward declartions */ +static struct NodeCompatType p; + /* Global state */ static fpga::PCIeCard::List cards; -static std::map dmaMap; +static std::map dmaMap; static std::shared_ptr pciDevices; static std::shared_ptr vfioContainer; using namespace villas; +using namespace villas::node; -// static std::shared_ptr -// fpga_find_dma(const fpga::PCIeCard &card) -// { -// // for (auto &ip : card.ips) { - -// // } - -// return nullptr; -// } - -int fpga_type_start(node::SuperNode *sn) +int villas::node::fpga_type_start(SuperNode *sn) { vfioContainer = kernel::vfio::Container::create(); pciDevices = std::make_shared(); @@ -88,16 +79,16 @@ int fpga_type_start(node::SuperNode *sn) return 0; } -int fpga_type_stop() +int villas::node::fpga_type_stop() { vfioContainer.reset(); // TODO: is this the proper way? return 0; } -int fpga_init(struct vnode *n) +int villas::node::fpga_init(NodeCompat *n) { - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); f->coalesce = 0; f->irqFd = -1; @@ -112,18 +103,19 @@ int fpga_init(struct vnode *n) new (&f->dma) std::shared_ptr(); new (&f->intf) std::shared_ptr(); - // TODO: fixme - // new (&f->in.mem) std::shared_ptr(); - // new (&f->out.mem) std::shared_ptr(); + new (&f->in.block) std::unique_ptr(); + new (&f->out.block) std::unique_ptr(); return 0; } -int fpga_destroy(struct vnode *n) +int villas::node::fpga_destroy(NodeCompat *n) { - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); - using mbptr = MemoryAccessor; + // using maiptr = MemoryAccessor; + // using mafptr = MemoryAccessor; + using mbptr = MemoryBlock::Ptr; using cptr = std::shared_ptr; using nptr = std::shared_ptr; using dptr = std::shared_ptr; @@ -138,16 +130,16 @@ int fpga_destroy(struct vnode *n) f->dma.~dptr(); f->intf.~nptr(); - f->in.mem.~mbptr(); - f->out.mem.~mbptr(); + f->in.block.~mbptr(); + f->out.block.~mbptr(); return 0; } -int fpga_parse(struct vnode *n, json_t *json) +int villas::node::fpga_parse(NodeCompat *n, json_t *json) { int ret; - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); json_error_t err; @@ -180,9 +172,9 @@ int fpga_parse(struct vnode *n, json_t *json) return 0; } -char * fpga_print(struct vnode *n) +char * villas::node::fpga_print(NodeCompat *n) { - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); return strf("fpga=%s, dma=%s, if=%s, polling=%s, coalesce=%d", f->card->name.c_str(), @@ -192,18 +184,12 @@ char * fpga_print(struct vnode *n) ); } -int fpga_check(struct vnode *n) -{ - // struct fpga *f = (struct fpga *) n->_vd; - - return 0; -} - -int fpga_prepare(struct vnode *n) +int villas::node::fpga_prepare(NodeCompat *n) { int ret; - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); + // Select first FPGA card auto it = f->cardName.empty() ? cards.begin() : std::find_if(cards.begin(), cards.end(), [f](const fpga::PCIeCard::Ptr &c) { @@ -211,25 +197,27 @@ int fpga_prepare(struct vnode *n) }); if (it == cards.end()) - throw ConfigError(json_object_get(n->config, "fpga"), "node-config-node-fpga-card", "Invalid FPGA card name: {}", f->cardName); + throw ConfigError(json_object_get(n->getConfig(), "fpga"), "node-config-node-fpga-card", "Invalid FPGA card name: {}", f->cardName); f->card = *it; + // Select interface IP core auto intf = f->intfName.empty() ? f->card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) : f->card->lookupIp(f->intfName); if (!intf) - throw ConfigError(n->config, "node-config-node-fpga-interface", "There is no interface IP with the name: {}", f->intfName); + throw ConfigError(n->getConfig(), "node-config-node-fpga-interface", "There is no interface IP with the name: {}", f->intfName); f->intf = std::dynamic_pointer_cast(intf); if (!f->intf) throw RuntimeError("The IP {} is not a interface", *intf); + // Select DMA IP core auto dma = f->dmaName.empty() ? f->card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) : f->card->lookupIp(f->dmaName); if (!dma) - throw ConfigError(n->config, "node-config-node-fpga-dma", "There is no DMA IP with the name: {}", f->dmaName); + throw ConfigError(n->getConfig(), "node-config-node-fpga-dma", "There is no DMA IP with the name: {}", f->dmaName); f->dma = std::dynamic_pointer_cast(dma); if (!f->dma) @@ -241,16 +229,19 @@ int fpga_prepare(struct vnode *n) *(f->intf), *(f->dma) ); - auto &alloc = HostRam::getAllocator(); + auto &alloc = HostDmaRam::getAllocator(); - f->in.mem = alloc.allocate(0x100 / sizeof(int32_t)); - f->out.mem = alloc.allocate(0x100 / sizeof(int32_t)); + f->in.block = std::move(alloc.allocateBlock(0x100 / sizeof(int32_t))); + f->out.block = std::move(alloc.allocateBlock(0x100 / sizeof(int32_t))); - f->in.block = f->in.mem.getMemoryBlock(); - f->out.block = f->out.mem.getMemoryBlock(); + f->in.accessor.i = MemoryAccessor(*f->in.block); + f->in.accessor.f = MemoryAccessor(*f->in.block); - f->dma->makeAccesibleFromVA(f->in.block); - f->dma->makeAccesibleFromVA(f->out.block); + f->out.accessor.i = MemoryAccessor(*f->out.block); + f->out.accessor.f = MemoryAccessor(*f->out.block); + + f->dma->makeAccesibleFromVA(*f->in.block); + f->dma->makeAccesibleFromVA(*f->out.block); f->dma->dump(); f->intf->dump(); @@ -259,52 +250,66 @@ int fpga_prepare(struct vnode *n) return 0; } -int fpga_start(struct vnode *n) -{ - // struct fpga *f = (struct fpga *) n->_vd; - - return 0; -} - -int fpga_stop(struct vnode *n) -{ - //struct fpga *f = (struct fpga *) n->_vd; - - return 0; -} - -int fpga_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::fpga_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { unsigned read; - struct fpga *f = (struct fpga *) n->_vd; - struct sample *smp = smps[0]; + auto *f = n->getData(); + struct Sample *smp = smps[0]; assert(cnt == 1); - f->dma->read(f->in.block, f->in.block.getSize()); // TODO: calc size + f->dma->read(*f->in.block.get(), f->in.block->getSize()); // TODO: calc size const size_t bytesRead = f->dma->readComplete(); read = bytesRead / sizeof(int32_t); - for (unsigned i = 0; i < MIN(read, smp->capacity); i++) - smp->data[i].i = f->in.mem[i]; + for (unsigned i = 0; i < MIN(read, smp->capacity); i++) { + auto sig = n->getInputSignals(false)->getByIndex(i); - smp->signals = &n->in.signals; + switch (sig->type) { + case SignalType::INTEGER: + smp->data[i].i = f->in.accessor.i[i]; + break; + + case SignalType::FLOAT: + smp->data[i].f = f->in.accessor.f[i]; + break; + + default: {} + } + } + + smp->signals = n->getInputSignals(false); + smp->length = bytesRead / sizeof(uint32_t); + smp->flags = (int) SampleFlags::HAS_DATA; return read; } -int fpga_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::fpga_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int written; - struct fpga *f = (struct fpga *) n->_vd; - struct sample *smp = smps[0]; + auto *f = n->getData(); + struct Sample *smp = smps[0]; assert(cnt == 1); - for (unsigned i = 0; i < smps[0]->length; i++) - f->out.mem[i] = smps[0]->data[i].i; + for (unsigned i = 0; i < smps[0]->length; i++) { + auto sig = smp->signals->getByIndex(i); - bool state = f->dma->write(f->out.block, smp->length * sizeof(int32_t)); + switch (sig->type) { + case SignalType::INTEGER: + f->out.accessor.i[i] = smps[0]->data[i].i; + break; + + case SignalType::FLOAT: + f->out.accessor.f[i] = smps[0]->data[i].f; + break; + + default: {} + } + } + + bool state = f->dma->write(*f->out.block.get(), smp->length * sizeof(int32_t)); if (!state) return -1; @@ -313,9 +318,9 @@ int fpga_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return written; } -int fpga_poll_fds(struct vnode *n, int fds[]) +int villas::node::fpga_poll_fds(NodeCompat *n, int fds[]) { - struct fpga *f = (struct fpga *) n->_vd; + auto *f = n->getData(); if (f->polling) return 0; @@ -331,7 +336,7 @@ static void register_plugin() { p.name = "fpga"; p.description = "Communicate with VILLASfpga Xilinx FPGA boards"; p.vectorize = 1; - p.size = sizeof(struct fpga); + p.size = sizeof(struct fpga_node); p.type.start = fpga_type_start; p.type.stop = fpga_type_stop; p.init = fpga_init; @@ -339,16 +344,10 @@ static void register_plugin() { p.prepare = fpga_prepare; p.parse = fpga_parse; p.print = fpga_print; - p.check = fpga_check; - p.start = fpga_start; - p.stop = fpga_stop; p.read = fpga_read; p.write = fpga_write; p.poll_fds = fpga_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/go.cpp b/lib/nodes/go.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/lib/nodes/go/CMakeLists.txt b/lib/nodes/go/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/lib/nodes/go/example.go b/lib/nodes/go/example.go new file mode 100644 index 000000000..38e9db97e --- /dev/null +++ b/lib/nodes/go/example.go @@ -0,0 +1,264 @@ +package node + +import "C" +import ( + "time" + "unsafe" + + gopointer "github.com/mattn/go-pointer" +) + +func registerNode(name string, ctor CreateNode) { + +} + +type Signal struct { +} + +type Sample struct { + Timestamp struct { + Origin time.Time + Received time.Time + } + + Data []interface{} +} + +type Node interface { + Close() error + + Prepare() error + + Parse(cfg []byte) error + + Check() error + + Start() error + Stop() error + + Pause() error + Resume() error + Restart() error + + Read(smps []Sample) (int, error) + Write(smps []Sample) (int, error) + + Reverse() error + + GetPollFDs() ([]int, error) + GetNetemFDs() ([]int, error) + + // GetMemoryType() + + Details() string +} + +type CreateNode func() Node + +// Wrapper + +func intSliceToCArray(s []int) unsafe.Pointer { + b := (*[1 << 16]byte)(unsafe.Pointer(&s[0]))[0 : len(s)*8 : len(s)*8] + return C.CBytes(unsafe.Pointer(&b[0])) +} + +func errorToInt(err error) int { + if err == nil { + return -1 + } else { + return -22 + } +} + +//export NodeClose +func NodeClose(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Close()) +} + +//export NodePrepare +func NodePrepare(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Prepare()) +} + +//export NodeParse +func NodeParse(p unsafe.Pointer, c unsafe.Pointer) int { + cfg := gopointer.Restore(c).([]byte) + n := gopointer.Restore(p).(Node) + return errorToInt(n.Parse(cfg)) +} + +//export NodeCheck +func NodeCheck(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Check()) +} + +//export NodeStart +func NodeStart(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Start()) +} + +//export NodeStop +func NodeStop(p unsafe.Pointer) error { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Stop()) +} + +//export NodePause +func NodePause(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Pause()) +} + +//export NodeResume +func NodeResume(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Resume()) +} + +//export NodeRestart +func NodeRestart(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Restart()) +} + +//export NodeRead +func NodeRead(p unsafe.Pointer, smps []Sample) (int, error) { + n := gopointer.Restore(p).(Node) + return n.Read(smps) +} + +//export NodeWrite +func NodeWrite(p unsafe.Pointer, smps []Sample) (int, int) { + n := gopointer.Restore(p).(Node) + r, err := n.Write(smps) + return r, errorToInt(err) +} + +//export NodeReverse +func NodeReverse(p unsafe.Pointer) int { + n := gopointer.Restore(p).(Node) + return errorToInt(n.Reverse()) +} + +//export NodeGetPollFDs +func NodeGetPollFDs(p unsafe.Pointer) (unsafe.Pointer, int) { + n := gopointer.Restore(p).(Node) + f, err := n.GetPollFDs() + if err == nil { + return intSliceToCArray(f), 0 + } else { + return nil, errorToInt(err) + } +} + +//export NodeGetNetemFDs +func NodeGetNetemFDs(p unsafe.Pointer) (unsafe.Pointer, int) { + n := gopointer.Restore(p).(Node) + f, err := n.GetNetemFDs() + if err == nil { + return intSliceToCArray(f), 0 + } else { + return nil, errorToInt(err) + } +} + +//export NodeDetails +func NodeDetails(p unsafe.Pointer) *C.char { + n := gopointer.Restore(p).(Node) + d := n.Details() + return C.CString(d) +} + +// Example + +type ExampleNode struct { + Node +} + +func NewExampleNode() Node { + return &ExampleNode{} +} + +func (n *ExampleNode) Close() error { + + return nil +} + +func (n *ExampleNode) Prepare() error { + + return nil +} + +func (n *ExampleNode) Parse(cfg []byte) error { + + return nil +} + +func (n *ExampleNode) Check() error { + + return nil +} + +func (n *ExampleNode) Start() error { + + return nil +} + +func (n *ExampleNode) Stop() error { + + return nil +} + +func (n *ExampleNode) Pause() error { + + return nil +} + +func (n *ExampleNode) Resume() error { + + return nil +} + +func (n *ExampleNode) Restart() error { + + return nil +} + +func (n *ExampleNode) Read(smps []Sample) (int, error) { + + return 0, nil +} + +func (n *ExampleNode) Write(smps []Sample) (int, error) { + + return 0, nil +} + +func (n *ExampleNode) Reverse() error { + + return nil +} + +func (n *ExampleNode) GetPollFDs() ([]int, error) { + + return []int{}, nil +} + +func (n *ExampleNode) GetNetemFDs() ([]int, error) { + return []int{}, nil +} + +func (n *ExampleNode) Details() string { + + return "" +} + +// init + +func init() { + registerNode("example-go", NewExampleNode) +} diff --git a/lib/nodes/go/node.go b/lib/nodes/go/node.go new file mode 100644 index 000000000..06172f356 --- /dev/null +++ b/lib/nodes/go/node.go @@ -0,0 +1,12 @@ +package node + +/* +#include + + +*/ +import "C" + +func registerNode(name string, ctor CreateNode) { + +} diff --git a/lib/nodes/go/test/CMakeLists.txt b/lib/nodes/go/test/CMakeLists.txt new file mode 100644 index 000000000..8eb104d9f --- /dev/null +++ b/lib/nodes/go/test/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0) +project (test) + +add_subdirectory(go) + +add_executable(test test.c) + +target_link_libraries(test goshim pthread) diff --git a/lib/nodes/go/test/build/CMakeCache.txt b/lib/nodes/go/test/build/CMakeCache.txt new file mode 100644 index 000000000..479e29484 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeCache.txt @@ -0,0 +1,374 @@ +# This is the CMakeCache file. +# For build in directory: /global/projects/villas/node/lib/nodes/go/test/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O2 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O2 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=test + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +test_BINARY_DIR:STATIC=/global/projects/villas/node/lib/nodes/go/test/build + +//Value Computed by CMake +test_SOURCE_DIR:STATIC=/global/projects/villas/node/lib/nodes/go/test + +//Value Computed by CMake +test_go_BINARY_DIR:STATIC=/global/projects/villas/node/lib/nodes/go/test/build/go + +//Value Computed by CMake +test_go_SOURCE_DIR:STATIC=/global/projects/villas/node/lib/nodes/go/test/go + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/global/projects/villas/node/lib/nodes/go/test/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=18 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/global/projects/villas/node/lib/nodes/go/test +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=2 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCCompiler.cmake b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCCompiler.cmake new file mode 100644 index 000000000..e583039e4 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCCompiler.cmake @@ -0,0 +1,77 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "8.4.1") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/8/include;/usr/local/include;/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/8;/usr/lib64;/lib64;/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCXXCompiler.cmake b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCXXCompiler.cmake new file mode 100644 index 000000000..10d2b4206 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeCXXCompiler.cmake @@ -0,0 +1,89 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "8.4.1") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/8;/usr/include/c++/8/x86_64-redhat-linux;/usr/include/c++/8/backward;/usr/lib/gcc/x86_64-redhat-linux/8/include;/usr/local/include;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/8;/usr/lib64;/lib64;/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_C.bin b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 000000000..106875da1 Binary files /dev/null and b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_C.bin differ diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_CXX.bin b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 000000000..a9be1ade7 Binary files /dev/null and b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeSystem.cmake b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeSystem.cmake new file mode 100644 index 000000000..e53f7ee39 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-4.18.0-305.3.1.el8_4.x86_64") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "4.18.0-305.3.1.el8_4.x86_64") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-4.18.0-305.3.1.el8_4.x86_64") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "4.18.0-305.3.1.el8_4.x86_64") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/CMakeCCompilerId.c b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 000000000..6c0aa93cb --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,674 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if !defined(__STDC__) +# if (defined(_MSC_VER) && !defined(__clang__)) \ + || (defined(__ibmxl__) || defined(__IBMC__)) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/a.out b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/a.out new file mode 100755 index 000000000..c5e1fe443 Binary files /dev/null and b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/a.out differ diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 000000000..37c21cafe --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,663 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/a.out b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/a.out new file mode 100755 index 000000000..472a537f8 Binary files /dev/null and b/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/a.out differ diff --git a/lib/nodes/go/test/build/CMakeFiles/CMakeDirectoryInformation.cmake b/lib/nodes/go/test/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 000000000..98d218353 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/global/projects/villas/node/lib/nodes/go/test") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/global/projects/villas/node/lib/nodes/go/test/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/lib/nodes/go/test/build/CMakeFiles/CMakeOutput.log b/lib/nodes/go/test/build/CMakeFiles/CMakeOutput.log new file mode 100644 index 000000000..2236771f4 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/CMakeOutput.log @@ -0,0 +1,409 @@ +The system is: Linux - 4.18.0-305.3.1.el8_4.x86_64 - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /usr/bin/cc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdC/a.out" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /usr/bin/c++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/3.18.2/CompilerIdCXX/a.out" + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake cmTC_194bc/fast && /usr/bin/gmake -f CMakeFiles/cmTC_194bc.dir/build.make CMakeFiles/cmTC_194bc.dir/build +gmake[1]: Entering directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o +/usr/bin/cc -v -o CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake/Modules/CMakeCCompilerABI.c +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +OFFLOAD_TARGET_NAMES=nvptx-none +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-redhat-linux +Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/8/cc1 -quiet -v /usr/share/cmake/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -version -o /tmp/ccQ2G8ES.s +GNU C17 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux) + compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1), GMP version 6.1.2, MPFR version 3.1.6-p2, MPC version 1.0.2, isl version isl-0.16.1-GMP + +warning: MPC header version 1.0.2 differs from library version 1.1.0. +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/lib/gcc/x86_64-redhat-linux/8/include + /usr/local/include + /usr/include +End of search list. +GNU C17 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux) + compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1), GMP version 6.1.2, MPFR version 3.1.6-p2, MPC version 1.0.2, isl version isl-0.16.1-GMP + +warning: MPC header version 1.0.2 differs from library version 1.1.0. +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: 4200654a8a5e4de8e22bfb5ed3a1f615 +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o /tmp/ccQ2G8ES.s +GNU assembler version 2.30 (x86_64-redhat-linux) using BFD version version 2.30-93.el8 +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' +Linking C executable cmTC_194bc +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_194bc.dir/link.txt --verbose=1 +/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -o cmTC_194bc +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-redhat-linux +Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_194bc' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/8/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccStT1og.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_194bc /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../.. CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/8/crtend.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_194bc' '-mtune=generic' '-march=x86-64' +gmake[1]: Leaving directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp' + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-redhat-linux/8/include] + add: [/usr/local/include] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/8/include] ==> [/usr/lib/gcc/x86_64-redhat-linux/8/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/lib/gcc/x86_64-redhat-linux/8/include;/usr/local/include;/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_194bc/fast && /usr/bin/gmake -f CMakeFiles/cmTC_194bc.dir/build.make CMakeFiles/cmTC_194bc.dir/build] + ignore line: [gmake[1]: Entering directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp'] + ignore line: [Building C object CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/libexec/gcc/x86_64-redhat-linux/8/cc1 -quiet -v /usr/share/cmake/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -version -o /tmp/ccQ2G8ES.s] + ignore line: [GNU C17 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux)] + ignore line: [ compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1) GMP version 6.1.2 MPFR version 3.1.6-p2 MPC version 1.0.2 isl version isl-0.16.1-GMP] + ignore line: [] + ignore line: [warning: MPC header version 1.0.2 differs from library version 1.1.0.] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/8/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux)] + ignore line: [ compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1) GMP version 6.1.2 MPFR version 3.1.6-p2 MPC version 1.0.2 isl version isl-0.16.1-GMP] + ignore line: [] + ignore line: [warning: MPC header version 1.0.2 differs from library version 1.1.0.] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 4200654a8a5e4de8e22bfb5ed3a1f615] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o /tmp/ccQ2G8ES.s] + ignore line: [GNU assembler version 2.30 (x86_64-redhat-linux) using BFD version version 2.30-93.el8] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking C executable cmTC_194bc] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_194bc.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -o cmTC_194bc ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) ] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_194bc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/libexec/gcc/x86_64-redhat-linux/8/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccStT1og.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_194bc /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../.. CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/8/crtend.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o] + arg [/usr/libexec/gcc/x86_64-redhat-linux/8/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccStT1og.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--no-add-needed] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-o] ==> ignore + arg [cmTC_194bc] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] + arg [-L/lib/../lib64] ==> dir [/lib/../lib64] + arg [-L/usr/lib/../lib64] ==> dir [/usr/lib/../lib64] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8/../../..] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../..] + arg [CMakeFiles/cmTC_194bc.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o] ==> ignore + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8] ==> [/usr/lib/gcc/x86_64-redhat-linux/8] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] ==> [/usr/lib64] + collapse library dir [/lib/../lib64] ==> [/lib64] + collapse library dir [/usr/lib/../lib64] ==> [/usr/lib64] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../..] ==> [/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit dirs: [/usr/lib/gcc/x86_64-redhat-linux/8;/usr/lib64;/lib64;/usr/lib] + implicit fwks: [] + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake cmTC_bce9b/fast && /usr/bin/gmake -f CMakeFiles/cmTC_bce9b.dir/build.make CMakeFiles/cmTC_bce9b.dir/build +gmake[1]: Entering directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o +/usr/bin/c++ -v -o CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +OFFLOAD_TARGET_NAMES=nvptx-none +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-redhat-linux +Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/8/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/ccT60iIG.s +GNU C++14 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux) + compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1), GMP version 6.1.2, MPFR version 3.1.6-p2, MPC version 1.0.2, isl version isl-0.16.1-GMP + +warning: MPC header version 1.0.2 differs from library version 1.1.0. +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 + /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux + /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward + /usr/lib/gcc/x86_64-redhat-linux/8/include + /usr/local/include + /usr/include +End of search list. +GNU C++14 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux) + compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1), GMP version 6.1.2, MPFR version 3.1.6-p2, MPC version 1.0.2, isl version isl-0.16.1-GMP + +warning: MPC header version 1.0.2 differs from library version 1.1.0. +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: b52810184d801135c3a3dd4ab4785304 +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccT60iIG.s +GNU assembler version 2.30 (x86_64-redhat-linux) using BFD version version 2.30-93.el8 +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +Linking CXX executable cmTC_bce9b +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_bce9b.dir/link.txt --verbose=1 +/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_bce9b +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-redhat-linux +Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bce9b' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/8/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccMOKZ64.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_bce9b /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../.. CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/8/crtend.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bce9b' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +gmake[1]: Leaving directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp' + + + +Parsed CXX implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8] + add: [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux] + add: [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward] + add: [/usr/lib/gcc/x86_64-redhat-linux/8/include] + add: [/usr/local/include] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8] ==> [/usr/include/c++/8] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux] ==> [/usr/include/c++/8/x86_64-redhat-linux] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward] ==> [/usr/include/c++/8/backward] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/8/include] ==> [/usr/lib/gcc/x86_64-redhat-linux/8/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/8;/usr/include/c++/8/x86_64-redhat-linux;/usr/include/c++/8/backward;/usr/lib/gcc/x86_64-redhat-linux/8/include;/usr/local/include;/usr/include] + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_bce9b/fast && /usr/bin/gmake -f CMakeFiles/cmTC_bce9b.dir/build.make CMakeFiles/cmTC_bce9b.dir/build] + ignore line: [gmake[1]: Entering directory '/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/CMakeTmp'] + ignore line: [Building CXX object CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/libexec/gcc/x86_64-redhat-linux/8/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/ccT60iIG.s] + ignore line: [GNU C++14 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux)] + ignore line: [ compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1) GMP version 6.1.2 MPFR version 3.1.6-p2 MPC version 1.0.2 isl version isl-0.16.1-GMP] + ignore line: [] + ignore line: [warning: MPC header version 1.0.2 differs from library version 1.1.0.] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/8/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (GCC) version 8.4.1 20200928 (Red Hat 8.4.1-1) (x86_64-redhat-linux)] + ignore line: [ compiled by GNU C version 8.4.1 20200928 (Red Hat 8.4.1-1) GMP version 6.1.2 MPFR version 3.1.6-p2 MPC version 1.0.2 isl version isl-0.16.1-GMP] + ignore line: [] + ignore line: [warning: MPC header version 1.0.2 differs from library version 1.1.0.] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: b52810184d801135c3a3dd4ab4785304] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccT60iIG.s] + ignore line: [GNU assembler version 2.30 (x86_64-redhat-linux) using BFD version version 2.30-93.el8] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking CXX executable cmTC_bce9b] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_bce9b.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_bce9b ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) ] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bce9b' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/libexec/gcc/x86_64-redhat-linux/8/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccMOKZ64.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_bce9b /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../.. CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/8/crtend.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o] + arg [/usr/libexec/gcc/x86_64-redhat-linux/8/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccMOKZ64.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--no-add-needed] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-o] ==> ignore + arg [cmTC_bce9b] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] + arg [-L/lib/../lib64] ==> dir [/lib/../lib64] + arg [-L/usr/lib/../lib64] ==> dir [/usr/lib/../lib64] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/8/../../..] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../..] + arg [CMakeFiles/cmTC_bce9b.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-redhat-linux/8/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o] ==> ignore + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8] ==> [/usr/lib/gcc/x86_64-redhat-linux/8] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64] ==> [/usr/lib64] + collapse library dir [/lib/../lib64] ==> [/lib64] + collapse library dir [/usr/lib/../lib64] ==> [/usr/lib64] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/8/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit dirs: [/usr/lib/gcc/x86_64-redhat-linux/8;/usr/lib64;/lib64;/usr/lib] + implicit fwks: [] + + diff --git a/lib/nodes/go/test/build/CMakeFiles/CMakeRuleHashes.txt b/lib/nodes/go/test/build/CMakeFiles/CMakeRuleHashes.txt new file mode 100644 index 000000000..859133061 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/CMakeRuleHashes.txt @@ -0,0 +1,3 @@ +# Hashes of file build rules. +e95f75a28652e6ca21e4beba0a9f3dc4 go/CMakeFiles/shim_go +fa0c0014583ef68ee4d523d5a4786b76 go/test.so diff --git a/lib/nodes/go/test/build/CMakeFiles/Makefile.cmake b/lib/nodes/go/test/build/CMakeFiles/Makefile.cmake new file mode 100644 index 000000000..3cd514faf --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,124 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.18.2/CMakeCCompiler.cmake" + "CMakeFiles/3.18.2/CMakeCXXCompiler.cmake" + "CMakeFiles/3.18.2/CMakeSystem.cmake" + "../go/CMakeLists.txt" + "/usr/share/cmake/Modules/CMakeCCompiler.cmake.in" + "/usr/share/cmake/Modules/CMakeCCompilerABI.c" + "/usr/share/cmake/Modules/CMakeCInformation.cmake" + "/usr/share/cmake/Modules/CMakeCXXCompiler.cmake.in" + "/usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp" + "/usr/share/cmake/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake" + "/usr/share/cmake/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake/Modules/CMakeCompilerIdDetection.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCCompiler.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCXXCompiler.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCompileFeatures.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCompiler.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCompilerABI.cmake" + "/usr/share/cmake/Modules/CMakeDetermineCompilerId.cmake" + "/usr/share/cmake/Modules/CMakeDetermineSystem.cmake" + "/usr/share/cmake/Modules/CMakeFindBinUtils.cmake" + "/usr/share/cmake/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake/Modules/CMakeInitializeConfigs.cmake" + "/usr/share/cmake/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake" + "/usr/share/cmake/Modules/CMakeParseImplicitLinkInfo.cmake" + "/usr/share/cmake/Modules/CMakeSystem.cmake.in" + "/usr/share/cmake/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake/Modules/CMakeTestCCompiler.cmake" + "/usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake" + "/usr/share/cmake/Modules/CMakeTestCompilerCommon.cmake" + "/usr/share/cmake/Modules/CMakeUnixFindMake.cmake" + "/usr/share/cmake/Modules/Compiler/ADSP-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Borland-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/share/cmake/Modules/Compiler/Clang-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + "/usr/share/cmake/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Cray-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/GHS-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake/Modules/Compiler/GNU-FindBinUtils.cmake" + "/usr/share/cmake/Modules/Compiler/GNU.cmake" + "/usr/share/cmake/Modules/Compiler/HP-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/IAR-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + "/usr/share/cmake/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + "/usr/share/cmake/Modules/Compiler/Intel-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/MIPSpro-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/MSVC-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/PGI-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/PathScale-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/SCO-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/TI-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/Watcom-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/XL-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" + "/usr/share/cmake/Modules/Internal/CMakeCheckCompilerFlag.cmake" + "/usr/share/cmake/Modules/Internal/FeatureTesting.cmake" + "/usr/share/cmake/Modules/Platform/Linux-Determine-CXX.cmake" + "/usr/share/cmake/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake/Modules/Platform/Linux.cmake" + "/usr/share/cmake/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/3.18.2/CMakeSystem.cmake" + "CMakeFiles/3.18.2/CMakeCCompiler.cmake" + "CMakeFiles/3.18.2/CMakeCXXCompiler.cmake" + "CMakeFiles/3.18.2/CMakeCCompiler.cmake" + "CMakeFiles/3.18.2/CMakeCXXCompiler.cmake" + "CMakeFiles/CMakeDirectoryInformation.cmake" + "go/CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/test.dir/DependInfo.cmake" + "go/CMakeFiles/shim_go.dir/DependInfo.cmake" + ) diff --git a/lib/nodes/go/test/build/CMakeFiles/Makefile2 b/lib/nodes/go/test/build/CMakeFiles/Makefile2 new file mode 100644 index 000000000..6b4a4d957 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/Makefile2 @@ -0,0 +1,172 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /global/projects/villas/node/lib/nodes/go/test + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /global/projects/villas/node/lib/nodes/go/test/build + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/test.dir/all +all: go/all + +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: go/preinstall + +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/test.dir/clean +clean: go/clean + +.PHONY : clean + +#============================================================================= +# Directory level rules for directory go + +# Recursive "all" directory target. +go/all: + +.PHONY : go/all + +# Recursive "preinstall" directory target. +go/preinstall: + +.PHONY : go/preinstall + +# Recursive "clean" directory target. +go/clean: go/CMakeFiles/shim_go.dir/clean + +.PHONY : go/clean + +#============================================================================= +# Target rules for target CMakeFiles/test.dir + +# All Build rule for target. +CMakeFiles/test.dir/all: go/CMakeFiles/shim_go.dir/all + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles --progress-num=2,3 "Built target test" +.PHONY : CMakeFiles/test.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/test.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 3 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/test.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 0 +.PHONY : CMakeFiles/test.dir/rule + +# Convenience name for target. +test: CMakeFiles/test.dir/rule + +.PHONY : test + +# clean rule for target. +CMakeFiles/test.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/clean +.PHONY : CMakeFiles/test.dir/clean + +#============================================================================= +# Target rules for target go/CMakeFiles/shim_go.dir + +# All Build rule for target. +go/CMakeFiles/shim_go.dir/all: + $(MAKE) $(MAKESILENT) -f go/CMakeFiles/shim_go.dir/build.make go/CMakeFiles/shim_go.dir/depend + $(MAKE) $(MAKESILENT) -f go/CMakeFiles/shim_go.dir/build.make go/CMakeFiles/shim_go.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles --progress-num=1 "Built target shim_go" +.PHONY : go/CMakeFiles/shim_go.dir/all + +# Build rule for subdir invocation for target. +go/CMakeFiles/shim_go.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 1 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/CMakeFiles/shim_go.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 0 +.PHONY : go/CMakeFiles/shim_go.dir/rule + +# Convenience name for target. +shim_go: go/CMakeFiles/shim_go.dir/rule + +.PHONY : shim_go + +# clean rule for target. +go/CMakeFiles/shim_go.dir/clean: + $(MAKE) $(MAKESILENT) -f go/CMakeFiles/shim_go.dir/build.make go/CMakeFiles/shim_go.dir/clean +.PHONY : go/CMakeFiles/shim_go.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/lib/nodes/go/test/build/CMakeFiles/TargetDirectories.txt b/lib/nodes/go/test/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 000000000..db3796e52 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,6 @@ +/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/rebuild_cache.dir +/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/test.dir +/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/edit_cache.dir +/global/projects/villas/node/lib/nodes/go/test/build/go/CMakeFiles/rebuild_cache.dir +/global/projects/villas/node/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir +/global/projects/villas/node/lib/nodes/go/test/build/go/CMakeFiles/edit_cache.dir diff --git a/lib/nodes/go/test/build/CMakeFiles/cmake.check_cache b/lib/nodes/go/test/build/CMakeFiles/cmake.check_cache new file mode 100644 index 000000000..3dccd7317 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/lib/nodes/go/test/build/CMakeFiles/progress.marks b/lib/nodes/go/test/build/CMakeFiles/progress.marks new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +3 diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/C.includecache b/lib/nodes/go/test/build/CMakeFiles/test.dir/C.includecache new file mode 100644 index 000000000..304e5e2f9 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/C.includecache @@ -0,0 +1,18 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/global/projects/villas/node/lib/nodes/go/test/test.c +stdio.h +- +test.h +/global/projects/villas/node/lib/nodes/go/test/test.h + +go/test.h +stddef.h +- + diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/DependInfo.cmake b/lib/nodes/go/test/build/CMakeFiles/test.dir/DependInfo.cmake new file mode 100644 index 000000000..33c31d609 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/DependInfo.cmake @@ -0,0 +1,21 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/global/projects/villas/node/lib/nodes/go/test/test.c" "/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/test.dir/test.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "go" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/build.make b/lib/nodes/go/test/build/CMakeFiles/test.dir/build.make new file mode 100644 index 000000000..e7d58c6d4 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/build.make @@ -0,0 +1,118 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /global/projects/villas/node/lib/nodes/go/test + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /global/projects/villas/node/lib/nodes/go/test/build + +# Include any dependencies generated for this target. +include CMakeFiles/test.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/test.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/test.dir/flags.make + +CMakeFiles/test.dir/test.c.o: CMakeFiles/test.dir/flags.make +CMakeFiles/test.dir/test.c.o: ../test.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/test.dir/test.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/test.dir/test.c.o -c /global/projects/villas/node/lib/nodes/go/test/test.c + +CMakeFiles/test.dir/test.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/test.dir/test.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /global/projects/villas/node/lib/nodes/go/test/test.c > CMakeFiles/test.dir/test.c.i + +CMakeFiles/test.dir/test.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/test.dir/test.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /global/projects/villas/node/lib/nodes/go/test/test.c -o CMakeFiles/test.dir/test.c.s + +# Object files for target test +test_OBJECTS = \ +"CMakeFiles/test.dir/test.c.o" + +# External object files for target test +test_EXTERNAL_OBJECTS = + +test: CMakeFiles/test.dir/test.c.o +test: CMakeFiles/test.dir/build.make +test: go/test.so +test: CMakeFiles/test.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable test" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/test.dir/build: test + +.PHONY : CMakeFiles/test.dir/build + +CMakeFiles/test.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/test.dir/cmake_clean.cmake +.PHONY : CMakeFiles/test.dir/clean + +CMakeFiles/test.dir/depend: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /global/projects/villas/node/lib/nodes/go/test /global/projects/villas/node/lib/nodes/go/test /global/projects/villas/node/lib/nodes/go/test/build /global/projects/villas/node/lib/nodes/go/test/build /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles/test.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/test.dir/depend + diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/cmake_clean.cmake b/lib/nodes/go/test/build/CMakeFiles/test.dir/cmake_clean.cmake new file mode 100644 index 000000000..b11d7054e --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/test.dir/test.c.o" + "test" + "test.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/test.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.internal b/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.internal new file mode 100644 index 000000000..5a1200cfa --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.internal @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/test.dir/test.c.o + /global/projects/villas/node/lib/nodes/go/test/test.c + go/test.h diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.make b/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.make new file mode 100644 index 000000000..0c69726bc --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/depend.make @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/test.dir/test.c.o: ../test.c +CMakeFiles/test.dir/test.c.o: go/test.h + diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/flags.make b/lib/nodes/go/test/build/CMakeFiles/test.dir/flags.make new file mode 100644 index 000000000..05235f075 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = + +C_INCLUDES = -isystem /global/projects/villas/node/lib/nodes/go/test/build/go + +C_FLAGS = + diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/link.txt b/lib/nodes/go/test/build/CMakeFiles/test.dir/link.txt new file mode 100644 index 000000000..afd57cd7f --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/cc -rdynamic CMakeFiles/test.dir/test.c.o -o test go/test.so -lpthread diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/progress.make b/lib/nodes/go/test/build/CMakeFiles/test.dir/progress.make new file mode 100644 index 000000000..251317162 --- /dev/null +++ b/lib/nodes/go/test/build/CMakeFiles/test.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 2 +CMAKE_PROGRESS_2 = 3 + diff --git a/lib/nodes/go/test/build/CMakeFiles/test.dir/test.c.o b/lib/nodes/go/test/build/CMakeFiles/test.dir/test.c.o new file mode 100644 index 000000000..ea60da3c3 Binary files /dev/null and b/lib/nodes/go/test/build/CMakeFiles/test.dir/test.c.o differ diff --git a/lib/nodes/go/test/build/Makefile b/lib/nodes/go/test/build/Makefile new file mode 100644 index 000000000..21813ce5f --- /dev/null +++ b/lib/nodes/go/test/build/Makefile @@ -0,0 +1,211 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /global/projects/villas/node/lib/nodes/go/test + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /global/projects/villas/node/lib/nodes/go/test/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles /global/projects/villas/node/lib/nodes/go/test/build//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named test + +# Build rule for target. +test: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 test +.PHONY : test + +# fast build rule for target. +test/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build +.PHONY : test/fast + +#============================================================================= +# Target rules for targets named shim_go + +# Build rule for target. +shim_go: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 shim_go +.PHONY : shim_go + +# fast build rule for target. +shim_go/fast: + $(MAKE) $(MAKESILENT) -f go/CMakeFiles/shim_go.dir/build.make go/CMakeFiles/shim_go.dir/build +.PHONY : shim_go/fast + +test.o: test.c.o + +.PHONY : test.o + +# target to build an object file +test.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/test.c.o +.PHONY : test.c.o + +test.i: test.c.i + +.PHONY : test.i + +# target to preprocess a source file +test.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/test.c.i +.PHONY : test.c.i + +test.s: test.c.s + +.PHONY : test.s + +# target to generate assembly for a file +test.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/test.c.s +.PHONY : test.c.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... shim_go" + @echo "... test" + @echo "... test.o" + @echo "... test.i" + @echo "... test.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/lib/nodes/go/test/build/cmake_install.cmake b/lib/nodes/go/test/build/cmake_install.cmake new file mode 100644 index 000000000..6014c382c --- /dev/null +++ b/lib/nodes/go/test/build/cmake_install.cmake @@ -0,0 +1,60 @@ +# Install script for directory: /global/projects/villas/node/lib/nodes/go/test + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "0") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + include("/global/projects/villas/node/lib/nodes/go/test/build/go/cmake_install.cmake") + +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/global/projects/villas/node/lib/nodes/go/test/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/lib/nodes/go/test/build/go/CMakeFiles/CMakeDirectoryInformation.cmake b/lib/nodes/go/test/build/go/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 000000000..98d218353 --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/global/projects/villas/node/lib/nodes/go/test") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/global/projects/villas/node/lib/nodes/go/test/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/lib/nodes/go/test/build/go/CMakeFiles/progress.marks b/lib/nodes/go/test/build/go/CMakeFiles/progress.marks new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/progress.marks @@ -0,0 +1 @@ +0 diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/DependInfo.cmake b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/DependInfo.cmake new file mode 100644 index 000000000..19fab2149 --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/DependInfo.cmake @@ -0,0 +1,11 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) +# The set of files for implicit dependencies of each language: + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/build.make b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/build.make new file mode 100644 index 000000000..26ca3bca0 --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/build.make @@ -0,0 +1,100 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /global/projects/villas/node/lib/nodes/go/test + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /global/projects/villas/node/lib/nodes/go/test/build + +# Utility rule file for shim_go. + +# Include the progress variables for this target. +include go/CMakeFiles/shim_go.dir/progress.make + +go/CMakeFiles/shim_go: go/test.so + + +go/test.so: ../go/test.go + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building Go library" + cd /global/projects/villas/node/lib/nodes/go/test/go && env GOPATH= go build -buildmode=c-archive -o /global/projects/villas/node/lib/nodes/go/test/build/go/test.so ./... + +shim_go: go/CMakeFiles/shim_go +shim_go: go/test.so +shim_go: go/CMakeFiles/shim_go.dir/build.make + +.PHONY : shim_go + +# Rule to build all files generated by this target. +go/CMakeFiles/shim_go.dir/build: shim_go + +.PHONY : go/CMakeFiles/shim_go.dir/build + +go/CMakeFiles/shim_go.dir/clean: + cd /global/projects/villas/node/lib/nodes/go/test/build/go && $(CMAKE_COMMAND) -P CMakeFiles/shim_go.dir/cmake_clean.cmake +.PHONY : go/CMakeFiles/shim_go.dir/clean + +go/CMakeFiles/shim_go.dir/depend: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /global/projects/villas/node/lib/nodes/go/test /global/projects/villas/node/lib/nodes/go/test/go /global/projects/villas/node/lib/nodes/go/test/build /global/projects/villas/node/lib/nodes/go/test/build/go /global/projects/villas/node/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : go/CMakeFiles/shim_go.dir/depend + diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/cmake_clean.cmake b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/cmake_clean.cmake new file mode 100644 index 000000000..792ddd3db --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/cmake_clean.cmake @@ -0,0 +1,9 @@ +file(REMOVE_RECURSE + "CMakeFiles/shim_go" + "test.so" +) + +# Per-language clean rules from dependency scanning. +foreach(lang ) + include(CMakeFiles/shim_go.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.internal b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.internal new file mode 100644 index 000000000..756f521ce --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.internal @@ -0,0 +1,3 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.make b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.make new file mode 100644 index 000000000..756f521ce --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/depend.make @@ -0,0 +1,3 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + diff --git a/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/progress.make b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/progress.make new file mode 100644 index 000000000..781c7de27 --- /dev/null +++ b/lib/nodes/go/test/build/go/CMakeFiles/shim_go.dir/progress.make @@ -0,0 +1,2 @@ +CMAKE_PROGRESS_1 = 1 + diff --git a/lib/nodes/go/test/build/go/Makefile b/lib/nodes/go/test/build/go/Makefile new file mode 100644 index 000000000..2742263b1 --- /dev/null +++ b/lib/nodes/go/test/build/go/Makefile @@ -0,0 +1,169 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /global/projects/villas/node/lib/nodes/go/test + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /global/projects/villas/node/lib/nodes/go/test/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + cd /global/projects/villas/node/lib/nodes/go/test/build && $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles /global/projects/villas/node/lib/nodes/go/test/build/go//CMakeFiles/progress.marks + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/all + $(CMAKE_COMMAND) -E cmake_progress_start /global/projects/villas/node/lib/nodes/go/test/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +go/CMakeFiles/shim_go.dir/rule: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 go/CMakeFiles/shim_go.dir/rule +.PHONY : go/CMakeFiles/shim_go.dir/rule + +# Convenience name for target. +shim_go: go/CMakeFiles/shim_go.dir/rule + +.PHONY : shim_go + +# fast build rule for target. +shim_go/fast: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(MAKE) $(MAKESILENT) -f go/CMakeFiles/shim_go.dir/build.make go/CMakeFiles/shim_go.dir/build +.PHONY : shim_go/fast + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... shim_go" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /global/projects/villas/node/lib/nodes/go/test/build && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/lib/nodes/go/test/build/go/cmake_install.cmake b/lib/nodes/go/test/build/go/cmake_install.cmake new file mode 100644 index 000000000..d417fb486 --- /dev/null +++ b/lib/nodes/go/test/build/go/cmake_install.cmake @@ -0,0 +1,44 @@ +# Install script for directory: /global/projects/villas/node/lib/nodes/go/test/go + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "0") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + diff --git a/lib/nodes/go/test/build/go/test.h b/lib/nodes/go/test/build/go/test.h new file mode 100644 index 000000000..4c98e5be0 --- /dev/null +++ b/lib/nodes/go/test/build/go/test.h @@ -0,0 +1,82 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package git.rwth-aachen.de/acs/public/villas/node */ + + +#line 1 "cgo-builtin-export-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + +#line 3 "test.go" + + + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern GoInt TestBla(void* ptr); +extern void* NewTest(GoInt number); +extern void* NewTest2(GoInt number); + +#ifdef __cplusplus +} +#endif diff --git a/lib/nodes/go/test/build/go/test.so b/lib/nodes/go/test/build/go/test.so new file mode 100644 index 000000000..0c0516b92 Binary files /dev/null and b/lib/nodes/go/test/build/go/test.so differ diff --git a/lib/nodes/go/test/build/test b/lib/nodes/go/test/build/test new file mode 100755 index 000000000..59ca0f83c Binary files /dev/null and b/lib/nodes/go/test/build/test differ diff --git a/lib/nodes/go/test/go/CMakeLists.txt b/lib/nodes/go/test/go/CMakeLists.txt new file mode 100644 index 000000000..fba2c352e --- /dev/null +++ b/lib/nodes/go/test/go/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.0) +project(test_go) + +set(TARGET shim_go) + +set(SRCS test.go) +set(LIB test.so) + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${LIB} + DEPENDS ${SRCS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND env GOPATH=${GOPATH} go build -buildmode=c-archive + -o "${CMAKE_CURRENT_BINARY_DIR}/${LIB}" + ${CMAKE_GO_FLAGS} ./... + COMMENT "Building Go library") + +add_custom_target(${TARGET} DEPENDS ${LIB} ${HEADER}) +add_library(goshim STATIC IMPORTED GLOBAL) +add_dependencies(goshim ${TARGET}) +set_target_properties(goshim + PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${LIB} + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/lib/nodes/go/test/go/go.mod b/lib/nodes/go/test/go/go.mod new file mode 100644 index 000000000..238543b62 --- /dev/null +++ b/lib/nodes/go/test/go/go.mod @@ -0,0 +1,5 @@ +module git.rwth-aachen.de/acs/public/villas/node + +go 1.16 + +require github.com/mattn/go-pointer v0.0.1 // indirect diff --git a/lib/nodes/go/test/go/go.sum b/lib/nodes/go/test/go/go.sum new file mode 100644 index 000000000..1fdefeab4 --- /dev/null +++ b/lib/nodes/go/test/go/go.sum @@ -0,0 +1,2 @@ +github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= +github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= diff --git a/lib/nodes/go/test/go/test.go b/lib/nodes/go/test/go/test.go new file mode 100644 index 000000000..7502e586a --- /dev/null +++ b/lib/nodes/go/test/go/test.go @@ -0,0 +1,76 @@ +package main + +/* + + */ +import "C" +import ( + "fmt" + "unsafe" + + gopointer "github.com/mattn/go-pointer" +) + +type Bla interface { + Bla() int +} + +type Test struct { + Number int +} + +type Test2 struct { + Number int +} + +type TestPtr unsafe.Pointer + +func (t *Test) Bla() int { + fmt.Printf("Hello World: %d\n", t.Number) + + t.Number++ + + return t.Number +} + +func (t *Test2) Bla() int { + fmt.Printf("Hello World: %d\n", t.Number) + + t.Number++ + t.Number++ + + return t.Number +} + +//export TestBla +func TestBla(ptr unsafe.Pointer) int { + t := gopointer.Restore(ptr).(Bla) + return t.Bla() +} + +//export NewTest +func NewTest(number int) unsafe.Pointer { + t := &Test{ + Number: number, + } + + ptr := gopointer.Save(t) + + return ptr +} + +//export NewTest2 +func NewTest2(number int) unsafe.Pointer { + t := &Test2{ + Number: number, + } + + ptr := gopointer.Save(t) + + return ptr +} + +func main() { + // We need the main function to make possible + // CGO compiler to compile the package as C shared library +} diff --git a/lib/nodes/go/test/test.c b/lib/nodes/go/test/test.c new file mode 100644 index 000000000..78889f0a2 --- /dev/null +++ b/lib/nodes/go/test/test.c @@ -0,0 +1,14 @@ +#include + +#include "test.h" + +int main() { + void *ptr = NewTest2(55); + + TestBla(ptr); + TestBla(ptr); + TestBla(ptr); + int r = TestBla(ptr); + + printf("final %d\n", r); +} diff --git a/lib/nodes/go/types.go b/lib/nodes/go/types.go new file mode 100644 index 000000000..2b4023a62 --- /dev/null +++ b/lib/nodes/go/types.go @@ -0,0 +1 @@ +package node diff --git a/lib/nodes/iec61850.cpp b/lib/nodes/iec61850.cpp index c287526c4..bf7c0075d 100644 --- a/lib/nodes/iec61850.cpp +++ b/lib/nodes/iec61850.cpp @@ -1,7 +1,7 @@ /** Node type: IEC 61850-9-2 (Sampled Values) * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,9 +24,9 @@ #include #include -#include +#include #include -#include +#include #include #include @@ -64,12 +64,13 @@ const struct iec61850_type_descriptor type_descriptors[] = { }; /** Each network interface needs a separate receiver */ -static struct vlist receivers; +static struct List receivers; static pthread_t thread; static EthernetHandleSet hset; static int users = 0; -static void * iec61850_thread(void *ctx) +static +void * iec61850_thread(void *ctx) { int ret; @@ -78,8 +79,8 @@ static void * iec61850_thread(void *ctx) if (ret < 0) continue; - for (unsigned i = 0; i < vlist_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) vlist_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; @@ -91,7 +92,7 @@ static void * iec61850_thread(void *ctx) return nullptr; } -const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name) +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)) @@ -101,15 +102,14 @@ const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name) return nullptr; } -int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct vlist *node_signals) +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; - struct signal *sig; json_error_t err; - ret = vlist_init(signals); + ret = list_init(signals); if (ret) return ret; @@ -126,7 +126,7 @@ int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct v if (!node_signals) return -1; - sig = (struct signal *) vlist_at(node_signals, i); + auto sig = node_signals->getByIndex(i); if (!sig) return -1; @@ -152,7 +152,7 @@ int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct v if (!td) return -1; - vlist_push(signals, (void *) td); + list_push(signals, (void *) td); total_size += td->size; } @@ -166,8 +166,8 @@ int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct v if (!td) return -1; - for (unsigned i = 0; i < vlist_length(node_signals); i++) { - vlist_push(signals, (void *) td); + for (unsigned i = 0; i < node_signals->size(); i++) { + list_push(signals, (void *) td); total_size += td->size; } @@ -176,7 +176,7 @@ int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct v return total_size; } -int iec61850_type_start(villas::node::SuperNode *sn) +int villas::node::iec61850_type_start(villas::node::SuperNode *sn) { int ret; @@ -184,7 +184,7 @@ int iec61850_type_start(villas::node::SuperNode *sn) if (users > 0) return 0; - ret = vlist_init(&receivers); + ret = list_init(&receivers); if (ret) return ret; @@ -197,15 +197,15 @@ int iec61850_type_start(villas::node::SuperNode *sn) return 0; } -int iec61850_type_stop() +int villas::node::iec61850_type_stop() { int ret; if (--users > 0) return 0; - for (unsigned i = 0; i < vlist_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) vlist_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); } @@ -220,14 +220,14 @@ int iec61850_type_stop() EthernetHandleSet_destroy(hset); - ret = vlist_destroy(&receivers, (dtor_cb_t) iec61850_receiver_destroy, true); + ret = list_destroy(&receivers, (dtor_cb_t) iec61850_receiver_destroy, true); if (ret) return ret; return 0; } -int iec61850_receiver_start(struct iec61850_receiver *r) +int villas::node::iec61850_receiver_start(struct iec61850_receiver *r) { switch (r->type) { case iec61850_receiver::Type::GOOSE: @@ -244,7 +244,7 @@ int iec61850_receiver_start(struct iec61850_receiver *r) return 0; } -int iec61850_receiver_stop(struct iec61850_receiver *r) +int villas::node::iec61850_receiver_stop(struct iec61850_receiver *r) { EthernetHandleSet_removeSocket(hset, r->socket); @@ -261,7 +261,7 @@ int iec61850_receiver_stop(struct iec61850_receiver *r) return 0; } -int iec61850_receiver_destroy(struct iec61850_receiver *r) +int villas::node::iec61850_receiver_destroy(struct iec61850_receiver *r) { switch (r->type) { case iec61850_receiver::Type::GOOSE: @@ -278,10 +278,10 @@ int iec61850_receiver_destroy(struct iec61850_receiver *r) return 0; } -struct iec61850_receiver * iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf) +struct iec61850_receiver * villas::node::iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf) { - for (unsigned i = 0; i < vlist_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) vlist_at(&receivers, i); + 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; @@ -290,7 +290,7 @@ struct iec61850_receiver * iec61850_receiver_lookup(enum iec61850_receiver::Type return nullptr; } -struct iec61850_receiver * iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf) +struct iec61850_receiver * villas::node::iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf) { struct iec61850_receiver *r; @@ -318,7 +318,7 @@ struct iec61850_receiver * iec61850_receiver_create(enum iec61850_receiver::Type iec61850_receiver_start(r); - vlist_push(&receivers, r); + list_push(&receivers, r); } return r; diff --git a/lib/nodes/iec61850_sv.cpp b/lib/nodes/iec61850_sv.cpp index a854f8182..ca6a44b99 100644 --- a/lib/nodes/iec61850_sv.cpp +++ b/lib/nodes/iec61850_sv.cpp @@ -1,7 +1,7 @@ /** Node type: IEC 61850-9-2 (Sampled Values) * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,6 +25,8 @@ #include #include +#include +#include #include #define CONFIG_SV_DEFAULT_APPID 0x4000 @@ -36,11 +38,12 @@ using namespace villas; using namespace villas::utils; using namespace villas::node; -static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU asdu) +static +void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU asdu) { - struct vnode *n = (struct vnode *) ctx; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; - struct sample *smp; + auto *n = (NodeCompat *) ctx; + auto *i = n->getData(); + struct Sample *smp; const char* svid = SVSubscriber_ASDU_getSvId(asdu); int smpcnt = SVSubscriber_ASDU_getSmpCnt(asdu); @@ -74,7 +77,7 @@ static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscribe smp->sequence = smpcnt; smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; smp->length = 0; - smp->signals = &n->in.signals; + smp->signals = n->getInputSignals(false); if (SVSubscriber_ASDU_hasRefrTm(asdu)) { uint64_t refrtm = SVSubscriber_ASDU_getRefrTmAsMs(asdu); @@ -85,9 +88,9 @@ static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscribe } unsigned offset = 0; - for (size_t j = 0; j < vlist_length(&i->in.signals); j++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) vlist_at(&i->in.signals, j); - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, j); + 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; @@ -136,10 +139,10 @@ static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscribe pushed = queue_signalled_push(&i->in.queue, smp); } -int iec61850_sv_parse(struct vnode *n, json_t *json) +int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) { int ret; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + auto *i = n->getData(); const char *dst_address = nullptr; const char *interface = nullptr; @@ -215,7 +218,7 @@ int iec61850_sv_parse(struct vnode *n, json_t *json) i->out.svid = svid ? strdup(svid) : nullptr; - ret = iec61850_parse_signals(json_signals, &i->out.signals, &n->out.signals); + ret = iec61850_parse_signals(json_signals, &i->out.signals, n->getOutputSignals()); if (ret <= 0) throw RuntimeError("Failed to parse setting 'signals'"); @@ -232,7 +235,7 @@ int iec61850_sv_parse(struct vnode *n, json_t *json) if (ret) throw ConfigError(json_in, err, "node-config-node-iec61850-in"); - ret = iec61850_parse_signals(json_signals, &i->in.signals, &n->in.signals); + ret = iec61850_parse_signals(json_signals, &i->in.signals, n->getInputSignals(false)); if (ret <= 0) throw RuntimeError("Failed to parse setting 'signals'"); @@ -242,10 +245,10 @@ int iec61850_sv_parse(struct vnode *n, json_t *json) return 0; } -char * iec61850_sv_print(struct vnode *n) +char * villas::node::iec61850_sv_print(NodeCompat *n) { char *buf; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + auto *i = n->getData(); buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, i->app_id, ether_ntoa(&i->dst_address)); @@ -256,29 +259,29 @@ char * iec61850_sv_print(struct vnode *n) i->out.vlan_priority, i->out.vlan_id, i->out.confrev, - vlist_length(&i->out.signals) + n->getOutputSignals()->size() ); } /* Subscriber part */ if (i->in.enabled) - strcatf(&buf, ", sub.#fields=%zu", vlist_length(&i->in.signals)); + strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); return buf; } -int iec61850_sv_start(struct vnode *n) +int villas::node::iec61850_sv_start(NodeCompat *n) { int ret; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + 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, node_name_short(n), i->out.confrev); + i->out.asdu = SVPublisher_addASDU(i->out.publisher, i->out.svid, n->getNameShort().c_str(), i->out.confrev); - for (unsigned k = 0; k < vlist_length(&i->out.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) vlist_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: @@ -327,7 +330,7 @@ int iec61850_sv_start(struct vnode *n) 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(vlist_length(&n->in.signals))); + ret = pool_init(&i->in.pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); if (ret) return ret; @@ -335,9 +338,9 @@ int iec61850_sv_start(struct vnode *n) if (ret) return ret; - for (unsigned k = 0; k < vlist_length(&i->in.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) vlist_at(&i->in.signals, k); - struct signal *sig = (struct signal *) vlist_at(&n->in.signals, 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; @@ -349,20 +352,25 @@ int iec61850_sv_start(struct vnode *n) return 0; } -int iec61850_sv_stop(struct vnode *n) +int villas::node::iec61850_sv_stop(NodeCompat *n) { - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + int ret; + auto *i = n->getData(); if (i->in.enabled) SVReceiver_removeSubscriber(i->in.receiver, i->in.subscriber); + ret = queue_signalled_close(&i->in.queue); + if (ret) + return ret; + return 0; } -int iec61850_sv_destroy(struct vnode *n) +int villas::node::iec61850_sv_destroy(NodeCompat *n) { int ret; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + auto *i = n->getData(); /* Deinitialize publisher */ if (i->out.enabled && i->out.publisher) @@ -382,11 +390,11 @@ int iec61850_sv_destroy(struct vnode *n) return 0; } -int iec61850_sv_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int pulled; - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; - struct sample *smpt[cnt]; + auto *i = n->getData(); + struct Sample *smpt[cnt]; if (!i->in.enabled) return -1; @@ -399,17 +407,17 @@ int iec61850_sv_read(struct vnode *n, struct sample * const smps[], unsigned cnt return pulled; } -int iec61850_sv_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + auto *i = n->getData(); 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, vlist_length(&i->out.signals)); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) vlist_at(&i->out.signals, k); + 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; @@ -465,16 +473,16 @@ int iec61850_sv_write(struct vnode *n, struct sample * const smps[], unsigned cn return cnt; } -int iec61850_sv_poll_fds(struct vnode *n, int fds[]) +int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) { - struct iec61850_sv *i = (struct iec61850_sv *) n->_vd; + auto *i = n->getData(); fds[0] = queue_signalled_fd(&i->in.queue); return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -493,8 +501,5 @@ static void register_plugin() { p.write = iec61850_sv_write; p.poll_fds = iec61850_sv_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index 4d7952af6..84162e0ea 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -1,7 +1,7 @@ /** Node type: infiniband * * @author Dennis Potter - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,22 +25,23 @@ #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(struct vnode *n) +static +int ib_disconnect(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); struct ibv_wc wc[MAX(ib->recv_cq_size, ib->send_cq_size)]; int wcs; @@ -55,14 +56,14 @@ static int ib_disconnect(struct vnode *n) ib->conn.available_recv_wrs -= wcs; for (int j = 0; j < wcs; j++) - sample_decref((struct sample *) (intptr_t) (wc[j].wr_id)); + 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)); + sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); /* Destroy QP */ rdma_destroy_qp(ib->ctx.id); @@ -72,9 +73,10 @@ static int ib_disconnect(struct vnode *n) return ib->stopThreads; } -static void ib_build_ibv(struct vnode *n) +static +void ib_build_ibv(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; n->logger->debug("Starting to build IBV components"); @@ -108,9 +110,10 @@ static void ib_build_ibv(struct vnode *n) n->logger->info("Maximum inline size is set to {} byte", ib->qp_init.cap.max_inline_data); } -static int ib_addr_resolved(struct vnode *n) +static +int ib_addr_resolved(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; n->logger->debug("Successfully resolved address"); @@ -126,9 +129,10 @@ static int ib_addr_resolved(struct vnode *n) return 0; } -static int ib_route_resolved(struct vnode *n) +static +int ib_route_resolved(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; struct rdma_conn_param cm_params; @@ -144,9 +148,10 @@ static int ib_route_resolved(struct vnode *n) return 0; } -static int ib_connect_request(struct vnode *n, struct rdma_cm_id *id) +static +int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; n->logger->debug("Received a connection request!"); @@ -167,18 +172,18 @@ static int ib_connect_request(struct vnode *n, struct rdma_cm_id *id) return 0; } -int ib_reverse(struct vnode *n) +int villas::node::ib_reverse(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); SWAP(ib->conn.src_addr, ib->conn.dst_addr); return 0; } -int ib_parse(struct vnode *n, json_t *json) +int villas::node::ib_parse(NodeCompat *n, json_t *json) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); throw ConfigError(json, "The infiniband node-type is currently broken!"); @@ -346,9 +351,9 @@ int ib_parse(struct vnode *n, json_t *json) return 0; } -int ib_check(struct vnode *n) +int villas::node::ib_check(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); /* Check if read substraction makes sense */ if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) @@ -397,19 +402,20 @@ int ib_check(struct vnode *n) return 0; } -char * ib_print(struct vnode *n) +char * villas::node::ib_print(NodeCompat *n) { return 0; } -int ib_destroy(struct vnode *n) +int villas::node::ib_destroy(NodeCompat *n) { return 0; } -static void ib_create_bind_id(struct vnode *n) +static +void ib_create_bind_id(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; /* Create rdma_cm_id @@ -467,9 +473,10 @@ static void ib_create_bind_id(struct vnode *n) ib->ctx.listen_id = ib->ctx.id; } -static void ib_continue_as_listen(struct vnode *n, struct rdma_cm_event *event) +static +void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; if (ib->conn.use_fallback) @@ -478,7 +485,7 @@ static void ib_continue_as_listen(struct vnode *n, struct rdma_cm_event *event) 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->state = State::STARTED; + n->setState(State::STARTED); /* Acknowledge event */ rdma_ack_cm_event(event); @@ -500,17 +507,18 @@ static void ib_continue_as_listen(struct vnode *n, struct rdma_cm_event *event) n->logger->info("Use listening mode"); } +static void * ib_rdma_cm_event_thread(void *ctx) { - struct vnode *n = (struct vnode *) ctx; - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *n = (NodeCompat *) ctx; + auto *ib = n->getData(); struct rdma_cm_event *event; int ret = 0; n->logger->debug("Started rdma_cm_event thread"); /* Wait until node is completely started */ - while (n->state != State::STARTED); + while (n->getState() != State::STARTED); /* Monitor event channel */ while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { @@ -553,9 +561,9 @@ void * ib_rdma_cm_event_thread(void *ctx) * with rdma_connect. */ if (ib->conn.port_space == RDMA_PS_UDP && !ib->is_source) - n->state = State::CONNECTED; + n->setState(State::CONNECTED); else - n->state = State::PENDING_CONNECT; + n->setState(State::PENDING_CONNECT); break; @@ -580,14 +588,14 @@ void * ib_rdma_cm_event_thread(void *ctx) ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); } - n->state = State::CONNECTED; + n->setState(State::CONNECTED); n->logger->info("Connection established"); break; case RDMA_CM_EVENT_DISCONNECTED: - n->state = State::STARTED; + n->setState(State::STARTED); ret = ib_disconnect(n); @@ -612,9 +620,9 @@ void * ib_rdma_cm_event_thread(void *ctx) return nullptr; } -int ib_start(struct vnode *n) +int villas::node::ib_start(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; n->logger->debug("Started ib_start"); @@ -676,9 +684,9 @@ int ib_start(struct vnode *n) return 0; } -int ib_stop(struct vnode *n) +int villas::node::ib_stop(NodeCompat *n) { - struct infiniband *ib = (struct infiniband *) n->_vd; + auto *ib = n->getData(); int ret; n->logger->debug("Called ib_stop"); @@ -689,7 +697,7 @@ int ib_stop(struct vnode *n) * Will flush all outstanding WRs to the Completion Queue and * will call RDMA_CM_EVENT_DISCONNECTED if that is done. */ - if (n->state == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { + if (n->getState() == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { ret = rdma_disconnect(ib->ctx.id); if (ret) @@ -729,9 +737,9 @@ int ib_stop(struct vnode *n) return 0; } -int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct infiniband *ib = (struct infiniband *) n->_vd; + 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]; @@ -741,7 +749,7 @@ int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt) n->logger->debug("ib_read is called"); - if (n->state == State::CONNECTED || n->state == State::PENDING_CONNECT) { + if (n->getState() == State::CONNECTED || n->getState() == State::PENDING_CONNECT) { max_wr_post = cnt; @@ -749,13 +757,13 @@ int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt) * 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++) { + 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 * should return immediately if this condition holds */ - if (n->state != State::CONNECTED) return 0; + if (n->getState() != State::CONNECTED) return 0; wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); if (wcs) { @@ -785,7 +793,7 @@ int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } /* Get Memory Region */ - mr = memory_ib_get_mr(pool_buffer(sample_pool(smps[0]))); + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); for (int i = 0; i < max_wr_post; i++) { int j = 0; @@ -860,21 +868,21 @@ int ib_read(struct vnode *n, struct sample * const smps[], unsigned cnt) 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); + // 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->in.signals; + smps[j]->signals = n->getInputSignals(false); } } return read_values; } -int ib_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct infiniband *ib = (struct infiniband *) n->_vd; + 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]; @@ -885,14 +893,14 @@ int ib_write(struct vnode *n, struct sample * const smps[], unsigned cnt) n->logger->debug("ib_write is called"); - if (n->state == State::CONNECTED) { + if (n->getState() == State::CONNECTED) { // TODO: fix release logic // *release = 0; /* First, write */ /* Get Memory Region */ - mr = memory_ib_get_mr(pool_buffer(sample_pool(smps[0]))); + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); for (sent = 0; sent < cnt; sent++) { int j = 0; @@ -998,7 +1006,7 @@ int ib_write(struct vnode *n, struct sample * const smps[], unsigned cnt) wc[i].status); // TODO: fix release logic - // smps[*release] = (struct sample *) (wc[i].wr_id); + // smps[*release] = (struct Sample *) (wc[i].wr_id); // (*release)++; } @@ -1009,7 +1017,7 @@ int ib_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return sent; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -1028,10 +1036,7 @@ static void register_plugin() { p.read = ib_read; p.write = ib_write; p.reverse = ib_reverse; - p.memory_type = memory_ib; + p.memory_type = memory::ib; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/influxdb.cpp b/lib/nodes/influxdb.cpp index 8ffc7edb7..8284027d9 100644 --- a/lib/nodes/influxdb.cpp +++ b/lib/nodes/influxdb.cpp @@ -1,7 +1,7 @@ /** Node-type for InfluxDB. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,12 +26,12 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include #include #include @@ -39,9 +39,9 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -int influxdb_parse(struct vnode *n, json_t *json) +int villas::node::influxdb_parse(NodeCompat *n, json_t *json) { - struct influxdb *i = (struct influxdb *) n->_vd; + auto *i = n->getData(); json_error_t err; int ret; @@ -70,10 +70,10 @@ int influxdb_parse(struct vnode *n, json_t *json) return 0; } -int influxdb_open(struct vnode *n) +int villas::node::influxdb_open(NodeCompat *n) { int ret; - struct influxdb *i = (struct influxdb *) n->_vd; + auto *i = n->getData(); struct addrinfo hints, *servinfo, *p; @@ -105,9 +105,9 @@ int influxdb_open(struct vnode *n) return p ? 0 : -1; } -int influxdb_close(struct vnode *n) +int villas::node::influxdb_close(NodeCompat *n) { - struct influxdb *i = (struct influxdb *) n->_vd; + auto *i = n->getData(); close(i->sd); @@ -121,23 +121,25 @@ int influxdb_close(struct vnode *n) return 0; } -int influxdb_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct influxdb *i = (struct influxdb *) n->_vd; + auto *i = n->getData(); + + char *buf = strf(""); ssize_t sentlen, buflen; - auto *buf = strf(""); - for (unsigned k = 0; k < cnt; k++) { - const struct sample *smp = smps[k]; + const struct Sample *smp = smps[k]; /* Key */ strcatf(&buf, "%s", i->key); /* Fields */ for (unsigned j = 0; j < smp->length; j++) { - struct signal *sig = (struct signal *) vlist_at(smp->signals, j); - const union signal_data *data = &smp->data[j]; + const auto *data = &smp->data[j]; + auto sig = smp->signals->getByIndex(j); + if (!sig) + return -1; if ( sig->type != SignalType::BOOLEAN && @@ -150,25 +152,14 @@ int influxdb_write(struct vnode *n, struct sample * const smps[], unsigned cnt) } strcatf(&buf, "%c", j == 0 ? ' ' : ','); - - sig = (struct signal *) vlist_at(smp->signals, j); - if (!sig) - return -1; - - char name[32]; - if (sig->name) - strncpy(name, sig->name, sizeof(name)-1); - else - snprintf(name, sizeof(name), "value%u", j); - if (sig->type == SignalType::COMPLEX) { strcatf(&buf, "%s_re=%f, %s_im=%f", - name, std::real(data->z), - name, std::imag(data->z) + sig->name.c_str(), std::real(data->z), + sig->name.c_str(), std::imag(data->z) ); } else { - strcatf(&buf, "%s=", name); + strcatf(&buf, "%s=", sig->name.c_str()); switch (sig->type) { case SignalType::BOOLEAN: @@ -205,9 +196,9 @@ int influxdb_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -char * influxdb_print(struct vnode *n) +char * villas::node::influxdb_print(NodeCompat *n) { - struct influxdb *i = (struct influxdb *) n->_vd; + auto *i = n->getData(); char *buf = nullptr; strcatf(&buf, "host=%s, port=%s, key=%s", i->host, i->port, i->key); @@ -215,7 +206,7 @@ char * influxdb_print(struct vnode *n) return buf; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -229,8 +220,5 @@ static void register_plugin() { p.stop = influxdb_close; p.write = influxdb_write; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/kafka.cpp b/lib/nodes/kafka.cpp index 1edadc42c..cd8950797 100644 --- a/lib/nodes/kafka.cpp +++ b/lib/nodes/kafka.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -34,11 +34,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 vlist clients; +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) { @@ -65,12 +66,13 @@ static void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, co } } -static void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) +static +void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) { int ret; - struct vnode *n = (struct vnode *) ctx; - struct kafka *k = (struct kafka *) n->_vd; - struct sample *smps[n->in.vectorize]; + 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); @@ -98,7 +100,8 @@ static void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) n->logger->warn("Failed to enqueue samples"); } -static void * kafka_loop_thread(void *ctx) +static +void * kafka_loop_thread(void *ctx) { int ret; @@ -108,9 +111,9 @@ static void * kafka_loop_thread(void *ctx) throw RuntimeError("Unable to set cancel type of Kafka communication thread to asynchronous."); while (true) { - for (unsigned i = 0; i < vlist_length(&clients); i++) { - struct vnode *n = (struct vnode *) vlist_at(&clients, i); - struct kafka *k = (struct kafka *) n->_vd; + 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) { @@ -126,19 +129,18 @@ static void * kafka_loop_thread(void *ctx) return nullptr; } -int kafka_reverse(struct vnode *n) +int villas::node::kafka_reverse(NodeCompat *n) { - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); SWAP(k->produce, k->consume); return 0; } -int kafka_init(struct vnode *n) +int villas::node::kafka_init(NodeCompat *n) { - int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); /* Default values */ k->server = nullptr; @@ -159,15 +161,15 @@ int kafka_init(struct vnode *n) k->ssl.ca = nullptr; - ret = 0; + k->formatter = nullptr; - return ret; + return 0; } -int kafka_parse(struct vnode *n, json_t *json) +int villas::node::kafka_parse(NodeCompat *n, json_t *json) { int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); const char *server; const char *produce = nullptr; @@ -245,22 +247,25 @@ int kafka_parse(struct vnode *n, json_t *json) } /* 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; } -int kafka_prepare(struct vnode *n) +int villas::node::kafka_prepare(NodeCompat *n) { int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); - k->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + k->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); - ret = pool_init(&k->pool, 1024, SAMPLE_LENGTH(vlist_length(&n->in.signals))); + ret = pool_init(&k->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); if (ret) return ret; @@ -271,9 +276,9 @@ int kafka_prepare(struct vnode *n) return 0; } -char * kafka_print(struct vnode *n) +char * villas::node::kafka_print(NodeCompat *n) { - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); char *buf = nullptr; @@ -293,10 +298,10 @@ char * kafka_print(struct vnode *n) return buf; } -int kafka_destroy(struct vnode *n) +int villas::node::kafka_destroy(NodeCompat *n) { int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); if (k->producer.client) rd_kafka_destroy(k->producer.client); @@ -304,7 +309,8 @@ int kafka_destroy(struct vnode *n) if (k->consumer.client) rd_kafka_destroy(k->consumer.client); - delete k->formatter; + if (k->formatter) + delete k->formatter; ret = pool_destroy(&k->pool); if (ret) @@ -331,11 +337,11 @@ int kafka_destroy(struct vnode *n) return 0; } -int kafka_start(struct vnode *n) +int villas::node::kafka_start(NodeCompat *n) { int ret; char errstr[1024]; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); rd_kafka_conf_t *rdkconf = rd_kafka_conf_new(); if (!rdkconf) @@ -433,7 +439,7 @@ int kafka_start(struct vnode *n) // Add client to global list of kafka clients // so that thread can call kafka loop for this client - vlist_push(&clients, n); + list_push(&clients, n); rd_kafka_conf_destroy(rdkconf); @@ -447,10 +453,10 @@ kafka_config_error: return -1; } -int kafka_stop(struct vnode *n) +int villas::node::kafka_stop(NodeCompat *n) { int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); if (k->producer.client) { ret = rd_kafka_flush(k->producer.client, k->timeout * 1000); @@ -466,18 +472,22 @@ int kafka_stop(struct vnode *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 - vlist_remove_all(&clients, n); + list_remove_all(&clients, n); + + ret = queue_signalled_close(&k->queue); + if (ret) + return ret; return 0; } -int kafka_type_start(villas::node::SuperNode *sn) +int villas::node::kafka_type_start(villas::node::SuperNode *sn) { int ret; logger = logging.get("node:kafka"); - ret = vlist_init(&clients); + ret = list_init(&clients); if (ret) goto kafka_error; @@ -494,7 +504,7 @@ kafka_error: return ret; } -int kafka_type_stop() +int villas::node::kafka_type_stop() { int ret; @@ -510,10 +520,10 @@ int kafka_type_stop() goto kafka_error; // When this is called the list of clients should be empty - if (vlist_length(&clients) > 0) + 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 = vlist_destroy(&clients, nullptr, false); + ret = list_destroy(&clients, nullptr, false); if (ret) goto kafka_error; @@ -525,11 +535,11 @@ kafka_error: return ret; } -int kafka_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int pulled; - struct kafka *k = (struct kafka *) n->_vd; - struct sample *smpt[cnt]; + auto *k = n->getData(); + struct Sample *smpt[cnt]; pulled = queue_signalled_pull_many(&k->queue, (void **) smpt, cnt); @@ -539,10 +549,10 @@ int kafka_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return pulled; } -int kafka_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); size_t wbytes; @@ -567,16 +577,16 @@ int kafka_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int kafka_poll_fds(struct vnode *n, int fds[]) +int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) { - struct kafka *k = (struct kafka *) n->_vd; + auto *k = n->getData(); fds[0] = queue_signalled_fd(&k->queue); return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -600,8 +610,5 @@ static void register_plugin() { p.reverse = kafka_reverse; p.poll_fds = kafka_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/loopback.cpp b/lib/nodes/loopback.cpp index ddb385074..c01f5fe0e 100644 --- a/lib/nodes/loopback.cpp +++ b/lib/nodes/loopback.cpp @@ -1,7 +1,7 @@ /** Node-type for loopback connections. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,39 +22,112 @@ #include -#include -#include +#include +#include #include #include -#include +#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static struct vnode_type p; - -int loopback_init(struct vnode *n) +LoopbackNode::LoopbackNode(const std::string &name) : + Node(name), + queuelen(DEFAULT_QUEUE_LENGTH), + mode(QueueSignalledMode::AUTO) { - struct loopback *l = (struct loopback *) n->_vd; + queue.queue.state = State::DESTROYED; +} - l->mode = QueueSignalledMode::AUTO; - l->queuelen = DEFAULT_QUEUE_LENGTH; +LoopbackNode::~LoopbackNode() +{ + int ret __attribute__((unused)); + + ret = queue_signalled_destroy(&queue); +} + +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"); + + state = State::PREPARED; return 0; } -int loopback_parse(struct vnode *n, json_t *json) +int LoopbackNode::stop() +{ + int ret; + + ret = queue_signalled_close(&queue); + if (ret) + return ret; + + return 0; +} + +int LoopbackNode::_read(struct Sample * smps[], unsigned cnt) +{ + int avail; + + struct Sample *cpys[cnt]; + + avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); + + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); + + return avail; +} + +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; + } + + /* Released unpushed samples */ + if ((unsigned) pushed < cnt) { + sample_decref_many(smps + pushed, cnt - pushed); + logger->warn("Queue overrun"); + } + + return pushed; +} + +std::vector LoopbackNode::getPollFDs() +{ + return { queue_signalled_fd(&queue) }; +} + +const std::string & LoopbackNode::getDetails() +{ + if (details.empty()) { + details = fmt::format("queuelen={}", queuelen); + } + + return details; +} + +int LoopbackNode::parse(json_t *json) { - struct loopback *l = (struct loopback *) n->_vd; const char *mode_str = nullptr; json_error_t err; int ret; ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", - "queuelen", &l->queuelen, + "queuelen", queuelen, "mode", &mode_str ); if (ret) @@ -62,15 +135,15 @@ int loopback_parse(struct vnode *n, json_t *json) if (mode_str) { if (!strcmp(mode_str, "auto")) - l->mode = QueueSignalledMode::AUTO; + mode = QueueSignalledMode::AUTO; #ifdef HAVE_EVENTFD else if (!strcmp(mode_str, "eventfd")) - l->mode = QueueSignalledMode::EVENTFD; + mode = QueueSignalledMode::EVENTFD; #endif else if (!strcmp(mode_str, "pthread")) - l->mode = QueueSignalledMode::PTHREAD; + mode = QueueSignalledMode::PTHREAD; else if (!strcmp(mode_str, "polling")) - l->mode = QueueSignalledMode::POLLING; + mode = QueueSignalledMode::POLLING; #ifdef __APPLE__ else if (!strcmp(mode_str, "pipe")) l->mode = QueueSignalledMode::PIPE; @@ -82,81 +155,8 @@ int loopback_parse(struct vnode *n, json_t *json) return 0; } -int loopback_prepare(struct vnode *n) -{ - struct loopback *l = (struct loopback *) n->_vd; - - return queue_signalled_init(&l->queue, l->queuelen, memory_default, l->mode); -} - -int loopback_destroy(struct vnode *n) -{ - struct loopback *l= (struct loopback *) n->_vd; - - return queue_signalled_destroy(&l->queue); -} - -int loopback_read(struct vnode *n, struct sample * const smps[], unsigned cnt) -{ - int avail; - - struct loopback *l = (struct loopback *) n->_vd; - struct sample *cpys[cnt]; - - avail = queue_signalled_pull_many(&l->queue, (void **) cpys, cnt); - - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); - - return avail; -} - -int loopback_write(struct vnode *n, struct sample * const smps[], unsigned cnt) -{ - struct loopback *l = (struct loopback *) n->_vd; - - sample_incref_many(smps, cnt); - - return queue_signalled_push_many(&l->queue, (void **) smps, cnt); -} - -char * loopback_print(struct vnode *n) -{ - struct loopback *l = (struct loopback *) n->_vd; - char *buf = nullptr; - - strcatf(&buf, "queuelen=%d", l->queuelen); - - return buf; -} - -int loopback_poll_fds(struct vnode *n, int fds[]) -{ - struct loopback *l = (struct loopback *) n->_vd; - - fds[0] = queue_signalled_fd(&l->queue); - - return 1; -} - -__attribute__((constructor(110))) -static void register_plugin() { - p.name = "loopback"; - p.description = "Loopback to connect multiple paths"; - p.vectorize = 0; - p.flags = 0; - p.size = sizeof(struct loopback); - p.parse = loopback_parse; - p.print = loopback_print; - p.prepare = loopback_prepare; - p.init = loopback_init; - p.destroy = loopback_destroy; - p.read = loopback_read; - p.write = loopback_write; - p.poll_fds = loopback_poll_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); -} +static char n[] = "loopback"; +static char d[] = "loopback node-type"; +static NodePlugin nf; diff --git a/lib/nodes/loopback_internal.cpp b/lib/nodes/loopback_internal.cpp index fe0f7a4bb..75d0eb3be 100644 --- a/lib/nodes/loopback_internal.cpp +++ b/lib/nodes/loopback_internal.cpp @@ -1,7 +1,7 @@ /** Node-type for internal loopback_internal connections. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,53 +22,68 @@ #include -#include -#include +#include #include #include -#include +#include +#include +#include using namespace villas; using namespace villas::node; -static struct vnode_type p; +static InternalLoopbackNodeFactory nf; -int loopback_internal_init(struct vnode *n) +InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) : + Node(fmt::format("{}.lo{}", src->getNameShort(), id)), + queuelen(ql), + source(src) { - struct loopback_internal *l = (struct loopback_internal *) n->_vd; + int ret = uuid::generateFromString(uuid, fmt::format("lo{}", id), src->getUuid()); + if (ret) + throw RuntimeError("Failed to initialize UUID"); - l->queuelen = DEFAULT_QUEUE_LENGTH; + factory = &nf; + name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_short, nf.getName()); + + auto logger_name = fmt::format("node:{}", getNameShort()); + + logger = logging.get(logger_name); + + in.signals = source->getInputSignals(false); + + ret = queue_signalled_init(&queue, queuelen); + if (ret) + throw RuntimeError("Failed to initialize queue"); + + state = State::PREPARED; +} + +InternalLoopbackNode::~InternalLoopbackNode() +{ + int ret __attribute__((unused)); + + ret = queue_signalled_destroy(&queue); +} + +int InternalLoopbackNode::stop() +{ + int ret; + + ret = queue_signalled_close(&queue); + if (ret) + return ret; return 0; } -int loopback_internal_prepare(struct vnode *n) -{ - int ret; - struct loopback_internal *l = (struct loopback_internal *) n->_vd; - - ret = signal_list_copy(&n->in.signals, &l->source->in.signals); - if (ret) - return -1; - - return queue_signalled_init(&l->queue, l->queuelen, memory_default, QueueSignalledMode::AUTO); -} - -int loopback_internal_destroy(struct vnode *n) -{ - struct loopback_internal *l= (struct loopback_internal *) n->_vd; - - return queue_signalled_destroy(&l->queue); -} - -int loopback_internal_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int InternalLoopbackNode::_read(struct Sample * smps[], unsigned cnt) { int avail; - struct loopback_internal *l = (struct loopback_internal *) n->_vd; - struct sample *cpys[cnt]; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&l->queue, (void **) cpys, cnt); + avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); sample_copy_many(smps, cpys, avail); sample_decref_many(cpys, avail); @@ -76,63 +91,26 @@ int loopback_internal_read(struct vnode *n, struct sample * const smps[], unsign return avail; } -int loopback_internal_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int InternalLoopbackNode::_write(struct Sample * smps[], unsigned cnt) { - struct loopback_internal *l = (struct loopback_internal *) n->_vd; - sample_incref_many(smps, cnt); - return queue_signalled_push_many(&l->queue, (void **) smps, cnt); + 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"); + } + + return pushed; } -int loopback_internal_poll_fds(struct vnode *n, int fds[]) +std::vector InternalLoopbackNode::getPollFDs() { - struct loopback_internal *l = (struct loopback_internal *) n->_vd; - - fds[0] = queue_signalled_fd(&l->queue); - - return 1; -} - -struct vnode * loopback_internal_create(struct vnode *orig) -{ - int ret; - struct vnode *n; - struct loopback_internal *l; - - n = new struct vnode; - if (!n) - throw MemoryAllocationError(); - - ret = node_init(n, &p); - if (ret) - return nullptr; - - l = (struct loopback_internal *) n->_vd; - - l->source = orig; - - asprintf(&n->name, "%s_lo%zu", node_name_short(orig), vlist_length(&orig->sources)); - - return n; -} - -__attribute__((constructor(110))) -static void register_plugin() { - p.name = "loopback_internal"; - p.description = "internal loopback to connect multiple paths"; - p.vectorize = 0; - p.flags = (int) NodeFlags::PROVIDES_SIGNALS | (int) NodeFlags::INTERNAL; - p.size = sizeof(struct loopback_internal); - p.prepare = loopback_internal_prepare; - p.init = loopback_internal_init; - p.destroy = loopback_internal_destroy; - p.read = loopback_internal_read; - p.write = loopback_internal_write; - p.poll_fds = loopback_internal_poll_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + return { queue_signalled_fd(&queue) }; } diff --git a/lib/nodes/mqtt.cpp b/lib/nodes/mqtt.cpp index 6f166b2ed..9170800f0 100644 --- a/lib/nodes/mqtt.cpp +++ b/lib/nodes/mqtt.cpp @@ -1,7 +1,7 @@ /** Node type: mqtt * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,9 +21,10 @@ *********************************************************************************/ #include +#include #include -#include +#include #include #include #include @@ -33,38 +34,42 @@ using namespace villas::node; using namespace villas::utils; // Each process has a list of clients for which a thread invokes the mosquitto loop -static struct vlist clients; +static std::list clients; +static std::mutex clients_lock; + static pthread_t thread; static Logger logger; -static void * mosquitto_loop_thread(void *ctx) +static +void * mosquitto_loop_thread(void *ctx) { int ret; + auto logger = logging.get("mqtt"); + // 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 MQTT communication thread to asynchronous."); while (true) { - for (unsigned i = 0; i < vlist_length(&clients); i++) { - struct vnode *n = (struct vnode *) vlist_at(&clients, i); - struct mqtt *m = (struct mqtt *) n->_vd; + std::lock_guard guard(clients_lock); + for (auto *client : clients) { // Execute mosquitto loop for this client - ret = mosquitto_loop(m->client, 0, 1); + ret = mosquitto_loop(client, 0, 1); if (ret) { - n->logger->warn("Connection error: {}, attempting reconnect", mosquitto_strerror(ret)); + logger->warn("Connection error: {}, attempting reconnect", mosquitto_strerror(ret)); - ret = mosquitto_reconnect(m->client); + ret = mosquitto_reconnect(client); if (ret != MOSQ_ERR_SUCCESS) - n->logger->warn("Reconnection to broker failed: {}", mosquitto_strerror(ret)); + logger->warn("Reconnection to broker failed: {}", mosquitto_strerror(ret)); else - n->logger->warn("Successfully reconnected to broker: {}", mosquitto_strerror(ret)); + logger->warn("Successfully reconnected to broker: {}", mosquitto_strerror(ret)); - ret = mosquitto_loop(m->client, 0, 1); + ret = mosquitto_loop(client, 0, 1); if (ret != MOSQ_ERR_SUCCESS) - n->logger->warn("Persisting connection error: {}", mosquitto_strerror(ret)); + logger->warn("Persisting connection error: {}", mosquitto_strerror(ret)); } } } @@ -72,9 +77,10 @@ static void * mosquitto_loop_thread(void *ctx) return nullptr; } -static void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, const char *str) +static +void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, const char *str) { - struct vnode *n = (struct vnode *) ctx; + auto *n = (NodeCompat *) ctx; switch (level) { case MOSQ_LOG_NONE: @@ -97,10 +103,11 @@ static void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, const char } } -static void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) +static +void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) { - struct vnode *n = (struct vnode *) ctx; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *n = (NodeCompat *) ctx; + auto *m = n->getData(); int ret; @@ -115,20 +122,22 @@ static void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) n->logger->warn("No subscription as no topic is configured"); } -static void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) +static +void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) { - struct vnode *n = (struct vnode *) ctx; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *n = (NodeCompat *) ctx; + auto *m = n->getData(); n->logger->info("Disconnected from broker {}", m->host); } -static void mqtt_message_cb(struct mosquitto *mosq, void *ctx, const struct mosquitto_message *msg) +static +void mqtt_message_cb(struct mosquitto *mosq, void *ctx, const struct mosquitto_message *msg) { int ret; - struct vnode *n = (struct vnode *) ctx; - struct mqtt *m = (struct mqtt *) n->_vd; - struct sample *smps[n->in.vectorize]; + 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); @@ -156,27 +165,28 @@ static void mqtt_message_cb(struct mosquitto *mosq, void *ctx, const struct mosq 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) +static +void mqtt_subscribe_cb(struct mosquitto *mosq, void *ctx, int mid, int qos_count, const int *granted_qos) { - struct vnode *n = (struct vnode *) ctx; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *n = (NodeCompat *) ctx; + auto *m = n->getData(); n->logger->info("Subscribed to broker {}", m->host); } -int mqtt_reverse(struct vnode *n) +int villas::node::mqtt_reverse(NodeCompat *n) { - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); SWAP(m->publish, m->subscribe); return 0; } -int mqtt_init(struct vnode *n) +int villas::node::mqtt_init(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); m->client = mosquitto_new(nullptr, true, (void *) n); if (!m->client) @@ -192,6 +202,8 @@ int mqtt_init(struct vnode *n) mosquitto_message_callback_set(m->client, mqtt_message_cb); mosquitto_subscribe_callback_set(m->client, mqtt_subscribe_cb); + m->formatter = nullptr; + /* Default values */ m->port = 1883; m->qos = 0; @@ -222,10 +234,10 @@ mosquitto_error: return ret; } -int mqtt_parse(struct vnode *n, json_t *json) +int villas::node::mqtt_parse(NodeCompat *n, json_t *json) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); const char *host; const char *publish = nullptr; @@ -299,18 +311,21 @@ int mqtt_parse(struct vnode *n, json_t *json) } /* 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; } -int mqtt_check(struct vnode *n) +int villas::node::mqtt_check(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); ret = mosquitto_sub_topic_check(m->subscribe); if (ret != MOSQ_ERR_SUCCESS) @@ -323,14 +338,14 @@ int mqtt_check(struct vnode *n) return 0; } -int mqtt_prepare(struct vnode *n) +int villas::node::mqtt_prepare(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); - m->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + m->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); - ret = pool_init(&m->pool, 1024, SAMPLE_LENGTH(vlist_length(&n->in.signals))); + ret = pool_init(&m->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); if (ret) return ret; @@ -341,9 +356,9 @@ int mqtt_prepare(struct vnode *n) return 0; } -char * mqtt_print(struct vnode *n) +char * villas::node::mqtt_print(NodeCompat *n) { - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); char *buf = nullptr; @@ -367,15 +382,13 @@ char * mqtt_print(struct vnode *n) return buf; } -int mqtt_destroy(struct vnode *n) +int villas::node::mqtt_destroy(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); mosquitto_destroy(m->client); - delete m->formatter; - ret = pool_destroy(&m->pool); if (ret) return ret; @@ -386,22 +399,29 @@ int mqtt_destroy(struct vnode *n) if (m->publish) free(m->publish); + if (m->subscribe) free(m->subscribe); + if (m->password) free(m->password); + if (m->username) free(m->username); - free(m->host); + if (m->host) + free(m->host); + + if (m->formatter) + delete m->formatter; return 0; } -int mqtt_start(struct vnode *n) +int villas::node::mqtt_start(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); if (m->username && m->password) { ret = mosquitto_username_pw_set(m->client, m->username, m->password); @@ -429,7 +449,10 @@ int mqtt_start(struct vnode *n) // Add client to global list of MQTT clients // so that thread can call mosquitto loop for this client - vlist_push(&clients, n); + { + std::lock_guard guard(clients_lock); + clients.push_back(m->client); + } return 0; @@ -439,15 +462,18 @@ mosquitto_error: return ret; } -int mqtt_stop(struct vnode *n) +int villas::node::mqtt_stop(NodeCompat *n) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); // Unregister client from global MQTT client list // so that mosquitto loop is no longer invoked for this client // important to do that before disconnecting from broker, otherwise, mosquitto thread will attempt to reconnect - vlist_remove(&clients, vlist_index(&clients, n)); + { + std::lock_guard guard(clients_lock); + clients.remove(m->client); + } ret = mosquitto_disconnect(m->client); if (ret != MOSQ_ERR_SUCCESS) @@ -461,16 +487,12 @@ mosquitto_error: return ret; } -int mqtt_type_start(villas::node::SuperNode *sn) +int villas::node::mqtt_type_start(villas::node::SuperNode *sn) { int ret; logger = logging.get("node:mqtt"); - ret = vlist_init(&clients); - if (ret) - return ret; - ret = mosquitto_lib_init(); if (ret != MOSQ_ERR_SUCCESS) goto mosquitto_error; @@ -488,7 +510,7 @@ mosquitto_error: return ret; } -int mqtt_type_stop() +int villas::node::mqtt_type_stop() { int ret; @@ -508,13 +530,9 @@ int mqtt_type_stop() goto mosquitto_error; // When this is called the list of clients should be empty - if (vlist_length(&clients) > 0) + if (clients.size() > 0) throw RuntimeError("List of MQTT clients contains elements at time of destruction. Call node_stop for each MQTT node before stopping node type!"); - ret = vlist_destroy(&clients, nullptr, false); - if (ret) - return ret; - return 0; mosquitto_error: @@ -523,11 +541,11 @@ mosquitto_error: return ret; } -int mqtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int pulled; - struct mqtt *m = (struct mqtt *) n->_vd; - struct sample *smpt[cnt]; + auto *m = n->getData(); + struct Sample *smpt[cnt]; pulled = queue_signalled_pull_many(&m->queue, (void **) smpt, cnt); @@ -537,10 +555,10 @@ int mqtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return pulled; } -int mqtt_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); size_t wbytes; @@ -563,16 +581,16 @@ int mqtt_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int mqtt_poll_fds(struct vnode *n, int fds[]) +int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) { - struct mqtt *m = (struct mqtt *) n->_vd; + auto *m = n->getData(); fds[0] = queue_signalled_fd(&m->queue); return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -597,8 +615,5 @@ static void register_plugin() { p.reverse = mqtt_reverse; p.poll_fds = mqtt_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/nanomsg.cpp b/lib/nodes/nanomsg.cpp index 1ee088b3d..a0e51af5f 100644 --- a/lib/nodes/nanomsg.cpp +++ b/lib/nodes/nanomsg.cpp @@ -1,7 +1,7 @@ /** Node type: nanomsg * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -33,24 +33,44 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -int nanomsg_reverse(struct vnode *n) +int villas::node::nanomsg_init(NodeCompat *n) { - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); - if (vlist_length(&m->out.endpoints) != 1 || - vlist_length(&m->in.endpoints) != 1) - return -1; - - char *subscriber = (char *) vlist_first(&m->in.endpoints); - char *publisher = (char *) vlist_first(&m->out.endpoints); - - vlist_set(&m->in.endpoints, 0, publisher); - vlist_set(&m->out.endpoints, 0, subscriber); + m->formatter = nullptr; return 0; } -static int nanomsg_parse_endpoints(struct vlist *l, json_t *json) +int villas::node::nanomsg_destroy(NodeCompat *n) +{ + auto *m = n->getData(); + + if (m->formatter) + delete m->formatter; + + return 0; +} + +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; + + 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); + + return 0; +} + +static +int nanomsg_parse_endpoints(struct List *l, json_t *json) { const char *ep; @@ -64,14 +84,14 @@ static int nanomsg_parse_endpoints(struct vlist *l, json_t *json) if (!ep) return -1; - vlist_push(l, strdup(ep)); + list_push(l, strdup(ep)); } break; case JSON_STRING: ep = json_string_value(json); - vlist_push(l, strdup(ep)); + list_push(l, strdup(ep)); break; default: @@ -81,21 +101,21 @@ static int nanomsg_parse_endpoints(struct vlist *l, json_t *json) return 0; } -int nanomsg_parse(struct vnode *n, json_t *json) +int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) { int ret; - struct nanomsg *m = (struct nanomsg *) n->_vd; + 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; - ret = vlist_init(&m->out.endpoints); + ret = list_init(&m->out.endpoints); if (ret) return ret; - ret = vlist_init(&m->in.endpoints); + ret = list_init(&m->in.endpoints); if (ret) return ret; @@ -122,6 +142,8 @@ int nanomsg_parse(struct vnode *n, json_t *json) } /* Format */ + if (m->formatter) + delete m->formatter; m->formatter = json_format ? FormatFactory::make(json_format) : FormatFactory::make("json"); @@ -131,24 +153,24 @@ int nanomsg_parse(struct vnode *n, json_t *json) return 0; } -char * nanomsg_print(struct vnode *n) +char * villas::node::nanomsg_print(NodeCompat *n) { - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); char *buf = nullptr; strcatf(&buf, "in.endpoints=[ "); - for (size_t i = 0; i < vlist_length(&m->in.endpoints); i++) { - char *ep = (char *) vlist_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, "], out.endpoints=[ "); - for (size_t i = 0; i < vlist_length(&m->out.endpoints); i++) { - char *ep = (char *) vlist_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); } @@ -158,12 +180,12 @@ char * nanomsg_print(struct vnode *n) return buf; } -int nanomsg_start(struct vnode *n) +int villas::node::nanomsg_start(NodeCompat *n) { int ret; - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); - m->formatter->start(&n->in.signals, ~(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) @@ -179,8 +201,8 @@ int nanomsg_start(struct vnode *n) return ret; /* Bind publisher to socket */ - for (size_t i = 0; i < vlist_length(&m->out.endpoints); i++) { - char *ep = (char *) vlist_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); ret = nn_bind(m->out.socket, ep); if (ret < 0) @@ -188,8 +210,8 @@ int nanomsg_start(struct vnode *n) } /* Connect subscribers socket */ - for (size_t i = 0; i < vlist_length(&m->in.endpoints); i++) { - char *ep = (char *) vlist_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); ret = nn_connect(m->in.socket, ep); if (ret < 0) @@ -199,10 +221,10 @@ int nanomsg_start(struct vnode *n) return 0; } -int nanomsg_stop(struct vnode *n) +int villas::node::nanomsg_stop(NodeCompat *n) { int ret; - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); ret = nn_close(m->in.socket); if (ret < 0) @@ -212,21 +234,19 @@ int nanomsg_stop(struct vnode *n) if (ret < 0) return ret; - delete m->formatter; - return 0; } -int nanomsg_type_stop() +int villas::node::nanomsg_type_stop() { nn_term(); return 0; } -int nanomsg_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); int bytes; char data[NANOMSG_MAX_PACKET_LEN]; @@ -238,10 +258,10 @@ int nanomsg_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return m->formatter->sscan(data, bytes, nullptr, smps, cnt); } -int nanomsg_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); size_t wbytes; @@ -258,10 +278,10 @@ int nanomsg_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int nanomsg_poll_fds(struct vnode *n, int fds[]) +int villas::node::nanomsg_poll_fds(NodeCompat *n, int fds[]) { int ret; - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); int fd; size_t len = sizeof(fd); @@ -275,16 +295,16 @@ int nanomsg_poll_fds(struct vnode *n, int fds[]) return 1; } -int nanomsg_netem_fds(struct vnode *n, int fds[]) +int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) { - struct nanomsg *m = (struct nanomsg *) n->_vd; + auto *m = n->getData(); fds[0] = m->out.socket; return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -293,6 +313,8 @@ static void register_plugin() { 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; @@ -303,8 +325,5 @@ static void register_plugin() { p.poll_fds = nanomsg_poll_fds; p.netem_fds = nanomsg_netem_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ngsi.cpp b/lib/nodes/ngsi.cpp index b1384fc5e..ec7ceaa35 100644 --- a/lib/nodes/ngsi.cpp +++ b/lib/nodes/ngsi.cpp @@ -1,7 +1,7 @@ /** Node type: OMA Next Generation Services Interface 9 (NGSI) (FIWARE context broker) * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,13 +31,13 @@ #include #include -#include +#include #include #include #include #include -#include -#include +#include +#include using namespace villas; using namespace villas::node; @@ -54,6 +54,7 @@ using namespace villas::utils; /** 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) { auto logger = logging.get("curl"); @@ -65,7 +66,8 @@ void handle_error(const char *file, int lineno, const char *msg) /* exit(-1); */ } -static void curl_ssl_locking_function(int mode, int n, const char *file, int line) +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]); @@ -73,7 +75,8 @@ static void curl_ssl_locking_function(int mode, int n, const char *file, int lin pthread_mutex_unlock(&mutex_buf[n]); } -static unsigned long curl_ssl_thread_id_function(void) +static +unsigned long curl_ssl_thread_id_function(void) { return ((unsigned long) pthread_self()); } @@ -135,12 +138,12 @@ public: size_t index; std::list metadata; - NgsiAttribute(json_t *json, size_t j, struct signal *s) + NgsiAttribute(json_t *json, size_t j, Signal::Ptr s) { parse(json, j, s); } - void parse(json_t *json, size_t j, struct signal *s) + void parse(json_t *json, size_t j, Signal::Ptr s) { int ret; @@ -160,10 +163,10 @@ public: /* Copy values from node signal, if 'ngsi_attribute' settings not provided */ if (s && !nam) - nam = s->name ? s->name : ""; + nam = !s->name.empty() ? s->name.c_str() : ""; if (s && !typ) - typ = s->unit ? s->unit : ""; + typ = !s->unit.empty() ? s->unit.c_str() : ""; name = nam; type = typ; @@ -182,7 +185,7 @@ public: metadata.emplace_back("index", "integer", fmt::format("{}", j)); } - json_t * build(const struct sample * const smps[], unsigned cnt, int flags) + 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(), @@ -195,24 +198,22 @@ public: json_t *json_value = json_array(); for (unsigned k = 0; k < cnt; k++) { - struct sample *smp = &smps[k]; - - union signal_data *sd = &smp->data[index]; - struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, index); + const auto *sig = (Signal *) list_at_safe(smp->signals, index); + const auto *smp = &smps[k]; + const auto *data = &smp->data[index]; json_array_append_new(json_value, json_pack("[ f, o, i ]", time_to_double(smp->ts.origin), - signal_data_to_json(sd, sig->type), + data->toJson(sig->type), smp->sequence )); } #else - const struct sample *smp = smps[0]; + const auto *smp = smps[0]; + const auto sig = smp->signals->getByIndex(index); + const auto *data = &smp->data[index]; - const union signal_data *sd = &smp->data[index]; - const struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, index); - - json_t *json_value = signal_data_to_json(sd, sig->type); + json_t *json_value = data->toJson(sig->type); #endif json_object_set(json_attribute, "value", json_value); @@ -241,9 +242,10 @@ struct ngsi_response { size_t len; }; -static json_t* ngsi_build_entity(struct vnode *n, const struct sample * const smps[], unsigned cnt, int flags) +static +json_t* ngsi_build_entity(NodeCompat *n, const struct Sample * const smps[], unsigned cnt, int flags) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); json_t *json_entity = json_pack("{ s: s, s: s, s: b }", "id", i->entity_id, @@ -255,8 +257,8 @@ static json_t* ngsi_build_entity(struct vnode *n, const struct sample * const sm json_t *json_attrs = json_array(); if (flags & NGSI_ENTITY_ATTRIBUTES_IN) { - for (size_t j = 0; j < vlist_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) vlist_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); auto *json_attr = attr->build(smps, cnt, flags); @@ -265,8 +267,8 @@ static json_t* ngsi_build_entity(struct vnode *n, const struct sample * const sm } if (flags & NGSI_ENTITY_ATTRIBUTES_OUT) { - for (size_t j = 0; j < vlist_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) vlist_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); auto *json_attr = attr->build(smps, cnt, flags); @@ -280,12 +282,13 @@ static json_t* ngsi_build_entity(struct vnode *n, const struct sample * const sm return json_entity; } -static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample * const smps[], unsigned cnt) +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; - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); size_t l; json_error_t err; @@ -321,7 +324,7 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample return -3; /* Check attribute name and type */ - attr = vlist_lookup_name(&i->in.signals, name); + attr = list_lookup_name(&i->in.signals, name); if (!attr || attr->type != type) continue; /* skip unknown attributes */ @@ -341,7 +344,7 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample size_t k; json_array_foreach(json_value, k, json_tuple) { - struct sample *smp = smps[k]; + struct Sample *smp = smps[k]; /* Check sample format */ if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) @@ -359,8 +362,8 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample smp->ts.origin = tss; - union signal_data *sd = &smp->data[attr->index]; - struct signal *sig = (struct signal *) vlist_at_safe(&n->in.signals, attr->index); + auto *sd = &smp->data[attr->index]; + auto *sig = (Signal *) list_at_safe(n->getInputSignals(false), attr->index); if (!sig) return -11; @@ -373,7 +376,7 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample } } #else - struct sample *smp = smps[0]; + struct Sample *smp = smps[0]; /* Check number of values */ if (!json_is_string(json_value)) @@ -381,15 +384,15 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample value = json_string_value(json_value); - union signal_data *sd = &smp->data[attr->index]; - struct signal *sig = (struct signal *) vlist_at_safe(&n->in.signals, attr->index); + 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 */ - *sd = sig->init; + *data = sig->init; else { - signal_data_parse_str(sd, sig->type, value, &end); + data->parseString(sig->type, value, &end); if (value == end) return -10; } @@ -397,10 +400,10 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample } for (unsigned k = 0; k < cnt; k++) { - struct sample *smp = smps[k]; + struct Sample *smp = smps[k]; smp->length = length; - smp->signals = &n->in.signals; + smp->signals = n->getInputSignals(false); smp->flags = (int) SampleFlags::HAS_DATA; #ifdef NGSI_VECTORS @@ -412,7 +415,8 @@ static int ngsi_parse_entity(struct vnode *n, json_t *json_entity, struct sample return cnt; } -static int ngsi_parse_signals(json_t *json_signals, struct vlist *ngsi_signals, struct vlist *node_signals) +static +int ngsi_parse_signals(json_t *json_signals, struct List *ngsi_signals, SignalList::Ptr node_signals) { size_t j; json_t *json_signal; @@ -421,19 +425,19 @@ static int ngsi_parse_signals(json_t *json_signals, struct vlist *ngsi_signals, return -1; json_array_foreach(json_signals, j, json_signal) { - auto *s = (struct signal *) vlist_at_safe(node_signals, j); - + auto s = node_signals->getByIndex(j); auto *a = new NgsiAttribute(json_signal, j, s); if (!a) throw MemoryAllocationError(); - vlist_push(ngsi_signals, a); + list_push(ngsi_signals, a); } return 0; } -static int ngsi_parse_context_response(json_t *json_response, int *code, char **reason, json_t **json_rentity, Logger logger) { +static +int ngsi_parse_context_response(json_t *json_response, int *code, char **reason, json_t **json_rentity, Logger logger) { int ret; char *codestr; @@ -459,7 +463,8 @@ static int ngsi_parse_context_response(json_t *json_response, int *code, char ** return ret; } -static size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, void *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; @@ -475,7 +480,8 @@ static size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, voi return realsize; } -static int ngsi_request(CURL *handle, const char *endpoint, const char *operation, json_t *json_request, json_t **json_response, Logger logger) +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)); @@ -519,7 +525,8 @@ out: free(post); return ret; } -static int ngsi_request_context_query(CURL *handle, const char *endpoint, json_t *json_entity, json_t **json_rentity, Logger logger) +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; @@ -543,7 +550,8 @@ out: json_decref(json_request); return ret; } -static int ngsi_request_context_update(CURL *handle, const char *endpoint, const char *action, json_t *json_entity, Logger logger) +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; @@ -570,7 +578,7 @@ out: json_decref(json_request); return ret; } -int 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()]; @@ -589,7 +597,7 @@ int ngsi_type_start(villas::node::SuperNode *sn) return curl_global_init(CURL_GLOBAL_ALL); } -int ngsi_type_stop() +int villas::node::ngsi_type_stop() { #ifdef CURL_SSL_REQUIRES_LOCKING if (!mutex_buf) @@ -609,9 +617,9 @@ int ngsi_type_stop() return 0; } -int ngsi_parse(struct vnode *n, json_t *json) +int villas::node::ngsi_parse(NodeCompat *n, json_t *json) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); int ret; json_error_t err; @@ -643,13 +651,13 @@ int ngsi_parse(struct vnode *n, json_t *json) i->remove = remove; if (json_signals_in) { - ret = ngsi_parse_signals(json_signals_in, &i->in.signals, &n->in.signals); + 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); } if (json_signals_out) { - ret = ngsi_parse_signals(json_signals_out, &i->out.signals, &n->out.signals); + 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); } @@ -657,17 +665,17 @@ int ngsi_parse(struct vnode *n, json_t *json) return 0; } -char * ngsi_print(struct vnode *n) +char * villas::node::ngsi_print(NodeCompat *n) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); return strf("endpoint=%s, timeout=%.3f secs", i->endpoint, i->timeout); } -int ngsi_start(struct vnode *n) +int villas::node::ngsi_start(NodeCompat *n) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); i->in.curl = curl_easy_init(); i->out.curl = curl_easy_init(); @@ -711,9 +719,9 @@ int ngsi_start(struct vnode *n) return 0; } -int ngsi_stop(struct vnode *n) +int villas::node::ngsi_stop(NodeCompat *n) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); int ret; i->task.stop(); @@ -732,9 +740,9 @@ int ngsi_stop(struct vnode *n) return ret; } -int ngsi_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ngsi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); int ret; if (i->task.wait() == 0) @@ -757,9 +765,9 @@ out: json_decref(json_entity); return ret; } -int ngsi_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); int ret; json_t *json_entity = ngsi_build_entity(n, smps, cnt, NGSI_ENTITY_ATTRIBUTES_OUT | NGSI_ENTITY_VALUES); @@ -771,27 +779,27 @@ int ngsi_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return ret ? 0 : cnt; } -int ngsi_poll_fds(struct vnode *n, int fds[]) +int villas::node::ngsi_poll_fds(NodeCompat *n, int fds[]) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); fds[0] = i->task.getFD(); return 1; } -int ngsi_init(struct vnode *n) +int villas::node::ngsi_init(NodeCompat *n) { int ret; - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); new (&i->task) Task(CLOCK_REALTIME); - ret = vlist_init(&i->in.signals); + ret = list_init(&i->in.signals); if (ret) return ret; - ret = vlist_init(&i->out.signals); + ret = list_init(&i->out.signals); if (ret) return ret; @@ -804,29 +812,29 @@ int ngsi_init(struct vnode *n) return 0; } -int ngsi_destroy(struct vnode *n) +int villas::node::ngsi_destroy(NodeCompat *n) { int ret; - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); - for (size_t j = 0; j < vlist_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) vlist_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; } - for (size_t j = 0; j < vlist_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) vlist_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; } - ret = vlist_destroy(&i->in.signals); + ret = list_destroy(&i->in.signals); if (ret) return ret; - ret = vlist_destroy(&i->out.signals); + ret = list_destroy(&i->out.signals); if (ret) return ret; @@ -835,18 +843,18 @@ int ngsi_destroy(struct vnode *n) return 0; } -int ngsi_reverse(struct vnode *n) +int villas::node::ngsi_reverse(NodeCompat *n) { - struct ngsi *i = (struct ngsi *) n->_vd; + auto *i = n->getData(); - SWAP(n->in.signals, n->out.signals); + n->swapSignals(); SWAP(i->in.signals, i->out.signals); return 0; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -871,8 +879,5 @@ static void register_plugin() { p.poll_fds = ngsi_poll_fds; p.reverse = ngsi_reverse; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 182d131c0..cc1b5a790 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -3,7 +3,7 @@ * This file implements the opal subtype for nodes. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include @@ -103,6 +103,7 @@ extern "C" { } } +static int opal_register_region(int argc, char *argv[]) { if (argc != 4) @@ -115,7 +116,7 @@ int opal_register_region(int argc, char *argv[]) return 0; } -int opal_type_start(villas::node::SuperNode *sn) +int villas::node::opal_type_start(villas::node::SuperNode *sn) { int err, noRecvIcons, noSendIcons; @@ -163,7 +164,7 @@ int opal_type_start(villas::node::SuperNode *sn) return 0; } -int opal_type_stop() +int villas::node::opal_type_stop() { int err; @@ -183,6 +184,7 @@ int opal_type_stop() return 0; } +static int opal_print_global() { auto logger = logging.get("node:opal"); @@ -207,9 +209,9 @@ int opal_print_global() return 0; } -int opal_parse(struct vnode *n, json_t *json) +int villas::node::opal_parse(NodeCompat *n, json_t *json) { - struct opal *o = (struct opal *) n->_vd; + auto *o = n->getData(); int ret; json_error_t err; @@ -225,9 +227,9 @@ int opal_parse(struct vnode *n, json_t *json) return 0; } -char * opal_print(struct vnode *n) +char * villas::node::opal_print(NodeCompat *n) { - struct opal *o = (struct opal *) n->_vd; + auto *o = n->getData(); /** @todo Print send_params, recv_params */ @@ -235,9 +237,9 @@ char * opal_print(struct vnode *n) o->sendID, o->recvID, o->reply); } -int opal_start(struct vnode *n) +int villas::node::opal_start(NodeCompat *n) { - struct opal *o = (struct opal *) n->_vd; + auto *o = n->getData(); /* Search for valid send and recv ids */ int sfound = 0, rfound = 0; @@ -261,14 +263,14 @@ int opal_start(struct vnode *n) return 0; } -int opal_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct opal *o = (struct opal *) n->_vd; + auto *o = n->getData(); int state, ret, len; unsigned id; - struct sample *s = smps[0]; + struct Sample *s = smps[0]; double data[s->capacity]; @@ -326,11 +328,11 @@ int opal_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return 1; } -int opal_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct opal *o = (struct opal *) n->_vd; + auto *o = n->getData(); - struct sample *s = smps[0]; + struct Sample *s = smps[0]; int state; int len; @@ -359,7 +361,7 @@ int opal_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -375,8 +377,5 @@ static void register_plugin() { p.read = opal_read; p.write = opal_write; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/redis.cpp b/lib/nodes/redis.cpp index 8db1b69dd..68b36580d 100644 --- a/lib/nodes/redis.cpp +++ b/lib/nodes/redis.cpp @@ -29,25 +29,26 @@ #include #include #include -#include +#include #include #include #include -#include -#include - -/* Forward declartions */ -static struct vnode_type p; -static void redis_on_message(struct vnode *n, const std::string &channel, const std::string &msg); +#include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -using namespace sw::redis; -static std::unordered_map connections; +/* Forward declartions */ +static NodeCompatType p; +static void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg); -RedisConnection::RedisConnection(const ConnectionOptions &opts) : +static std::unordered_map connections; + +RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) : context(opts), subscriber(context.subscriber()), logger(logging.get("nodes:redis")) @@ -64,7 +65,7 @@ RedisConnection::RedisConnection(const ConnectionOptions &opts) : state = State::INITIALIZED; } -RedisConnection * RedisConnection::get(const ConnectionOptions &opts) +RedisConnection * RedisConnection::get(const sw::redis::ConnectionOptions &opts) { RedisConnection *conn; @@ -74,7 +75,7 @@ RedisConnection * RedisConnection::get(const ConnectionOptions &opts) else { try { conn = new RedisConnection(opts); - } catch (IoError &e) { + } catch (sw::redis::IoError &e) { throw RuntimeError(e.what()); } @@ -88,20 +89,20 @@ void RedisConnection::onMessage(const std::string &channel, const std::string &m { auto itp = subscriberMap.equal_range(channel); for (auto it = itp.first; it != itp.second; ++it) { - struct vnode *n = it->second; + NodeCompat *n = it->second; redis_on_message(n, channel, msg); } } -void RedisConnection::subscribe(struct vnode *n, const std::string &channel) +void RedisConnection::subscribe(NodeCompat *n, const std::string &channel) { subscriber.subscribe(channel); subscriberMap.emplace(channel, n); } -void RedisConnection::unsubscribe(struct vnode *n, const std::string &channel) +void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) { auto itp = subscriberMap.equal_range(channel); for (auto it = itp.first; it != itp.second; ++it) { @@ -138,23 +139,24 @@ void RedisConnection::loop() try { subscriber.consume(); } - catch (const TimeoutError &e) { + catch (const sw::redis::TimeoutError &e) { continue; } - catch (const ReplyError &e) { + catch (const sw::redis::ReplyError &e) { continue; } - catch (const Error &e) { + catch (const sw::redis::Error &e) { /* Create a new subscriber */ subscriber = context.subscriber(); } } } -static int redis_get(struct vnode *n, struct sample * const smps[], unsigned cnt) +static +int redis_get(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); switch (r->mode) { case RedisMode::KEY: { @@ -173,11 +175,11 @@ static int redis_get(struct vnode *n, struct sample * const smps[], unsigned cnt } case RedisMode::HASH: { - struct sample *smp = smps[0]; + struct Sample *smp = smps[0]; - for (unsigned j = 0; j < vlist_length(&n->in.signals); j++) { - struct signal *sig = (struct signal *) vlist_at(&n->in.signals, j); - union signal_data *data = &smp->data[j]; + for (unsigned j = 0; j < n->getInputSignals(false)->size(); j++) { + auto sig = n->getInputSignals(false)->getByIndex(j); + auto *data = &smp->data[j]; *data = sig->init; } @@ -190,16 +192,16 @@ static int redis_get(struct vnode *n, struct sample * const smps[], unsigned cnt auto &name = it.first; auto &value = it.second; - struct signal *sig = vlist_lookup_name(&n->in.signals, name); + auto sig = n->getInputSignals(false)->getByName(name); if (!sig) continue; - auto idx = vlist_index(&n->in.signals, sig); + auto idx = n->getInputSignals(false)->getIndexByName(name); if (idx > max_idx) max_idx = idx; char *end; - ret = signal_data_parse_str(&smp->data[idx], sig->type, value.c_str(), &end); + ret = smp->data[idx].parseString(sig->type, value.c_str(), &end); if (ret < 0) continue; } @@ -218,15 +220,16 @@ static int redis_get(struct vnode *n, struct sample * const smps[], unsigned cnt } } -static void redis_on_message(struct vnode *n, const std::string &channel, const std::string &msg) +static +void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); n->logger->debug("Message: {}: {}", channel, msg); int alloc, scanned, pushed; unsigned cnt = n->in.vectorize; - struct sample *smps[cnt]; + struct Sample *smps[cnt]; alloc = sample_alloc_many(&r->pool, smps, cnt); if (alloc < 0) { @@ -269,33 +272,34 @@ static void redis_on_message(struct vnode *n, const std::string &channel, const out: sample_decref_many(smps + pushed, alloc - pushed); } -int redis_init(struct vnode *n) +int villas::node::redis_init(NodeCompat *n) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); r->mode = RedisMode::KEY; r->formatter = nullptr; r->notify = true; r->rate = 1.0; - new (&r->options) ConnectionOptions; + new (&r->options) sw::redis::ConnectionOptions; new (&r->task) Task(CLOCK_REALTIME); new (&r->key) std::string(); return 0; } -int redis_destroy(struct vnode *n) +int villas::node::redis_destroy(NodeCompat *n) { int ret; - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); if (r->formatter) delete r->formatter; using string = std::string; + using redis_co = sw::redis::ConnectionOptions; - r->options.~ConnectionOptions(); + r->options.~redis_co(); r->key.~string(); r->task.~Task(); @@ -310,10 +314,10 @@ int redis_destroy(struct vnode *n) return 0; } -int redis_parse(struct vnode *n, json_t *json) +int villas::node::redis_parse(NodeCompat *n, json_t *json) { int ret; - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); json_error_t err; json_t *json_ssl = nullptr; @@ -403,6 +407,8 @@ int redis_parse(struct vnode *n, json_t *json) } /* Format */ + if (r->formatter) + delete r->formatter; r->formatter = json_format ? FormatFactory::make(json_format) : FormatFactory::make("json"); @@ -419,7 +425,7 @@ int redis_parse(struct vnode *n, json_t *json) /* Connection options */ if (uri) - r->options = ConnectionOptions(uri); + r->options = sw::redis::ConnectionOptions(uri); if (db >= 0) r->options.db = db; @@ -448,9 +454,9 @@ int redis_parse(struct vnode *n, json_t *json) return 0; } -int redis_check(struct vnode *n) +int villas::node::redis_check(NodeCompat *n) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); if (!r->options.host.empty() && !r->options.path.empty()) return -1; @@ -461,9 +467,9 @@ int redis_check(struct vnode *n) return 0; } -char * redis_print(struct vnode *n) +char * villas::node::redis_print(NodeCompat *n) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); std::stringstream ss; @@ -479,17 +485,17 @@ char * redis_print(struct vnode *n) return strdup(ss.str().c_str()); } -int redis_prepare(struct vnode *n) +int villas::node::redis_prepare(NodeCompat *n) { int ret; - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); r->options.type = r->options.path.empty() - ? ConnectionType::TCP - : ConnectionType::UNIX; + ? sw::redis::ConnectionType::TCP + : sw::redis::ConnectionType::UNIX; if (r->key.empty()) - r->key = node_name_short(n); + r->key = n->getNameShort(); ret = queue_signalled_init(&r->queue, 1024); if (ret) @@ -506,11 +512,11 @@ int redis_prepare(struct vnode *n) return 0; } -int redis_start(struct vnode *n) +int villas::node::redis_start(NodeCompat *n) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); - r->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); if (!r->notify) r->task.setRate(r->rate); @@ -534,9 +540,9 @@ int redis_start(struct vnode *n) return 0; } -int redis_stop(struct vnode *n) +int villas::node::redis_stop(NodeCompat *n) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); r->conn->stop(); @@ -560,14 +566,14 @@ int redis_stop(struct vnode *n) return 0; } -int redis_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); /* Wait for new data */ if (r->notify || r->mode == RedisMode::CHANNEL) { int pulled_cnt; - struct sample *pulled_smps[cnt]; + struct Sample *pulled_smps[cnt]; pulled_cnt = queue_signalled_pull_many(&r->queue, (void **) pulled_smps, cnt); @@ -584,10 +590,10 @@ int redis_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } } -int redis_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); switch (r->mode) { case RedisMode::CHANNEL: @@ -621,18 +627,15 @@ int redis_write(struct vnode *n, struct sample * const smps[], unsigned cnt) case RedisMode::HASH: { /* We only update the signals with their latest value here. */ - struct sample *smp = smps[cnt - 1]; + struct Sample *smp = smps[cnt - 1]; std::unordered_map kvs; - for (unsigned j = 0; j < MIN(vlist_length(smp->signals), smp->length); j++) { - struct signal *sig = (struct signal *) vlist_at(smp->signals, j); - union signal_data *data = &smp->data[j]; + for (unsigned j = 0; j < MIN(smp->signals->size(), smp->length); j++) { + const auto sig = smp->signals->getByIndex(j); + const auto *data = &smp->data[j]; - char val[128]; - signal_data_print_str(data, sig->type, val, sizeof(val), 16); - - kvs[sig->name] = val; + kvs[sig->name] = data->toString(sig->type); } r->conn->context.hmset(r->key, kvs.begin(), kvs.end()); @@ -643,9 +646,9 @@ int redis_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int redis_poll_fds(struct vnode *n, int fds[]) +int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) { - struct redis *r = (struct redis *) n->_vd; + auto *r = n->getData(); fds[0] = r->notify ? queue_signalled_fd(&r->queue) @@ -672,8 +675,5 @@ static void register_plugin() { p.write = redis_write; p.poll_fds = redis_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index 8542e8b36..e8b6f686f 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -2,7 +2,7 @@ * * @author Steffen Vogel * @author Marvin Klimke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -39,7 +39,7 @@ extern "C" { #undef ALIGN_MASK } -#include +#include #include #include #include @@ -57,11 +57,13 @@ using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -static struct vnode_type p; +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static int rtp_aimd(struct vnode *n, double loss_frac) +static +int rtp_aimd(NodeCompat *n, double loss_frac) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); double rate; @@ -88,34 +90,37 @@ static int rtp_aimd(struct vnode *n, double loss_frac) return 0; } -int rtp_init(struct vnode *n) +int villas::node::rtp_init(NodeCompat *n) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); n->logger = villas::logging.get("node:rtp"); /* Default values */ - r->aimd.rate = 1; - 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.log_filename = nullptr; r->aimd.log = nullptr; r->rtcp.enabled = false; r->aimd.rate_hook_type = RTPHookType::DISABLED; + r->formatter = nullptr; + return 0; } -int rtp_reverse(struct vnode *n) +int villas::node::rtp_reverse(NodeCompat *n) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); SWAP(r->in.saddr_rtp, r->out.saddr_rtp); SWAP(r->in.saddr_rtcp, r->out.saddr_rtcp); @@ -123,10 +128,10 @@ int rtp_reverse(struct vnode *n) return 0; } -int rtp_parse(struct vnode *n, json_t *json) +int villas::node::rtp_parse(NodeCompat *n, json_t *json) { int ret = 0; - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); const char *local, *remote; const char *log = nullptr; @@ -185,6 +190,8 @@ int rtp_parse(struct vnode *n, json_t *json) 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"); @@ -218,9 +225,9 @@ int rtp_parse(struct vnode *n, json_t *json) return 0; } -char * rtp_print(struct vnode *n) +char * villas::node::rtp_print(NodeCompat *n) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); char *buf; char *local = socket_print_addr((struct sockaddr *) &r->in.saddr_rtp.u); @@ -260,11 +267,12 @@ char * rtp_print(struct vnode *n) return buf; } -static void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf *mb, void *arg) +static +void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf *mb, void *arg) { int ret; - struct vnode *n = (struct vnode *) arg; - struct rtp *r = (struct rtp *) n->_vd; + auto *n = (NodeCompat *) arg; + auto *r = n->getData(); /* source, header not used */ (void) src; @@ -279,10 +287,11 @@ static void rtp_handler(const struct sa *src, const struct rtp_header *hdr, stru } } -static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) +static +void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) { - struct vnode *n = (struct vnode *) arg; - struct rtp *r = (struct rtp *) n->_vd; + auto *n = (NodeCompat *) arg; + auto *r = n->getData(); /* source not used */ (void) src; @@ -297,10 +306,11 @@ static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) rtp_aimd(n, loss_frac); - if (n->stats) { - n->stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost); - n->stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac); - n->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); @@ -312,18 +322,18 @@ static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) r->rtcp.num_rrs++; } -int rtp_start(struct vnode *n) +int villas::node::rtp_start(NodeCompat *n) { int ret; - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); /* Initialize queue */ - ret = queue_signalled_init(&r->recv_queue, 1024, &memory_heap); + ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); if (ret) return ret; /* Initialize IO */ - r->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); /* Initialize memory buffer for sending */ r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); @@ -339,11 +349,11 @@ int rtp_start(struct vnode *n) #ifdef WITH_HOOKS switch (r->aimd.rate_hook_type) { case RTPHookType::DECIMATE: - r->aimd.rate_hook = new DecimateHook(nullptr, n, 0, 0); + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); break; case RTPHookType::LIMIT_RATE: - r->aimd.rate_hook = new LimitRateHook(nullptr, n, 0, 0); + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); break; default: @@ -355,9 +365,9 @@ int rtp_start(struct vnode *n) r->aimd.rate_hook->init(); - vlist_push(&n->out.hooks, (void *) r->aimd.rate_hook); + n->out.hooks.push_back(r->aimd.rate_hook); - r->aimd.rate_hook->setRate(r->aimd.rate_last); + r->aimd.rate_hook->setRate(r->aimd.rate, r->aimd.rate_source); #else throw RuntimeError("Rate limiting is not supported"); @@ -377,7 +387,7 @@ int rtp_start(struct vnode *n) if (r->rtcp.enabled) { r->rtcp.num_rrs = 0; - rtcp_start(r->rs, node_name(n), &r->out.saddr_rtcp); + rtcp_start(r->rs, n->getNameShort().c_str(), &r->out.saddr_rtcp); if (r->aimd.log_filename) { char fn[128]; @@ -402,10 +412,10 @@ int rtp_start(struct vnode *n) return ret; } -int rtp_stop(struct vnode *n) +int villas::node::rtp_stop(NodeCompat *n) { int ret; - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); mem_deref(r->rs); @@ -422,14 +432,12 @@ int rtp_stop(struct vnode *n) if (r->aimd.log) r->aimd.log->close(); - delete r->formatter; - return 0; } -int rtp_destroy(struct vnode *n) +int villas::node::rtp_destroy(NodeCompat *n) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); if (r->aimd.log) delete r->aimd.log; @@ -437,17 +445,21 @@ int rtp_destroy(struct vnode *n) if (r->aimd.log_filename) free(r->aimd.log_filename); + if (r->formatter) + delete r->formatter; + return 0; } -static void stop_handler(int sig, siginfo_t *si, void *ctx) +static +void stop_handler(int sig, siginfo_t *si, void *ctx) { re_cancel(); } typedef void *(*pthread_start_routine)(void *); -int rtp_type_start(villas::node::SuperNode *sn) +int villas::node::rtp_type_start(villas::node::SuperNode *sn) { int ret; @@ -471,8 +483,9 @@ int rtp_type_start(villas::node::SuperNode *sn) #ifdef WITH_NETEM /* Gather list of used network interfaces */ - for (auto *n : p.instances) { - struct rtp *r = (struct rtp *) n->_vd; + 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) @@ -485,7 +498,7 @@ int rtp_type_start(villas::node::SuperNode *sn) return 0; } -int rtp_type_stop() +int villas::node::rtp_type_stop() { int ret; @@ -500,10 +513,10 @@ int rtp_type_stop() return 0; } -int rtp_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); struct mbuf *mb; /* Get data from queue */ @@ -519,10 +532,10 @@ int rtp_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return ret; } -int rtp_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); size_t wbytes; size_t avail; @@ -555,18 +568,18 @@ retry: mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); return cnt; } -int rtp_poll_fds(struct vnode *n, int fds[]) +int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); fds[0] = queue_signalled_fd(&r->recv_queue); return 1; } -int rtp_netem_fds(struct vnode *n, int fds[]) +int villas::node::rtp_netem_fds(NodeCompat *n, int fds[]) { - struct rtp *r = (struct rtp *) n->_vd; + auto *r = n->getData(); int m = 0; struct udp_sock *rtp = (struct udp_sock *) rtp_sock(r->rs); @@ -603,9 +616,4 @@ static void register_plugin() { p.reverse = rtp_reverse; p.poll_fds = rtp_poll_fds; p.netem_fds = rtp_netem_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); } diff --git a/lib/nodes/shmem.cpp b/lib/nodes/shmem.cpp index 1853fae95..1b1ccda1f 100644 --- a/lib/nodes/shmem.cpp +++ b/lib/nodes/shmem.cpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,33 +31,38 @@ #include #include #include -#include -#include +#include +#include #include -#include +#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -int shmem_parse(struct vnode *n, json_t *json) +int villas::node::shmem_init(NodeCompat *n) { - struct shmem *shm = (struct shmem *) n->_vd; + auto *shm = n->getData(); + + /* Default values */ + shm->conf.queuelen = -1; + shm->conf.samplelen = -1; + shm->conf.polling = false; + shm->exec = nullptr; + + return 0; +} + +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 len = MAX(vlist_length(&n->in.signals), vlist_length(&n->out.signals)); - - /* Default values */ - shm->conf.queuelen = MAX(DEFAULT_SHMEM_QUEUELEN, n->in.vectorize); - shm->conf.samplelen = len; - shm->conf.polling = false; - shm->exec = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: { s: s }, s: { s: s }, s?: i, s?: o, s?: s }", "out", "name", &shm->out_name, @@ -103,9 +108,29 @@ int shmem_parse(struct vnode *n, json_t *json) return 0; } -int shmem_start(struct vnode *n) +int villas::node::shmem_prepare(NodeCompat *n) { - struct shmem *shm = (struct shmem *) n->_vd; + auto *shm = n->getData(); + + 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 (n->getOutputSignals(true)) + output_sigs = n->getOutputSignals(true)->size(); + + shm->conf.samplelen = MAX(input_sigs, output_sigs); + } + + return 0; +} + +int villas::node::shmem_start(NodeCompat *n) +{ + auto *shm = n->getData(); int ret; if (shm->exec) { @@ -123,18 +148,18 @@ int shmem_start(struct vnode *n) return 0; } -int shmem_stop(struct vnode *n) +int villas::node::shmem_stop(NodeCompat *n) { - struct shmem* shm = (struct shmem *) n->_vd; + auto* shm = n->getData(); return shmem_int_close(&shm->intf); } -int shmem_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct shmem *shm = (struct shmem *) n->_vd; + auto *shm = n->getData(); int recv; - struct sample *shared_smps[cnt]; + struct Sample *shared_smps[cnt]; do { recv = shmem_int_read(&shm->intf, shared_smps, cnt); @@ -146,7 +171,7 @@ int shmem_read(struct vnode *n, struct sample * const smps[], unsigned cnt) n->logger->info("Shared memory segment has been closed."); - n->state = State::STOPPING; + n->setState(State::STOPPING); return recv; } @@ -156,15 +181,15 @@ int shmem_read(struct vnode *n, struct sample * const smps[], unsigned cnt) /** @todo signal descriptions are currently not shared between processes */ for (int i = 0; i < recv; i++) - smps[i]->signals = &n->in.signals; + smps[i]->signals = n->getInputSignals(false); return recv; } -int shmem_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct shmem *shm = (struct shmem *) n->_vd; - struct sample *shared_smps[cnt]; /* Samples need to be copied to the shared pool first */ + 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); @@ -182,9 +207,9 @@ int shmem_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return pushed; } -char * shmem_print(struct vnode *n) +char * villas::node::shmem_print(NodeCompat *n) { - struct shmem *shm = (struct shmem *) n->_vd; + auto *shm = n->getData(); char *buf = nullptr; strcatf(&buf, "out_name=%s, in_name=%s, queuelen=%d, polling=%s", @@ -202,7 +227,7 @@ char * shmem_print(struct vnode *n) return buf; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -216,9 +241,8 @@ static void register_plugin() { p.stop = shmem_stop; p.read = shmem_read; p.write = shmem_write; + p.prepare = shmem_prepare; + p.init = shmem_init; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/signal.cpp b/lib/nodes/signal.cpp new file mode 100644 index 000000000..82beea6c0 --- /dev/null +++ b/lib/nodes/signal.cpp @@ -0,0 +1,396 @@ +/** Node-type for signal generation. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +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); + + 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; + + throw std::invalid_argument("Invalid signal type"); +} + +std::string SignalNodeSignal::typeToString(enum Type type) +{ + switch (type) { + case Type::CONSTANT: + return "constant"; + + case Type::SINE: + return "sine"; + + case Type::TRIANGLE: + return "triangle"; + + case Type::SQUARE: + return "square"; + + case Type::RAMP: + return "ramp"; + + case Type::COUNTER: + return "counter"; + + case Type::RANDOM: + return "random"; + + case Type::MIXED: + return "mixed"; + + case Type::PULSE: + return "pulse"; + + default: + return nullptr; + } +} + +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; + } +} + +int SignalNodeSignal::parse(json_t *json) +{ + int ret; + const char *type_str; + + json_error_t err; + + 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"); + + try { + type = lookupType(type_str); + } catch (std::invalid_argument &e) { + throw ConfigError(json, "node-config-node-signal-type", "Unknown signal type: {}", type_str); + } + + return 0; +} + +Signal::Ptr SignalNodeSignal::toSignal(Signal::Ptr tpl) const +{ + auto isDefaultName = tpl->name.rfind("signal", 0) == 0; + + auto name = isDefaultName ? typeToString(type) : tpl->name; + auto unit = tpl->unit; + + auto sig = std::make_shared(name, unit, SignalType::FLOAT); + + sig->init.f = offset; + + return sig; +} + +SignalNode::SignalNode(const std::string &name) : + Node(name), + task(CLOCK_MONOTONIC), + rt(1), + rate(10), + monitor_missed(true), + limit(-1), + missed_steps(0) +{ } + +int SignalNode::prepare() +{ + assert(state == State::CHECKED); + + for (unsigned i = 0; i < signals.size(); i++) { + auto &sig = (*in.signals)[i]; + auto &ssig = signals[i]; + + sig = ssig.toSignal(sig); + } + + in.signals->dump(logger); + + return Node::prepare(); +} + +int SignalNode::parse(json_t *json, const uuid_t sn_uuid) +{ + int r = -1, m = -1, ret = Node::parse(json, sn_uuid); + if (ret) + return ret; + + json_error_t err; + + size_t i; + json_t *json_signals, *json_signal; + + 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 (r >= 0) + rt = r != 0; + + 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::start() +{ + assert(state == State::PREPARED || + state == State::PAUSED); + + missed_steps = 0; + started = time_now(); + + for (auto sig : signals) + sig.start(); + + /* Setup task */ + if (rt) + task.setRate(rate); + + int ret = Node::start(); + if (!ret) + state = State::STARTED; + + return ret; +} + +int SignalNode::stop() +{ + assert(state == State::STARTED || + state == State::PAUSED || + state == State::STOPPING); + + int ret = Node::stop(); + if (ret) + return ret; + + if (rt) + task.stop(); + + if (missed_steps > 0 && monitor_missed) + logger->warn("Missed a total of {} steps.", missed_steps); + + state = State::STOPPED; + + return 0; +} + +int SignalNode::_read(struct Sample *smps[], unsigned cnt) +{ + struct Sample *t = smps[0]; + + struct timespec ts; + uint64_t steps, counter = sequence - sequence_init; + + 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; +} + +const std::string & SignalNode::getDetails() +{ + if (details.empty()) { + details = fmt::format("rt={}, rate={}", rt ? "yes" : "no", rate); + + if (limit > 0) + details += fmt::format(", limit={}", limit); + + } + + return details; +} + +std::vector SignalNode::getPollFDs() +{ + if (rt) + return { task.getFD() }; + + return {}; +} + +static char n[] = "signal.v2"; +static char d[] = "Signal generator"; +static NodePlugin p; diff --git a/lib/nodes/signal_generator.cpp b/lib/nodes/signal_v1.cpp similarity index 68% rename from lib/nodes/signal_generator.cpp rename to lib/nodes/signal_v1.cpp index 5eff67207..d1c5ed13d 100644 --- a/lib/nodes/signal_generator.cpp +++ b/lib/nodes/signal_v1.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,66 +26,68 @@ #include #include -#include -#include +#include +#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static enum signal_generator::SignalType signal_generator_lookup_type(const char *type) +static +enum signal_node::SignalType signal_node_lookup_type(const char *type) { if (!strcmp(type, "random")) - return signal_generator::SignalType::RANDOM; + return signal_node::SignalType::RANDOM; else if (!strcmp(type, "sine")) - return signal_generator::SignalType::SINE; + return signal_node::SignalType::SINE; else if (!strcmp(type, "square")) - return signal_generator::SignalType::SQUARE; + return signal_node::SignalType::SQUARE; else if (!strcmp(type, "triangle")) - return signal_generator::SignalType::TRIANGLE; + return signal_node::SignalType::TRIANGLE; else if (!strcmp(type, "ramp")) - return signal_generator::SignalType::RAMP; + return signal_node::SignalType::RAMP; else if (!strcmp(type, "counter")) - return signal_generator::SignalType::COUNTER; + return signal_node::SignalType::COUNTER; else if (!strcmp(type, "constant")) - return signal_generator::SignalType::CONSTANT; + return signal_node::SignalType::CONSTANT; else if (!strcmp(type, "mixed")) - return signal_generator::SignalType::MIXED; + return signal_node::SignalType::MIXED; else if (!strcmp(type, "pulse")) - return signal_generator::SignalType::PULSE; + return signal_node::SignalType::PULSE; throw std::invalid_argument("Invalid signal type"); } -static const char * signal_generator_type_str(enum signal_generator::SignalType type) +static +const char * signal_node_type_str(enum signal_node::SignalType type) { switch (type) { - case signal_generator::SignalType::CONSTANT: + case signal_node::SignalType::CONSTANT: return "constant"; - case signal_generator::SignalType::SINE: + case signal_node::SignalType::SINE: return "sine"; - case signal_generator::SignalType::TRIANGLE: + case signal_node::SignalType::TRIANGLE: return "triangle"; - case signal_generator::SignalType::SQUARE: + case signal_node::SignalType::SQUARE: return "square"; - case signal_generator::SignalType::RAMP: + case signal_node::SignalType::RAMP: return "ramp"; - case signal_generator::SignalType::COUNTER: + case signal_node::SignalType::COUNTER: return "counter"; - case signal_generator::SignalType::RANDOM: + case signal_node::SignalType::RANDOM: return "random"; - case signal_generator::SignalType::MIXED: + case signal_node::SignalType::MIXED: return "mixed"; - case signal_generator::SignalType::PULSE: + case signal_node::SignalType::PULSE: return "pulse"; default: @@ -93,9 +95,9 @@ static const char * signal_generator_type_str(enum signal_generator::SignalType } } -int signal_generator_init(struct vnode *n) +int villas::node::signal_node_init(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); new (&s->task) Task(CLOCK_MONOTONIC); @@ -105,6 +107,7 @@ int signal_generator_init(struct vnode *n) s->rate = 10; s->monitor_missed = 1; + s->type = nullptr; s->frequency = nullptr; s->amplitude = nullptr; s->stddev = nullptr; @@ -117,46 +120,60 @@ int signal_generator_init(struct vnode *n) return 0; } -int signal_generator_destroy(struct vnode *n) +int villas::node::signal_node_destroy(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); s->task.~Task(); + if (s->type) + delete[] s->type; + if (s->frequency) - delete s->frequency; + delete[] s->frequency; if (s->amplitude) - delete s->amplitude; + delete[] s->amplitude; if (s->stddev) - delete s->stddev; + delete[] s->stddev; if (s->offset) - delete s->offset; + delete[] s->offset; + + if (s->phase) + delete[] s->phase; + + if (s->pulse_width) + delete[] s->pulse_width; + + if (s->pulse_low) + delete[] s->pulse_low; + + if (s->pulse_high) + delete[] s->pulse_high; return 0; } -int signal_generator_prepare(struct vnode *n) +int villas::node::signal_node_prepare(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; - - assert(vlist_length(&n->in.signals) == 0); + auto *s = n->getData(); + n->in.signals = std::make_shared(); for (unsigned i = 0; i < s->values; i++) { - auto name = signal_generator_type_str((enum signal_generator::SignalType) s->type[i]); - auto *sig = signal_create(name, nullptr, SignalType::FLOAT); + auto name = signal_node_type_str((enum signal_node::SignalType) s->type[i]); + auto sig = std::make_shared(name, "", SignalType::FLOAT); - vlist_push(&n->in.signals, sig); + n->in.signals->push_back(sig); } return 0; } -int signal_generator_parse(struct vnode *n, json_t *json) +int villas::node::signal_node_parse(NodeCompat *n, json_t *json) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); int ret; @@ -212,9 +229,9 @@ int signal_generator_parse(struct vnode *n, json_t *json) size_t i; json_t *json_value; const char *type_str; - signal_generator::SignalType type; + signal_node::SignalType type; - s->type = new enum signal_generator::SignalType[s->values]; + s->type = new enum signal_node::SignalType[s->values]; switch (json_typeof(json_type)) { case JSON_ARRAY: @@ -226,17 +243,17 @@ int signal_generator_parse(struct vnode *n, json_t *json) if (!type_str) throw ConfigError(json_value, "node-config-node-signal", "Signal type must be a string"); - s->type[i] = signal_generator_lookup_type(type_str); + s->type[i] = signal_node_lookup_type(type_str); } break; case JSON_STRING: type_str = json_string_value(json_type); - type = signal_generator_lookup_type(type_str); + type = signal_node_lookup_type(type_str); for (size_t i = 0; i < s->values; i++) { - s->type[i] = (type == signal_generator::SignalType::MIXED - ? (signal_generator::SignalType) (i % 7) + s->type[i] = (type == signal_node::SignalType::MIXED + ? (signal_node::SignalType) (i % 7) : type); } break; @@ -288,9 +305,9 @@ int signal_generator_parse(struct vnode *n, json_t *json) return 0; } -int signal_generator_start(struct vnode *n) +int villas::node::signal_node_start(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); s->missed_steps = 0; s->counter = 0; @@ -309,9 +326,9 @@ int signal_generator_start(struct vnode *n) return 0; } -int signal_generator_stop(struct vnode *n) +int villas::node::signal_node_stop(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); if (s->rt) s->task.stop(); @@ -324,10 +341,10 @@ int signal_generator_stop(struct vnode *n) return 0; } -int signal_generator_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct signal_generator *s = (struct signal_generator *) n->_vd; - struct sample *t = smps[0]; + auto *s = n->getData(); + struct Sample *t = smps[0]; struct timespec ts; int steps; @@ -350,43 +367,43 @@ int signal_generator_read(struct vnode *n, struct sample * const smps[], unsigne t->ts.origin = ts; t->sequence = s->counter; t->length = MIN(s->values, t->capacity); - t->signals = &n->in.signals; + t->signals = n->getInputSignals(false); for (unsigned i = 0; i < t->length; i++) { switch (s->type[i]) { - case signal_generator::SignalType::CONSTANT: + case signal_node::SignalType::CONSTANT: t->data[i].f = s->offset[i] + s->amplitude[i]; break; - case signal_generator::SignalType::SINE: + 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_generator::SignalType::TRIANGLE: + 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_generator::SignalType::SQUARE: + 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_generator::SignalType::RAMP: + case signal_node::SignalType::RAMP: t->data[i].f = s->offset[i] + s->amplitude[i] * fmod(running, s->frequency[i]); break; - case signal_generator::SignalType::COUNTER: + case signal_node::SignalType::COUNTER: t->data[i].f = s->offset[i] + s->amplitude[i] * s->counter; break; - case signal_generator::SignalType::RANDOM: + case signal_node::SignalType::RANDOM: s->last[i] += boxMuller(0, s->stddev[i]); t->data[i].f = s->last[i]; break; - case signal_generator::SignalType::MIXED: + case signal_node::SignalType::MIXED: break; - case signal_generator::SignalType::PULSE: + 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]; @@ -398,7 +415,7 @@ int signal_generator_read(struct vnode *n, struct sample * const smps[], unsigne if (s->limit > 0 && s->counter >= (unsigned) s->limit) { n->logger->info("Reached limit."); - n->state = State::STOPPING; + n->setState(State::STOPPING); return -1; } @@ -418,9 +435,9 @@ int signal_generator_read(struct vnode *n, struct sample * const smps[], unsigne return 1; } -char * signal_generator_print(struct vnode *n) +char * villas::node::signal_node_print(NodeCompat *n) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); char *buf = nullptr; strcatf(&buf, "rt=%s, rate=%.2f, values=%d", s->rt ? "yes" : "no", s->rate, s->values); @@ -431,9 +448,9 @@ char * signal_generator_print(struct vnode *n) return buf; } -int signal_generator_poll_fds(struct vnode *n, int fds[]) +int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) { - struct signal_generator *s = (struct signal_generator *) n->_vd; + auto *s = n->getData(); if (s->rt) { fds[0] = s->task.getFD(); @@ -444,27 +461,24 @@ int signal_generator_poll_fds(struct vnode *n, int fds[]) return 0; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { p.name = "signal"; - p.description = "Signal generator"; + p.description = "Legacy Signal generator"; p.vectorize = 1; - p.flags = (int) NodeFlags::PROVIDES_SIGNALS; - p.size = sizeof(struct signal_generator); - p.init = signal_generator_init; - p.destroy = signal_generator_destroy; - p.parse = signal_generator_parse; - p.prepare = signal_generator_prepare; - p.print = signal_generator_print; - p.start = signal_generator_start; - p.stop = signal_generator_stop; - p.read = signal_generator_read; - p.poll_fds = signal_generator_poll_fds; + 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; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/socket.cpp b/lib/nodes/socket.cpp index 2c5b428b2..580af51f8 100644 --- a/lib/nodes/socket.cpp +++ b/lib/nodes/socket.cpp @@ -1,7 +1,7 @@ /** The socket node-type for Layer 2, 3, 4 BSD-style sockets * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,10 +26,10 @@ #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -43,20 +43,22 @@ #include #endif /* WITH_NETEM */ -/* Forward declartions */ -static struct vnode_type p; - using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -int socket_type_start(villas::node::SuperNode *sn) +/* Forward declartions */ +static NodeCompatType p; +static NodeCompatFactory ncp(&p); + +int villas::node::socket_type_start(villas::node::SuperNode *sn) { #ifdef WITH_NETEM /* Gather list of used network interfaces */ - for (auto *n : p.instances) { - struct socket *s = (struct socket *) n->_vd; + for (auto *n : ncp.instances) { + auto *nc = dynamic_cast(n); + auto *s = nc->getData(); if (s->layer == SocketLayer::UNIX) continue; @@ -71,9 +73,28 @@ int socket_type_start(villas::node::SuperNode *sn) return 0; } -char * socket_print(struct vnode *n) +int villas::node::socket_init(NodeCompat *n) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); + + s->formatter = nullptr; + + return 0; +} + +int villas::node::socket_destroy(NodeCompat *n) +{ + auto *s = n->getData(); + + if (s->formatter) + delete s->formatter; + + return 0; +} + +char * villas::node::socket_print(NodeCompat *n) +{ + auto *s = n->getData(); const char *layer = nullptr; char *buf; @@ -120,9 +141,9 @@ char * socket_print(struct vnode *n) return buf; } -int socket_check(struct vnode *n) +int villas::node::socket_check(NodeCompat *n) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); /* Some checks on the addresses */ if (s->layer != SocketLayer::UNIX) { @@ -156,13 +177,13 @@ int socket_check(struct vnode *n) return 0; } -int socket_start(struct vnode *n) +int villas::node::socket_start(NodeCompat *n) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); int ret; /* Initialize IO */ - s->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + s->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); /* Create socket */ switch (s->layer) { @@ -278,9 +299,9 @@ int socket_start(struct vnode *n) return 0; } -int socket_reverse(struct vnode *n) +int villas::node::socket_reverse(NodeCompat *n) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); union sockaddr_union tmp; tmp = s->in.saddr; @@ -290,10 +311,10 @@ int socket_reverse(struct vnode *n) return 0; } -int socket_stop(struct vnode *n) +int villas::node::socket_stop(NodeCompat *n) { int ret; - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); if (s->multicast.enabled) { ret = setsockopt(s->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &s->multicast.mreq, sizeof(s->multicast.mreq)); @@ -307,17 +328,16 @@ int socket_stop(struct vnode *n) return ret; } - delete s->formatter; delete[] s->in.buf; delete[] s->out.buf; return 0; } -int socket_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::socket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); char *ptr; ssize_t bytes; @@ -328,8 +348,12 @@ int socket_read(struct vnode *n, struct sample * const smps[], unsigned cnt) /* Receive next sample */ bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); - if (bytes < 0) + if (bytes < 0) { + if (errno == EINTR) + return -1; + throw SystemError("Failed recvfrom()"); + } else if (bytes == 0) return 0; @@ -372,9 +396,9 @@ int socket_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return ret; } -int socket_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::socket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); int ret; ssize_t bytes; @@ -444,10 +468,10 @@ retry2: bytes = sendto(s->sd, s->out.buf, wbytes, 0, (struct sockaddr *) &s->out return cnt; } -int socket_parse(struct vnode *n, json_t *json) +int villas::node::socket_parse(NodeCompat *n, json_t *json) { int ret; - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); const char *local, *remote; const char *layer = nullptr; @@ -474,6 +498,8 @@ int socket_parse(struct vnode *n, json_t *json) 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"); @@ -537,9 +563,9 @@ int socket_parse(struct vnode *n, json_t *json) return 0; } -int socket_fds(struct vnode *n, int fds[]) +int villas::node::socket_fds(NodeCompat *n, int fds[]) { - struct socket *s = (struct socket *) n->_vd; + auto *s = n->getData(); fds[0] = s->sd; @@ -555,9 +581,11 @@ static void register_plugin() { p.description = "BSD network sockets for Ethernet / IP / UDP"; #endif p.vectorize = 0; - p.size = sizeof(struct socket); + 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; @@ -567,9 +595,4 @@ static void register_plugin() { p.write = socket_write; p.poll_fds = socket_fds; p.netem_fds = socket_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); } diff --git a/lib/nodes/stats.cpp b/lib/nodes/stats.cpp index fd7a7ed7c..958897e81 100644 --- a/lib/nodes/stats.cpp +++ b/lib/nodes/stats.cpp @@ -1,7 +1,7 @@ /** Sending statistics to another node. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,12 +22,12 @@ #include -#include +#include #include #include #include #include -#include +#include #include using namespace villas; @@ -36,14 +36,14 @@ using namespace villas::utils; static NodeList nodes; /** The global list of nodes */ -int stats_node_signal_destroy(struct stats_node_signal *s) +int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) { free(s->node_str); return 0; } -int stats_node_signal_parse(struct stats_node_signal *s, json_t *json) +int villas::node::stats_node_signal_parse(struct stats_node_signal *s, json_t *json) { json_error_t err; @@ -84,103 +84,102 @@ invalid_format: return -1; } -int stats_node_type_start(villas::node::SuperNode *sn) +int villas::node::stats_node_type_start(villas::node::SuperNode *sn) { nodes = sn->getNodes(); return 0; } -int stats_node_prepare(struct vnode *n) +int villas::node::stats_node_prepare(NodeCompat *n) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); - assert(vlist_length(&n->in.signals) == 0); + assert(n->getInputSignals(false)->size() == 0); /* Generate signal list */ - for (size_t i = 0; i < vlist_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) vlist_at(&s->signals, i); - struct signal *sig; + 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; auto name = fmt::format("{}.{}.{}", stats_sig->node_str, metric, type); - sig = signal_create(name.c_str(), + auto sig = std::make_shared(name.c_str(), Stats::metrics[stats_sig->metric].unit, Stats::types[stats_sig->type].signal_type); - vlist_push(&n->in.signals, sig); + n->in.signals->push_back(sig); } return 0; } -int stats_node_start(struct vnode *n) +int villas::node::stats_node_start(NodeCompat *n) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); s->task.setRate(s->rate); - for (size_t i = 0; i < vlist_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) vlist_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->config, "node-config-node-stats-node", "Invalid reference node {}", stats_sig->node_str); + throw ConfigError(n->getConfig(), "node-config-node-stats-node", "Invalid reference node {}", stats_sig->node_str); } return 0; } -int stats_node_stop(struct vnode *n) +int villas::node::stats_node_stop(NodeCompat *n) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); s->task.stop(); return 0; } -char * stats_node_print(struct vnode *n) +char * villas::node::stats_node_print(NodeCompat *n) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); return strf("rate=%f", s->rate); } -int stats_node_init(struct vnode *n) +int villas::node::stats_node_init(NodeCompat *n) { int ret; - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); new (&s->task) Task(CLOCK_MONOTONIC); - ret = vlist_init(&s->signals); + ret = list_init(&s->signals); if (ret) return ret; return 0; } -int stats_node_destroy(struct vnode *n) +int villas::node::stats_node_destroy(NodeCompat *n) { int ret; - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); s->task.~Task(); - ret = vlist_destroy(&s->signals, (dtor_cb_t) stats_node_signal_destroy, true); + ret = list_destroy(&s->signals, (dtor_cb_t) stats_node_signal_destroy, true); if (ret) return ret; return 0; } -int stats_node_parse(struct vnode *n, json_t *json) +int villas::node::stats_node_parse(NodeCompat *n, json_t *json) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); int ret; size_t i; @@ -210,27 +209,27 @@ int stats_node_parse(struct vnode *n, json_t *json) if (ret) throw ConfigError(json_signal, "node-config-node-stats-signals", "Failed to parse statistics signal definition"); - vlist_push(&s->signals, stats_sig); + list_push(&s->signals, stats_sig); } return 0; } -int stats_node_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::stats_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); if (!cnt) return 0; s->task.wait(); - unsigned len = MIN(vlist_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 *) vlist_at(&s->signals, i); + struct stats_node_signal *sig = (struct stats_node_signal *) list_at(&s->signals, i); - auto st = sig->node->stats; + auto st = sig->node->getStats(); if (!st) return -1; @@ -239,28 +238,28 @@ int stats_node_read(struct vnode *n, struct sample * const smps[], unsigned cnt) smps[0]->length = len; smps[0]->flags = (int) SampleFlags::HAS_DATA; - smps[0]->signals = &n->in.signals; + smps[0]->signals = n->getInputSignals(false); return 1; } -int stats_node_poll_fds(struct vnode *n, int fds[]) +int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) { - struct stats_node *s = (struct stats_node *) n->_vd; + auto *s = n->getData(); fds[0] = s->task.getFD(); return 0; } -static struct vnode_type 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) NodeFlags::PROVIDES_SIGNALS; + 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; @@ -273,8 +272,5 @@ static void register_plugin() { p.read = stats_node_read; p.poll_fds = stats_node_poll_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/temper.cpp b/lib/nodes/temper.cpp index 374e49ea5..25c5a76a3 100644 --- a/lib/nodes/temper.cpp +++ b/lib/nodes/temper.cpp @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ static std::list devices; static struct libusb_context *context; /* Forward declartions */ -static struct vnode_type p; +static NodeCompatType p; TEMPerDevice::TEMPerDevice(struct libusb_device *dev) : @@ -91,7 +91,7 @@ void TEMPerDevice::close() libusb_close(handle); } -void TEMPerDevice::read(struct sample *smp) +void TEMPerDevice::read(struct Sample *smp) { unsigned char answer[8]; float temp[2]; @@ -244,7 +244,7 @@ bool TEMPerHUMDevice::match(struct libusb_device *dev) desc.idVendor == 0x7402; } -int temper_type_start(villas::node::SuperNode *sn) +int villas::node::temper_type_start(villas::node::SuperNode *sn) { context = usb::get_context(); @@ -273,16 +273,16 @@ int temper_type_start(villas::node::SuperNode *sn) return 0; } -int temper_type_stop() +int villas::node::temper_type_stop() { usb::deinit_context(context); return 0; } -int temper_init(struct vnode *n) +int villas::node::temper_init(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); t->calibration.scale = 1.0; t->calibration.offset = 0.0; @@ -297,9 +297,9 @@ int temper_init(struct vnode *n) return 0; } -int temper_destroy(struct vnode *n) +int villas::node::temper_destroy(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); if (t->device) delete t->device; @@ -307,10 +307,10 @@ int temper_destroy(struct vnode *n) return 0; } -int temper_parse(struct vnode *n, json_t *json) +int villas::node::temper_parse(NodeCompat *n, json_t *json) { int ret; - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); json_error_t err; @@ -328,9 +328,9 @@ int temper_parse(struct vnode *n, json_t *json) return 0; } -char * temper_print(struct vnode *n) +char * villas::node::temper_print(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + 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(), @@ -343,9 +343,9 @@ char * temper_print(struct vnode *n) ); } -int temper_prepare(struct vnode *n) +int villas::node::temper_prepare(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); /* Find matching USB device */ t->device = nullptr; @@ -360,48 +360,48 @@ int temper_prepare(struct vnode *n) throw RuntimeError("No matching TEMPer USB device found!"); /* Create signal list */ - assert(vlist_length(&n->in.signals) == 0); + assert(n->getInputSignals(false)->size() == 0); /* Temperature 1 */ - auto *sig1 = signal_create(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - vlist_push(&n->in.signals, sig1); + 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 = signal_create(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - vlist_push(&n->in.signals, sig2); + 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 = signal_create("humidity", "%", SignalType::FLOAT); - vlist_push(&n->in.signals, sig3); + auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); + n->in.signals->push_back(sig3); } return 0; } -int temper_start(struct vnode *n) +int villas::node::temper_start(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); t->device->open(); return 0; } -int temper_stop(struct vnode *n) +int villas::node::temper_stop(NodeCompat *n) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); t->device->close(); return 0; } -int temper_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct temper *t = (struct temper *) n->_vd; + auto *t = n->getData(); assert(cnt == 1); @@ -415,7 +415,7 @@ static void register_plugin() { p.name = "temper"; p.description = "An temper for staring new node-type implementations"; p.vectorize = 1; - p.flags = (int) NodeFlags::PROVIDES_SIGNALS; + p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; p.size = sizeof(struct temper); p.type.start = temper_type_start; p.type.stop = temper_type_stop; @@ -428,8 +428,5 @@ static void register_plugin() { p.stop = temper_stop; p.read = temper_read; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/test_rtt.cpp b/lib/nodes/test_rtt.cpp index d9e21e34d..3963deee8 100644 --- a/lib/nodes/test_rtt.cpp +++ b/lib/nodes/test_rtt.cpp @@ -2,7 +2,7 @@ /** Node type: Node-type for testing Round-trip Time. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,24 +27,25 @@ #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 struct vnode_type p; +static NodeCompatType p; -static int test_rtt_case_start(struct vnode *n, int id) +static +int test_rtt_case_start(NodeCompat *n, int id) { - struct test_rtt *t = (struct test_rtt *) n->_vd; - struct test_rtt_case *c = (struct test_rtt_case *) vlist_at(&t->cases, 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); @@ -62,10 +63,11 @@ static int test_rtt_case_start(struct vnode *n, int id) return 0; } -static int test_rtt_case_stop(struct vnode *n, int id) +static +int test_rtt_case_stop(NodeCompat *n, int id) { int ret; - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); /* Stop timer */ t->task.stop(); @@ -79,7 +81,8 @@ static int test_rtt_case_stop(struct vnode *n, int id) return 0; } -static int test_rtt_case_destroy(struct test_rtt_case *c) +static +int test_rtt_case_destroy(struct test_rtt_case *c) { if (c->filename) free(c->filename); @@ -90,11 +93,10 @@ static int test_rtt_case_destroy(struct test_rtt_case *c) return 0; } -int test_rtt_prepare(struct vnode *n) +int villas::node::test_rtt_prepare(NodeCompat *n) { - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); - int ret; unsigned max_values = 0; /* Take current for time for test case prefix */ @@ -102,8 +104,8 @@ int test_rtt_prepare(struct vnode *n) struct tm tm; gmtime_r(&ts, &tm); - for (size_t i = 0; i < vlist_length(&t->cases); i++) { - struct test_rtt_case *c = (struct test_rtt_case *) vlist_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; @@ -115,20 +117,18 @@ int test_rtt_prepare(struct vnode *n) strftime(c->filename_formatted, NAME_MAX, c->filename, &tm); } - ret = signal_list_generate(&n->in.signals, max_values, SignalType::FLOAT); - if (ret) - return ret; + n->in.signals = std::make_shared(max_values, SignalType::FLOAT); return 0; } -int test_rtt_parse(struct vnode *n, json_t *json) +int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) { int ret; - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); const char *output = "."; - const char *prefix = node_name_short(n); + const char *prefix = nullptr; std::vector rates; std::vector values; @@ -141,7 +141,7 @@ int test_rtt_parse(struct vnode *n, json_t *json) t->cooldown = 0; /* Generate list of test cases */ - ret = vlist_init(&t->cases); + ret = list_init(&t->cases); if (ret) return ret; @@ -156,7 +156,7 @@ int test_rtt_parse(struct vnode *n, json_t *json) throw ConfigError(json, err, "node-config-node-test-rtt"); t->output = strdup(output); - t->prefix = strdup(prefix); + t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); /* Initialize IO module */ if (!json_format) @@ -166,7 +166,7 @@ int test_rtt_parse(struct vnode *n, json_t *json) if (!t->formatter) throw ConfigError(json, "node-config-node-test-rtt-format", "Invalid value for setting 'format'"); - /* Construct vlist 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."); @@ -239,7 +239,7 @@ int test_rtt_parse(struct vnode *n, json_t *json) c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, c->values, c->rate); - vlist_push(&t->cases, c); + list_push(&t->cases, c); } } } @@ -247,21 +247,23 @@ int test_rtt_parse(struct vnode *n, json_t *json) return 0; } -int test_rtt_init(struct vnode *n) +int villas::node::test_rtt_init(NodeCompat *n) { - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); new (&t->task) Task(CLOCK_MONOTONIC); + t->formatter = nullptr; + return 0; } -int test_rtt_destroy(struct vnode *n) +int villas::node::test_rtt_destroy(NodeCompat *n) { int ret; - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); - ret = vlist_destroy(&t->cases, (dtor_cb_t) test_rtt_case_destroy, true); + ret = list_destroy(&t->cases, (dtor_cb_t) test_rtt_case_destroy, true); if (ret) return ret; @@ -273,22 +275,25 @@ int test_rtt_destroy(struct vnode *n) if (t->prefix) free(t->prefix); + if (t->formatter) + delete t->formatter; + return 0; } -char * test_rtt_print(struct vnode *n) +char * villas::node::test_rtt_print(NodeCompat *n) { - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); - return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, t->prefix, t->cooldown, vlist_length(&t->cases)); + return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, t->prefix, t->cooldown, list_length(&t->cases)); } -int test_rtt_start(struct vnode *n) +int villas::node::test_rtt_start(NodeCompat *n) { int ret; struct stat st; - struct test_rtt *t = (struct test_rtt *) n->_vd; - struct test_rtt_case *c = (struct test_rtt_case *) vlist_first(&t->cases); + 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); @@ -298,7 +303,7 @@ int test_rtt_start(struct vnode *n) throw SystemError("Failed to create output directory: {}", t->output); } - t->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_DATA); + t->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_DATA); t->task.setRate(c->rate); @@ -308,10 +313,10 @@ int test_rtt_start(struct vnode *n) return 0; } -int test_rtt_stop(struct vnode *n) +int villas::node::test_rtt_stop(NodeCompat *n) { int ret; - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); if (t->counter >= 0) { ret = test_rtt_case_stop(n, t->current); @@ -324,13 +329,13 @@ int test_rtt_stop(struct vnode *n) return 0; } -int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; unsigned i; uint64_t steps; - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); /* Handle start/stop of new cases */ if (t->counter == -1) { @@ -345,10 +350,10 @@ int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) t->current++; } - if ((unsigned) t->current >= vlist_length(&t->cases)) { + if ((unsigned) t->current >= list_length(&t->cases)) { n->logger->info("This was the last case."); - n->state = State::STOPPING; + n->setState(State::STOPPING); return -1; } @@ -359,7 +364,7 @@ int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } } - struct test_rtt_case *c = (struct test_rtt_case *) vlist_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(); @@ -387,7 +392,7 @@ int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) 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->in.signals; + smps[i]->signals = n->getInputSignals(false); t->counter++; } @@ -396,14 +401,14 @@ int test_rtt_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } } -int test_rtt_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); if (t->current < 0) return 0; - struct test_rtt_case *c = (struct test_rtt_case *) vlist_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++) { @@ -418,9 +423,9 @@ int test_rtt_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return i; } -int test_rtt_poll_fds(struct vnode *n, int fds[]) +int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) { - struct test_rtt *t = (struct test_rtt *) n->_vd; + auto *t = n->getData(); fds[0] = t->task.getFD(); @@ -432,7 +437,7 @@ static void register_plugin() { p.name = "test_rtt"; p.description = "Test round-trip time with loopback"; p.vectorize = 0; - p.flags = (int) NodeFlags::PROVIDES_SIGNALS; + p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; p.size = sizeof(struct test_rtt); p.parse = test_rtt_parse; p.prepare = test_rtt_prepare; @@ -444,8 +449,5 @@ static void register_plugin() { p.read = test_rtt_read; p.write = test_rtt_write; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/uldaq.cpp b/lib/nodes/uldaq.cpp index d7ce8dd03..1ff137cde 100644 --- a/lib/nodes/uldaq.cpp +++ b/lib/nodes/uldaq.cpp @@ -3,7 +3,7 @@ * @file * @author Manuel Pitz * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,11 +24,11 @@ #include -#include -#include +#include +#include #include #include -#include +#include #include using namespace villas; @@ -107,7 +107,8 @@ static const struct { { "unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005 } }; -static AiInputMode uldaq_parse_input_mode(const char *str) +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)) @@ -117,7 +118,8 @@ static AiInputMode uldaq_parse_input_mode(const char *str) return (AiInputMode) -1; } -static DaqDeviceInterface uldaq_parse_interface_type(const char *str) +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)) @@ -127,7 +129,8 @@ static DaqDeviceInterface uldaq_parse_interface_type(const char *str) return (DaqDeviceInterface) -1; } -static const char * uldaq_print_interface_type(DaqDeviceInterface iftype) +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) @@ -137,7 +140,8 @@ static const char * uldaq_print_interface_type(DaqDeviceInterface iftype) return nullptr; } -static Range uldaq_parse_range(const char *str) +static +Range uldaq_parse_range(const char *str) { for (unsigned i = 0; i < ARRAY_LEN(ranges); i++) { if (!strcmp(ranges[i].name, str)) @@ -147,7 +151,8 @@ static Range uldaq_parse_range(const char *str) return (Range) -1; } -static DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) { +static +DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) { DaqDeviceDescriptor *d = nullptr; if (num_devs == 0) @@ -175,9 +180,10 @@ static DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) { return nullptr; } -static int uldaq_connect(struct vnode *n) +static +int uldaq_connect(NodeCompat *n) { - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); UlError err; /* Find Matching device */ @@ -213,7 +219,7 @@ static int uldaq_connect(struct vnode *n) return 0; } -int uldaq_type_start(villas::node::SuperNode *sn) +int villas::node::uldaq_type_start(villas::node::SuperNode *sn) { UlError err; @@ -233,10 +239,10 @@ int uldaq_type_start(villas::node::SuperNode *sn) return 0; } -int uldaq_init(struct vnode *n) +int villas::node::uldaq_init(NodeCompat *n) { int ret; - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); u->device_id = nullptr; u->device_interface_type = ANY_IFC; @@ -257,10 +263,10 @@ int uldaq_init(struct vnode *n) return 0; } -int uldaq_destroy(struct vnode *n) +int villas::node::uldaq_destroy(NodeCompat *n) { int ret; - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); if (u->in.queues) delete[] u->in.queues; @@ -276,10 +282,10 @@ int uldaq_destroy(struct vnode *n) return 0; } -int uldaq_parse(struct vnode *n, json_t *json) +int villas::node::uldaq_parse(NodeCompat *n, json_t *json) { int ret; - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); const char *default_range_str = nullptr; const char *default_input_mode_str = nullptr; @@ -313,7 +319,7 @@ int uldaq_parse(struct vnode *n, json_t *json) if (u->in.queues) delete[] u->in.queues; - u->in.channel_count = vlist_length(&n->in.signals); + u->in.channel_count = n->getInputSignals(false)->size(); u->in.queues = new struct AiQueueElement[u->in.channel_count]; if (!u->in.queues) throw MemoryAllocationError(); @@ -361,9 +367,9 @@ int uldaq_parse(struct vnode *n, json_t *json) return ret; } -char * uldaq_print(struct vnode *n) +char * villas::node::uldaq_print(NodeCompat *n) { - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); char *buf = nullptr; @@ -386,16 +392,16 @@ char * uldaq_print(struct vnode *n) return buf; } -int uldaq_check(struct vnode *n) +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; - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); UlError err; if (n->in.vectorize < 100) - throw ConfigError(n->config, "node-config-node-vectorize", "Setting 'vectorize' must be larger than 100"); + throw ConfigError(n->getConfig(), "node-config-node-vectorize", "Setting 'vectorize' must be larger than 100"); ret = uldaq_connect(n); if (ret) @@ -449,11 +455,11 @@ int uldaq_check(struct vnode *n) 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 < vlist_length(&n->in.signals); i++) { - struct signal *s = (struct signal *) vlist_at(&n->in.signals, 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 (s->type != SignalType::FLOAT) + if (sig->type != SignalType::FLOAT) throw RuntimeError("Node supports only signals of type = float!"); switch (q->inputMode) { @@ -482,10 +488,11 @@ found: if (q->channel > max_channel) return 0; } +static void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type, unsigned long long event_data, void *ctx) { - struct vnode *n = (struct vnode *) ctx; - struct uldaq *u = (struct uldaq *) n->_vd; + auto *n = (NodeCompat *) ctx; + auto *u = n->getData(); pthread_mutex_lock(&u->in.mutex); @@ -500,9 +507,9 @@ void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type pthread_cond_signal(&u->in.cv); } -int uldaq_start(struct vnode *n) +int villas::node::uldaq_start(NodeCompat *n) { - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); u->sequence = 0; u->in.buffer_pos = 0; @@ -520,7 +527,7 @@ int uldaq_start(struct vnode *n) if (ret) return ret; - err = ulAInLoadQueue(u->device_handle, u->in.queues, vlist_length(&n->in.signals)); + 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"); @@ -552,9 +559,9 @@ int uldaq_start(struct vnode *n) return 0; } -int uldaq_stop(struct vnode *n) +int villas::node::uldaq_stop(NodeCompat *n) { - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); UlError err; @@ -586,9 +593,9 @@ int uldaq_stop(struct vnode *n) return 0; } -int uldaq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { - struct uldaq *u = (struct uldaq *) n->_vd; + auto *u = n->getData(); pthread_mutex_lock(&u->in.mutex); @@ -602,7 +609,7 @@ int uldaq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) pthread_cond_wait(&u->in.cv, &u->in.mutex); for (unsigned j = 0; j < cnt; j++) { - struct sample *smp = smps[j]; + struct Sample *smp = smps[j]; long long scan_index = start_index + j * u->in.channel_count; @@ -613,7 +620,7 @@ int uldaq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) } smp->length = u->in.channel_count; - smp->signals = &n->in.signals; + smp->signals = n->getInputSignals(false); smp->sequence = u->sequence++; smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; } @@ -625,7 +632,7 @@ int uldaq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -643,8 +650,5 @@ static void register_plugin() { p.stop = uldaq_stop; p.read = uldaq_read; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index 11f1e317f..a18fa174d 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -1,7 +1,7 @@ /** Node type: Websockets (libwebsockets) * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,9 +28,9 @@ #include -#include +#include #include -#include +#include #include #include @@ -41,15 +41,17 @@ using namespace villas::utils; #define DEFAULT_WEBSOCKET_BUFFER_SIZE (1 << 12) /* Private static storage */ -static struct vlist connections; /**< List of active libwebsocket connections which receive samples from all nodes (catch all) */ +static struct List connections; /**< List of active libwebsocket connections which receive samples from all nodes (catch all) */ static villas::node::Web *web; static villas::Logger logger = logging.get("websocket"); /* Forward declarations */ -static struct vnode_type p; +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static void websocket_destination_destroy(struct websocket_destination *d) +static +void websocket_destination_destroy(struct websocket_destination *d) { free(d->uri); @@ -57,7 +59,8 @@ static void websocket_destination_destroy(struct websocket_destination *d) free((char *) d->info.address); } -static int websocket_connection_init(struct websocket_connection *c) +static +int websocket_connection_init(struct websocket_connection *c) { int ret; @@ -65,7 +68,7 @@ static int websocket_connection_init(struct websocket_connection *c) if (ret) return ret; - c->formatter->start(&c->node->in.signals, ~(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); @@ -78,7 +81,8 @@ static int websocket_connection_init(struct websocket_connection *c) return 0; } -static int websocket_connection_destroy(struct websocket_connection *c) +static +int websocket_connection_destroy(struct websocket_connection *c) { int ret; @@ -86,7 +90,7 @@ static int websocket_connection_destroy(struct websocket_connection *c) /* Return all samples to pool */ int avail; - struct sample *smp; + struct Sample *smp; while ((avail = queue_pull(&c->queue, (void **) &smp))) sample_decref(smp); @@ -105,7 +109,8 @@ static int websocket_connection_destroy(struct websocket_connection *c) return 0; } -static int websocket_connection_write(struct websocket_connection *c, struct sample * const smps[], unsigned cnt) +static +int websocket_connection_write(struct websocket_connection *c, struct Sample * const smps[], unsigned cnt) { int pushed; @@ -120,21 +125,22 @@ static int websocket_connection_write(struct websocket_connection *c, struct sam c->node->logger->debug("Enqueued {} samples to {}", pushed, *c); - /* Client connections which are currently conecting 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); return 0; } -static void websocket_connection_close(struct websocket_connection *c, struct lws *wsi, enum lws_close_status status, const char *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, status, reason); } -int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +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; @@ -182,7 +188,14 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi format = (char *) "villas.web"; /* Search for node whose name matches the URI. */ - c->node = p.instances.lookup(node); + 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); @@ -204,7 +217,7 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi return -1; } - vlist_push(&connections, c); + list_push(&connections, c); c->node->logger->info("Established WebSocket connection: {}", *c); @@ -225,7 +238,7 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi } if (connections.state == State::INITIALIZED) - vlist_remove_all(&connections, c); + list_remove_all(&connections, c); if (c->state == websocket_connection::State::INITIALIZED) websocket_connection_destroy(c); @@ -237,7 +250,7 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi case LWS_CALLBACK_CLIENT_WRITEABLE: case LWS_CALLBACK_SERVER_WRITEABLE: { - struct sample *smps[cnt]; + struct Sample *smps[cnt]; pulled = queue_pull_many(&c->queue, (void **) smps, cnt); if (pulled > 0) { @@ -274,11 +287,11 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi /* 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(); - struct vnode *n = c->node; + auto *n = c->node; int avail, enqueued; - struct websocket *w = (struct websocket *) n->_vd; - struct sample *smps[cnt]; + auto *w = n->getData(); + struct Sample *smps[cnt]; avail = sample_alloc_many(&w->pool, smps, cnt); if (avail < cnt) @@ -323,11 +336,11 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi return 0; } -int websocket_type_start(villas::node::SuperNode *sn) +int villas::node::websocket_type_start(villas::node::SuperNode *sn) { int ret; - ret = vlist_init(&connections); + ret = list_init(&connections); if (ret) return ret; @@ -338,12 +351,12 @@ int websocket_type_start(villas::node::SuperNode *sn) return 0; } -int websocket_start(struct vnode *n) +int villas::node::websocket_start(NodeCompat *n) { int ret; - struct websocket *w = (struct websocket *) n->_vd; + auto *w = n->getData(); - ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, SAMPLE_LENGTH(vlist_length(&n->in.signals))); + ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, SAMPLE_LENGTH(n->getInputSignals(false)->size())); if (ret) return ret; @@ -351,9 +364,9 @@ int websocket_start(struct vnode *n) if (ret) return ret; - for (size_t i = 0; i < vlist_length(&w->destinations); i++) { + for (size_t i = 0; i < list_length(&w->destinations); i++) { const char *format; - auto *d = (struct websocket_destination *) vlist_at(&w->destinations, i); + auto *d = (struct websocket_destination *) list_at(&w->destinations, i); auto *c = new struct websocket_connection; if (!c) throw MemoryAllocationError(); @@ -383,13 +396,13 @@ int websocket_start(struct vnode *n) return 0; } -int websocket_stop(struct vnode *n) +int villas::node::websocket_stop(NodeCompat *n) { - int ret, open_connections = 0;; - struct websocket *w = (struct websocket *) n->_vd; + int ret, open_connections = 0; + auto *w = n->getData(); - for (size_t i = 0; i < vlist_length(&connections); i++) { - struct websocket_connection *c = (struct websocket_connection *) vlist_at(&connections, i); + for (size_t i = 0; i < list_length(&connections); i++) { + struct websocket_connection *c = (struct websocket_connection *) list_at(&connections, i); if (c->node != n) continue; @@ -400,8 +413,8 @@ int websocket_stop(struct vnode *n) } /* Count open connections belonging to this node */ - for (size_t i = 0; i < vlist_length(&connections); i++) { - struct websocket_connection *c = (struct websocket_connection *) vlist_at(&connections, i); + for (size_t i = 0; i < list_length(&connections); i++) { + struct websocket_connection *c = (struct websocket_connection *) list_at(&connections, i); if (c->node == n) open_connections++; @@ -427,24 +440,24 @@ int websocket_stop(struct vnode *n) return 0; } -int websocket_destroy(struct vnode *n) +int villas::node::websocket_destroy(NodeCompat *n) { - struct websocket *w = (struct websocket *) n->_vd; + auto *w = n->getData(); int ret; - ret = vlist_destroy(&w->destinations, (dtor_cb_t) websocket_destination_destroy, true); + ret = list_destroy(&w->destinations, (dtor_cb_t) websocket_destination_destroy, true); if (ret) return ret; return 0; } -int websocket_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int avail; - struct websocket *w = (struct websocket *) n->_vd; - 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) @@ -456,12 +469,12 @@ int websocket_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return avail; } -int websocket_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int avail; - struct websocket *w = (struct websocket *) n->_vd; - 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); @@ -470,8 +483,8 @@ int websocket_write(struct vnode *n, struct sample * const smps[], unsigned cnt) sample_copy_many(cpys, smps, avail); - for (size_t i = 0; i < vlist_length(&connections); i++) { - struct websocket_connection *c = (struct websocket_connection *) vlist_at(&connections, i); + for (size_t i = 0; i < list_length(&connections); i++) { + struct websocket_connection *c = (struct websocket_connection *) list_at(&connections, i); if (c->node == n) websocket_connection_write(c, cpys, cnt); @@ -482,9 +495,9 @@ int websocket_write(struct vnode *n, struct sample * const smps[], unsigned cnt) return cnt; } -int websocket_parse(struct vnode *n, json_t *json) +int villas::node::websocket_parse(NodeCompat *n, json_t *json) { - struct websocket *w = (struct websocket *) n->_vd; + auto *w = n->getData(); int ret; size_t i; @@ -492,7 +505,7 @@ int websocket_parse(struct vnode *n, json_t *json) json_t *json_dest; json_error_t err; - ret = vlist_init(&w->destinations); + ret = list_init(&w->destinations); if (ret) return ret; @@ -531,23 +544,23 @@ int websocket_parse(struct vnode *n, json_t *json) d->info.ietf_version_or_minus_one = -1; d->info.protocol = "live"; - vlist_push(&w->destinations, d); + list_push(&w->destinations, d); } } return 0; } -char * websocket_print(struct vnode *n) +char * villas::node::websocket_print(NodeCompat *n) { - struct websocket *w = (struct websocket *) n->_vd; + auto *w = n->getData(); char *buf = nullptr; buf = strcatf(&buf, "destinations=[ "); - for (size_t i = 0; i < vlist_length(&w->destinations); i++) { - struct websocket_destination *d = (struct websocket_destination *) vlist_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", @@ -562,9 +575,9 @@ char * websocket_print(struct vnode *n) return buf; } -int websocket_poll_fds(struct vnode *n, int fds[]) +int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) { - struct websocket *w = (struct websocket *) n->_vd; + auto *w = n->getData(); fds[0] = queue_signalled_fd(&w->queue); @@ -585,9 +598,5 @@ __attribute__((constructor(110))) static void UNIQUE(__ctor)() { p.read = websocket_read; p.write = websocket_write; p.poll_fds = websocket_poll_fds; - - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + p.flags = (int) NodeFactory::Flags::REQUIRES_WEB; } diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 71dd7a916..b41c2cb3d 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -1,7 +1,7 @@ /** Node type: ZeroMQ * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,7 +27,7 @@ #include #endif -#include +#include #include #include #include @@ -44,7 +44,8 @@ static void *context; * 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) +static +int get_monitor_event(void *monitor, int *value, char **address) { /* First frame in message contains event number and value */ zmq_msg_t msg; @@ -77,27 +78,27 @@ static int get_monitor_event(void *monitor, int *value, char **address) return event; } -int zeromq_reverse(struct vnode *n) +int villas::node::zeromq_reverse(NodeCompat *n) { - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); - if (vlist_length(&z->out.endpoints) != 1 || - vlist_length(&z->in.endpoints) != 1) + if (list_length(&z->out.endpoints) != 1 || + list_length(&z->in.endpoints) != 1) return -1; - char *subscriber = (char *) vlist_first(&z->in.endpoints); - char *publisher = (char *) vlist_first(&z->out.endpoints); + char *subscriber = (char *) list_first(&z->in.endpoints); + char *publisher = (char *) list_first(&z->out.endpoints); - vlist_set(&z->in.endpoints, 0, publisher); - vlist_set(&z->out.endpoints, 0, subscriber); + list_set(&z->in.endpoints, 0, publisher); + list_set(&z->out.endpoints, 0, subscriber); return 0; } -int zeromq_init(struct vnode *n) +int villas::node::zeromq_init(NodeCompat *n) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); z->out.bind = 1; z->in.bind = 0; @@ -108,18 +109,21 @@ int zeromq_init(struct vnode *n) z->in.pending = 0; z->out.pending = 0; - ret = vlist_init(&z->in.endpoints); + ret = list_init(&z->in.endpoints); if (ret) return ret; - ret = vlist_init(&z->out.endpoints); + ret = list_init(&z->out.endpoints); if (ret) return ret; + z->formatter = nullptr; + return 0; } -int zeromq_parse_endpoints(json_t *json_ep, struct vlist *epl) +static +int zeromq_parse_endpoints(json_t *json_ep, struct List *epl) { json_t *json_val; size_t i; @@ -132,13 +136,13 @@ int zeromq_parse_endpoints(json_t *json_ep, struct vlist *epl) if (!ep) throw ConfigError(json_val, "node-config-node-publish", "All 'publish' settings must be strings"); - vlist_push(epl, strdup(ep)); + list_push(epl, strdup(ep)); } break; case JSON_STRING: ep = json_string_value(json_ep); - vlist_push(epl, strdup(ep)); + list_push(epl, strdup(ep)); break; default: @@ -148,9 +152,9 @@ int zeromq_parse_endpoints(json_t *json_ep, struct vlist *epl) return 0; } -int zeromq_parse(struct vnode *n, json_t *json) +int villas::node::zeromq_parse(NodeCompat *n, json_t *json) { - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); int ret; const char *type = nullptr; @@ -184,6 +188,8 @@ int zeromq_parse(struct vnode *n, json_t *json) 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"); @@ -237,15 +243,15 @@ int zeromq_parse(struct vnode *n, json_t *json) z->pattern = zeromq::Pattern::RADIODISH; #endif else - throw ConfigError(json, "node-config-node-zeromq-type", "Invalid type for ZeroMQ node: {}", node_name_short(n)); + throw ConfigError(json, "node-config-node-zeromq-type", "Invalid type for ZeroMQ node: {}", n->getNameShort()); } return 0; } -char * zeromq_print(struct vnode *n) +char * villas::node::zeromq_print(NodeCompat *n) { - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); char *buf = nullptr; const char *pattern = nullptr; @@ -270,16 +276,16 @@ char * zeromq_print(struct vnode *n) z->out.bind ? "yes" : "no" ); - for (size_t i = 0; i < vlist_length(&z->in.endpoints); i++) { - char *ep = (char *) vlist_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, "], out.publish=[ "); - for (size_t i = 0; i < vlist_length(&z->out.endpoints); i++) { - char *ep = (char *) vlist_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); } @@ -295,37 +301,37 @@ char * zeromq_print(struct vnode *n) return buf; } -int zeromq_check(struct vnode *n) +int villas::node::zeromq_check(NodeCompat *n) { - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); - if (vlist_length(&z->in.endpoints) == 0 && - vlist_length(&z->out.endpoints) == 0) + if (list_length(&z->in.endpoints) == 0 && + list_length(&z->out.endpoints) == 0) return -1; return 0; } -int zeromq_type_start(villas::node::SuperNode *sn) +int villas::node::zeromq_type_start(villas::node::SuperNode *sn) { context = zmq_ctx_new(); return context == nullptr; } -int zeromq_type_stop() +int villas::node::zeromq_type_stop() { return zmq_ctx_term(context); } -int zeromq_start(struct vnode *n) +int villas::node::zeromq_start(NodeCompat *n) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); struct zeromq::Dir* dirs[] = { &z->out, &z->in }; - z->formatter->start(&n->in.signals, ~(int) SampleFlags::HAS_OFFSET); + z->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); switch (z->pattern) { #ifdef ZMQ_BUILD_DISH @@ -429,8 +435,8 @@ int zeromq_start(struct vnode *n) goto fail; /* Connect / bind sockets to endpoints */ - for (size_t i = 0; i < vlist_length(&d->endpoints); i++) { - char *ep = (char *) vlist_at(&d->endpoints, i); + 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); @@ -475,10 +481,10 @@ fail: return ret; } -int zeromq_stop(struct vnode *n) +int villas::node::zeromq_stop(NodeCompat *n) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); struct zeromq::Dir* dirs[] = { &z->out, &z->in }; @@ -492,15 +498,13 @@ int zeromq_stop(struct vnode *n) return ret; } - delete z->formatter; - return 0; } -int zeromq_destroy(struct vnode *n) +int villas::node::zeromq_destroy(NodeCompat *n) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); if (z->in.filter) free(z->in.filter); @@ -508,17 +512,20 @@ int zeromq_destroy(struct vnode *n) if (z->out.filter) free(z->out.filter); - ret = vlist_destroy(&z->out.endpoints, nullptr, true); + ret = list_destroy(&z->out.endpoints, nullptr, true); if (ret) return ret; + if (z->formatter) + delete z->formatter; + return 0; } -int zeromq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int recv, ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); zmq_msg_t m; @@ -551,10 +558,10 @@ int zeromq_read(struct vnode *n, struct sample * const smps[], unsigned cnt) return recv; } -int zeromq_write(struct vnode *n, struct sample * const smps[], unsigned cnt) +int villas::node::zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); size_t wbytes; zmq_msg_t m; @@ -601,10 +608,10 @@ fail: return ret; } -int zeromq_poll_fds(struct vnode *n, int fds[]) +int villas::node::zeromq_poll_fds(NodeCompat *n, int fds[]) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); int fd; size_t len = sizeof(fd); @@ -618,10 +625,10 @@ int zeromq_poll_fds(struct vnode *n, int fds[]) return 1; } -int zeromq_netem_fds(struct vnode *n, int fds[]) +int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) { int ret; - struct zeromq *z = (struct zeromq *) n->_vd; + auto *z = n->getData(); int fd; size_t len = sizeof(fd); @@ -635,7 +642,7 @@ int zeromq_netem_fds(struct vnode *n, int fds[]) return 1; } -static struct vnode_type p; +static NodeCompatType p; __attribute__((constructor(110))) static void register_plugin() { @@ -658,8 +665,5 @@ static void register_plugin() { p.poll_fds = zeromq_poll_fds; p.netem_fds = zeromq_netem_fds; - if (!node_types) - node_types = new NodeTypeList(); - - node_types->push_back(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/path.cpp b/lib/path.cpp index a06e20982..6bbcf64c5 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -1,7 +1,7 @@ /** Message paths. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,56 +28,62 @@ #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; + + return p->poll + ? p->runPoll() + : p->runSingle(); +} + /** Main thread function per path: * read samples from source -> write samples to destinations * - * This is an optimized version of path_run_poll() which is + * This is an optimized version of runPoll() which is * used for paths which only have a single source. * In this case we case save a call to poll() and directly call - * path_source_read() / node_read(). + * PathSource::read() / Node::read(). */ -static void * path_run_single(void *arg) +void * Path::runSingle() { int ret; - struct vpath *p = (struct vpath *) arg; - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p->sources, 0); + auto ps = sources.front(); /* there is only a single source */ - while (p->state == State::STARTED) { + while (state == State::STARTED) { pthread_testcancel(); - ret = path_source_read(ps, p, 0); + ret = ps->read(0); if (ret <= 0) continue; - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - struct vpath_destination *pd = (struct vpath_destination *) vlist_at(&p->destinations, i); - - path_destination_write(pd, p); - } + for (auto pd : destinations) + pd->write(); } return nullptr; @@ -89,295 +95,264 @@ static void * path_run_single(void *arg) * This variant of the path uses poll() to listen on an event from * all path sources. */ -static void * path_run_poll(void *arg) +void * Path::runPoll() { - int ret; - struct vpath *p = (struct vpath *) arg; - - while (p->state == State::STARTED) { - ret = poll(p->reader.pfds, p->reader.nfds, -1); + while (state == State::STARTED) { + int ret = ::poll(pfds.data(), pfds.size(), -1); if (ret < 0) throw SystemError("Failed to poll"); - p->logger->debug("Path {} returned from poll(2)", *p); + logger->debug("returned from poll(2): ret={}", ret); - for (int i = 0; i < p->reader.nfds; i++) { - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p->sources, i); + for (unsigned i = 0; i < pfds.size(); i++) { + auto &pfd = pfds[i]; - if (p->reader.pfds[i].revents & POLLIN) { + if (pfd.revents & POLLIN) { /* Timeout: re-enqueue the last sample */ - if (p->reader.pfds[i].fd == p->timeout.getFD()) { - p->timeout.wait(); + if (pfd.fd == timeout.getFD()) { + timeout.wait(); - p->last_sample->sequence = p->last_sequence++; + last_sample->sequence = last_sequence++; - path_destination_enqueue(p, &p->last_sample, 1); + PathDestination::enqueueAll(this, &last_sample, 1); } /* A source is ready to receive samples */ - else - path_source_read(ps, p, i); + else { + auto ps = sources[i]; + + ps->read(i); + } } } - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - struct vpath_destination *pd = (struct vpath_destination *) vlist_at(&p->destinations, i); - - path_destination_write(pd, p); - } + for (auto pd : destinations) + pd->write(); } return nullptr; } -int path_init(struct vpath *p) +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++))) { - int ret; + uuid_clear(uuid); - new (&p->logger) Logger; - new (&p->received) std::bitset; - new (&p->mask) std::bitset; - new (&p->timeout) Task(CLOCK_MONOTONIC); - - static int path_id; - auto logger_name = fmt::format("path:{}", path_id++); - p->logger = logging.get(logger_name); - - uuid_clear(p->uuid); - - ret = vlist_init(&p->destinations); - if (ret) - return ret; - - ret = vlist_init(&p->sources); - if (ret) - return ret; - - ret = signal_list_init(&p->signals); - if (ret) - return ret; - - ret = vlist_init(&p->mappings); - if (ret) - return ret; - -#ifdef WITH_HOOKS - ret = hook_list_init(&p->hooks); - if (ret) - return ret; -#endif /* WITH_HOOKS */ - - p->reader.pfds = nullptr; - p->reader.nfds = 0; - - /* Default values */ - p->mode = PathMode::ANY; - p->rate = 0; /* Disabled */ - - p->builtin = 1; - p->reverse = 0; - p->enabled = 1; - p->poll = -1; - p->queuelen = DEFAULT_QUEUE_LENGTH; - p->original_sequence_no = -1; - p->affinity = 0; - - p->state = State::INITIALIZED; - - return 0; + pool.state = State::DESTROYED; } -static int path_prepare_poll(struct vpath *p) +void Path::startPoll() { - int fds[16], n = 0, m; + pfds.clear(); - if (p->reader.pfds) - delete[] p->reader.pfds; - - p->reader.pfds = nullptr; - p->reader.nfds = 0; - - for (unsigned i = 0; i < vlist_length(&p->sources); i++) { - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p->sources, i); - - m = node_poll_fds(ps->node, fds); - if (m <= 0) - throw RuntimeError("Failed to get file descriptor for node {}", *ps->node); - - p->reader.nfds += m; - p->reader.pfds = (struct pollfd *) realloc(p->reader.pfds, p->reader.nfds * sizeof(struct pollfd)); - - for (int i = 0; i < m; i++) { - if (fds[i] < 0) - throw RuntimeError("Failed to get file descriptor for node {}", *ps->node); + 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()); /* This slot is only used if it is not masked */ - p->reader.pfds[n].events = POLLIN; - p->reader.pfds[n++].fd = fds[i]; + struct pollfd pfd = { + .fd = fd, + .events = POLLIN + }; + + pfds.push_back(pfd); } } /* We use the last slot for the timeout timer. */ - if (p->rate > 0) { - p->timeout.setRate(p->rate); + if (rate > 0) { + timeout.setRate(rate); - p->reader.nfds++; - p->reader.pfds = (struct pollfd *) realloc(p->reader.pfds, p->reader.nfds * sizeof(struct pollfd)); + struct pollfd pfd = { + .fd = timeout.getFD(), + .events = POLLIN + }; - p->reader.pfds[p->reader.nfds-1].events = POLLIN; - p->reader.pfds[p->reader.nfds-1].fd = p->timeout.getFD(); - if (p->reader.pfds[p->reader.nfds-1].fd < 0) { - p->logger->warn("Failed to get file descriptor for timer of path {}", *p); - return -1; - } + if (pfd.fd < 0) + throw RuntimeError("Failed to get file descriptor for timer of path {}", *this); + + pfds.push_back(pfd); } - - return 0; } -int path_prepare(struct vpath *p, NodeList &nodes) +void Path::prepare(NodeList &nodes) { int ret; - unsigned pool_size = 0; - struct memory_type *pool_mt = memory_default; + struct memory::Type *pool_mt = memory::default_type; - assert(p->state == State::CHECKED); + assert(state == State::CHECKED); - p->mask.reset(); + mask.reset(); + signals = std::make_shared(); /* Prepare mappings */ - ret = mapping_list_prepare(&p->mappings, nodes); + ret = mappings.prepare(nodes); if (ret) - return ret; - - p->muxed = path_is_muxed(p); + throw RuntimeError("Failed to prepare mappings of path: {}", *this); /* Create path sources */ - std::map pss; - for (size_t i = 0; i < vlist_length(&p->mappings); i++) { - struct mapping_entry *me = (struct mapping_entry *) vlist_at(&p->mappings, i); - struct vnode *n = me->node; - struct vpath_source *ps; + std::map psm; + unsigned i = 0, j = 0; + for (auto me : mappings) { + Node *n = me->node; + PathSource::Ptr ps; - if (pss.find(n) != pss.end()) + if (psm.find(n) != psm.end()) /* We already have a path source for this mapping entry */ - ps = pss[n]; + ps = psm[n]; else { - /* Create new path source */ - ps = pss[n] = new struct vpath_source; - if (!ps) - throw MemoryAllocationError(); - /* 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 = vlist_length(&n->sources) > 0; - ret = isSecondary - ? path_source_init_secondary(ps, n) - : path_source_init_master(ps, n); - if (ret) - return ret; + bool isSecondary = n->sources.size() > 0; - if (ps->type == PathSourceType::SECONDARY) { - nodes.push_back(ps->node); - vlist_push(&ps->node->sources, ps); + /* 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(); + + mps->addSecondary(sps); + + ps = sps; + } + else { + ps = std::make_shared(this, n); + if (!ps) + throw MemoryAllocationError(); } - if (p->mask_list.empty() || std::find(p->mask_list.begin(), p->mask_list.end(), n) != p->mask_list.end()) { + if (masked.empty() || std::find(masked.begin(), masked.end(), n) != masked.end()) { ps->masked = true; - p->mask.set(i); + mask.set(j); } - vlist_push(&n->sources, ps); - vlist_push(&p->sources, ps); + /* Get the real node backing this path source + * In case of a secondary path source, its the internal loopback node! + */ + auto *rn = ps->getNode(); + + rn->sources.push_back(ps); + + sources.push_back(ps); + j++; + psm[n] = ps; } - struct vlist *sigs = node_input_signals(me->node); + SignalList::Ptr sigs = me->node->getInputSignals(); /* Update signals of path */ for (unsigned j = 0; j < (unsigned) me->length; j++) { - struct signal *sig; + Signal::Ptr sig; /* For data mappings we simple refer to the existing * signal descriptors of the source node. */ - if (me->type == MappingType::DATA) { - sig = (struct signal *) vlist_at_safe(sigs, me->data.offset + j); + if (me->type == MappingEntry::Type::DATA) { + sig = sigs->getByIndex(me->data.offset + j); if (!sig) { - p->logger->warn("Failed to create signal description for path {}", *p); + logger->warn("Failed to create signal description for path {}", *this); continue; } - - signal_incref(sig); } /* For other mappings we create new signal descriptors */ else { - sig = new struct signal; + sig = me->toSignal(j); if (!sig) - throw MemoryAllocationError(); - - ret = signal_init_from_mapping(sig, me, j); - if (ret) - return -1; + throw RuntimeError("Failed to create signal from mapping"); } - vlist_extend(&p->signals, me->offset + j + 1, nullptr); - vlist_set(&p->signals, me->offset + j, sig); + signals->resize(me->offset + j + 1); + (*signals)[me->offset + j] = sig; } - vlist_push(&ps->mappings, me); + ps->mappings.push_back(me); + i++; } /* Prepare path destinations */ - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - auto *pd = (struct vpath_destination *) vlist_at(&p->destinations, i); + 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"); + } - if (node_type(pd->node)->memory_type) - pool_mt = node_memory_type(pd->node); + pool_mt = pd_mt; + mt_cnt++; + } - ret = path_destination_prepare(pd, p->queuelen); + ret = pd->prepare(queuelen); if (ret) - return ret; + throw RuntimeError("Failed to prepare path destination {} of path {}", *pd->node, *this); } /* Autodetect whether to use original sequence numbers or not */ - if (p->original_sequence_no == -1) - p->original_sequence_no = vlist_length(&p->sources) == 1; + if (original_sequence_no == -1) + original_sequence_no = sources.size() == 1; - /* Prepare poll() */ - if (p->poll) { - ret = path_prepare_poll(p); - if (ret) - return ret; + /* 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 = p->builtin ? (int) Hook::Flags::PATH | (int) Hook::Flags::BUILTIN : 0; + int m = builtin + ? (int) Hook::Flags::PATH | + (int) Hook::Flags::BUILTIN + : 0; /* Add internal hooks if they are not already in the list */ - hook_list_prepare(&p->hooks, &p->signals, m, p, nullptr); + hooks.prepare(signals, m, this, nullptr); + hooks.dump(logger, fmt::format("path {}", *this)); #endif /* WITH_HOOKS */ /* Prepare pool */ - pool_size = MAX(1UL, vlist_length(&p->destinations)) * p->queuelen; - ret = pool_init(&p->pool, pool_size, SAMPLE_LENGTH(path_output_signals_max_cnt(p)), pool_mt); + 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) - return ret; + throw RuntimeError("Failed to initialize pool of path: {}", *this); - p->logger->info("Prepared path {} with {} output signals", *p, vlist_length(path_output_signals(p))); - signal_list_dump(p->logger, path_output_signals(p)); + logger->debug("Prepared path {} with {} output signals:", *this, osigs->size()); + osigs->dump(logger); - p->state = State::PREPARED; + checkPrepared(); - return 0; + state = State::PREPARED; } -int path_parse(struct vpath *p, json_t *json, NodeList &nodes, const uuid_t sn_uuid) +void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) { - int ret; + int ret, en = -1, rev = -1; json_error_t err; json_t *json_in; @@ -385,115 +360,94 @@ int path_parse(struct vpath *p, json_t *json, NodeList &nodes, const uuid_t sn_u json_t *json_hooks = nullptr; json_t *json_mask = nullptr; - const char *mode = nullptr; + const char *mode_str = nullptr; const char *uuid_str = nullptr; - struct vlist destinations; - - ret = vlist_init(&destinations); - if (ret) - return ret; - 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", &p->reverse, - "enabled", &p->enabled, - "builtin", &p->builtin, - "queuelen", &p->queuelen, - "mode", &mode, - "poll", &p->poll, - "rate", &p->rate, + "reverse", &rev, + "enabled", &en, + "builtin", &builtin, + "queuelen", &queuelen, + "mode", &mode_str, + "poll", &poll, + "rate", &rate, "mask", &json_mask, - "original_sequence_no", &p->original_sequence_no, + "original_sequence_no", &original_sequence_no, "uuid", &uuid_str, - "affinity", &p->affinity + "affinity", &affinity ); if (ret) throw ConfigError(json, err, "node-config-path", "Failed to parse path configuration"); + if (en >= 0) + enabled = en != 0; + + if (rev >= 0) + reversed = rev != 0; + /* Optional settings */ - if (mode) { - if (!strcmp(mode, "any")) - p->mode = PathMode::ANY; - else if (!strcmp(mode, "all")) - p->mode = PathMode::ALL; + 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); + throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", mode_str); } /* UUID */ if (uuid_str) { - ret = uuid_parse(uuid_str, p->uuid); + 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(p->uuid, json, sn_uuid); + uuid::generateFromJson(uuid, json, sn_uuid); /* Input node(s) */ - ret = mapping_list_parse(&p->mappings, json_in); + ret = mappings.parse(json_in); if (ret) - throw ConfigError(json_in, "node-config-path-in", "Failed to parse input mapping of path {}", *p); + throw ConfigError(json_in, "node-config-path-in", "Failed to parse input mapping of path {}", *this); /* Output node(s) */ + NodeList dests; if (json_out) { - ret = node_list_parse(&destinations, json_out, nodes); + ret = dests.parse(json_out, nodes); if (ret) throw ConfigError(json_out, "node-config-path-out", "Failed to parse output nodes"); } - for (size_t i = 0; i < vlist_length(&destinations); i++) { - struct vnode *n = (struct vnode *) vlist_at(&destinations, i); - + 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 = p; + n->out.path = this; - auto *pd = new struct vpath_destination; + auto pd = std::make_shared(this, n); if (!pd) throw MemoryAllocationError(); - ret = path_destination_init(pd, n); - if (ret) - return ret; - - vlist_push(&n->destinations, pd); - vlist_push(&p->destinations, pd); + n->destinations.push_back(pd); + destinations.push_back(pd); } #ifdef WITH_HOOKS if (json_hooks) - hook_list_parse(&p->hooks, json_hooks, (int) Hook::Flags::PATH, p, nullptr); + hooks.parse(json_hooks, (int) Hook::Flags::PATH, this, nullptr); #endif /* WITH_HOOKS */ if (json_mask) - path_parse_mask(p, json_mask, nodes); + parseMask(json_mask, nodes); - ret = vlist_destroy(&destinations, nullptr, false); - if (ret) - return ret; - - /* Autodetect whether to use poll() for this path or not */ - if (p->poll == -1) { - if (p->rate > 0) - p->poll = 1; - else if (vlist_length(&p->sources) > 1) - p->poll = 1; - else - p->poll = 0; - } - - p->config = json; - p->state = State::PARSED; - - return 0; + config = json; + state = State::PARSED; } -void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList &nodes) +void Path::parseMask(json_t *json_mask, NodeList &nodes) { json_t *json_entry; size_t i; @@ -503,7 +457,7 @@ void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList json_array_foreach(json_mask, i, json_entry) { const char *name; - struct vnode *node; + Node *node; name = json_string_value(json_entry); if (!name) @@ -513,127 +467,126 @@ void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList if (!node) throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' entry '{}' is not a valid node name", name); - p->mask_list.push_back(node); + masked.push_back(node); } } -void path_check(struct vpath *p) +void Path::check() { - assert(p->state != State::DESTROYED); + assert(state != State::DESTROYED); - if (p->rate < 0) - throw RuntimeError("Setting 'rate' of path {} must be a positive number.", *p); + if (rate < 0) + throw RuntimeError("Setting 'rate' of path {} must be a positive number.", *this); - if (p->poll > 0) { - if (p->rate <= 0) { - /* Check that all path sources provide a file descriptor for polling */ - for (size_t i = 0; i < vlist_length(&p->sources); i++) { - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p->sources, i); - - if (!node_type(ps->node)->poll_fds) - throw RuntimeError("Node {} can not be used in polling mode with path {}", *ps->node, *p); - } - } + if (!IS_POW2(queuelen)) { + queuelen = LOG2_CEIL(queuelen); + logger->warn("Queue length should always be a power of 2. Adjusting to {}", queuelen); } - else { + +#ifdef WITH_HOOKS + hooks.check(); +#endif /* WITH_HOOKS */ + + 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 (vlist_length(&p->sources) > 1) + 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 (p->rate > 0) + if (rate > 0) throw RuntimeError("Setting 'poll' must be activated when used together with setting 'rate'"); } - - if (!IS_POW2(p->queuelen)) { - p->queuelen = LOG2_CEIL(p->queuelen); - p->logger->warn("Queue length should always be a power of 2. Adjusting to {}", p->queuelen); + 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(), *this); + } + } } - - for (size_t i = 0; i < vlist_length(&p->sources); i++) { - struct vpath_source *ps = (struct vpath_source *) vlist_at(&p->sources, i); - - path_source_check(ps); - } - - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - struct vpath_destination *ps = (struct vpath_destination *) vlist_at(&p->destinations, i); - - path_destination_check(ps); - } - -#ifdef WITH_HOOKS - hook_list_check(&p->hooks); -#endif /* WITH_HOOKS */ - - p->state = State::CHECKED; } -int path_start(struct vpath *p) +void Path::start() { int ret; - const char *mode; + const char *mode_str; - assert(p->state == State::PREPARED); + assert(state == State::PREPARED); - switch (p->mode) { - case PathMode::ANY: - mode = "any"; + switch (mode) { + case Mode::ANY: + mode_str = "any"; break; - case PathMode::ALL: - mode = "all"; + case Mode::ALL: + mode_str = "all"; break; default: - mode = "unknown"; + mode_str = "unknown"; break; } - p->logger->info("Starting path {}: #signals={}({}), #hooks={}, #sources={}, " - "#destinations={}, mode={}, poll={}, mask={:b}, rate={}, " + logger->info("Starting path {}: #signals={}/{}, #hooks={}, #sources={}, " + "#destinations={}, mode={}, poll={}, mask=0b{:b}, rate={}, " "enabled={}, reversed={}, queuelen={}, original_sequence_no={}", - *p, - vlist_length(&p->signals), - vlist_length(path_output_signals(p)), - vlist_length(&p->hooks), - vlist_length(&p->sources), - vlist_length(&p->destinations), - mode, - p->poll ? "yes" : "no", - p->mask.to_ullong(), - p->rate, - path_is_enabled(p) ? "yes" : "no", - path_is_reversed(p) ? "yes" : "no", - p->queuelen, - p->original_sequence_no ? "yes" : "no" + *this, + 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 - hook_list_start(&p->hooks); + hooks.start(); #endif /* WITH_HOOKS */ - p->last_sequence = 0; + last_sequence = 0; - p->received.reset(); + received.reset(); /* We initialize the intial sample */ - p->last_sample = sample_alloc(&p->pool); - if (!p->last_sample) - return -1; + last_sample = sample_alloc(&pool); + if (!last_sample) + throw MemoryAllocationError(); - p->last_sample->length = 0; - p->last_sample->signals = &p->signals; - p->last_sample->sequence = 0; - p->last_sample->flags = p->last_sample->length > 0 ? (int) SampleFlags::HAS_DATA : 0; + last_sample->length = signals->size(); + last_sample->signals = signals; - for (size_t i = 0; i < p->last_sample->length; i++) { - struct signal *sig = (struct signal *) vlist_at(p->last_sample->signals, i); + last_sample->ts.origin = time_now(); + last_sample->flags = (int) SampleFlags::HAS_TS_ORIGIN; - p->last_sample->data[i] = sig->init; + 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); + + last_sample->data[i] = sig->init; } - p->state = State::STARTED; + if (poll > 0) + startPoll(); + + state = State::STARTED; /* Start one thread per path for sending to destinations * @@ -641,131 +594,89 @@ int path_start(struct vpath *p) * does not offer a file descriptor for polling, we will use a special * thread function. */ - ret = pthread_create(&p->tid, nullptr, p->poll ? path_run_poll : path_run_single, p); + ret = pthread_create(&tid, nullptr, runWrapper, this); if (ret) - return ret; + throw RuntimeError("Failed to create path thread"); - if (p->affinity) - kernel::rt::setThreadAffinity(p->tid, p->affinity); - - return 0; + if (affinity) + kernel::rt::setThreadAffinity(tid, affinity); } -int path_stop(struct vpath *p) +void Path::stop() { int ret; - if (p->state != State::STARTED && p->state != State::STOPPING) - return 0; + if (state != State::STARTED && + state != State::STOPPING) + return; - p->logger->info("Stopping path: {}", *p); + logger->info("Stopping path: {}", *this); - if (p->state != State::STOPPING) - p->state = State::STOPPING; + if (state != State::STOPPING) + state = State::STOPPING; /* Cancel the thread in case is currently in a blocking syscall. * * We dont care if the thread has already been terminated. */ - ret = pthread_cancel(p->tid); + ret = pthread_cancel(tid); if (ret && ret != ESRCH) - return ret; + throw RuntimeError("Failed to cancel path thread"); - ret = pthread_join(p->tid, nullptr); + ret = pthread_join(tid, nullptr); if (ret) - return ret; + throw RuntimeError("Failed to join path thread"); #ifdef WITH_HOOKS - hook_list_stop(&p->hooks); + hooks.stop(); #endif /* WITH_HOOKS */ - sample_decref(p->last_sample); + sample_decref(last_sample); - p->state = State::STOPPED; - - return 0; + state = State::STOPPED; } -int path_destroy(struct vpath *p) +Path::~Path() { - int ret; + int ret __attribute__((unused)); - if (p->state == State::DESTROYED) - return 0; + assert(state != State::DESTROYED); -#ifdef WITH_HOOKS - ret = hook_list_destroy(&p->hooks); - if (ret) - return ret; -#endif - ret = signal_list_destroy(&p->signals); - if (ret) - return ret; - - ret = vlist_destroy(&p->sources, (dtor_cb_t) path_source_destroy, true); - if (ret) - return ret; - - ret = vlist_destroy(&p->destinations, (dtor_cb_t) path_destination_destroy, true); - if (ret) - return ret; - - ret = vlist_destroy(&p->mappings, (dtor_cb_t) mapping_entry_destroy, true); - if (ret) - return ret; - - if (p->reader.pfds) - delete[] p->reader.pfds; - - ret = pool_destroy(&p->pool); - if (ret) - return ret; - - using bs = std::bitset; - using lg = std::shared_ptr; - - p->received.~bs(); - p->mask.~bs(); - p->logger.~lg(); - p->timeout.~Task(); - - p->state = State::DESTROYED; - - return 0; + ret = pool_destroy(&pool); } -bool path_is_simple(const struct vpath *p) +bool Path::isSimple() const { int ret; const char *in = nullptr, *out = nullptr; json_error_t err; - ret = json_unpack_ex(p->config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); + ret = json_unpack_ex(config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); if (ret) return false; - ret = node_is_valid_name(in); + ret = Node::isValidName(in); if (!ret) return false; - ret = node_is_valid_name(out); + ret = Node::isValidName(out); if (!ret) return false; return true; } -bool path_is_muxed(const struct vpath *p) +bool Path::isMuxed() const { - if (vlist_length(&p->sources) > 0) + if (sources.size() > 0) return true; - if (vlist_length(&p->mappings) > 0) + if (mappings.size() > 0) return true; - struct mapping_entry *me = (struct mapping_entry *) vlist_at_safe(&p->mappings, 0); + auto me = mappings.front(); - if (me->type != MappingType::DATA) + if (me->type != MappingEntry::Type::DATA) return true; if (me->data.offset != 0) @@ -777,78 +688,64 @@ bool path_is_muxed(const struct vpath *p) return false; } -bool path_is_enabled(const struct vpath *p) -{ - return p->enabled; -} - -bool path_is_reversed(const struct vpath *p) -{ - return p->reverse; -} - -struct vlist * path_output_signals(struct vpath *p) +SignalList::Ptr Path::getOutputSignals(bool after_hooks) { #ifdef WITH_HOOKS - if (vlist_length(&p->hooks) > 0) - return hook_list_get_signals(&p->hooks); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif /* WITH_HOOKS */ - return &p->signals; + return signals; } -unsigned path_output_signals_max_cnt(struct vpath *p) +unsigned Path::getOutputSignalsMaxCount() { #ifdef WITH_HOOKS - if (vlist_length(&p->hooks) > 0) - return MAX(vlist_length(&p->signals), hook_list_get_signals_max_cnt(&p->hooks)); + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif /* WITH_HOOKS */ - return vlist_length(&p->signals); + return signals->size(); } -json_t * path_to_json(struct vpath *p) +json_t * Path::toJson() const { - char uuid[37]; - uuid_unparse(p->uuid, uuid); + char uuid_str[37]; + uuid_unparse(uuid, uuid_str); - json_t *json_signals = signal_list_to_json(&p->signals); + json_t *json_signals = signals->toJson(); #ifdef WITH_HOOKS - json_t *json_hooks = hook_list_to_json(&p->hooks); + json_t *json_hooks = hooks.toJson(); +#else + json_t *json_hooks = json_array(); #endif /* WITH_HOOKS */ json_t *json_sources = json_array(); json_t *json_destinations = json_array(); - for (size_t i = 0; i < vlist_length(&p->sources); i++) { - struct vpath_source *pd = (struct vpath_source *) vlist_at_safe(&p->sources, i); + for (auto ps : sources) + json_array_append_new(json_sources, json_string(ps->node->getNameShort().c_str())); - json_array_append_new(json_sources, json_string(node_name_short(pd->node))); - } - - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - struct vpath_destination *pd = (struct vpath_destination *) vlist_at_safe(&p->destinations, i); - - json_array_append_new(json_destinations, json_string(node_name_short(pd->node))); - } + 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, - "state", stateToString(p->state).c_str(), - "mode", p->mode == PathMode::ANY ? "any" : "all", - "enabled", p->enabled, - "builtin", p->builtin, - "reverse", p->reverse, - "original_sequence_no", p->original_sequence_no, - "last_sequence", p->last_sequence, - "poll", p->poll, - "queuelen", p->queuelen, + "uuid", uuid_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, -#ifdef WITH_HOOKS "hooks", json_hooks, -#endif /* WITH_HOOKS */ "in", json_sources, "out", json_destinations ); return json_path; } + +int villas::node::Path::id = 0; diff --git a/lib/path_destination.cpp b/lib/path_destination.cpp index f46242fbb..2dde4dbe2 100644 --- a/lib/path_destination.cpp +++ b/lib/path_destination.cpp @@ -1,7 +1,7 @@ /** Path destination * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,59 +21,52 @@ *********************************************************************************/ #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include using namespace villas; +using namespace villas::node; -int path_destination_init(struct vpath_destination *pd, struct vnode *n) +PathDestination::PathDestination(Path *p, Node *n) : + node(n), + path(p) { - pd->node = n; - - vlist_push(&n->destinations, pd); - - return 0; + queue.state = State::DESTROYED; } -int path_destination_prepare(struct vpath_destination *pd, int queuelen) +PathDestination::~PathDestination() +{ + int ret __attribute__((unused)); + + ret = queue_destroy(&queue); +} + +int PathDestination::prepare(int queuelen) { int ret; - ret = queue_init(&pd->queue, queuelen); + ret = queue_init(&queue, queuelen); if (ret) return ret; return 0; } -int path_destination_destroy(struct vpath_destination *pd) -{ - int ret; - - ret = queue_destroy(&pd->queue); - if (ret) - return ret; - - return 0; -} - -void path_destination_enqueue(struct vpath *p, const struct sample * const smps[], unsigned cnt) +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); - for (size_t i = 0; i < vlist_length(&p->destinations); i++) { - struct vpath_destination *pd = (struct vpath_destination *) vlist_at(&p->destinations, i); - + 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); @@ -87,43 +80,43 @@ void path_destination_enqueue(struct vpath *p, const struct sample * const smps[ sample_decref_many(clones, cloned); } -void path_destination_write(struct vpath_destination *pd, struct vpath *p) +void PathDestination::write() { - int cnt = pd->node->out.vectorize; + 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 (1) { - allocated = queue_pull_many(&pd->queue, (void **) smps, cnt); + while (true) { + allocated = queue_pull_many(&queue, (void **) smps, cnt); if (allocated == 0) break; else if (allocated < cnt) - p->logger->debug("Queue underrun for path {}: allocated={} expected={}", *p, allocated, cnt); + path->logger->debug("Queue underrun for path {}: allocated={} expected={}", *path, allocated, cnt); - p->logger->debug("Dequeued {} samples from queue of node {} which is part of path {}", allocated, *pd->node, *p); + path->logger->debug("Dequeued {} samples from queue of node {} which is part of path {}", allocated, *node, *path); - sent = node_write(pd->node, smps, allocated); + sent = node->write(smps, allocated); if (sent < 0) { - p->logger->error("Failed to sent {} samples to node {}: reason={}", cnt, *pd->node, sent); + path->logger->error("Failed to sent {} samples to node {}: reason={}", cnt, *node, sent); return; } else if (sent < allocated) - p->logger->debug("Partial write to node {}: written={}, expected={}", *pd->node, sent, allocated); + path->logger->debug("Partial write to node {}: written={}, expected={}", *node, sent, allocated); int released = sample_decref_many(smps, allocated); - p->logger->debug("Released {} samples back to memory pool", released); + path->logger->debug("Released {} samples back to memory pool", released); } } -void path_destination_check(struct vpath_destination *pd) +void PathDestination::check() { - if (!node_is_enabled(pd->node)) - throw RuntimeError("Destination {} is not enabled", *pd->node); + if (!node->isEnabled()) + throw RuntimeError("Destination {} is not enabled", *node); - if (!node_type(pd->node)->write) - throw RuntimeError("Destiation node {} is not supported as a sink for path ", *pd->node); + if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_WRITE)) + throw RuntimeError("Destination node {} is not supported as a sink for path ", *node); } diff --git a/lib/path_list.cpp b/lib/path_list.cpp index ddb2ceaeb..275749768 100644 --- a/lib/path_list.cpp +++ b/lib/path_list.cpp @@ -21,11 +21,11 @@ */ #include -#include +#include using namespace villas::node; -struct vpath * PathList::lookup(const uuid_t &uuid) +Path * PathList::lookup(const uuid_t &uuid) const { for (auto *p : *this) { if (!uuid_compare(uuid, p->uuid)) @@ -34,3 +34,13 @@ struct vpath * PathList::lookup(const uuid_t &uuid) return nullptr; } + +json_t * PathList::toJson() const +{ + json_t *json_paths = json_array(); + + for (auto *p : *this) + json_array_append_new(json_paths, p->toJson()); + + return json_paths; +} diff --git a/lib/path_source.cpp b/lib/path_source.cpp index bed33d62c..98bc3cba6 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -1,7 +1,7 @@ /** Path source * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,146 +23,81 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include #include -#include -#include +#include +#include using namespace villas; +using namespace villas::node; -int path_source_init_master(struct vpath_source *ps, struct vnode *n) +PathSource::PathSource(Path *p, Node *n) : + node(n), + path(p), + masked(false) { int ret; - ps->node = n; - ps->masked = false; - ps->type = PathSourceType::MASTER; - - ret = vlist_init(&ps->mappings); + 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) - return ret; - - ret = vlist_init(&ps->secondaries); - if (ret) - return ret; - - int pool_size = MAX(DEFAULT_QUEUE_LENGTH, 20 * ps->node->in.vectorize); - - ret = pool_init(&ps->pool, pool_size, SAMPLE_LENGTH(node_input_signals_max_cnt(ps->node)), node_memory_type(ps->node)); - - if (ret) - return ret; - - return 0; + throw RuntimeError("Failed to initialize pool"); } -int path_source_init_secondary(struct vpath_source *ps, struct vnode *n) +PathSource::~PathSource() { - int ret; - struct vpath_source *mps; + int ret __attribute__((unused)); - ret = path_source_init_master(ps, n); - if (ret) - return ret; - - ps->type = PathSourceType::SECONDARY; - - ps->node = loopback_internal_create(n); - if (!ps->node) - return -1; - - ret = node_check(ps->node); - if (ret) - return -1; - - ret = node_prepare(ps->node); - if (ret) - return -1; - - mps = (struct vpath_source *) vlist_at_safe(&n->sources, 0); - if (!mps) - return -1; - - vlist_push(&mps->secondaries, ps); - - return 0; + ret = pool_destroy(&pool); } -int path_source_destroy(struct vpath_source *ps) +int PathSource::read(int i) { - int ret; + int ret, recv, tomux, allocated, cnt, toenqueue, enqueued; - ret = pool_destroy(&ps->pool); - if (ret) - return ret; + cnt = node->in.vectorize; - ret = vlist_destroy(&ps->mappings, nullptr, false); - if (ret) - return ret; - - ret = vlist_destroy(&ps->secondaries, nullptr, false); - if (ret) - return ret; - - return 0; -} - -int path_source_read(struct vpath_source *ps, struct vpath *p, int i) -{ - int ret, recv, tomux, allocated, cnt, toenqueue, enqueued = 0; - - cnt = ps->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(&ps->pool, read_smps, cnt); + allocated = sample_alloc_many(&pool, read_smps, cnt); if (allocated != cnt) - p->logger->warn("Pool underrun for path source {}", *ps->node); + path->logger->warn("Pool underrun for path source {}", *node); /* Read ready samples and store them to blocks pointed by smps[] */ - recv = node_read(ps->node, read_smps, allocated); + recv = node->read(read_smps, allocated); if (recv == 0) { enqueued = 0; goto out2; } else if (recv < 0) { - if (ps->node->state == State::STOPPING) { - p->state = State::STOPPING; + if (node->getState() == State::STOPPING) { + path->state = State::STOPPING; enqueued = -1; goto out2; } else { - p->logger->error("Failed to read samples from node {}", *ps->node); + path->logger->error("Failed to read samples from node {}", *node); + enqueued = 0; goto out2; } } else if (recv < allocated) - p->logger->warn("Partial read for path {}: read={}, expected={}", *p, recv, allocated); + path->logger->warn("Partial read for path {}: read={}, expected={}", *path, recv, allocated); - /* Forward samples to secondary path sources */ - for (size_t i = 0; i < vlist_length(&ps->secondaries); i++) { - auto *sps = (struct vpath_source *) vlist_at(&ps->secondaries, i); + /* Let the master path sources forward received samples to their secondaries */ + writeToSecondaries(read_smps, recv); - int sent; - - sent = node_write(sps->node, read_smps, recv); - if (sent < recv) - p->logger->warn("Partial write to secondary path source {} of path {}", *sps->node, *p); - } - - p->received.set(i); - - if (p->mode == PathMode::ANY) { /* Mux all samples */ + if (path->mode == Path::Mode::ANY) { /* Mux all samples */ tomux_smps = read_smps; tomux = recv; } @@ -173,19 +108,19 @@ int path_source_read(struct vpath_source *ps, struct vpath *p, int i) for (int i = 0; i < tomux; i++) { muxed_smps[i] = i == 0 - ? sample_clone(p->last_sample) + ? sample_clone(path->last_sample) : sample_clone(muxed_smps[i-1]); if (!muxed_smps[i]) { - p->logger->error("Pool underrun in path {}", *p); + path->logger->error("Pool underrun in path {}", *path); return -1; } - if (p->original_sequence_no) { + 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 = p->last_sequence++; + muxed_smps[i]->sequence = path->last_sequence++; muxed_smps[i]->flags |= (int) SampleFlags::HAS_SEQUENCE; } @@ -198,7 +133,7 @@ int path_source_read(struct vpath_source *ps, struct vpath *p, int i) muxed_smps[i]->ts = tomux_smps[i]->ts; muxed_smps[i]->flags |= tomux_smps[i]->flags & (int) SampleFlags::HAS_TS; - ret = mapping_list_remap(&ps->mappings, muxed_smps[i], tomux_smps[i]); + ret = mappings.remap(muxed_smps[i], tomux_smps[i]); if (ret) return ret; @@ -206,35 +141,44 @@ int path_source_read(struct vpath_source *ps, struct vpath *p, int i) muxed_smps[i]->flags |= (int) SampleFlags::HAS_DATA; } - sample_copy(p->last_sample, muxed_smps[tomux-1]); - - p->logger->debug("Path {} received = {}", *p, p->received.to_ullong()); + sample_copy(path->last_sample, muxed_smps[tomux-1]); #ifdef WITH_HOOKS - toenqueue = hook_list_process(&p->hooks, muxed_smps, tomux); + toenqueue = path->hooks.process(muxed_smps, tomux); if (toenqueue == -1) { - p->logger->error("An error occured during hook processing. Skipping sample"); + path->logger->error("An error occured during hook processing. Skipping sample"); } else if (toenqueue != tomux) { int skipped = tomux - toenqueue; - p->logger->debug("Hooks skipped {} out of {} samples for path {}", skipped, tomux, *p); + path->logger->debug("Hooks skipped {} out of {} samples for path {}", skipped, tomux, *path); } #else toenqueue = tomux; #endif - if (p->mask.test(i)) { - /* Check if we received an update from all nodes */ - if ((p->mode == PathMode::ANY) || - (p->mode == PathMode::ALL && p->mask == p->received)) { - path_destination_enqueue(p, muxed_smps, toenqueue); + path->received.set(i); - /* Reset mask of updated nodes */ - p->received.reset(); + 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); + + path->received.reset(); + + enqueued = toenqueue; + } + else + enqueued = 0; } } @@ -244,11 +188,40 @@ out2: sample_decref_many(read_smps, recv); return enqueued; } -void path_source_check(struct vpath_source *ps) +void PathSource::check() { - if (!node_is_enabled(ps->node)) - throw RuntimeError("Source {} is not enabled", *ps->node); + if (!node->isEnabled()) + throw RuntimeError("Source {} is not enabled", *node); - if (!node_type(ps->node)->read) - throw RuntimeError("Node {} is not supported as a source for a path", *ps->node); + if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_READ)) + throw RuntimeError("Node {} is not supported as a source for a path", *node); +} + +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(), *path); + else if ((unsigned) sent < cnt) + path->logger->warn("Partial write to secondary path source {} of path {}", *sps->getNode(), *path); + } +} + +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"); + + /* 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 6a8def7bd..8330ec086 100644 --- a/lib/pool.cpp +++ b/lib/pool.cpp @@ -1,7 +1,7 @@ /** Memory pool for fixed size objects. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,14 +22,14 @@ #include #include -#include -#include +#include +#include #include #include using namespace villas; -int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memory_type *m) +int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *m) { int ret; @@ -38,7 +38,7 @@ int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memory_type *m) p->blocksz = p->alignment * CEIL(blocksz, p->alignment); p->len = cnt * p->blocksz; - void *buffer = memory_alloc_aligned(p->len, p->alignment, m); + void *buffer = memory::alloc_aligned(p->len, p->alignment, m); if (!buffer) throw MemoryAllocationError(); @@ -59,7 +59,7 @@ int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memory_type *m) return 0; } -int pool_destroy(struct pool *p) +int villas::node::pool_destroy(struct Pool *p) { int ret; @@ -71,7 +71,7 @@ int pool_destroy(struct pool *p) return ret; void *buffer = (char *) p + p->buffer_off; - ret = memory_free(buffer); + ret = memory::free(buffer); if (ret == 0) p->state = State::DESTROYED; diff --git a/lib/queue.cpp b/lib/queue.cpp index 777816af8..d0b6a2523 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -33,13 +33,13 @@ #include #include -#include +#include #include using namespace villas; /** Initialize MPMC queue */ -int queue_init(struct queue *q, size_t size, struct memory_type *m) +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)) { @@ -51,7 +51,7 @@ int queue_init(struct queue *q, size_t size, struct memory_type *m) } q->buffer_mask = size - 1; - struct queue_cell *buffer = (struct queue_cell *) memory_alloc(sizeof(struct queue_cell) * size, m); + struct CQueue_cell *buffer = (struct CQueue_cell *) memory::alloc(sizeof(struct CQueue_cell) * size, m); if (!buffer) return -2; @@ -73,7 +73,7 @@ int queue_init(struct queue *q, size_t size, struct memory_type *m) return 0; } -int queue_destroy(struct queue *q) +int villas::node::queue_destroy(struct CQueue *q) { void *buffer = (char *) q + q->buffer_off; int ret = 0; @@ -81,29 +81,29 @@ int queue_destroy(struct queue *q) if (q->state == State::DESTROYED) return 0; - ret = memory_free(buffer); + ret = memory::free(buffer); if (ret == 0) q->state = State::DESTROYED; return ret; } -size_t queue_available(struct queue *q) +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 queue_push(struct queue *q, void *ptr) +int villas::node::queue_push(struct CQueue *q, void *ptr) { - struct queue_cell *cell, *buffer; + 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; - buffer = (struct queue_cell *) ((char *) q + q->buffer_off); + 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]; @@ -126,16 +126,16 @@ int queue_push(struct queue *q, void *ptr) return 1; } -int queue_pull(struct queue *q, void **ptr) +int villas::node::queue_pull(struct CQueue *q, void **ptr) { - struct queue_cell *cell, *buffer; + 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; - buffer = (struct queue_cell *) ((char *) q + q->buffer_off); + 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]; @@ -158,7 +158,7 @@ int queue_pull(struct queue *q, void **ptr) return 1; } -int queue_push_many(struct queue *q, void *ptr[], size_t cnt) +int villas::node::queue_push_many(struct CQueue *q, void *ptr[], size_t cnt) { int ret; size_t i; @@ -175,7 +175,7 @@ int queue_push_many(struct queue *q, void *ptr[], size_t cnt) return i; } -int queue_pull_many(struct queue *q, void *ptr[], size_t cnt) +int villas::node::queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt) { int ret; size_t i; @@ -192,7 +192,7 @@ int queue_pull_many(struct queue *q, void *ptr[], size_t cnt) return i; } -int queue_close(struct queue *q) +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)) diff --git a/lib/queue_signalled.cpp b/lib/queue_signalled.cpp index 6243b606a..7095383de 100644 --- a/lib/queue_signalled.cpp +++ b/lib/queue_signalled.cpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,22 +21,25 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include #ifdef HAS_EVENTFD #include #endif -static void queue_signalled_cleanup(void *p) +using namespace villas::node; + +static +void queue_signalled_cleanup(void *p) { - struct queue_signalled *qs = (struct queue_signalled *) p; + struct CQueueSignalled *qs = (struct CQueueSignalled *) p; if (qs->mode == QueueSignalledMode::PTHREAD) pthread_mutex_unlock(&qs->pthread.mutex); } -int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem, enum QueueSignalledMode mode, int flags) +int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, struct memory::Type *mem, enum QueueSignalledMode mode, int flags) { int ret; @@ -107,7 +110,7 @@ int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_ return 0; } -int queue_signalled_destroy(struct queue_signalled *qs) +int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) { int ret; @@ -141,7 +144,7 @@ int queue_signalled_destroy(struct queue_signalled *qs) return 0; } -int queue_signalled_push(struct queue_signalled *qs, void *ptr) +int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) { int pushed; @@ -180,7 +183,7 @@ int queue_signalled_push(struct queue_signalled *qs, void *ptr) return pushed; } -int queue_signalled_push_many(struct queue_signalled *qs, void *ptr[], size_t cnt) +int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) { int pushed; @@ -219,7 +222,7 @@ int queue_signalled_push_many(struct queue_signalled *qs, void *ptr[], size_t cn return pushed; } -int queue_signalled_pull(struct queue_signalled *qs, void **ptr) +int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) { int pulled = 0; @@ -268,7 +271,7 @@ int queue_signalled_pull(struct queue_signalled *qs, void **ptr) return pulled; } -int queue_signalled_pull_many(struct queue_signalled *qs, void *ptr[], size_t cnt) +int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) { int pulled = 0; @@ -317,7 +320,7 @@ int queue_signalled_pull_many(struct queue_signalled *qs, void *ptr[], size_t cn return pulled; } -int queue_signalled_close(struct queue_signalled *qs) +int villas::node::queue_signalled_close(struct CQueueSignalled *qs) { int ret; @@ -358,7 +361,7 @@ int queue_signalled_close(struct queue_signalled *qs) return ret; } -int queue_signalled_fd(struct queue_signalled *qs) +int villas::node::queue_signalled_fd(struct CQueueSignalled *qs) { switch (qs->mode) { #ifdef HAS_EVENTFD diff --git a/lib/sample.cpp b/lib/sample.cpp index 97575e411..cb474a923 100644 --- a/lib/sample.cpp +++ b/lib/sample.cpp @@ -1,7 +1,7 @@ /** The internal datastructure for a sample of simulation data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,49 +24,56 @@ #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 sample_init(struct sample *s) +int villas::node::sample_init(struct Sample *s) { - struct pool *p = sample_pool(s); + struct Pool *p = sample_pool(s); s->length = 0; - s->capacity = (p->blocksz - sizeof(struct sample)) / sizeof(s->data[0]); + s->capacity = (p->blocksz - sizeof(struct Sample)) / sizeof(s->data[0]); s->refcnt = ATOMIC_VAR_INIT(1); + new (&s->signals) std::shared_ptr; + return 0; } -struct sample * sample_alloc(struct pool *p) +struct Sample * villas::node::sample_alloc(struct Pool *p) { - struct sample *s; + struct Sample *s; - s = (struct sample *) pool_get(p); + s = (struct Sample *) pool_get(p); if (!s) return nullptr; s->pool_off = (char *) p - (char *) s; - sample_init(s); + int ret = sample_init(s); + if (ret) { + pool_put(p, s); + return nullptr; + } return s; } -struct sample * sample_alloc_mem(int capacity) +struct Sample * villas::node::sample_alloc_mem(int capacity) { size_t sz = SAMPLE_LENGTH(capacity); - auto *s = (struct sample *) new char[sz]; + auto *s = (struct Sample *) new char[sz]; if (!s) throw MemoryAllocationError(); @@ -81,9 +88,9 @@ struct sample * sample_alloc_mem(int capacity) return s; } -void sample_free(struct sample *s) +void villas::node::sample_free(struct Sample *s) { - struct pool *p = sample_pool(s); + struct Pool *p = sample_pool(s); if (p) pool_put(p, s); @@ -91,7 +98,7 @@ void sample_free(struct sample *s) delete[] (char *) s; } -int sample_alloc_many(struct pool *p, struct sample *smps[], int cnt) +int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], int cnt) { int ret; @@ -108,13 +115,13 @@ int sample_alloc_many(struct pool *p, struct sample *smps[], int cnt) return ret; } -void sample_free_many(struct sample *smps[], int cnt) +void villas::node::sample_free_many(struct Sample *smps[], int cnt) { for (int i = 0; i < cnt; i++) sample_free(smps[i]); } -int sample_decref_many(struct sample * const smps[], int cnt) +int villas::node::sample_decref_many(struct Sample * const smps[], int cnt) { int released = 0; @@ -126,7 +133,7 @@ int sample_decref_many(struct sample * const smps[], int cnt) return released; } -int sample_incref_many(struct sample * const smps[], int cnt) +int villas::node::sample_incref_many(struct Sample * const smps[], int cnt) { for (int i = 0; i < cnt; i++) sample_incref(smps[i]); @@ -134,12 +141,12 @@ int sample_incref_many(struct sample * const smps[], int cnt) return cnt; } -int sample_incref(struct sample *s) +int villas::node::sample_incref(struct Sample *s) { return atomic_fetch_add(&s->refcnt, 1) + 1; } -int sample_decref(struct sample *s) +int villas::node::sample_decref(struct Sample *s) { int prev = atomic_fetch_sub(&s->refcnt, 1); @@ -150,7 +157,7 @@ int sample_decref(struct sample *s) return prev - 1; } -int sample_copy(struct sample *dst, const struct sample *src) +int villas::node::sample_copy(struct Sample *dst, const struct Sample *src) { dst->length = MIN(src->length, dst->capacity); @@ -164,10 +171,10 @@ int sample_copy(struct sample *dst, const struct sample *src) return 0; } -struct sample * sample_clone(struct sample *orig) +struct Sample * villas::node::sample_clone(struct Sample *orig) { - struct sample *clone; - struct pool *pool; + struct Sample *clone; + struct Pool *pool; pool = sample_pool(orig); if (!pool) @@ -182,10 +189,10 @@ struct sample * sample_clone(struct sample *orig) return clone; } -int sample_clone_many(struct sample *dsts[], const struct sample * const srcs[], int cnt) +int villas::node::sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt) { int alloced, copied; - struct pool *pool; + struct Pool *pool; if (cnt <= 0) return 0; @@ -201,7 +208,7 @@ int sample_clone_many(struct sample *dsts[], const struct sample * const srcs[], return copied; } -int sample_copy_many(struct sample * const dsts[], const struct sample * const srcs[], int cnt) +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]); @@ -209,7 +216,7 @@ int sample_copy_many(struct sample * const dsts[], const struct sample * const s return cnt; } -int sample_cmp(struct sample *a, struct sample *b, double epsilon, int flags) +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); @@ -281,16 +288,14 @@ int sample_cmp(struct sample *a, struct sample *b, double epsilon, int flags) return 0; } -enum SignalType sample_format(const struct sample *s, unsigned idx) +enum SignalType villas::node::sample_format(const struct Sample *s, unsigned idx) { - struct signal *sig; - - sig = (struct signal *) vlist_at_safe(s->signals, idx); + auto sig = s->signals->getByIndex(idx); return sig ? sig->type : SignalType::INVALID; } -void sample_dump(Logger logger, struct sample *s) +void villas::node::sample_dump(Logger logger, struct Sample *s) { logger->info("Sample: sequence={}, length={}, capacity={}," "flags={:#x}, #signals={}, " @@ -299,7 +304,7 @@ void sample_dump(Logger logger, struct sample *s) s->length, s->capacity, s->flags, - s->signals ? vlist_length(s->signals) : -1, + s->signals ? s->signals->size() : -1, atomic_load(&s->refcnt), s->pool_off); @@ -311,11 +316,11 @@ void sample_dump(Logger logger, struct sample *s) if (s->signals) { logger->info(" Signals:"); - signal_list_dump(logger, s->signals, s->data, s->length); + s->signals->dump(logger, s->data, s->length); } } -void sample_data_insert(struct sample *smp, const union signal_data *src, size_t offset, size_t 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); @@ -323,7 +328,7 @@ void sample_data_insert(struct sample *smp, const union signal_data *src, size_t smp->length += len; } -void sample_data_remove(struct sample *smp, size_t offset, size_t len) +void villas::node::sample_data_remove(struct Sample *smp, size_t offset, size_t len) { size_t sz = sizeof(smp->data[0]) * len; diff --git a/lib/shmem.cpp b/lib/shmem.cpp index f44bbb174..c21411303 100644 --- a/lib/shmem.cpp +++ b/lib/shmem.cpp @@ -2,7 +2,7 @@ * * @file * @author Georg Martin Reinke - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,37 +28,38 @@ #include #include -#include +#include #include -#include -#include +#include +#include using namespace villas; +using namespace villas::node; -size_t shmem_total_size(int queuelen, int samplelen) +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) + return sizeof(struct memory::Type) /* and the shared struct itself */ - + sizeof(struct shmem_shared) + + sizeof(struct ShmemShared) /* the size of the actual queue and the queue for the pool */ - + queuelen * (2 * sizeof(struct queue_cell)) + + 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) + + 4 * sizeof(struct memory::Block) /* and some extra buffer for alignment */ + 1024; } -int shmem_int_open(const char *wname, const char* rname, struct shmem_int *shm, struct shmem_conf *conf) +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 shmem_shared *shared; + struct memory::Type *manager; + struct ShmemShared *shared; struct stat stat_buf; sem_t *sem_own, *sem_other; @@ -95,8 +96,8 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); close(fd); - manager = memory_managed(base, len); - shared = (struct shmem_shared *) memory_alloc(sizeof(struct shmem_shared), manager); + manager = memory::managed(base, len); + shared = (struct ShmemShared *) memory::alloc(sizeof(struct ShmemShared), manager); if (!shared) { errno = ENOMEM; return -5; @@ -145,8 +146,8 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); if (base == MAP_FAILED) return -10; - cptr = (char *) base + sizeof(struct memory_type) + sizeof(struct memory_block); - shared = (struct shmem_shared *) cptr; + 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; @@ -162,7 +163,7 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); return 0; } -int shmem_int_close(struct shmem_int *shm) +int villas::node::shmem_int_close(struct ShmemInterface *shm) { int ret; @@ -183,7 +184,7 @@ int shmem_int_close(struct shmem_int *shm) return 0; } -int shmem_int_read(struct shmem_int *shm, struct sample * const smps[], unsigned cnt) +int villas::node::shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt) { int ret; @@ -197,7 +198,7 @@ int shmem_int_read(struct shmem_int *shm, struct sample * const smps[], unsigned return ret; } -int shmem_int_write(struct shmem_int *shm, const struct sample * const smps[], unsigned cnt) +int villas::node::shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt) { int ret; @@ -211,7 +212,7 @@ int shmem_int_write(struct shmem_int *shm, const struct sample * const smps[], u return ret; } -int shmem_int_alloc(struct shmem_int *shm, struct sample *smps[], unsigned 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 69291da5f..eff771ff1 100644 --- a/lib/signal.cpp +++ b/lib/signal.cpp @@ -1,7 +1,7 @@ /** Signal meta data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,251 +20,134 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include -#include #include -#include -#include +#include +#include using namespace villas; +using namespace villas::node; using namespace villas::utils; -int signal_init(struct signal *s) -{ - s->enabled = true; +Signal::Signal(const std::string &n, const std::string &u, enum SignalType t) : + name(n), + unit(u), + init(SignalData::nan()), + type(t) +{ } - s->name = nullptr; - s->unit = nullptr; - s->type = SignalType::INVALID; - s->init = signal_data::nan(); - - s->refcnt = ATOMIC_VAR_INIT(1); - - return 0; -} - -int signal_init_from_mapping(struct signal *s, const struct mapping_entry *me, unsigned index) -{ - int ret; - - ret = signal_init(s); - if (ret) - return ret; - - ret = mapping_entry_to_str(me, index, &s->name); - if (ret) - return ret; - - switch (me->type) { - case MappingType::STATS: - s->type = Stats::types[me->stats.type].signal_type; - break; - - case MappingType::HEADER: - switch (me->header.type) { - case MappingHeaderType::LENGTH: - case MappingHeaderType::SEQUENCE: - s->type = SignalType::INTEGER; - break; - } - break; - - case MappingType::TIMESTAMP: - s->type = SignalType::INTEGER; - break; - - case MappingType::DATA: - s->type = me->data.signal->type; - s->init = me->data.signal->init; - s->enabled = me->data.signal->enabled; - - if (me->data.signal->name) - s->name = strdup(me->data.signal->name); - - if (me->data.signal->unit) - s->name = strdup(me->data.signal->unit); - break; - - case MappingType::UNKNOWN: - return -1; - } - - return 0; -} - -int signal_destroy(struct signal *s) -{ - if (s->name) - free(s->name); - - if (s->unit) - free(s->unit); - - return 0; -} - -struct signal * signal_create(const char *name, const char *unit, enum SignalType fmt) -{ - int ret; - struct signal *sig; - - sig = new struct signal; - if (!sig) - throw MemoryAllocationError(); - - ret = signal_init(sig); - if (ret) - return nullptr; - - if (name) - sig->name = strdup(name); - - if (unit) - sig->unit = strdup(unit); - - sig->type = fmt; - - return sig; -} - -int signal_free(struct signal *s) -{ - int ret; - - ret = signal_destroy(s); - if (ret) - return ret; - - delete s; - - return 0; -} - -int signal_incref(struct signal *s) -{ - return atomic_fetch_add(&s->refcnt, 1) + 1; -} - -int signal_decref(struct signal *s) -{ - int prev = atomic_fetch_sub(&s->refcnt, 1); - - /* Did we had the last reference? */ - if (prev == 1) { - int ret = signal_free(s); - if (ret) - throw RuntimeError("Failed to release sample"); - } - - return prev - 1; -} - -struct signal * signal_copy(struct signal *s) -{ - int ret; - struct signal *ns; - - ns = new struct signal; - if (!ns) - throw MemoryAllocationError(); - - ret = signal_init(ns); - if (!ret) - throw RuntimeError("Failed to initialize signal"); - - ns->type = s->type; - ns->init = s->init; - ns->enabled = s->enabled; - - if (s->name) - ns->name = strdup(s->name); - - if (s->unit) - ns->name = strdup(s->unit); - - return ns; -} - -int signal_parse(struct signal *s, json_t *json) +int Signal::parse(json_t *json) { int ret; json_error_t err; json_t *json_init = nullptr; - const char *name = nullptr; - const char *unit = nullptr; - const char *type = "float"; + 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, s?: b }", - "name", &name, - "unit", &unit, - "type", &type, - "init", &json_init, - "enabled", &s->enabled + 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) - s->name = strdup(name); + if (name_str) + name = name_str; - if (unit) - s->unit = strdup(unit); + if (unit_str) + unit = unit_str; - if (type) { - s->type = signal_type_from_str(type); - if (s->type == SignalType::INVALID) + if (type_str) { + type = signalTypeFromString(type_str); + if (type == SignalType::INVALID) return -1; } if (json_init) { - ret = signal_data_parse_json(&s->init, s->type, json_init); + ret = init.parseJson(type, json_init); if (ret) return ret; } else - signal_data_set(&s->init, s->type, 0); + init.set(type, 0); return 0; } -json_t * signal_to_json(struct signal *s) +json_t * Signal::toJson() const { - json_t *json_sig = json_pack("{ s: s, s: b, s: o }", - "type", signal_type_to_str(s->type), - "enabled", s->enabled, - "init", signal_data_to_json(&s->init, s->type) + json_t *json_sig = json_pack("{ s: s, s: o }", + "type", signalTypeToString(type).c_str(), + "init", init.toJson(type) ); - if (s->name) - json_object_set(json_sig, "name", json_string(s->name)); + if (!name.empty()) + json_object_set(json_sig, "name", json_string(name.c_str())); - if (s->unit) - json_object_set(json_sig, "unit", json_string(s->unit)); + if (!unit.empty()) + json_object_set(json_sig, "unit", json_string(unit.c_str())); return json_sig; } -char * signal_print(const struct signal *s, const union signal_data *d) +std::string Signal::toString(const union SignalData *d) const { - char *buf = nullptr; + std::stringstream ss; - if (s->name) - strcatf(&buf, " %s", s->name); + if (!name.empty()) + ss << " " << name; - if (s->unit) - strcatf(&buf, " [%s]", s->unit); + if (!unit.empty()) + ss << " [" << unit << "]"; - strcatf(&buf, "(%s)", signal_type_to_str(s->type)); + ss << "(" << signalTypeToString(type) << ")"; - if (d) { - char val[32]; + if (d) + ss << " = " << d->toString(type); - signal_data_print_str(d, s->type, val, sizeof(val)); - - strcatf(&buf, " = %s", val); - } - - return buf; + 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); + + /* 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); + + return na + 1 == nb; + } catch (std::exception &) { + 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; + + return isNextName(name, sig.name); } diff --git a/lib/signal_data.cpp b/lib/signal_data.cpp index 8da92622f..efac78c52 100644 --- a/lib/signal_data.cpp +++ b/lib/signal_data.cpp @@ -1,7 +1,7 @@ /** Signal data. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -23,35 +23,37 @@ #include #include -#include -#include +#include +#include -void signal_data_set(union signal_data *data, enum SignalType type, double val) +using namespace villas::node; + +void SignalData::set(enum SignalType type, double val) { switch (type) { case SignalType::BOOLEAN: - data->b = val; + this->b = val; break; case SignalType::FLOAT: - data->f = val; + this->f = val; break; case SignalType::INTEGER: - data->i = val; + this->i = val; break; case SignalType::COMPLEX: - data->z = val; + this->z = val; break; case SignalType::INVALID: - *data = signal_data::nan(); + *this = nan(); break; } } -void signal_data_cast(union signal_data *data, enum SignalType from, enum SignalType to) +void SignalData::cast(enum SignalType from, enum SignalType to) { if (from == to) /* Nothing to do */ return; @@ -63,15 +65,15 @@ void signal_data_cast(union signal_data *data, enum SignalType from, enum Signal break; case SignalType::INTEGER: - data->b = data->i; + this->b = this->i; break; case SignalType::FLOAT: - data->b = data->f; + this->b = this->f; break; case SignalType::COMPLEX: - data->b = std::real(data->z); + this->b = std::real(this->z); break; default: { } @@ -81,18 +83,18 @@ void signal_data_cast(union signal_data *data, enum SignalType from, enum Signal case SignalType::INTEGER: switch(from) { case SignalType::BOOLEAN: - data->i = data->b; + this->i = this->b; break; case SignalType::INTEGER: break; case SignalType::FLOAT: - data->i = data->f; + this->i = this->f; break; case SignalType::COMPLEX: - data->i = std::real(data->z); + this->i = std::real(this->z); break; default: { } @@ -102,18 +104,18 @@ void signal_data_cast(union signal_data *data, enum SignalType from, enum Signal case SignalType::FLOAT: switch(from) { case SignalType::BOOLEAN: - data->f = data->b; + this->f = this->b; break; case SignalType::INTEGER: - data->f = data->i; + this->f = this->i; break; case SignalType::FLOAT: break; case SignalType::COMPLEX: - data->f = std::real(data->z); + this->f = std::real(this->z); break; default: { } @@ -123,15 +125,15 @@ void signal_data_cast(union signal_data *data, enum SignalType from, enum Signal case SignalType::COMPLEX: switch(from) { case SignalType::BOOLEAN: - data->z = data->b; + this->z = this->b; break; case SignalType::INTEGER: - data->z = data->i; + this->z = this->i; break; case SignalType::FLOAT: - data->z = data->f; + this->z = this->f; break; case SignalType::COMPLEX: @@ -145,19 +147,19 @@ void signal_data_cast(union signal_data *data, enum SignalType from, enum Signal } } -int signal_data_parse_str(union signal_data *data, enum SignalType type, const char *ptr, char **end) +int SignalData::parseString(enum SignalType type, const char *ptr, char **end) { switch (type) { case SignalType::FLOAT: - data->f = strtod(ptr, end); + this->f = strtod(ptr, end); break; case SignalType::INTEGER: - data->i = strtol(ptr, end, 10); + this->i = strtol(ptr, end, 10); break; case SignalType::BOOLEAN: - data->b = strtol(ptr, end, 10); + this->b = strtol(ptr, end, 10); break; case SignalType::COMPLEX: { @@ -186,7 +188,7 @@ int signal_data_parse_str(union signal_data *data, enum SignalType type, const c (*end)++; } - data->z = std::complex(real, imag); + this->z = std::complex(real, imag); break; } @@ -197,21 +199,21 @@ int signal_data_parse_str(union signal_data *data, enum SignalType type, const c return 0; } -int signal_data_parse_json(union signal_data *data, enum SignalType type, json_t *json) +int SignalData::parseJson(enum SignalType type, json_t *json) { int ret; switch (type) { case SignalType::FLOAT: - data->f = json_real_value(json); + this->f = json_number_value(json); break; case SignalType::INTEGER: - data->i = json_integer_value(json); + this->i = json_integer_value(json); break; case SignalType::BOOLEAN: - data->b = json_boolean_value(json); + this->b = json_boolean_value(json); break; case SignalType::COMPLEX: { @@ -225,7 +227,7 @@ int signal_data_parse_json(union signal_data *data, enum SignalType type, json_t if (ret) return -2; - data->z = std::complex(real, imag); + this->z = std::complex(real, imag); break; } @@ -236,22 +238,22 @@ int signal_data_parse_json(union signal_data *data, enum SignalType type, json_t return 0; } -json_t * signal_data_to_json(const union signal_data *data, enum SignalType type) +json_t * SignalData::toJson(enum SignalType type) const { switch (type) { case SignalType::INTEGER: - return json_integer(data->i); + return json_integer(this->i); case SignalType::FLOAT: - return json_real(data->f); + return json_real(this->f); case SignalType::BOOLEAN: - return json_boolean(data->b); + return json_boolean(this->b); case SignalType::COMPLEX: return json_pack("{ s: f, s: f }", - "real", std::real(data->z), - "imag", std::imag(data->z) + "real", std::real(this->z), + "imag", std::imag(this->z) ); case SignalType::INVALID: @@ -261,22 +263,31 @@ json_t * signal_data_to_json(const union signal_data *data, enum SignalType type return nullptr; } -int signal_data_print_str(const union signal_data *data, enum SignalType type, char *buf, size_t len, int precision) +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, data->f); + return snprintf(buf, len, "%.*f", precision, this->f); case SignalType::INTEGER: - return snprintf(buf, len, "%" PRIi64, data->i); + return snprintf(buf, len, "%" PRIi64, this->i); case SignalType::BOOLEAN: - return snprintf(buf, len, "%u", data->b); + return snprintf(buf, len, "%u", this->b); case SignalType::COMPLEX: - return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(data->z), precision, std::imag(data->z)); + return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(this->z), precision, std::imag(this->z)); default: return snprintf(buf, len, ""); } } + +std::string SignalData::toString(enum SignalType type, int precission) const +{ + char buf[128]; + + printString(type, buf, sizeof(buf), precission); + + return buf; +} diff --git a/lib/signal_list.cpp b/lib/signal_list.cpp index 60fed6a59..9b3dfda12 100644 --- a/lib/signal_list.cpp +++ b/lib/signal_list.cpp @@ -1,7 +1,7 @@ /** Signal metadata list. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,99 +20,58 @@ * along with this program. If not, see . *********************************************************************************/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include using namespace villas; +using namespace villas::node; using namespace villas::utils; -int signal_list_init(struct vlist *list) +int SignalList::parse(json_t *json) { int ret; - ret = vlist_init(list); - if (ret) - return ret; - - return 0; -} - -int signal_list_clear(struct vlist *list) -{ - for (size_t i = 0; i < vlist_length(list); i++) { - struct signal *sig = (struct signal *) vlist_at(list, i); - - signal_decref(sig); - } - - vlist_clear(list); - - return 0; -} - -int signal_list_destroy(struct vlist *list) -{ - int ret; - - ret = vlist_destroy(list, (dtor_cb_t) signal_decref, false); - if (ret) - return ret; - - return 0; -} - -int signal_list_parse(struct vlist *list, json_t *json) -{ - int ret; - struct signal *s; - if (!json_is_array(json)) return -1; size_t i; json_t *json_signal; json_array_foreach(json, i, json_signal) { - s = new struct signal; - if (!s) + auto sig = std::make_shared(); + if (!sig) throw MemoryAllocationError(); - ret = signal_init(s); + ret = sig->parse(json_signal); if (ret) return ret; - ret = signal_parse(s, json_signal); - if (ret) - return ret; - - vlist_push(list, s); + push_back(sig); } return 0; } -int signal_list_generate(struct vlist *list, unsigned len, enum SignalType typ) +SignalList::SignalList(unsigned len, enum SignalType typ) { char name[32]; for (unsigned i = 0; i < len; i++) { snprintf(name, sizeof(name), "signal%u", i); - struct signal *sig = signal_create(name, nullptr, typ); + auto sig = std::make_shared(name, "", typ); if (!sig) - return -1; + throw RuntimeError("Failed to create signal list"); - vlist_push(list, sig); + push_back(sig); } - - return 0; } -int signal_list_generate2(struct vlist *list, const char *dt) +SignalList::SignalList(const char *dt) { int len, i = 0; char name[32], *e; @@ -123,71 +82,35 @@ int signal_list_generate2(struct vlist *list, const char *dt) if (t == e) len = 1; - typ = signal_type_from_fmtstr(*e); + typ = signalTypeFromFormatString(*e); if (typ == SignalType::INVALID) - return -1; + throw RuntimeError("Failed to create signal list"); for (int j = 0; j < len; j++) { snprintf(name, sizeof(name), "signal%d", i++); - struct signal *sig = signal_create(name, nullptr, typ); + auto sig = std::make_shared(name, "", typ); if (!sig) - return -1; + throw RuntimeError("Failed to create signal list"); - vlist_push(list, sig); + push_back(sig); } } - - return 0; } -/** Check if two signal names are numbered ascendingly - * - * E.g. signal3 -> signal4 - */ -static -bool signal_name_is_next(const char *a, const char *b) -{ - unsigned i; - unsigned long na, nb; - char *ea, *eb; - - /* Find common prefix */ - for (i = 0; a[i] && b[i] && a[i] == b[i]; i++); - - na = strtoul(a + i, &ea, 10); - nb = strtoul(b + i, &eb, 10); - - return !*ea && !*eb && na + 1 == nb; -} - -static -bool signal_is_next(const struct signal *a, const struct signal *b) -{ - if (a->type != b->type) - return false; - - if (a->unit && b->unit && strcmp(a->unit, b->unit)) - return false; - - return signal_name_is_next(a->name, b->name); -} - -void signal_list_dump(Logger logger, const struct vlist *list, const union signal_data *data, unsigned len) +void SignalList::dump(Logger logger, const union SignalData *data, unsigned len) const { const char *pfx; bool abbrev = false; - for (size_t i = 0; i < vlist_length(list); i++) { - struct signal *sig = (struct signal *) vlist_at(list, i); - + 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 < vlist_length(list) - 1) { - struct signal *prevSig = (struct signal *) vlist_at(list, i - 1); - - if (signal_is_next(prevSig, sig)) { + if (i >= 1 && i < size() - 1) { + if (prevSig->isNext(*sig)) { abbrev = true; - continue; + goto skip; } } @@ -198,51 +121,57 @@ void signal_list_dump(Logger logger, const struct vlist *list, const union signa else pfx = " "; - char *buf = signal_print(sig, i < len ? &data[i] : nullptr); - logger->debug(" {}{:>3}: {}", pfx, i, buf); - free(buf); + logger->debug(" {}{:>3}: {}", pfx, i, sig->toString(i < len ? &data[i] : nullptr)); + +skip: prevSig = sig; + i++; } } -int signal_list_copy(struct vlist *dst, const struct vlist *src) -{ - assert(src->state == State::INITIALIZED); - assert(dst->state == State::INITIALIZED); - - for (size_t i = 0; i < vlist_length(src); i++) { - struct signal *sig = (struct signal *) vlist_at_safe(src, i); - - signal_incref(sig); - - vlist_push(dst, sig); - } - - return 0; -} - -json_t * signal_list_to_json(struct vlist *list) +json_t * SignalList::toJson() const { json_t *json_signals = json_array(); - for (size_t i = 0; i < vlist_length(list); i++) { - struct signal *sig = (struct signal *) vlist_at_safe(list, i); - - json_t *json_signal = json_pack("{ s: s, s: b }", - "type", signal_type_to_str(sig->type), - "enabled", sig->enabled - ); - - if (sig->name) - json_object_set_new(json_signal, "name", json_string(sig->name)); - - if (sig->unit) - json_object_set_new(json_signal, "unit", json_string(sig->unit)); - - if (!sig->init.is_nan()) - json_object_set_new(json_signal, "init", signal_data_to_json(&sig->init, sig->type)); - - json_array_append_new(json_signals, json_signal); - } + for (const auto &sig : *this) + json_array_append_new(json_signals, sig->toJson()); return json_signals; } + +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; +} + +Signal::Ptr SignalList::getByName(const std::string &name) +{ + for (auto s : *this) { + if (name == s->name) + return s; + } + + return Signal::Ptr(); +} + +SignalList::Ptr SignalList::clone() +{ + auto l = std::make_shared(); + + for (auto s : *this) + l->push_back(s); + + return l; +} diff --git a/lib/signal_type.cpp b/lib/signal_type.cpp index 0e4da1c8b..5d1d290fa 100644 --- a/lib/signal_type.cpp +++ b/lib/signal_type.cpp @@ -1,7 +1,7 @@ /** Signal types. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,23 +22,25 @@ #include -#include +#include -enum SignalType signal_type_from_str(const char *str) +using namespace villas::node; + +enum SignalType villas::node::signalTypeFromString(const std::string &str) { - if (!strcmp(str, "boolean")) + if (str == "boolean") return SignalType::BOOLEAN; - else if (!strcmp(str, "complex")) + else if (str == "complex") return SignalType::COMPLEX; - else if (!strcmp(str, "float")) + else if (str == "float") return SignalType::FLOAT; - else if (!strcmp(str, "integer")) + else if (str == "integer") return SignalType::INTEGER; else return SignalType::INVALID; } -enum SignalType signal_type_from_fmtstr(char c) +enum SignalType villas::node::signalTypeFromFormatString(char c) { switch (c) { case 'f': @@ -58,7 +60,7 @@ enum SignalType signal_type_from_fmtstr(char c) } } -const char * signal_type_to_str(enum SignalType fmt) +std::string villas::node::signalTypeToString(enum SignalType fmt) { switch (fmt) { case SignalType::BOOLEAN: @@ -80,20 +82,17 @@ const char * signal_type_to_str(enum SignalType fmt) return nullptr; } -enum SignalType signal_type_detect(const char *val) +enum SignalType villas::node::signalTypeDetect(const std::string &val) { - const char *brk; int len; - brk = strchr(val, 'i'); - if (brk) + if (val.find('i') != std::string::npos) return SignalType::COMPLEX; - brk = strchr(val, '.'); - if (brk) + if (val.find(',') != std::string::npos) return SignalType::FLOAT; - len = strlen(val); + len = val.size(); if (len == 1 && (val[0] == '1' || val[0] == '0')) return SignalType::BOOLEAN; diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index c1e9b7930..5ac1275c4 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -1,7 +1,7 @@ /** Various functions to work with socket addresses * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -34,12 +34,13 @@ #endif /* WITH_SOCKET_LAYER_ETH */ using namespace villas; +using namespace villas::node; using namespace villas::utils; -char * socket_print_addr(struct sockaddr *saddr) +char * villas::node::socket_print_addr(struct sockaddr *saddr) { union sockaddr_union *sa = (union sockaddr_union *) saddr; - char *buf = new char[64]; + char *buf = new char[256]; if (!buf) throw MemoryAllocationError(); @@ -61,7 +62,7 @@ char * socket_print_addr(struct sockaddr *saddr) break; #endif /* WITH_SOCKET_LAYER_ETH */ case AF_UNIX: - strcatf(&buf, "%s", sa->sun.sun_path); + snprintf(buf, 256, "%s", sa->sun.sun_path); break; default: @@ -92,7 +93,7 @@ char * socket_print_addr(struct sockaddr *saddr) return buf; } -int socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLayer layer, int flags) +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; @@ -194,7 +195,7 @@ int socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLa return ret; } -int socket_compare_addr(struct sockaddr *x, struct sockaddr *y) +int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) { #define CMP(a, b) if (a != b) return a < b ? -1 : 1 diff --git a/lib/stats.cpp b/lib/stats.cpp index 4307d5790..6e26873d2 100644 --- a/lib/stats.cpp +++ b/lib/stats.cpp @@ -1,7 +1,7 @@ /** Statistic collection. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,12 +24,13 @@ #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 = { @@ -158,13 +159,13 @@ void Stats::setupTable() } } -void Stats::printPeriodic(FILE *f, enum Format fmt, struct vnode *n) const +void Stats::printPeriodic(FILE *f, enum Format fmt, node::Node *n) const { switch (fmt) { case Format::HUMAN: setupTable(); table->row(11, - node_name_short(n), + 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(), @@ -181,7 +182,7 @@ void Stats::printPeriodic(FILE *f, enum Format fmt, struct vnode *n) const 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", node_name(n), + "node", n->getNameShort().c_str(), "recv", histograms.at(Metric::OWD).getTotal(), "sent", histograms.at(Metric::AGE).getTotal(), "dropped", histograms.at(Metric::SMPS_REORDERED).getTotal(), @@ -221,10 +222,10 @@ void Stats::print(FILE *f, enum Format fmt, int verbose) const } } -union signal_data Stats::getValue(enum Metric sm, enum Type st) const +union SignalData Stats::getValue(enum Metric sm, enum Type st) const { const Hist &h = histograms.at(sm); - union signal_data d; + union SignalData d; switch (st) { case Type::TOTAL: diff --git a/lib/super_node.cpp b/lib/super_node.cpp index cf1d956e7..29c9f646c 100644 --- a/lib/super_node.cpp +++ b/lib/super_node.cpp @@ -1,7 +1,7 @@ /** The super node object holding the state of the application. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,17 +25,14 @@ #include #include -#include -#include -#include -#include +#include +#include #include -#include #include -#include +#include #include #include -#include +#include #include #include #include @@ -97,7 +94,9 @@ void SuperNode::parse(json_t *root) { int ret; - assert(state != State::STARTED); + assert(state == State::PARSED || + state == State::INITIALIZED || + state == State::CHECKED); const char *uuid_str = nullptr; @@ -147,10 +146,9 @@ void SuperNode::parse(json_t *root) const char *name; json_t *json_node; json_object_foreach(json_nodes, name, json_node) { - struct vnode_type *nt; const char *type; - ret = node_is_valid_name(name); + ret = Node::isValidName(name); if (!ret) throw RuntimeError("Invalid name for node: {}", name); @@ -158,21 +156,13 @@ void SuperNode::parse(json_t *root) if (ret) throw ConfigError(root, err, "node-config-node-type", "Failed to parse type of node '{}'", name); - json_object_set(json_node, "name", json_string(name)); + json_object_set_new(json_node, "name", json_string(name)); - nt = node_type_lookup(type); - if (!nt) - throw ConfigError(json_node, "node-config-node-type", "Invalid node type: {}", type); - - auto *n = new struct vnode; + auto *n = NodeFactory::make(type); if (!n) throw MemoryAllocationError(); - ret = node_init(n, nt); - if (ret) - throw RuntimeError("Failed to initialize node"); - - ret = node_parse(n, json_node, uuid); + ret = n->parse(json_node, uuid); if (ret) { auto config_id = fmt::format("node-config-node-{}", type); @@ -193,23 +183,17 @@ void SuperNode::parse(json_t *root) size_t i; json_t *json_path; json_array_foreach(json_paths, i, json_path) { -parse: auto *p = new vpath; +parse: auto *p = new Path(); if (!p) throw MemoryAllocationError(); - ret = path_init(p); - if (ret) - throw RuntimeError("Failed to initialize path"); - - ret = path_parse(p, json_path, nodes, uuid); - if (ret) - throw RuntimeError("Failed to parse path"); + p->parse(json_path, nodes, uuid); paths.push_back(p); - if (p->reverse) { + if (p->isReversed()) { /* Only simple paths can be reversed */ - ret = path_is_simple(p); + ret = p->isSimple(); if (!ret) throw RuntimeError("Complex paths can not be reversed!"); @@ -238,16 +222,18 @@ 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 = node_check(n); + ret = n->check(); if (ret) throw RuntimeError("Invalid configuration for node {}", *n); } for (auto *p : paths) - path_check(p); + p->check(); state = State::CHECKED; } @@ -257,9 +243,14 @@ void SuperNode::prepareNodeTypes() int ret; for (auto *n : nodes) { - ret = node_type_start(node_type(n), this); + auto *nf = n->getFactory(); + + if (nf->getState() == State::STARTED) + continue; + + ret = nf->start(this); if (ret) - throw RuntimeError("Failed to start node-type: {}", *node_type(n)); + throw RuntimeError("Failed to start node-type: {}", *n->getFactory()); } } @@ -281,10 +272,10 @@ void SuperNode::startNodes() int ret; for (auto *n : nodes) { - if (!node_is_enabled(n)) + if (!n->isEnabled()) continue; - ret = node_start(n); + ret = n->start(); if (ret) throw RuntimeError("Failed to start node: {}", *n); } @@ -292,15 +283,9 @@ void SuperNode::startNodes() void SuperNode::startPaths() { - int ret; - for (auto *p : paths) { - if (!path_is_enabled(p)) - continue; - - ret = path_start(p); - if (ret) - throw RuntimeError("Failed to start path: {}", *p); + if (p->isEnabled()) + p->start(); } } @@ -309,10 +294,10 @@ void SuperNode::prepareNodes() int ret; for (auto *n : nodes) { - if (!node_is_enabled(n)) + if (!n->isEnabled()) continue; - ret = node_prepare(n); + ret = n->prepare(); if (ret) throw RuntimeError("Failed to prepare node: {}", *n); } @@ -320,15 +305,9 @@ void SuperNode::prepareNodes() void SuperNode::preparePaths() { - int ret; - for (auto *p : paths) { - if (!path_is_enabled(p)) - continue; - - ret = path_prepare(p, nodes); - if (ret) - throw RuntimeError("Failed to prepare path: {}", *p); + if (p->isEnabled()) + p->prepare(nodes); } } @@ -338,7 +317,7 @@ void SuperNode::prepare() assert(state == State::CHECKED); - ret = memory_init(hugepages); + ret = memory::init(hugepages); if (ret) throw RuntimeError("Failed to initialize memory system"); @@ -349,10 +328,10 @@ void SuperNode::prepare() preparePaths(); for (auto *n : nodes) { - if (vlist_length(&n->sources) == 0 && - vlist_length(&n->destinations) == 0) { + if (n->sources.size() == 0 && + n->destinations.size() == 0) { logger->info("Node {} is not used by any path. Disabling...", *n); - n->enabled = false; + n->setEnabled(false); } } @@ -385,12 +364,10 @@ void SuperNode::start() void SuperNode::stopPaths() { - int ret; - for (auto *p : paths) { - ret = path_stop(p); - if (ret) - throw RuntimeError("Failed to stop path: {}", *p); + if (p->getState() == State::STARTED || + p->getState() == State::PAUSED) + p->stop(); } } @@ -399,9 +376,13 @@ void SuperNode::stopNodes() int ret; for (auto *n : nodes) { - ret = node_stop(n); - if (ret) - throw RuntimeError("Failed to stop node: {}", *n); + 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); + } } } @@ -409,10 +390,15 @@ void SuperNode::stopNodeTypes() { int ret; - for (auto *vt : *node_types) { - ret = node_type_stop(vt); + for (auto *n : nodes) { + auto *nf = n->getFactory(); + + if (nf->getState() != State::STARTED) + continue; + + ret = nf->stop(); if (ret) - throw RuntimeError("Failed to stop node-type: {}", *vt); + throw RuntimeError("Failed to stop node-type: {}", *n->getFactory()); } } @@ -462,19 +448,17 @@ void SuperNode::run() SuperNode::~SuperNode() { - assert(state != State::STARTED); + assert(state == State::INITIALIZED || + state == State::PARSED || + state == State::CHECKED || + state == State::STOPPED || + state == State::PREPARED); - int ret __attribute__((unused)); - - for (auto *p : paths) { - ret = path_destroy(p); + for (auto *p : paths) delete p; - } - for (auto *n : nodes) { - ret = node_destroy(n); + for (auto *n : nodes) delete n; - } } int SuperNode::periodic() @@ -482,20 +466,20 @@ int SuperNode::periodic() int started = 0; for (auto *p : paths) { - if (p->state == State::STARTED) { + if (p->getState() == State::STARTED) { started++; #ifdef WITH_HOOKS - hook_list_periodic(&p->hooks); + p->hooks.periodic(); #endif /* WITH_HOOKS */ } } for (auto *n : nodes) { - if (n->state == State::STARTED) { + if (n->getState() == State::STARTED) { #ifdef WITH_HOOKS - hook_list_periodic(&n->in.hooks); - hook_list_periodic(&n->out.hooks); + n->in.hooks.periodic(); + n->out.hooks.periodic(); #endif /* WITH_HOOKS */ } } @@ -510,8 +494,8 @@ int SuperNode::periodic() } #ifdef WITH_GRAPHVIZ -static void -set_attr(void *ptr, const std::string &key, const std::string &value, bool html = false) { +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 *) ""; @@ -522,7 +506,6 @@ set_attr(void *ptr, const std::string &key, const std::string &value, bool html agsafeset(ptr, k, vd, d); } - graph_t * SuperNode::getGraph() { Agraph_t *g; @@ -530,17 +513,17 @@ graph_t * SuperNode::getGraph() g = agopen((char *) "g", Agdirected, 0); - std::map nodeMap; + std::map nodeMap; uuid_string_t uuid_str; for (auto *n : nodes) { - nodeMap[n] = agnode(g, (char *) node_name_short(n), 1); + nodeMap[n] = agnode(g, (char *) n->getNameShort().c_str(), 1); - uuid_unparse(n->uuid, uuid_str); + uuid_unparse(n->getUuid(), uuid_str); set_attr(nodeMap[n], "shape", "ellipse"); - set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", *node_type(n), uuid_str)); + set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", *n->getFactory(), uuid_str)); // set_attr(nodeMap[n], "fixedsize", "true"); // set_attr(nodeMap[n], "width", "0.15"); // set_attr(nodeMap[n], "height", "0.15"); @@ -557,17 +540,11 @@ graph_t * SuperNode::getGraph() set_attr(m, "shape", "box"); set_attr(m, "tooltip", fmt::format("uuid={}", uuid_str)); - for (size_t j = 0; j < vlist_length(&p->sources); j++) { - auto *ps = (struct vpath_source *) vlist_at(&p->sources, j); + for (auto ps : p->sources) + agedge(g, nodeMap[ps->getNode()], m, nullptr, 1); - agedge(g, nodeMap[ps->node], m, nullptr, 1); - } - - for (size_t j = 0; j < vlist_length(&p->destinations); j++) { - auto *pd = (struct vpath_destination *) vlist_at(&p->destinations, j); - - agedge(g, m, nodeMap[pd->node], nullptr, 1); - } + for (auto pd : p->destinations) + agedge(g, m, nodeMap[pd->getNode()], nullptr, 1); } return g; diff --git a/lib/usb.cpp b/lib/usb.cpp index 75d8fcc13..a91178846 100644 --- a/lib/usb.cpp +++ b/lib/usb.cpp @@ -27,12 +27,17 @@ using namespace villas; using namespace villas::usb; -static struct libusb_context *context = nullptr; -static int context_users = 0; +static +struct libusb_context *context = nullptr; -static Logger logger; +static +int context_users = 0; -static enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) +static +Logger logger; + +static +enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) { switch (lvl) { case Log::Level::trace: @@ -56,7 +61,8 @@ static enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) } } -static Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) +static +Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) { switch (lvl) { case LIBUSB_LOG_LEVEL_ERROR: @@ -77,7 +83,8 @@ static Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) } } -static void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, const char *str) +static +void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, const char *str) { auto level = libusb_to_spdlog_log_level(lvl); diff --git a/lib/web.cpp b/lib/web.cpp index fc55a4144..2b05126fd 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -1,7 +1,7 @@ /** LWS-releated functions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include @@ -34,7 +34,7 @@ using namespace villas; using namespace villas::node; /* Forward declarations */ -lws_callback_function websocket_protocol_cb; +lws_callback_function villas::node::websocket_protocol_cb; /** List of libwebsockets protocols. */ lws_protocols protocols[] = { @@ -69,7 +69,7 @@ lws_protocols protocols[] = { static lws_http_mount mounts[] = { #ifdef WITH_API { - .mount_next = &mounts[1], /* linked-list "next" */ + .mount_next = nullptr, /* linked-list "next" */ .mountpoint = "/api/v2", /* mountpoint URL */ .origin = "http-api", /* protocol */ .def = nullptr, @@ -85,26 +85,8 @@ static lws_http_mount mounts[] = { .cache_intermediaries = 0, .origin_protocol = LWSMPRO_CALLBACK, /* dynamic */ .mountpoint_len = 7 /* char count */ - }, -#endif /* WITH_API */ - { - .mount_next = nullptr, - .mountpoint = "/", - .origin = nullptr, - .def = "/index.html", - .protocol = nullptr, - .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_FILE, - .mountpoint_len = 1 } +#endif /* WITH_API */ }; /** List of libwebsockets extensions. */ @@ -179,15 +161,13 @@ int Web::lwsLogLevel(Log::Level lvl) { void Web::worker() { - lws *wsi; - logger->info("Started worker"); while (running) { lws_service(context, 0); while (!writables.empty()) { - wsi = writables.pop(); + auto *wsi = writables.pop(); lws_callback_on_writable(wsi); } @@ -202,7 +182,6 @@ Web::Web(Api *a) : context(nullptr), vhost(nullptr), port(getuid() > 0 ? 8080 : 80), - htdocs(WEB_PATH), api(a) { lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); @@ -213,13 +192,11 @@ int Web::parse(json_t *json) int ret, enabled = 1; const char *cert = nullptr; const char *pkey = nullptr; - const char *htd = nullptr; json_error_t err; - ret = json_unpack_ex(json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", + ret = json_unpack_ex(json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: i, s?: b }", "ssl_cert", &cert, "ssl_private_key", &pkey, - "htdocs", &htd, "port", &port, "enabled", &enabled ); @@ -232,9 +209,6 @@ int Web::parse(json_t *json) if (pkey) ssl_private_key = pkey; - if (htd) - htdocs = htd; - if (!enabled) port = CONTEXT_PORT_NO_LISTEN; @@ -252,7 +226,9 @@ void Web::start() ctx_info.port = port; ctx_info.protocols = protocols; +#ifndef LWS_WITHOUT_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; @@ -262,13 +238,10 @@ void Web::start() #if LWS_LIBRARY_VERSION_NUMBER <= 3000000 /* See: https://github.com/warmcat/libwebsockets/issues/1249 */ ctx_info.max_http_header_pool = 1024; - #endif +#endif ctx_info.mounts = mounts; - logger->info("Starting sub-system: htdocs={}", htdocs); - - /* update web root of mount point */ - mounts[ARRAY_LEN(mounts)-1].origin = htdocs.c_str(); + logger->info("Starting sub-system"); context = lws_create_context(&ctx_info); if (context == nullptr) @@ -280,7 +253,7 @@ void Web::start() break; ctx_info.port++; - logger->warn("WebSocket: failed to setup vhost. Trying another port: {}", ctx_info.port); + logger->warn("Failed to setup vhost. Trying another port: {}", ctx_info.port); } if (vhost == nullptr) diff --git a/libopal b/libopal new file mode 120000 index 000000000..bf36bd627 --- /dev/null +++ b/libopal @@ -0,0 +1 @@ +../libopal/ \ No newline at end of file diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 94337d18a..f4e45c657 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.alpine b/packaging/docker/Dockerfile.alpine index 5343bc677..88947c4a5 100644 --- a/packaging/docker/Dockerfile.alpine +++ b/packaging/docker/Dockerfile.alpine @@ -2,7 +2,7 @@ # Alpine Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.centos b/packaging/docker/Dockerfile.centos index 0cb88c33d..cbb026a37 100644 --- a/packaging/docker/Dockerfile.centos +++ b/packaging/docker/Dockerfile.centos @@ -1,7 +1,7 @@ # CentOS Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.debian b/packaging/docker/Dockerfile.debian index 83ddc38db..d0c1c1656 100644 --- a/packaging/docker/Dockerfile.debian +++ b/packaging/docker/Dockerfile.debian @@ -1,7 +1,7 @@ # Debian Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.debian-multiarch b/packaging/docker/Dockerfile.debian-multiarch index 6a4b21b82..59e12d3b8 100644 --- a/packaging/docker/Dockerfile.debian-multiarch +++ b/packaging/docker/Dockerfile.debian-multiarch @@ -1,7 +1,7 @@ # Debian Multiarch Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 6c453489b..d53463681 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -1,7 +1,7 @@ # Fedora Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.fedora-minimal b/packaging/docker/Dockerfile.fedora-minimal index 745b0a54a..647a323bf 100644 --- a/packaging/docker/Dockerfile.fedora-minimal +++ b/packaging/docker/Dockerfile.fedora-minimal @@ -1,7 +1,7 @@ # Minimal Fedora Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 2381a1f3f..a38fc4dca 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -1,7 +1,7 @@ # Ubuntu Dockerfile # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 6240c45eb..a6533911c 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/plugins/example_hook.cpp b/plugins/example_hook.cpp index 3400a664b..b2f9c7fec 100644 --- a/plugins/example_hook.cpp +++ b/plugins/example_hook.cpp @@ -1,7 +1,7 @@ /** A simple example hook function which can be loaded as a plugin. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,7 +21,7 @@ *********************************************************************************/ #include -#include +#include namespace villas { namespace node { diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e8f19756f..ae696216d 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,7 +1,7 @@ # Makefile. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/python/README.md b/python/README.md index 19aa45977..dd2161115 100644 --- a/python/README.md +++ b/python/README.md @@ -12,7 +12,7 @@ User documentation is available here: -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/src/villas-compare.cpp b/src/villas-compare.cpp index 170536666..3454eb034 100644 --- a/src/villas-compare.cpp +++ b/src/villas-compare.cpp @@ -1,7 +1,7 @@ /** Compare two data files. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -26,13 +26,13 @@ #include #include -#include +#include #include #include #include -#include +#include #include -#include +#include using namespace villas; @@ -47,7 +47,7 @@ public: std::string dtypes; std::string format; - struct sample *sample; + struct Sample *sample; Format *formatter; @@ -56,7 +56,7 @@ public: 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) : + CompareSide(const std::string &pth, const std::string &fmt, const std::string &dt, struct Pool *p) : path(pth), dtypes(dt), format(fmt) @@ -108,13 +108,13 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + 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; @@ -214,7 +214,7 @@ check: if (optarg == endptr) int ret, rc = 0, line, failed; unsigned eofs; - ret = pool_init(&pool, filenames.size(), SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory_heap); + ret = pool_init(&pool, filenames.size(), SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); if (ret) throw RuntimeError("Failed to initialize pool"); diff --git a/src/villas-conf2json.cpp b/src/villas-conf2json.cpp index 15d4e49bc..d0e924b8e 100644 --- a/src/villas-conf2json.cpp +++ b/src/villas-conf2json.cpp @@ -1,7 +1,7 @@ /** Convert old style config to new JSON format. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index e11334794..4a4ed7fa6 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -19,9 +19,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * @addtogroup tools Test and debug tools - * @{ *********************************************************************************/ #include @@ -31,12 +28,13 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include using namespace villas; +using namespace villas::node; namespace villas { namespace node { @@ -51,7 +49,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); @@ -143,7 +141,7 @@ protected: dirs[i].formatter->start(dtypes); } - struct sample *smp = sample_alloc_mem(DEFAULT_SAMPLE_LENGTH); + struct Sample *smp = sample_alloc_mem(DEFAULT_SAMPLE_LENGTH); while (true) { ret = dirs[0].formatter->scan(stdin, smp); @@ -172,5 +170,3 @@ int main(int argc, char *argv[]) return t.run(); } - -/** @} */ diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index 40b3b92a9..daf247823 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -19,9 +19,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * @addtogroup tools Test and debug tools - * @{ *********************************************************************************/ #include @@ -59,7 +56,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); @@ -154,5 +151,3 @@ int main(int argc, char *argv[]) return t.run(); } - -/** @} */ diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index 1b1e41a74..0483695bc 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -21,29 +21,24 @@ * along with this program. If not, see . *********************************************************************************/ -/** - * @addtogroup tools Test and debug tools - * @{ - */ - #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; @@ -69,7 +64,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); @@ -91,7 +86,7 @@ protected: std::string input_format; std::string dtypes; - struct pool p; + struct Pool p; Format *input; Format *output; @@ -217,7 +212,7 @@ check: if (optarg == endptr) int main() { int ret, recv, sent; - struct sample *smps[cnt]; + struct Sample *smps[cnt]; if (cnt < 1) throw RuntimeError("Vectorize option must be greater than 0"); @@ -285,7 +280,7 @@ check: if (optarg == endptr) unsigned send = 0; for (int processed = 0; processed < recv; processed++) { - struct sample *smp = smps[processed]; + struct Sample *smp = smps[processed]; if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)){ smp->ts.received = now; @@ -294,8 +289,7 @@ check: if (optarg == endptr) auto ret = h->process(smp); switch (ret) { - using Reason = villas::node::Hook::Reason; - + using Reason = node::Hook::Reason; case Reason::ERROR: throw RuntimeError("Failed to process samples"); @@ -322,8 +316,6 @@ stop: sent = output->print(stdout, smps, send); h->stop(); - delete h; - for (auto &d : descs) delete (*d.formatter); diff --git a/src/villas-node.cpp b/src/villas-node.cpp index b7eaac9e9..49becce67 100644 --- a/src/villas-node.cpp +++ b/src/villas-node.cpp @@ -1,7 +1,7 @@ /** Main routine. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -29,15 +29,15 @@ #include #include -#include +#include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -106,25 +106,27 @@ protected: #endif /* WITH_NODE_OPAL */ << "Supported node-types:" << std::endl; - for (auto *vt : *node_types) - std::cout << " - " << std::left << std::setw(18) << *vt << vt->description << std::endl; + for (auto p : Registry::lookup()) { + if (!p->isInternal()) + 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 (Plugin *p : Registry::lookup()) + for (auto p : Registry::lookup()) 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 (Plugin *p : Registry::lookup()) + for (auto p : Registry::lookup()) 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 (Plugin *p : Registry::lookup()) + for (auto p : Registry::lookup()) std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; std::cout << std::endl; #endif /* WITH_API */ @@ -222,5 +224,3 @@ int main(int argc, char *argv[]) return t.run(); } -/** @} */ - diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index efc7d0116..4c10fad11 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -19,9 +19,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * @addtogroup tools Test and debug tools - * @{ *********************************************************************************/ #include @@ -33,16 +30,16 @@ #include #include -#include +#include #include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -56,8 +53,8 @@ namespace tools { class PipeDirection { protected: - struct pool pool; - struct vnode *node; + struct Pool pool; + Node *node; Format *formatter; std::thread thread; @@ -67,7 +64,7 @@ protected: bool enabled; int limit; public: - PipeDirection(struct vnode *n, Format *fmt, bool en, int lim, const std::string &name) : + PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) : node(n), formatter(fmt), stop(false), @@ -80,7 +77,7 @@ public: /* 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_memory_type(node)); + 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."); } @@ -92,42 +89,44 @@ public: ret = pool_destroy(&pool); } - virtual void run() - { - - } + virtual + void run() = 0; void startThread() { stop = false; + if (enabled) - thread = std::thread(&villas::node::tools::PipeDirection::run, this); + thread = std::thread(&PipeDirection::run, this); } void stopThread() { stop = true; - /* We send a signal to the thread in order to interrupt blocking system calls */ - pthread_kill(thread.native_handle(), SIGUSR1); + if (enabled) { + /* We send a signal to the thread in order to interrupt blocking system calls */ + pthread_kill(thread.native_handle(), SIGUSR1); - thread.join(); + thread.join(); + } } }; class PipeSendDirection : public PipeDirection { public: - PipeSendDirection(struct vnode *n, Format *i, bool en = true, int lim = -1) : + PipeSendDirection(Node *n, Format *i, bool en = true, int lim = -1) : PipeDirection(n, i, en, lim, "send") { } - virtual void run() + virtual + void run() { unsigned last_sequenceno = 0; int scanned, sent, allocated, cnt = 0; - struct sample *smps[node->out.vectorize]; + struct Sample *smps[node->out.vectorize]; while (!stop && !feof(stdin)) { allocated = sample_alloc_many(&pool, smps, node->out.vectorize); @@ -155,7 +154,7 @@ public: smps[i]->sequence = last_sequenceno++; } - sent = node_write(node, smps, scanned); + sent = node->write(smps, scanned); sample_decref_many(smps, scanned); @@ -186,14 +185,15 @@ leave: if (feof(stdin)) { class PipeReceiveDirection : public PipeDirection { public: - PipeReceiveDirection(struct vnode *n, Format *i, bool en = true, int lim = -1) : + PipeReceiveDirection(Node *n, Format *i, bool en = true, int lim = -1) : PipeDirection(n, i, en, lim, "recv") { } - virtual void run() + virtual + void run() { int recv, cnt = 0, allocated = 0; - struct sample *smps[node->in.vectorize]; + struct Sample *smps[node->in.vectorize]; while (!stop) { allocated = sample_alloc_many(&pool, smps, node->in.vectorize); @@ -202,9 +202,9 @@ public: else if (allocated < (int) node->in.vectorize) logger->warn("Receive pool underrun: allocated only {} of {} samples", allocated, node->in.vectorize); - recv = node_read(node, smps, allocated); + recv = node->read(smps, allocated); if (recv < 0) { - if (node->state == State::STOPPING || stop) + if (node->getState() == State::STOPPING || stop) goto leave2; else logger->warn("Failed to receive samples from node {}: reason={}", *node, recv); @@ -242,14 +242,14 @@ public: format("villas.human"), dtypes("64f"), config_cli(json_object()), - enable_send(true), - enable_recv(true), + enable_write(true), + enable_read(true), limit_send(-1), limit_recv(-1) { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); } @@ -274,8 +274,8 @@ protected: json_t *config_cli; - bool enable_send; - bool enable_recv; + bool enable_write; + bool enable_read; int limit_send; int limit_recv; @@ -342,11 +342,11 @@ protected: break; case 's': - enable_recv = false; // send only + enable_read = false; // send only break; case 'r': - enable_send = false; // receive only + enable_write = false; // receive only break; case 'l': @@ -395,7 +395,7 @@ check: if (optarg == endptr) int main() { int ret; - struct vnode *node; + Node *node; json_t *json_format; json_error_t err; @@ -406,7 +406,6 @@ 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 */ json_format = json_loads(format.c_str(), 0, &err); formatter = json_format @@ -421,43 +420,43 @@ check: if (optarg == endptr) if (!node) throw RuntimeError("Node {} does not exist!", nodestr); - if (!node_type(node)->read && enable_recv) + if (enable_read && !(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 (!node_type(node)->write && enable_send) - throw RuntimeError("Node {} can not send data. Consider using receive-only mode by using '-r' option", nodestr); + if (enable_write && !(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_type(node)->start == websocket_start) { + if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { Web *w = sn.getWeb(); w->start(); } #endif /* WITH_NODE_WEBSOCKET */ if (reverse) - node_reverse(node); + node->reverse(); - ret = node_type_start(node_type(node), &sn); + ret = node->getFactory()->start(&sn); if (ret) - throw RuntimeError("Failed to intialize node type {}: reason={}", *node_type(node), ret); + throw RuntimeError("Failed to intialize node type {}: reason={}", *node->getFactory(), ret); sn.startInterfaces(); - ret = node_check(node); + ret = node->check(); if (ret) throw RuntimeError("Invalid node configuration"); - ret = node_prepare(node); + ret = node->prepare(); if (ret) throw RuntimeError("Failed to prepare node {}: reason={}", *node, ret); - ret = node_start(node); + ret = node->start(); if (ret) throw RuntimeError("Failed to start node {}: reason={}", *node, ret); - PipeReceiveDirection recv_dir(node, formatter, enable_recv, limit_recv); - PipeSendDirection send_dir(node, formatter, enable_send, limit_send); + PipeReceiveDirection recv_dir(node, formatter, enable_read, limit_recv); + PipeSendDirection send_dir(node, formatter, enable_write, limit_send); recv_dir.startThread(); send_dir.startThread(); @@ -470,20 +469,20 @@ check: if (optarg == endptr) recv_dir.stopThread(); send_dir.stopThread(); - ret = node_stop(node); + ret = node->stop(); if (ret) throw RuntimeError("Failed to stop node {}: reason={}", *node, ret); sn.stopInterfaces(); - ret = node_type_stop(node_type(node)); + ret = node->getFactory()->stop(); if (ret) - throw RuntimeError("Failed to stop node type {}: reason={}", *node_type(node), ret); + throw RuntimeError("Failed to stop node type {}: reason={}", *node->getFactory(), ret); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) /* Only start web subsystem if villas-pipe is used with a websocket node */ - if (node_type(node)->stop == websocket_stop) { - Web *w = sn.getWeb(); + if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { + Web *w = sn.getWeb(); w->stop(); } #endif /* WITH_NODE_WEBSOCKET */ @@ -505,5 +504,3 @@ int main(int argc, char *argv[]) return t.run(); } - -/** @} */ diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index fe0890f5d..53dde8f27 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -1,7 +1,7 @@ /** Simple WebSocket relay facilitating client-to-client connections. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,9 +31,9 @@ #include #include -#include +#include #include -#include +#include #include #include #include @@ -241,7 +241,7 @@ Relay::Relay(int argc, char *argv[]) : /* Default UUID is derived from hostname */ uuid::generateFromString(uuid, hname); - ret = memory_init(0); + ret = memory::init(0); if (ret) throw RuntimeError("Failed to initialize memory"); @@ -473,7 +473,9 @@ int Relay::main() { ctx_info.gid = -1; ctx_info.uid = -1; ctx_info.protocols = protocols.data(); +#ifndef LWS_WITHOUT_EXTENSIONS ctx_info.extensions = extensions.data(); +#endif ctx_info.port = port; ctx_info.mounts = &mount; ctx_info.user = (void *) this; diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index 22a2850e3..5f3291921 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index cacb0fd65..ec11a9db3 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -19,9 +19,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * @addtogroup tools Test and debug tools - * @{ **********************************************************************************/ #include @@ -36,11 +33,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include using namespace villas; @@ -61,7 +58,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); } @@ -69,9 +66,9 @@ public: protected: std::atomic stop; - struct vnode node; + Node *node; Format *formatter; - struct pool pool; + struct Pool pool; std::string format; @@ -110,6 +107,11 @@ protected: 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; @@ -118,7 +120,7 @@ protected: /* Parse optional command line arguments */ int c; char *endptr; - while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hV")) != -1) { + while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { switch (c) { case 'n': rt = 0; @@ -156,6 +158,22 @@ protected: stddev = strtof(optarg, &endptr); goto check; + case 'p': + phase = strtof(optarg, &endptr); + goto check; + + case 'w': + pulse_width = strtof(optarg, &endptr); + goto check; + + case 'L': + pulse_low = strtof(optarg, &endptr); + goto check; + + case 'H': + pulse_high = strtof(optarg, &endptr); + goto check; + case 'd': logging.setLevel(optarg); break; @@ -181,17 +199,31 @@ check: if (optarg == endptr) type = argv[optind]; - return json_pack("{ s: s, s: s, s: f, s: f, s: f, s: f, s: f, s: b, s: i, s: i }", + 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 + ); + + json_array_append_new(json_signals, json_signal); + } + + return json_pack("{ s: s, s: f, s: b, s: i, s: { s: o } }", "type", "signal", - "signal", type.c_str(), "rate", rate, - "frequency", frequency, - "amplitude", amplitude, - "stddev", stddev, - "offset", offset, "realtime", rt, - "values", values, - "limit", limit + "limit", limit, + "in", + "signals", json_signals ); } @@ -214,17 +246,12 @@ check: if (optarg == endptr) int ret; json_t *json, *json_format; json_error_t err; - struct vnode_type *nt; - struct sample *t; + struct Sample *t; - nt = node_type_lookup("signal"); - if (!nt) - throw RuntimeError("Signal generation is not supported."); - - ret = node_init(&node, nt); - if (ret) - throw RuntimeError("Failed to initialize node"); + node = NodeFactory::make("signal.v2"); + if (!node) + throw MemoryAllocationError(); json = parse_cli(argc, argv); if (!json) { @@ -235,24 +262,23 @@ check: if (optarg == endptr) uuid_t uuid; uuid_clear(uuid); - ret = node_parse(&node, json, uuid); + ret = node->parse(json, uuid); if (ret) { usage(); exit(EXIT_FAILURE); } - // nt == n._vt - ret = node_type_start(nt, nullptr); + ret = node->getFactory()->start(nullptr); if (ret) - throw RuntimeError("Failed to initialize node type: {}", *nt); + throw RuntimeError("Failed to intialize node type {}: reason={}", *node->getFactory(), ret); - ret = node_check(&node); + ret = node->check(); if (ret) throw RuntimeError("Failed to verify node configuration"); - ret = node_prepare(&node); + ret = node->prepare(); if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node, ret); + throw RuntimeError("Failed to prepare node {}: reason={}", *node, ret); /* Try parsing format config as JSON */ json_format = json_loads(format.c_str(), 0, &err); @@ -262,20 +288,20 @@ check: if (optarg == endptr) if (!formatter) throw RuntimeError("Failed to initialize output"); - formatter->start(&node.in.signals, ~(int) SampleFlags::HAS_OFFSET); + formatter->start(node->getInputSignals(), ~(int) SampleFlags::HAS_OFFSET); - ret = pool_init(&pool, 16, SAMPLE_LENGTH(vlist_length(&node.in.signals)), &memory_heap); + ret = pool_init(&pool, 16, SAMPLE_LENGTH(node->getInputSignals()->size()), &memory::heap); if (ret) throw RuntimeError("Failed to initialize pool"); - ret = node_start(&node); + ret = node->start(); if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node, ret); + throw RuntimeError("Failed to start node {}: reason={}", *node, ret); - while (!stop && node.state == State::STARTED) { + while (!stop && node->getState() == State::STARTED) { t = sample_alloc(&pool); -retry: ret = node_read(&node, &t, 1); +retry: ret = node->read(&t, 1); if (ret == 0) goto retry; else if (ret < 0) @@ -287,14 +313,15 @@ retry: ret = node_read(&node, &t, 1); out: sample_decref(t); } - ret = node_stop(&node); + ret = node->stop(); if (ret) throw RuntimeError("Failed to stop node"); - ret = node_destroy(&node); + ret = node->getFactory()->stop(); if (ret) - throw RuntimeError("Failed to destroy node"); + throw RuntimeError("Failed to de-intialize node type {}: reason={}", *node->getFactory(), ret); + delete node; delete formatter; ret = pool_destroy(&pool); @@ -315,5 +342,3 @@ int main(int argc, char *argv[]) return t.run(); } - -/** @} */ diff --git a/src/villas-test-config.cpp b/src/villas-test-config.cpp index 1f2249573..64d01e571 100644 --- a/src/villas-test-config.cpp +++ b/src/villas-test-config.cpp @@ -1,7 +1,7 @@ /** Main routine. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); } @@ -111,11 +111,11 @@ protected: 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; } diff --git a/src/villas-test-rtt.cpp b/src/villas-test-rtt.cpp index 30e36f42c..b3948f8ec 100644 --- a/src/villas-test-rtt.cpp +++ b/src/villas-test-rtt.cpp @@ -1,7 +1,7 @@ /** Measure round-trip time. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -31,15 +31,15 @@ #include #include -#include +#include #include #include #include -#include +#include #include #include -#include -#include +#include +#include #include #define CLOCK_ID CLOCK_MONOTONIC @@ -64,7 +64,7 @@ public: { int ret; - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); if (ret) throw RuntimeError("Failed to initialize memory"); } @@ -171,13 +171,13 @@ check: if (optarg == endptr) 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(); - struct vnode *node; + Node *node; if (!uri.empty()) sn.parse(uri); @@ -188,15 +188,15 @@ check: if (optarg == endptr) if (!node) throw RuntimeError("There's no node with the name '{}'", nodestr); - ret = node_type_start(node_type(node), &sn); + ret = node->getFactory()->start(&sn); if (ret) - throw RuntimeError("Failed to start node-type {}: reason={}", *node_type(node), ret); + throw RuntimeError("Failed to start node-type {}: reason={}", *node->getFactory(), ret); - ret = node_prepare(node); + ret = node->prepare(); if (ret) throw RuntimeError("Failed to prepare node {}: reason={}", *node, ret); - ret = node_start(node); + ret = node->start(); if (ret) throw RuntimeError("Failed to start node {}: reason={}", *node, ret); @@ -206,8 +206,8 @@ check: if (optarg == endptr) while (!stop && (count < 0 || count--)) { clock_gettime(CLOCK_ID, &send); - node_write(node, &smp_send, 1); /* Ping */ - node_read(node, &smp_recv, 1); /* Pong */ + node->write(&smp_send, 1); /* Ping */ + node->read(&smp_recv, 1); /* Pong */ clock_gettime(CLOCK_ID, &recv); @@ -238,13 +238,13 @@ check: if (optarg == endptr) hist.print(logger, true); - ret = node_stop(node); + ret = node->stop(); if (ret) throw RuntimeError("Failed to stop node {}: reason={}", *node, ret); - ret = node_type_stop(node_type(node)); + ret = node->getFactory()->stop(); if (ret) - throw RuntimeError("Failed to stop node-type {}: reason={}", *node_type(node), ret); + throw RuntimeError("Failed to stop node-type {}: reason={}", *node->getFactory(), ret); delete smp_send; delete smp_recv; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5037a6da1..ac7e7a745 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,7 @@ # Makefile. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tests/benchmarks/run-benchmark.sh b/tests/benchmarks/run-benchmark.sh index 9cd2b5298..13301ab97 100755 --- a/tests/benchmarks/run-benchmark.sh +++ b/tests/benchmarks/run-benchmark.sh @@ -3,7 +3,7 @@ # Integration Infiniband test using villas-node. # # @author Dennis Potter -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -21,6 +21,8 @@ # along with this program. If not, see . ################################################################################## +set -e + ###################################### # SETTINGS ########################### ###################################### @@ -40,20 +42,20 @@ IB_MODES=("RC") # Check if user is superuser. SU is used for namespace if [[ "$EUID" -ne 0 ]]; then - echo "Please run as root" - exit 99 + echo "Please run as root" + exit 99 fi # Check whether cpuset cset command is availble if [[ ! $(command -v cset) ]]; then - echo "Cset is not availble for root. Please install it: https://github.com/lpechacek/cpuset" - exit 99 + echo "Cset is not availble for root. Please install it: https://github.com/lpechacek/cpuset" + exit 99 fi # Check if Infiniband card is present if [[ ! $(lspci | grep Infiniband) ]]; then - echo "Did not find any Infiniband cards in system" - exit 99 + echo "Did not find any Infiniband cards in system" + exit 99 fi # Create list of configs and check whether they are valid @@ -62,32 +64,32 @@ OIFS=$IFS; IFS=$'\n'; CONFIG_FILES=($(ls configs | sed -e "s/.conf//")); IFS=$OI NODETYPES=() if [[ ! $1 ]]; then - echo "Please define for which node-type to run the script" - exit 1 + echo "Please define for which node-type to run the script" + exit 1 elif [[ $1 == all ]]; then - echo "Benchmarking the following nodes:" - for NODETYPE in "${CONFIG_FILES[@]}" - do - echo ${NODETYPE} - NODETYPES+=(${NODETYPE}) - done + echo "Benchmarking the following nodes:" + for NODETYPE in "${CONFIG_FILES[@]}" + do + echo ${NODETYPE} + NODETYPES+=(${NODETYPE}) + done else - FOUND=0 + FOUND=0 - for NODETYPE in "${CONFIG_FILES[@]}" - do - if [[ $1 == ${NODETYPE} ]]; then - NODETYPES=$1 - FOUND=1 - break - fi - done + for NODETYPE in "${CONFIG_FILES[@]}" + do + if [[ $1 == ${NODETYPE} ]]; then + NODETYPES=$1 + FOUND=1 + break + fi + done - if [[ ${FOUND} == 0 ]]; then - echo "Please define a valid node-type for which a config file is present in ./configs!" - exit 1 - fi + if [[ ${FOUND} == 0 ]]; then + echo "Please define a valid node-type for which a config file is present in ./configs!" + exit 1 + fi fi ###################################### @@ -113,19 +115,19 @@ echo ${CONFIG_FILES[1]} for NODETYPE in "${NODETYPES[@]}" do - ###################################### - # CREATE PATH CONFIG FILES ########### - ###################################### - - # Set target and source config file, which is the same for both runs + ###################################### + # CREATE PATH CONFIG FILES ########### + ###################################### + + # Set target and source config file, which is the same for both runs cat > ${CONFIG_SOURCE} < ${CONFIG_TARGET} < ${CONFIG_TARGET} < ${CONFIG} <> ${CONFIG} + cat configs/${NODETYPE}.conf | sed -e "s/\${NUM_VALUE}/${NUM_VALUE}/" -e "s/\${IB_MODE}/${IB_MODE}/" >> ${CONFIG} cat >> ${CONFIG} < -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tests/integration/api-capabilities.sh b/tests/integration/api-capabilities.sh index 442d74ee5..a8dd190ab 100755 --- a/tests/integration/api-capabilities.sh +++ b/tests/integration/api-capabilities.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -24,33 +24,33 @@ set -e -CONFIG_FILE=$(mktemp) -FETCHED_CONF=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat > ${CONFIG_FILE} < config.json < ${FETCHED_CONF} +curl -s http://localhost:8080/api/v2/capabilities > fetched.json -kill $PID -wait +kill %% +wait %% -jq -e '.apis | index( "capabilities" ) != null' < ${FETCHED_CONF} -RC=$? - -rm ${FETCHED_CONF} ${CONFIG_FILE} - -exit ${RC} +jq -e '.apis | index( "capabilities" ) != null' < fetched.json diff --git a/tests/integration/api-config.sh b/tests/integration/api-config.sh index dce0ec307..eb7905f45 100755 --- a/tests/integration/api-config.sh +++ b/tests/integration/api-config.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,20 +22,25 @@ # along with this program. If not, see . ################################################################################## -SCRIPT=$(realpath $0) -SCRIPTPATH=$(dirname ${SCRIPT}) +set -e -CONFIG_FILE=$(mktemp) -FETCHED_CONF=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat > ${CONFIG_FILE} < config.json < ${FETCHED_CONF} +curl -s http://localhost:8080/api/v2/config > fetched.json # Shutdown VILLASnode kill $! # Compare local config with the fetched one -diff -u <(jq -S . < ${FETCHED_CONF}) <(jq -S . < ${CONFIG_FILE}) -RC=$? - -rm -f ${FETCHED_CONF} ${CONFIG_FILE} - -exit ${RC} +diff -u <(jq -S . < fetched.json) <(jq -S . < config.json) diff --git a/tests/integration/api-nodes.sh b/tests/integration/api-nodes.sh index eb1601fda..dadc29c0f 100755 --- a/tests/integration/api-nodes.sh +++ b/tests/integration/api-nodes.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -24,32 +24,39 @@ set -e -CONFIG_FILE=$(mktemp) -FETCHED_NODES=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE} < ${FETCHED_NODES} +curl -s http://localhost:8080/api/v2/nodes > fetched.json # Shutdown VILLASnode kill $! # Compare local config with the fetched one -jq -e '.[0].name == "testnode1" and .[0].type == "websocket" and (. | length == 2)' ${FETCHED_NODES} > /dev/null -RC=$? - -rm -f ${CONFIG_FILE} ${FETCHED_NODES} - -exit ${RC} +jq -e '.[0].name == "testnode1" and .[0].type == "websocket" and (. | length == 2)' fetched.json > /dev/null diff --git a/tests/integration/api-paths.sh b/tests/integration/api-paths.sh index 367041abd..8bc408a66 100755 --- a/tests/integration/api-paths.sh +++ b/tests/integration/api-paths.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -24,32 +24,38 @@ set -e -CONFIG_FILE=$(mktemp) -FETCHED_PATHS=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE} < ${FETCHED_PATHS} +curl -s http://localhost:8080/api/v2/paths > fetched.json # Shutdown VILLASnode kill $! # Compare local config with the fetched one -jq -e '(.[0].in | index("testnode2")) and (.[0].out | index("testnode1")) and (. | length == 1)' ${FETCHED_PATHS} > /dev/null -RC=$? - -rm -f ${CONFIG_FILE} ${FETCHED_PATHS} - -exit ${RC} +jq -e '(.[0].in | index("testnode2")) and (.[0].out | index("testnode1")) and (. | length == 1)' fetched.json > /dev/null diff --git a/tests/integration/api-restart.sh b/tests/integration/api-restart.sh index 859651a72..a0f6d112c 100755 --- a/tests/integration/api-restart.sh +++ b/tests/integration/api-restart.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,45 +22,50 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -BASE_CONF=$(mktemp) -LOCAL_CONF=$(mktemp) -FETCHED_CONF=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat < ${BASE_CONF} +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + + +cat > base.json < ${LOCAL_CONF} +cat > local.json < ${LOCAL_CONF} EOF # Start with base configuration -villas node ${BASE_CONF} & -PID=$! +villas node base.json & # Wait for node to complete init sleep 1 # Restart with configuration -curl -sX POST --data '{ "config": "'${LOCAL_CONF}'" }' http://localhost:8080/api/v2/restart +curl -sX POST --data '{ "config": "local.json" }' http://localhost:8080/api/v2/restart # Wait for node to complete init sleep 2 # Fetch config via API -curl -s http://localhost:8080/api/v2/config > ${FETCHED_CONF} +curl -s http://localhost:8080/api/v2/config > fetched.json # Shutdown VILLASnode -kill ${PID} +kill %% +wait %% # Compare local config with the fetched one -diff -u <(jq -S . < ${FETCHED_CONF}) <(jq -S . < ${LOCAL_CONF}) -RC=$? - -rm -f ${LOCAL_CONF} ${FETCHED_CONF} ${BASE_CONF} - -exit ${RC} +diff -u <(jq -S . < fetched.json) <(jq -S . < local.json) diff --git a/tests/integration/api-shutdown.sh b/tests/integration/api-shutdown.sh index 8574345df..dbd281c77 100755 --- a/tests/integration/api-shutdown.sh +++ b/tests/integration/api-shutdown.sh @@ -3,7 +3,7 @@ # Integration test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -24,19 +24,27 @@ set -e -CONFIG_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat > ${CONFIG_FILE} < config.json <0 (fail) in case the 3 second timeout was reached diff --git a/tests/integration/api-stress.sh b/tests/integration/api-stress.sh index a2a8a9c5f..8a9fcb3ac 100755 --- a/tests/integration/api-stress.sh +++ b/tests/integration/api-stress.sh @@ -3,7 +3,7 @@ # Stress test for remote API # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,22 @@ # along with this program. If not, see . ################################################################################## +set -e +set -x + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + LOCAL_CONF=${SRCDIR}/etc/loopback.json # Start VILLASnode instance with local config villas node ${LOCAL_CONF} & -PID=$! # Wait for node to complete init sleep 1 @@ -35,8 +46,7 @@ RUNS=100 FAILED=0 SUCCESS=0 -FIFO=$(mktemp -t fifo.XXXXXX) -rm ${FIFO} +FIFO=$(mktemp -p ${DIR} -t fifo.XXXXXX -u) mkfifo ${FIFO} # Fifo must be opened in both directions! @@ -51,7 +61,7 @@ for J in $(seq 1 ${RUNS}); do set -e trap "echo error-trap >> ${FIFO}" ERR - FETCHED_CONF=$(mktemp) + FETCHED_CONF=$(mktemp -p ${DIR}) curl -s http://localhost:8080/api/v2/config > ${FETCHED_CONF} diff -u <(jq -S . < ${FETCHED_CONF}) <(jq -S . < ${LOCAL_CONF}) @@ -66,27 +76,24 @@ for J in $(seq 1 ${RUNS}); do JOBS+=" $!" done -echo "Waiting for jobs to complete: $JOBS" -wait $JOBS -kill $PID -wait $PID +echo "Waiting for jobs to complete: ${JOBS}" +wait ${JOBS} + +kill %1 +wait %1 echo "Check return codes" -FAILED=0 -SUCCESS=0 for J in $(seq 1 ${RUNS}); do - read status <&5 + read -t 10 -u 5 STATUS - if [ "$status" == "success" ]; then - let SUCCESS++ + if [ "${STATUS}" == "success" ]; then + let ++SUCCESS else - let FAILED++ + let ++FAILED fi done echo "Success: ${SUCCESS} / ${RUNS}" echo "Failed: ${FAILED} / ${RUNS}" -if [ "$FAILED" -gt "0" ]; then - exit 1; -fi +(( ${FAILED} == 0 )) diff --git a/tests/integration/compare.sh b/tests/integration/compare.sh index cf4df4fa5..7bb99dea9 100755 --- a/tests/integration/compare.sh +++ b/tests/integration/compare.sh @@ -3,7 +3,7 @@ # Integration test for villas compare. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,15 +22,16 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -TEMP_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -function fail() { - rm ${INPUT_FILE} ${TEMP_FILE} - exit $1; +function finish { + popd + rm -rf ${DIR} } +trap finish EXIT -cat > ${INPUT_FILE} < input.dat < ${INPUT_FILE} < ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 1 )) || fail 2 +head -n-1 input.dat > temp.dat +villas compare input.dat temp.dat +(( $? == 1 )) || exit 2 -( head -n-1 ${INPUT_FILE}; echo "1491095597.545159701(55) -0.587785" ) > ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 2 )) || fail 3 +( head -n-1 input.dat; echo "1491095597.545159701(55) -0.587785" ) > temp.dat +villas compare input.dat temp.dat +(( $? == 2 )) || exit 3 -( head -n-1 ${INPUT_FILE}; echo "1491095598.545159701(9) -0.587785" ) > ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 3 )) || fail 4 +( head -n-1 input.dat; echo "1491095598.545159701(9) -0.587785" ) > temp.dat +villas compare input.dat temp.dat +(( $? == 3 )) || exit 4 -( head -n-1 ${INPUT_FILE}; echo "1491095597.545159701(9) -0.587785 -0.587785" ) > ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 4 )) || fail 5 +( head -n-1 input.dat; echo "1491095597.545159701(9) -0.587785 -0.587785" ) > temp.dat +villas compare input.dat temp.dat +(( $? == 4 )) || exit 5 -( head -n-1 ${INPUT_FILE}; echo "1491095597.545159701(9) -1.587785" ) > ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 5 )) || fail 6 +( head -n-1 input.dat; echo "1491095597.545159701(9) -1.587785" ) > temp.dat +villas compare input.dat temp.dat +(( $? == 5 )) || exit 6 -( cat ${INPUT_FILE}; echo "1491095597.545159701(9) -0.587785" ) > ${TEMP_FILE} -villas compare ${INPUT_FILE} ${TEMP_FILE} -(( $? == 1 )) || fail 7 - -rm ${INPUT_FILE} ${TEMP_FILE} +( cat input.dat; echo "1491095597.545159701(9) -0.587785" ) > temp.dat +villas compare input.dat temp.dat +(( $? == 1 )) || exit 7 diff --git a/tests/integration/convert.sh b/tests/integration/convert.sh index 16571ab09..89038ece3 100755 --- a/tests/integration/convert.sh +++ b/tests/integration/convert.sh @@ -3,7 +3,7 @@ # Integration test for villas convert tool # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -24,17 +24,22 @@ set -e -OUTPUT_FILE=$(mktemp) -INPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT FORMATS="villas.human csv tsv json" -# Generate test data -villas signal -v5 -n -l20 mixed > ${INPUT_FILE} +villas signal -v5 -n -l20 mixed > input.dat for FORMAT in ${FORMATS}; do - villas convert -o ${FORMAT} < ${INPUT_FILE} | tee ${TEMP} | \ - villas convert -i ${FORMAT} > ${OUTPUT_FILE} + villas convert -o ${FORMAT} < input.dat | tee ${TEMP} | \ + villas convert -i ${FORMAT} > output.dat - villas compare ${INPUT_FILE} ${OUTPUT_FILE} + villas compare input.dat output.dat done diff --git a/tests/integration/hook-average.sh b/tests/integration/hook-average.sh index 96e33177c..d1c3bef90 100755 --- a/tests/integration/hook-average.sh +++ b/tests/integration/hook-average.sh @@ -3,7 +3,7 @@ # Integration test for average hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${INPUT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1548104309.934288200(9) 0.060849 0.007885 -1.000000 0.994980 0.001255 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} EOF # Average over first and third signal (mask = 0b101 = 5) -villas hook -o offset=0 -o signals=signal0,signal1,signal2,signal3,signal4 average < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook -o offset=0 -o signals=signal0,signal1,signal2,signal3,signal4 average < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-cast.sh b/tests/integration/hook-cast.sh index 9103587df..b49ef967e 100755 --- a/tests/integration/hook-cast.sh +++ b/tests/integration/hook-cast.sh @@ -3,7 +3,7 @@ # Integration test for cast hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,14 +22,18 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat < ${INPUT_FILE} +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1551015509.701653200(9) 0.060849 -58.778500 1.000000 0.600000 0.900000 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1551015509.701653200(9) 0.060849 -58 1.000000 0.600000 0.900000 EOF -villas hook cast -o new_name=test -o new_unit=V -o new_type=integer -o signal=1 < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook cast -o new_name=test -o new_unit=V -o new_type=integer -o signal=signal1 < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-decimate.sh b/tests/integration/hook-decimate.sh index 27ef0a8e6..7a851db0e 100755 --- a/tests/integration/hook-decimate.sh +++ b/tests/integration/hook-decimate.sh @@ -3,7 +3,7 @@ # Integration test for decimate hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${INPUT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${OUTPUT_FILE} +villas hook -o ratio=3 decimate < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} - -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-drop.sh b/tests/integration/hook-drop.sh index eb094ec10..015c6fc8f 100755 --- a/tests/integration/hook-drop.sh +++ b/tests/integration/hook-drop.sh @@ -3,7 +3,7 @@ # Integration test for drop hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${INPUT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 EOF -villas hook drop < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook drop < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} - -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-gate.sh b/tests/integration/hook-gate.sh index 1f028299c..3de757161 100755 --- a/tests/integration/hook-gate.sh +++ b/tests/integration/hook-gate.sh @@ -3,7 +3,7 @@ # Integration test for gate hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${INPUT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1561591855.174828300(9) 0.060849 0.056713 -1.000000 0.963876 1.001806 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1561591855.077804200(8) 0.015231 -0.149670 1.000000 -0.904358 0.904782 EOF -villas hook gate -o signal=signal2 -o mode=above < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook gate -o signal=signal2 -o mode=above < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-limit_rate.sh b/tests/integration/hook-limit_rate.sh index 526fc12b8..e71895acd 100755 --- a/tests/integration/hook-limit_rate.sh +++ b/tests/integration/hook-limit_rate.sh @@ -3,7 +3,7 @@ # Integration test for limit_rate hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,20 +22,21 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -villas signal -r 1000 -l 1000 -n sine > ${INPUT_FILE} -awk 'NR % 10 == 2' < ${INPUT_FILE} > ${EXPECT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} -villas hook -o rate=100 -o mode=origin limit_rate < ${INPUT_FILE} > ${OUTPUT_FILE} +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} +villas signal -r 1000 -l 1000 -n sine > input.dat -RC=$? +awk 'NR % 10 == 2' < input.dat > expect.dat -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} +villas hook -o rate=100 -o mode=origin limit_rate < input.dat > output.dat -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-lua.sh b/tests/integration/hook-lua.sh index 142462afc..3d67aa1c6 100755 --- a/tests/integration/hook-lua.sh +++ b/tests/integration/hook-lua.sh @@ -3,7 +3,7 @@ # Integration test for scale hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,12 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) -CONFIG_FILE=$(mktemp) +set -e -cat < ${CONFIG_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > config.json <= 0", "type": "boolean" }, @@ -39,7 +45,7 @@ cat < ${CONFIG_FILE} } EOF -cat < ${INPUT_FILE} +cat > input.dat < ${INPUT_FILE} 1551015509.701653200(9) 0.060849 -0.587785 1.000000 0.600000 0.900000 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1551015509.701653200+6.430676e+07(9) 0 0.587785 145.000000 9 1551015509.701653 EOF -villas hook lua -c ${CONFIG_FILE} < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook lua -c config.json < input.dat > output.dat -cat ${INPUT_FILE} -echo -cat ${OUTPUT_FILE} - -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-lua_script.sh b/tests/integration/hook-lua_script.sh index 7860a7b7e..af4550d34 100755 --- a/tests/integration/hook-lua_script.sh +++ b/tests/integration/hook-lua_script.sh @@ -3,7 +3,7 @@ # Integration test for scale hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,16 +22,18 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) -CONFIG_FILE=$(mktemp) -SCRIPT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -cat < ${SCRIPT_FILE} +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > script.lua < ${CONFIG_FILE} +cat > config.json < ${CONFIG_FILE} } EOF -cat < ${INPUT_FILE} +cat > input.dat < ${INPUT_FILE} 1551015509.701653200(9) 0.060849 -0.587785 1.000000 0.600000 0.900000 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1551015509.701653200+6.430638e+07(9) 555.000000 10.000000 1.600000 0.600000 0.900000 9.000000 EOF -villas hook lua -c ${CONFIG_FILE} < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook lua -c config.json < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-print.sh b/tests/integration/hook-print.sh index a461ddf37..02f73634c 100755 --- a/tests/integration/hook-print.sh +++ b/tests/integration/hook-print.sh @@ -3,7 +3,7 @@ # Integration test for print hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,21 +22,25 @@ # along with this program. If not, see . ################################################################################## -OUTPUT_FILE1=$(mktemp) -OUTPUT_FILE2=$(mktemp) -INPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} -# Prepare some test data -villas signal -v 1 -r 10 -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -v 1 -r 10 -l ${NUM_SAMPLES} -n random > input.dat -villas hook -o format=villas.human -o output=${OUTPUT_FILE1} print > ${OUTPUT_FILE2} < ${INPUT_FILE} +villas hook -o format=villas.human -o output=output1.dat print > output2.dat < input.dat -# Compare only the data values -villas compare ${OUTPUT_FILE1} ${OUTPUT_FILE2} ${INPUT_FILE} -RC=$? - -rm -f ${OUTPUT_FILE1} ${OUTPUT_FILE2} ${INPUT_FILE} - -exit ${RC} +if [ -s output1.dat -a -s output2.dat ]; then + villas compare output1.dat output2.dat input.dat +else + exit -1 +fi diff --git a/tests/integration/hook-scale.sh b/tests/integration/hook-scale.sh index 5f1750309..1894d3df6 100755 --- a/tests/integration/hook-scale.sh +++ b/tests/integration/hook-scale.sh @@ -3,7 +3,7 @@ # Integration test for scale hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${INPUT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < ${INPUT_FILE} 1551015509.701653200(9) 0.060849 -0.587785 1.000000 0.600000 0.900000 EOF -cat < ${EXPECT_FILE} +cat > expect.dat < ${EXPECT_FILE} 1551015509.701653200(9) 0.060849 -0.587785 1.000000 0.600000 145.000000 EOF -villas hook scale -o scale=100 -o offset=55 -o signal=signal4 < ${INPUT_FILE} > ${OUTPUT_FILE} +villas hook scale -o scale=100 -o offset=55 -o signal=signal4 < input.dat > output.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare output.dat expect.dat diff --git a/tests/integration/hook-shift_seq.sh b/tests/integration/hook-shift_seq.sh index 3da053668..aacef7477 100755 --- a/tests/integration/hook-shift_seq.sh +++ b/tests/integration/hook-shift_seq.sh @@ -3,7 +3,7 @@ # Integration test for shift_seq hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,20 +22,24 @@ # along with this program. If not, see . ################################################################################## -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT OFFSET=100 -villas signal -l ${NUM_SAMPLES} -n random | \ -villas hook -o offset=${OFFSET} shift_seq > ${OUTPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat + +villas hook -o offset=${OFFSET} shift_seq > output.dat < input.dat # Compare shifted sequence no diff -u \ - <(sed -re '/^#/d;s/^[0-9]+\.[0-9]+([\+\-][0-9]+\.[0-9]+(e[\+\-][0-9]+)?)?\(([0-9]+)\).*/\3/g' ${OUTPUT_FILE}) \ + <(sed -re '/^#/d;s/^[0-9]+\.[0-9]+([\+\-][0-9]+\.[0-9]+(e[\+\-][0-9]+)?)?\(([0-9]+)\).*/\3/g' output.dat) \ <(seq ${OFFSET} $((${NUM_SAMPLES}+${OFFSET}-1))) - -RC=$? - -rm -f ${OUTPUT_FILE} - -exit ${RC} diff --git a/tests/integration/hook-shift_ts.sh b/tests/integration/hook-shift_ts.sh index 602003655..c3f8cc54e 100755 --- a/tests/integration/hook-shift_ts.sh +++ b/tests/integration/hook-shift_ts.sh @@ -3,7 +3,7 @@ # Integration test for shift_ts hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,7 +22,16 @@ # along with this program. If not, see . ################################################################################## -STATS_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} @@ -32,13 +41,10 @@ EPSILON=0.5 villas signal -l ${NUM_SAMPLES} -r 50 random | \ villas hook -o offset=${OFFSET} shift_ts | \ villas hook fix | \ -villas hook -o format=json -o output="${STATS_FILE}" stats > /dev/null +villas hook -o format=json -o output=stats.json stats > /dev/null -jq .owd ${STATS_FILE} -jq -e ".owd.mean + ${OFFSET} | length < ${EPSILON}" ${STATS_FILE} > /dev/null +if ! [ -f stats.json ]; then + exit 1 +fi -RC=$? - -rm ${STATS_FILE} - -exit ${RC} +jq -e ".owd.mean + ${OFFSET} | length < ${EPSILON}" stats.json > /dev/null diff --git a/tests/integration/hook-skip_first.sh b/tests/integration/hook-skip_first.sh index a54c7597f..d912f6950 100755 --- a/tests/integration/hook-skip_first.sh +++ b/tests/integration/hook-skip_first.sh @@ -3,7 +3,7 @@ # Integration test for skip_first hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,21 +22,26 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT SKIP=10 -echo ${OUTPUT_FILE} +echo output.dat -villas signal -r 1 -l ${NUM_SAMPLES} -n random | \ -villas hook -o seconds=${SKIP} skip_first > ${OUTPUT_FILE} +villas signal -r 1 -l ${NUM_SAMPLES} -n random > input.dat -LINES=$(sed -re '/^#/d' ${OUTPUT_FILE} | wc -l) +villas hook -o seconds=${SKIP} skip_first > output.dat < input.dat -rm ${OUTPUT_FILE} +LINES=$(sed -re '/^#/d' output.dat | wc -l) # Test condition (( ${LINES} == ${NUM_SAMPLES} - ${SKIP} )) diff --git a/tests/integration/hook-skip_first2.sh b/tests/integration/hook-skip_first2.sh index 01b4b81e2..5a26f1378 100755 --- a/tests/integration/hook-skip_first2.sh +++ b/tests/integration/hook-skip_first2.sh @@ -3,7 +3,7 @@ # Integration test for skip_first hook. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,19 +22,24 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT SKIP=50 -villas signal -r 1 -l ${NUM_SAMPLES} -n random | \ -villas hook -o samples=${SKIP} skip_first > ${OUTPUT_FILE} +villas signal -r 1 -l ${NUM_SAMPLES} -n random > input.dat -LINES=$(sed -re '/^#/d' ${OUTPUT_FILE} | wc -l) +villas hook -o samples=${SKIP} skip_first > output.dat < input.dat -rm ${OUTPUT_FILE} +LINES=$(sed -re '/^#/d' output.dat | wc -l) # Test condition (( ${LINES} == ${NUM_SAMPLES} - ${SKIP} )) diff --git a/tests/integration/node-can.sh b/tests/integration/node-can.sh index e08d68190..db05e716a 100755 --- a/tests/integration/node-can.sh +++ b/tests/integration/node-can.sh @@ -3,7 +3,7 @@ # Integration can test using villas node. # # @author Niklas Eiling -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -26,13 +26,7 @@ # sudo ip link add dev vcan0 type vcan # sudo ip link set vcan0 up -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -CAN_OUT_FILE=$(mktemp) - -NUM_SAMPLES=${NUM_SAMPLES:-10} -NUM_VALUES=${NUM_VALUES:-3} +set -e CAN_IF=$(ip link show type vcan | head -n1 | awk '{match($2, /(.*):/,a)}END{print a[1]}') @@ -47,100 +41,103 @@ if [[ ! $(ip link show "${CAN_IF}" up) ]]; then exit 99 fi -cat > ${CONFIG_FILE} << EOF -nodes = { - can_node1 = { - type = "can" - interface_name = "${CAN_IF}" - sample_rate = 500000 +DIR=$(mktemp -d) +pushd ${DIR} - in = { - signals = ( - { - name = "sigin1", - unit = "Volts", - type = "float", - enabled = true, - can_id = 66, - can_size = 4, - can_offset = 0 - }, - { - name = "sigin2", - unit = "Volts", - type = "float", - enabled = true, - can_id = 66, - can_size = 4, - can_offset = 4 - }, - { - name = "sigin3", - unit = "Volts", - type = "float", - enabled = true, - can_id = 67, - can_size = 8, - can_offset = 0 - } - ) - } +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT - out = { - signals = ( - { - type = "float", - can_id = 66, - can_size = 4, - can_offset = 0 - }, - { - type = "float", - can_id = 66, - can_size = 4, - can_offset = 4 - }, - { - type = "float", - can_id = 67, - can_size = 8, - can_offset = 0 - } - ) +NUM_SAMPLES=${NUM_SAMPLES:-10} +NUM_VALUES=${NUM_VALUES:-3} + +cat > config.json << EOF +{ + "nodes": { + "can_node1": { + "type": "can", + "interface_name": "${CAN_IF}", + "sample_rate": 500000, + "in": { + "signals": [ + { + "name": "sigin1", + "unit": "Volts", + "type": "float", + "enabled": true, + "can_id": 66, + "can_size": 4, + "can_offset": 0 + }, + { + "name": "sigin2", + "unit": "Volts", + "type": "float", + "enabled": true, + "can_id": 66, + "can_size": 4, + "can_offset": 4 + }, + { + "name": "sigin3", + "unit": "Volts", + "type": "float", + "enabled": true, + "can_id": 67, + "can_size": 8, + "can_offset": 0 + } + ] + }, + "out": { + "signals": [ + { + "type": "float", + "can_id": 66, + "can_size": 4, + "can_offset": 0 + }, + { + "type": "float", + "can_id": 66, + "can_size": 4, + "can_offset": 4 + }, + { + "type": "float", + "can_id": 67, + "can_size": 8, + "can_offset": 0 + } + ] + } } } } EOF -# Generate test data -villas signal -v ${NUM_VALUES} -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -v ${NUM_VALUES} -l ${NUM_SAMPLES} -n random > input.dat -# Start node -villas node ${CONFIG_FILE} & +villas node config.json & # Wait for node to complete init sleep 1 -candump -n ${NUM_SAMPLES} -T 1000 -L ${CAN_IF} | awk '{print $3}' > ${CAN_OUT_FILE} & -CANDUMP_PID=$! +candump -n ${NUM_SAMPLES} -T 1000 -L ${CAN_IF} | awk '{print $3}' > can_out.dat & # Send / Receive data to node -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} can_node1 > ${OUTPUT_FILE} < ${INPUT_FILE} & +villas pipe -l ${NUM_SAMPLES} config.json can_node1 > output.dat < input.dat & -wait ${CANDUMP_PID} -cat ${CAN_OUT_FILE} | xargs -I % cansend ${CAN_IF} % +wait $candump + +cat can_out.dat | xargs -I % cansend ${CAN_IF} % # Wait for node to handle samples sleep 1 -# Stop node -kill %1 +kill %villas +wait %villas -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -#rm ${CAN_OUT_FILE} ${INPUT_FILE} ${OUTPUT_FILE} -rm ${INPUT_FILE} ${OUTPUT_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/node-hook.sh b/tests/integration/node-hook.sh index 4df16e247..b348e5154 100755 --- a/tests/integration/node-hook.sh +++ b/tests/integration/node-hook.sh @@ -3,7 +3,7 @@ # Test hooks in villas node # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,11 +22,18 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) +set -e -cat < ${EXPECT_FILE} +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > expect.dat < ${EXPECT_FILE} 1553690684.081211800-8.251890e-02(9) 6.748635 0.608491 0.535827 -1.000000 0.640000 0.090000 EOF -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE} < ${CONFIG_FILE} < ${CONFIG_FILE} < -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,181 +22,152 @@ # along with this program. If not, see . ################################################################################## +set -e + # Check if tools are present -if ! command -v lspci; then - echo "'lspci' tool is missing" - exit 99 +if ! command -v lspci > /dev/null; then + echo "lspci tool is missing" + exit 99 fi # Check if user is superuser. SU is used for namespace -if [[ "$EUID" -ne 0 ]]; then - echo "Please run as root" - exit 99 +if [[ "${EUID}" -ne 0 ]]; then + echo "Please run as root" + exit 99 fi # Check if Infiniband card is present if [[ ! $(lspci | grep Infiniband) ]]; then - echo "Did not find any Infiniband cards in system" - exit 99 + echo "Did not find any Infiniband cards in system" + exit 99 fi +DIR=$(mktemp -d) +pushd ${DIR} -CONFIG_FILE=$(mktemp /tmp/ib-configuration-XXXX.conf) -CONFIG_FILE_TARGET=$(mktemp /tmp/ib-configuration-target-XXXX.conf) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -RC=0 - -# Generate test data for RC, UC, and UD test -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} # Set config file with a MODE flag -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE_TARGET} < target.json < input.dat + # Declare modes MODES=("RC" "UC" "UD") # Run through modes -for MODE in "${MODES[@]}" -do +for MODE in "${MODES[@]}"; do - echo "#############################" - echo "#############################" - echo "## START ${MODE} ##" - echo "#############################" - echo "#############################" + echo "#############################" + echo "#############################" + echo "## START ${MODE} ##" + echo "#############################" + echo "#############################" - sed -i -e 's/MODE/'${MODE}'/g' ${CONFIG_FILE} + sed -i -e 's/MODE/'${MODE}'/g' config.json - # Start receiving node - villas node ${CONFIG_FILE_TARGET} & - node_proc=$! - - # Wait for node to complete init - sleep 1 - - # Preprare fifo - DATAFIFO=/tmp/datafifo - if [[ ! -p ${DATAFIFO} ]]; then - mkfifo ${DATAFIFO} - fi - - # Start sending pipe - ip netns exec namespace0 villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} ib_node_source >${OUTPUT_FILE} <${DATAFIFO} & - node_pipe=$! - - # Keep pipe alive - sleep 5 >${DATAFIFO} & - - # Wait for pipe to connect to node - sleep 3 - - # Write data to pipe - cat ${INPUT_FILE} >${DATAFIFO} & - - # Wait for node to handle samples - sleep 2 - - # Stop node - kill $node_pipe - kill $node_proc - - # Compare data - villas compare ${INPUT_FILE} ${OUTPUT_FILE} - RC=$? + # Start receiving node + villas node target.json & + PID_PROC=$! + + # Wait for node to complete init + sleep 1 + + # Preprare fifo + FIFO=$(mktemp -p ${DIR} -t) + if [[ ! -p ${FIFO} ]]; then + mkfifo ${FIFO} + fi + + # Start sending pipe + ip netns exec namespace0 \ + villas pipe -l ${NUM_SAMPLES} config.json ib_node_source >output.dat <${FIFO} & + PID_PIPE=$! + + # Keep pipe alive + sleep 5 >${FIFO} & + + # Wait for pipe to connect to node + sleep 3 + + # Write data to pipe + cat input.dat >${FIFO} & + + # Wait for node to handle samples + sleep 2 + + # Stop node + kill ${PID_PIPE} + kill ${PID_PROC} + + villas compare input.dat output.dat - # Exit, if an error occurs - if [[ $RC != 0 ]]; then - rm ${CONFIG_FILE} ${CONFIG_FILE_TARGET} ${INPUT_FILE} ${OUTPUT_FILE} ${DATAFIFO} - - exit ${RC} - fi - - echo "#############################" - echo "#############################" - echo "## STOP $MODE ##" - echo "#############################" - echo "#############################" - echo "" - - sed -i -e 's/'${MODE}'/MODE/g' ${CONFIG_FILE} + sed -i -e 's/'${MODE}'/MODE/g' config.json done - -rm ${CONFIG_FILE} ${CONFIG_FILE_TARGET} ${INPUT_FILE} ${OUTPUT_FILE} ${DATAFIFO} - -exit ${RC} diff --git a/tests/integration/node-loopback-socket.sh b/tests/integration/node-loopback-socket.sh index 2b23c82a0..b8a3ae994 100755 --- a/tests/integration/node-loopback-socket.sh +++ b/tests/integration/node-loopback-socket.sh @@ -3,7 +3,7 @@ # Integration loopback test using villas node. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,77 +22,79 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} + + kill -SIGTERM 0 # kill all decendants +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -cat > ${CONFIG_FILE} < config.json < ${INPUT_FILE} +VILLAS_LOG_PREFIX="[signal] " \ +villas signal -l ${NUM_SAMPLES} -n random > input.dat -# Start node -villas node ${CONFIG_FILE} & +VILLAS_LOG_PREFIX="[node] " \ +villas node config.json & # Wait for node to complete init -sleep 1 +sleep 2 # Send / Receive data to node -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node2 > ${OUTPUT_FILE} < ${INPUT_FILE} +VILLAS_LOG_PREFIX="[pipe] " \ +villas pipe -l ${NUM_SAMPLES} config.json node2 > output.dat < input.dat # Wait for node to handle samples sleep 1 -# Stop node -kill %1 +kill %% +wait %% -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -rm ${CONFIG_FILE} ${INPUT_FILE} ${OUTPUT_FILE} - -exit ${RC} +# Send / Receive data to node +VILLAS_LOG_PREFIX="[compare] " \ +villas compare input.dat output.dat diff --git a/tests/integration/node-mapping.sh b/tests/integration/node-mapping.sh new file mode 100755 index 000000000..a61bf5889 --- /dev/null +++ b/tests/integration/node-mapping.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# +# Integration loopback test using villas node. +# +# Test test checks if source mapping features for a path. +# +# @author Steffen Vogel +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > expect.dat < config.json < +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e +set -x + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > config.json < error.log + +# Error log must include description +grep -q "Every node must only be used by a single path as destination" error.log diff --git a/tests/integration/node-multiple-sources.sh b/tests/integration/node-multiple-sources.sh new file mode 100755 index 000000000..f3b60dd2f --- /dev/null +++ b/tests/integration/node-multiple-sources.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Integration loopback test using villas node. +# +# This test checks if a single node can be used as an input +# in multiple paths. +# +# @author Steffen Vogel +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > config.json < expect.dat + +timeout --preserve-status -k 15s 1s \ +villas node config.json + +villas compare output1.dat expect.dat && \ +villas compare output2.dat expect.dat diff --git a/tests/integration/node-multiple_sources.sh b/tests/integration/node-multiple_sources.sh deleted file mode 100755 index bb7f93ef5..000000000 --- a/tests/integration/node-multiple_sources.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -# -# Integration loopback test using villas node. -# -# @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC -# @license GNU General Public License (version 3) -# -# VILLASnode -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -################################################################################## - -# Test is broken -exit 99 - -CONFIG_FILE=$(mktemp) -OUTPUT_FILE1=$(mktemp) -OUTPUT_FILE2=$(mktemp) -EXPECT_FILE=$(mktemp) - -cat > ${CONFIG_FILE} < ${EXPECT_FILE} - -# Start node -villas node ${CONFIG_FILE} & -P1=$! - -sleep 2 - -kill ${P1} -wait ${P1} - -# Compare only the data values -villas compare ${OUTPUT_FILE1} ${EXPECT_FILE} && \ -villas compare ${OUTPUT_FILE2} ${EXPECT_FILE} -RC=$? - -rm ${CONFIG_FILE} ${EXPECT_FILE} \ - ${OUTPUT_FILE1} ${OUTPUT_FILE2} - -exit ${RC} diff --git a/tests/integration/node-multiplexing.sh b/tests/integration/node-multiplexing.sh new file mode 100755 index 000000000..b5031ad09 --- /dev/null +++ b/tests/integration/node-multiplexing.sh @@ -0,0 +1,137 @@ +#!/bin/bash +# +# Integration loopback test using villas node. +# +# @author Steffen Vogel +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > expect_all.dat < expect_any.dat < config.json < -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC -# @license GNU General Public License (version 3) -# -# VILLASnode -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -################################################################################## - -# Test is broken -exit 99 - -CONFIG_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -EXPECT_FILE=$(mktemp) - -cat < ${EXPECT_FILE} -1599745986.343431058+1.451000e-06(7) 4.000000 20.000000 100.000000 -1599745986.843081878+8.820000e-07(16) 9.000000 50.000000 200.000000 -1599745987.343081848+9.440000e-07(24) 14.000000 70.000000 300.000000 -1599745987.843081745+8.630000e-07(33) 19.000000 100.000000 400.000000 -EOF - -cat > ${CONFIG_FILE} < +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > expect.dat < config.json < -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,12 +22,20 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -STATS_LOG=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT RATE="33.0" -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE} < ${CONFIG_FILE} < ${CONFIG_FILE} < /dev/null -RC=$? - -rm ${STATS_LOG} ${CONFIG_FILE} - -exit ${RC} +tail -n1 stats.json | jq -e "(.data[0] - 1/${RATE} | length) < 1e-4 and .data[1] == 99" > /dev/null diff --git a/tests/integration/node-test_rtt.sh b/tests/integration/node-test_rtt.sh index e547c1066..8a62a3939 100755 --- a/tests/integration/node-test_rtt.sh +++ b/tests/integration/node-test_rtt.sh @@ -3,7 +3,7 @@ # Integration loopback test using villas node. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,13 +22,23 @@ # along with this program. If not, see . ################################################################################## -# We skip this test for now echo "Test not yet supported" exit 99 -CONFIG_FILE=$(mktemp) +set -e -cat > ${CONFIG_FILE} < config.json < ${CONFIG_FILE} < ${CONFIG_FILE} < ${CONFIG_FILE} < -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,54 +22,47 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} - -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} - FORMAT="protobuf" VECTORIZE="10" +HOST="localhost" -cat > ${CONFIG_FILE} << EOF +if [ -n "${CI}" ]; then + HOST="rabbitmq" +else + HOST="[::1]" +fi + +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "amqp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, + "nodes": { + "node1": { + "type": "amqp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, - "uri" : "amqp://localhost", - "port" : 5672, + "uri": "amqp://guest:guest@${HOST}:5672/%2f", - "exchange" : "mytestexchange", - "routing_key" : "abc", - - "ssl" : { - "verify_hostname" : true, - "verify_peer" : true, - - "ca_cert" : "/path/to/ca.crt", - "client_cert" : "/path/to/client.crt", - "client_key" : "/path/to/client.key" - } + "exchange": "mytestexchange", + "routing_key": "abc" } } } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare ${CMPFLAGS} input.dat output.dat diff --git a/tests/integration/pipe-loopback-exec.sh b/tests/integration/pipe-loopback-exec.sh index 6ef5c82e6..9a800f5eb 100755 --- a/tests/integration/pipe-loopback-exec.sh +++ b/tests/integration/pipe-loopback-exec.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,39 +22,37 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} - -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} - FORMAT="villas.human" -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "exec", - "format" : "${FORMAT}", + "nodes": { + "node1": { + "type": "exec", + "format": "${FORMAT}", - "exec" : "cat" + "shell": true, + + "exec": "tee /tmp/test" } } } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-file.sh b/tests/integration/pipe-loopback-file.sh index bc7687d25..7e22660e3 100755 --- a/tests/integration/pipe-loopback-file.sh +++ b/tests/integration/pipe-loopback-file.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,42 +22,41 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -NODE_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "file", + "nodes": { + "node1": { + "type": "file", - "uri" : "${NODE_FILE}", + "uri": "file.dat", - "in" : { - "epoch_mode" : "original", - "eof" : "wait" + "in": { + "epoch_mode": "original", + "eof": "wait" }, - "out" : { - "flush" : true + "out": { + "flush": true } } } } EOF -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} ${NODE_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-iec61850-9-2.sh b/tests/integration/pipe-loopback-iec61850-9-2.sh index 3b335baad..44ee23718 100755 --- a/tests/integration/pipe-loopback-iec61850-9-2.sh +++ b/tests/integration/pipe-loopback-iec61850-9-2.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,41 +22,45 @@ # along with this program. If not, see . ################################################################################## -# Test is broken +echo "Test is broken" exit 99 -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} -# Generate test data -villas signal -l ${NUM_SAMPLES} -v 4 -n random > ${INPUT_FILE} - -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "iec61850-9-2", + "nodes": { + "node1": { + "type": "iec61850-9-2", - "interface" : "lo", + "interface": "lo", - "out" : { - "svid" : "1234", - "signals" : [ - { "iec_type" : "float32" }, - { "iec_type" : "float32" }, - { "iec_type" : "float32" }, - { "iec_type" : "float32" } + "out": { + "svid": "1234", + "signals": [ + { "iec_type": "float32" }, + { "iec_type": "float32" }, + { "iec_type": "float32" }, + { "iec_type": "float32" } ] }, - "in" : { - "signals" : [ - { "iec_type" : "float32" }, - { "iec_type" : "float32" }, - { "iec_type" : "float32" }, - { "iec_type" : "float32" } + "in": { + "signals": [ + { "iec_type": "float32" }, + { "iec_type": "float32" }, + { "iec_type": "float32" }, + { "iec_type": "float32" } ] } } @@ -64,12 +68,8 @@ cat > ${CONFIG_FILE} << EOF } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -v 4 -n random > input.dat -# Compare data -villas compare -T ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare -T input.dat output.dat diff --git a/tests/integration/pipe-loopback-loopback.sh b/tests/integration/pipe-loopback-loopback.sh index 0a7f7c547..8a4fa1ed1 100755 --- a/tests/integration/pipe-loopback-loopback.sh +++ b/tests/integration/pipe-loopback-loopback.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,31 +22,31 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "loopback" + "nodes": { + "node1": { + "type": "loopback" } } } EOF -# Generate test data -villas signal -v 5 -l ${NUM_SAMPLES} -n mixed > ${INPUT_FILE} +villas signal -v 5 -l ${NUM_SAMPLES} -n mixed > input.dat -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-mqtt.sh b/tests/integration/pipe-loopback-mqtt.sh index e7c5a9127..9dafbd99f 100755 --- a/tests/integration/pipe-loopback-mqtt.sh +++ b/tests/integration/pipe-loopback-mqtt.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,51 +22,54 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} - -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} - FORMAT="protobuf" VECTORIZE="10" +HOST="localhost" -cat > ${CONFIG_FILE} << EOF +if [ -n "${CI}" ]; then + HOST="mosquitto" +else + HOST="localhost" +fi + +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "mqtt", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, + "nodes": { + "node1": { + "type": "mqtt", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, - "username" : "guest", - "password" : "guest", - "host" : "localhost", - "port" : 1883, + "username": "guest", + "password": "guest", + "host": "${HOST}", + "port": 1883, - "out" : { - "publish" : "test-topic" + "out": { + "publish": "test-topic" }, - "in" : { - "subscribe" : "test-topic" + "in": { + "subscribe": "test-topic" } } } } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < <(sleep 2; cat input.dat) -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-nanomsg.sh b/tests/integration/pipe-loopback-nanomsg.sh index e2b80943e..b98130817 100755 --- a/tests/integration/pipe-loopback-nanomsg.sh +++ b/tests/integration/pipe-loopback-nanomsg.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,49 +22,49 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} -# Generate test data -villas signal -v 5 -l ${NUM_SAMPLES} -n mixed > ${INPUT_FILE} - FORMAT="protobuf" VECTORIZE="10" -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "nanomsg", + "nodes": { + "node1": { + "type": "nanomsg", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, - "in" : { - "endpoints" : [ "tcp://127.0.0.1:12000" ], + "in": { + "endpoints": [ "tcp://127.0.0.1:12000" ], - "signals" : { - "type" : "float", - "count" : 5 + "signals": { + "type": "float", + "count": 5 } }, - "out" : { - "endpoints" : [ "tcp://127.0.0.1:12000" ] + "out": { + "endpoints": [ "tcp://127.0.0.1:12000" ] } } } } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -v 5 -l ${NUM_SAMPLES} -n mixed > input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare ${CMPFLAGS} input.dat output.dat diff --git a/tests/integration/hook-dp.sh b/tests/integration/pipe-loopback-redis.sh similarity index 55% rename from tests/integration/hook-dp.sh rename to tests/integration/pipe-loopback-redis.sh index 00a415585..7c82e0226 100755 --- a/tests/integration/hook-dp.sh +++ b/tests/integration/pipe-loopback-redis.sh @@ -1,9 +1,9 @@ #!/bin/bash # -# Integration test for dp hook. +# Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,32 +22,45 @@ # along with this program. If not, see . ################################################################################## -# Test is not ready yet +echo "Test not ready" exit 99 +set -e -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -RECON_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} -NUM_SAMPLES=10000 -RATE=5000 -F0=50 +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT +NUM_SAMPLES=${NUM_SAMPLES:-100} -OPTS="-o f0=${F0} -o rate=${RATE} -o signal=0 -o harmonics=0,1,3,5,7" +villas signal -l ${NUM_SAMPLES} -n random > input.dat -villas signal sine -v1 -l ${NUM_SAMPLES} -f ${F0} -r ${RATE} -n > ${INPUT_FILE} +FORMAT="protobuf" +VECTORIZE="10" +HOST="localhost" -villas hook dp -o inverse=false ${OPTS} < ${INPUT_FILE} > ${OUTPUT_FILE} +if [ -n "${CI}" ]; then + HOST="amqp" +fi -villas hook dp -o inverse=true ${OPTS} < ${OUTPUT_FILE} > ${RECON_FILE} +cat > config.json << EOF +{ + "nodes": { + "node1": { + "type": "redis", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + + "uri": "tcp://${HOST}:6379/0" + } + } +} +EOF -exit 0 +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -# Compare only the data values -villas compare ${OUTPUT_FILE} ${EXPECT_FILE} -RC=$? - -rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} - -exit ${RC} +villas compare ${CMPFLAGS} input.dat output.dat diff --git a/tests/integration/pipe-loopback-rtp-dual.sh b/tests/integration/pipe-loopback-rtp-dual.sh index fae42d029..c10fd7c5c 100755 --- a/tests/integration/pipe-loopback-rtp-dual.sh +++ b/tests/integration/pipe-loopback-rtp-dual.sh @@ -4,7 +4,7 @@ # # @author Steffen Vogel # @author Marvin Klimke -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -23,16 +23,19 @@ # along with this program. If not, see . ################################################################################## -if [ -n "${CI}" ]; then - # We skip this test for now in CI - echo "Test not yet supported" - exit 99 -fi +echo "Test is broken" +exit 99 -CONFIG_FILE_SRC=$(mktemp) -CONFIG_FILE_DEST=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT FORMAT="villas.binary" VECTORIZE="1" @@ -40,90 +43,80 @@ VECTORIZE="1" RATE=100 NUM_SAMPLES=2000 -cat > ${CONFIG_FILE_SRC} << EOF +cat > src.json << EOF { - "logging" : { - "level" : "info" + "logging": { + "level": "info" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, - "rtcp" : { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, + "rtcp": true, + "aimd": { + "a": 10, + "b": 0.5, + "hook_type": "decimate" }, - "aimd" : { - "a" : 10, - "b" : 0.5 - }, - "in" : { - "address" : "0.0.0.0:12002", - "signals" : { - "count" : 5, - "type" : "float" + "in": { + "address": "0.0.0.0:12002", + "signals": { + "count": 5, + "type": "float" } }, - "out" : { - "address" : "127.0.0.1:12000" + "out": { + "address": "127.0.0.1:12000" } } } } EOF -cat > ${CONFIG_FILE_DEST} << EOF +cat > dest.json << EOF { - "logging" : { - "level" : "info" + "logging": { + "level": "info" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, - "rtcp": { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, + "rtcp": true, + "aimd": { + "a": 10, + "b": 0.5, + + "hook_type": "decimate" }, - "aimd" : { - "a" : 10, - "b" : 0.5 - }, - "in" : { - "address" : "0.0.0.0:12000", - "signals" : { - "count" : 5, - "type" : "float" + "in": { + "address": "0.0.0.0:12000", + "signals": { + "count": 5, + "type": "float" } }, - "out" : { - "address" : "127.0.0.1:12002" + "out": { + "address": "127.0.0.1:12002" } } } } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE_DEST} rtp_node > ${OUTPUT_FILE} & -PID=$! +villas pipe -l ${NUM_SAMPLES} dest.json rtp_node > output.dat & sleep 1 -villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} | tee ${INPUT_FILE} | \ -villas pipe ${CONFIG_FILE_SRC} rtp_node > ${OUTPUT_FILE} +villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} > input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe ${CONFIG_FILE_SRC} rtp_node > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE_SRC} ${CONFIG_FILE_DEST} +villas compare ${CMPFLAGS} input.dat output.dat -kill $PID - -exit ${RC} +kill %% +wait %% diff --git a/tests/integration/pipe-loopback-rtp-remote.sh b/tests/integration/pipe-loopback-rtp-remote.sh index 58c6c3416..ed82a5cc2 100755 --- a/tests/integration/pipe-loopback-rtp-remote.sh +++ b/tests/integration/pipe-loopback-rtp-remote.sh @@ -4,7 +4,7 @@ # # @author Steffen Vogel # @author Marvin Klimke -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -23,11 +23,10 @@ # along with this program. If not, see . ################################################################################## -if [ -n "${CI}" ]; then - # We skip this test for now in CI - echo "Test not yet supported" - exit 99 -fi +set -e + +echo "Test is broken" +exit 99 LOCAL_ADDR=137.226.133.195 REMOTE_ADDR=157.230.251.200 @@ -37,10 +36,14 @@ REMOTE="ssh ${REMOTE_USER}@${REMOTE_ADDR}" PATH=/projects/villas/node/build/src:${PATH} ${REMOTE} PATH=/projects/villas/node/build/src:${PATH} -CONFIG_FILE_SRC=$(mktemp) -CONFIG_FILE_DEST=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT FORMAT="villas.binary" VECTORIZE="1" @@ -48,35 +51,35 @@ VECTORIZE="1" RATE=100 NUM_SAMPLES=100 -cat > ${CONFIG_FILE_SRC} << EOF +cat > src.json << EOF { - "logging" : { - "level" : "debug" + "logging": { + "level": "debug" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, - "rtcp" : { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, + "rtcp": { + "enabled": true, + "mode": "aimd", + "throttle_mode": "decimate" }, - "aimd" : { - "a" : 10, - "b" : 0.5 + "aimd": { + "a": 10, + "b": 0.5 }, - "in" : { - "address" : "0.0.0.0:33466", - "signals" : { - "count" : 5, - "type" : "float" + "in": { + "address": "0.0.0.0:33466", + "signals": { + "count": 5, + "type": "float" } }, - "out" : { - "address" : "${REMOTE_ADDR}:33464" + "out": { + "address": "${REMOTE_ADDR}:33464" } } } @@ -85,60 +88,56 @@ EOF # UDP ports: 33434 - 33534 -cat > ${CONFIG_FILE_DEST} << EOF +cat > dest.json << EOF { - "logging" : { - "level" : "debug" + "logging": { + "level": "debug" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, "rtcp": { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "enabled": true, + "mode": "aimd", + "throttle_mode": "decimate" }, - "aimd" : { - "a" : 10, - "b" : 0.5 + "aimd": { + "a": 10, + "b": 0.5 }, - "in" : { - "address" : "0.0.0.0:33464", - "signals" : { - "count" : 5, - "type" : "float" + "in": { + "address": "0.0.0.0:33464", + "signals": { + "count": 5, + "type": "float" } }, - "out" : { - "address" : "${LOCAL_ADDR}:33466" + "out": { + "address": "${LOCAL_ADDR}:33466" } } } } EOF -scp ${CONFIG_FILE_DEST} ${REMOTE_USER}@${REMOTE_ADDR}:${CONFIG_FILE_DEST} +scp dest.json ${REMOTE_USER}@${REMOTE_ADDR}:${CONFIG_FILE_DEST} -${REMOTE} villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE_DEST} rtp_node > ${OUTPUT_FILE} & -PID=$! +${REMOTE} villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE_DEST} rtp_node > output.dat & sleep 1 -villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} | tee ${INPUT_FILE} | \ -villas pipe ${CONFIG_FILE_SRC} rtp_node +villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} > input.dat -scp ${REMOTE_USER}@${REMOTE_ADDR}:${OUTPUT_FILE} ${OUTPUT_FILE} +villas pipe src.json rtp_node < input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +scp ${REMOTE_USER}@${REMOTE_ADDR}:output.dat output.dat -rm ${INPUT_FILE} ${OUTPUT_FILE} ${CONFIG_FILE_DEST} ${CONFIG_FILE_SRC} -${REMOTE} rm ${OUTPUT_FILE} ${CONFIG_FILE_DEST} +villas compare ${CMPFLAGS} input.dat output.dat -kill ${PID} +${REMOTE} rm -f output.dat ${CONFIG_FILE_DEST} -exit ${RC} +kill %% +wait %% diff --git a/tests/integration/pipe-loopback-rtp-tbf.sh b/tests/integration/pipe-loopback-rtp-tbf.sh index 7b95ba929..50ceaa4b5 100755 --- a/tests/integration/pipe-loopback-rtp-tbf.sh +++ b/tests/integration/pipe-loopback-rtp-tbf.sh @@ -4,7 +4,7 @@ # # @author Steffen Vogel # @author Marvin Klimke -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -23,16 +23,19 @@ # along with this program. If not, see . ################################################################################## -if [ -n "${CI}" ]; then - # We skip this test for now in CI - echo "Test not yet supported" - exit 99 -fi +echo "Test is broken" +exit 99 -CONFIG_FILE_SRC=$(mktemp) -CONFIG_FILE_DEST=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT FORMAT="villas.binary" VECTORIZE="1" @@ -41,68 +44,68 @@ RATE=500 NUM_SAMPLES=10000000 NUM_VALUES=5 -cat > ${CONFIG_FILE_SRC} << EOF +cat > src.json << EOF { - "logging" : { - "level" : "info" + "logging": { + "level": "info" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, - "rtcp" : { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, + "rtcp": { + "enabled": true, + "mode": "aimd", + "throttle_mode": "decimate" }, - "aimd" : { - "a" : 10, - "b" : 0.75, - "start_rate" : ${RATE} + "aimd": { + "a": 10, + "b": 0.75, + "start_rate": ${RATE} }, - "in" : { - "address" : "0.0.0.0:12002", - "signals" : { - "count" : ${NUM_VALUES}, - "type" : "float" + "in": { + "address": "0.0.0.0:12002", + "signals": { + "count": ${NUM_VALUES}, + "type": "float" } }, - "out" : { - "address" : "127.0.0.1:12000", - "fwmark" : 123 + "out": { + "address": "127.0.0.1:12000", + "fwmark": 123 } } } } EOF -cat > ${CONFIG_FILE_DEST} << EOF +cat > dest.json << EOF { - "logging" : { - "level" : "info" + "logging": { + "level": "info" }, - "nodes" : { - "rtp_node" : { - "type" : "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "rate" : ${RATE}, + "nodes": { + "rtp_node": { + "type": "rtp", + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "rate": ${RATE}, "rtcp": { - "enabled" : true, - "mode" : "aimd", - "throttle_mode" : "decimate" + "enabled": true, + "mode": "aimd", + "throttle_mode": "decimate" }, - "in" : { - "address" : "0.0.0.0:12000", - "signals" : { - "count" : ${NUM_VALUES}, - "type" : "float" + "in": { + "address": "0.0.0.0:12000", + "signals": { + "count": ${NUM_VALUES}, + "type": "float" } }, - "out" : { - "address" : "127.0.0.1:12002" + "out": { + "address": "127.0.0.1:12002" } } } @@ -114,19 +117,15 @@ tc qdisc add dev lo root handle 4000 prio bands 4 priomap 1 2 2 2 1 2 0 0 1 1 1 tc qdisc add dev lo parent 4000:3 tbf rate 40kbps burst 32kbit latency 200ms #peakrate 40kbps mtu 1000 minburst 1520 tc filter add dev lo protocol ip handle 123 fw flowid 4000:3 -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE_DEST} rtp_node > ${OUTPUT_FILE} & -PID=$! +villas pipe -l ${NUM_SAMPLES} dest.json rtp_node > output.dat & sleep 1 -villas signal mixed -v ${NUM_VALUES} -r ${RATE} -l ${NUM_SAMPLES} | tee ${INPUT_FILE} | \ -villas pipe ${CONFIG_FILE_SRC} rtp_node > ${OUTPUT_FILE} +villas signal mixed -v ${NUM_VALUES} -r ${RATE} -l ${NUM_SAMPLES} > input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe src.json rtp_node > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE_SRC} ${CONFIG_FILE_DEST} +villas compare ${CMPFLAGS} input.dat output.dat -kill $PID -exit ${RC} +kill %% +wait %% diff --git a/tests/integration/pipe-loopback-rtp.sh b/tests/integration/pipe-loopback-rtp.sh index 48c62e276..a46761799 100755 --- a/tests/integration/pipe-loopback-rtp.sh +++ b/tests/integration/pipe-loopback-rtp.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,15 +22,19 @@ # along with this program. If not, see . ################################################################################## -if [ -n "${CI}" ]; then - # We skip this test for now in CI - echo "Test not yet supported" - exit 99 -fi +echo "Test is broken" +exit 99 -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT FORMAT="villas.binary" VECTORIZE="1" @@ -38,52 +42,47 @@ VECTORIZE="1" RATE=1000 NUM_SAMPLES=$((10*${RATE})) -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "logging" : { - "level" : "debug" + "logging": { + "level": "debug" }, - "nodes" : { - "node1" : { - "type" : "rtp", + "nodes": { + "node1": { + "type": "rtp", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, - "rtcp" : { - "enabled" : true, - "throttle_mode" : "limit_rate" + "rtcp": { + "enabled": true, + "throttle_mode": "limit_rate" }, - "aimd" : { - "start_rate" : 1, - "a" : 10, - "b" : 0.5 + "aimd": { + "start_rate": 1, + "a": 10, + "b": 0.5 }, - "in" : { - "address" : "127.0.0.1:12000", + "in": { + "address": "127.0.0.1:12000", - "signals" : { - "type" : "float", - "count" : 5 + "signals": { + "type": "float", + "count": 5 } }, - "out" : { - "address" : "127.0.0.1:12000" + "out": { + "address": "127.0.0.1:12000" } } } } EOF -villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} | tee ${INPUT_FILE} | \ -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} +villas signal mixed -v 5 -r ${RATE} -l ${NUM_SAMPLES} > input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < intput.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare ${CMPFLAGS} input.dat output.dat diff --git a/tests/integration/pipe-loopback-shmem.sh b/tests/integration/pipe-loopback-shmem.sh index 3111b547d..bd31aaedc 100755 --- a/tests/integration/pipe-loopback-shmem.sh +++ b/tests/integration/pipe-loopback-shmem.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,9 +22,16 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} SIGNAL_COUNT=${SIGNAL_COUNT:-10} @@ -32,48 +39,29 @@ SIGNAL_COUNT=${SIGNAL_COUNT:-10} for MODE in polling pthread; do for VECTORIZE in 1 5; do -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "shmem", - "out" : { - "name" : "/villas-test" + "nodes": { + "node1": { + "type": "shmem", + "out": { + "name": "/villas-test" }, - "in" : { - "name" : "/villas-test" + "in": { + "name": "/villas-test" }, - "queuelen" : 1024, - "mode" : "${MODE}", - "vectorize" : ${VECTORIZE} + "queuelen": 1024, + "mode": "${MODE}", + "vectorize": ${VECTORIZE} } } } EOF -# Generate test data -villas signal -l ${NUM_SAMPLES} -v ${SIGNAL_COUNT} -n random > ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -v ${SIGNAL_COUNT} -n random > input.dat -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -if (( ${RC} != 0 )); then - echo "=========== Sub-test failed for: mode=${MODE}, vectorize=${VECTORIZE}, SIGNAL_COUNT=${SIGNAL_COUNT}" - cat ${CONFIG_FILE} - echo - cat ${INPUT_FILE} - echo - cat ${OUTPUT_FILE} - exit ${RC} -else - echo "=========== Sub-test succeeded for: mode=${MODE}, vectorize=${VECTORIZE}, SIGNAL_COUNT=${SIGNAL_COUNT}" -fi +villas compare input.dat output.dat done; done; - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} diff --git a/tests/integration/pipe-loopback-socket-multicast.sh b/tests/integration/pipe-loopback-socket-multicast.sh index 50588d36e..138e1b3fb 100755 --- a/tests/integration/pipe-loopback-socket-multicast.sh +++ b/tests/integration/pipe-loopback-socket-multicast.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,46 +22,46 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { + "nodes": { + "node1": { "type" : "socket", - "format" : "protobuf", + "format": "protobuf", - "in" : { - "address" : "*:12000", + "in": { + "address": "*:12000", - "multicast" : { - "enabled" : true, + "multicast": { + "enabled": true, "group" : "224.1.2.3", "loop" : true } }, - "out" : { - "address" : "224.1.2.3:12000" + "out": { + "address": "224.1.2.3:12000" } } } } EOF -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-socket-netem.sh b/tests/integration/pipe-loopback-socket-netem.sh index 917b8d5bc..18baea86b 100755 --- a/tests/integration/pipe-loopback-socket-netem.sh +++ b/tests/integration/pipe-loopback-socket-netem.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,37 +22,46 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 - if ! modprobe -aqn sch_prio sch_netem cls_fw; then echo "Netem / TC kernel modules are missing" exit 99 fi -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +if [[ "${EUID}" -ne 0 ]]; then + echo "Test requires root permissions" + exit 99 +fi + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { + "nodes": { + "node1": { "type" : "socket", - "format" : "protobuf", + "format": "protobuf", - "in" : { - "address" : "*:12000" + "in": { + "address": "*:12000" }, - "out" : { - "address" : "127.0.0.1:12000", - "netem" : { - "enabled" : true, - "delay" : 100000, - "jitter" : 30000, - "loss" : 20 + "out": { + "address": "127.0.0.1:12000", + "netem": { + "enabled": true, + "delay": 100000, + "jitter": 30000, + "loss": 20 } } } @@ -60,12 +69,9 @@ cat > ${CONFIG_FILE} << EOF } EOF -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat # Check network emulation characteristics -villas hook -o verbose stats < ${OUTPUT_FILE} > /dev/null - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} +villas hook -o verbose=true -o format=json stats < output.dat > /dev/null diff --git a/tests/integration/pipe-loopback-socket.sh b/tests/integration/pipe-loopback-socket.sh index 7992cdfb9..4f42434f1 100755 --- a/tests/integration/pipe-loopback-socket.sh +++ b/tests/integration/pipe-loopback-socket.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,30 +22,28 @@ # along with this program. If not, see . ################################################################################## -# Test is broken -exit 99 +set -e -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) -THEORIES=$(mktemp) +if [[ "${EUID}" -ne 0 ]]; then + echo "Test requires root permissions" + exit 99 +fi + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} NUM_VALUES=${NUM_VALUES:-4} FORMAT=${FORMAT:-villas.binary} - -# Generate test data -villas signal -v ${NUM_VALUES} -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +VECTORIZES="1 10" for LAYER in udp ip eth unix; do - -VECTORIZES="1" - -# The raw format does not support vectors -if villas_format_supports_vectorize ${FORMAT}; then - VECTORIZES="${VECTORIZES} 10" -fi - for VECTORIZE in ${VECTORIZES}; do case ${LAYER} in @@ -71,24 +69,24 @@ case ${LAYER} in ;; esac -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "socket", + "nodes": { + "node1": { + "type": "socket", - "vectorize" : ${VECTORIZE}, - "format" : "${FORMAT}", - "layer" : "${LAYER}", + "vectorize": ${VECTORIZE}, + "format": "${FORMAT}", + "layer": "${LAYER}", - "out" : { - "address" : "${REMOTE}" + "out": { + "address": "${REMOTE}" }, - "in" : { - "address" : "${LOCAL}", - "signals" : { - "count" : ${NUM_VALUES}, - "type" : "float" + "in": { + "address": "${LOCAL}", + "signals": { + "count": ${NUM_VALUES}, + "type": "float" } } } @@ -96,34 +94,10 @@ cat > ${CONFIG_FILE} << EOF } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 < ${INPUT_FILE} > ${OUTPUT_FILE} +villas signal -v ${NUM_VALUES} -l ${NUM_SAMPLES} -n random > input.dat -# Ignore timestamp and seqeunce no if in raw format -if ! villas_format_supports_header $FORMAT; then - CMPFLAGS=-ts -fi +villas pipe -l ${NUM_SAMPLES} config.json node1 < input.dat > output.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -if (( ${RC} != 0 )); then - echo "=========== Sub-test failed for: format=${FORMAT}, layer=${LAYER}, vectorize=${VECTORIZE}" - echo "Config:" - cat ${CONFIG_FILE} - echo - echo "Input:" - cat ${INPUT_FILE} - echo - echo "Output:" - cat ${OUTPUT_FILE} - exit ${RC} -else - echo "=========== Sub-test succeeded for: format=${FORMAT}, layer=${LAYER}, vectorize=${VECTORIZE}" -fi +villas compare ${CMPFLAGS} input.dat output.dat done; done - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} ${THEORIES} - -exit ${RC} diff --git a/tests/integration/pipe-loopback-websocket.sh b/tests/integration/pipe-loopback-websocket.sh index ced902ce8..2a68416c1 100755 --- a/tests/integration/pipe-loopback-websocket.sh +++ b/tests/integration/pipe-loopback-websocket.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,23 +22,29 @@ # along with this program. If not, see . ################################################################################## -# Test is broken +echo "Test is broken" exit 99 -CONFIG_FILE=$(mktemp) -CONFIG_FILE2=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-100} -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "websocket", + "nodes": { + "node1": { + "type": "websocket", - "destinations" : [ + "destinations": [ "ws://127.0.0.1:8080/node2.protobuf" ] } @@ -46,34 +52,27 @@ cat > ${CONFIG_FILE} << EOF } EOF -cat > ${CONFIG_FILE2} << EOF +cat > config2.json << EOF { - "http" : { - "port" : 8080 + "http": { + "port": 8080 }, - "nodes" : { - "node2" : { - "type" : "websocket" + "nodes": { + "node2": { + "type": "websocket" } } } EOF -# Generate test data -villas signal -l ${NUM_SAMPLES} -n random > ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n random > input.dat -villas pipe -r -l ${NUM_SAMPLES} ${CONFIG_FILE2} node2 | tee ${OUTPUT_FILE} & +villas pipe -r -l ${NUM_SAMPLES} ${CONFIG_FILE2} node2 | tee output.dat & sleep 1 -villas pipe -s ${CONFIG_FILE} node1 < <(sleep 1; cat ${INPUT_FILE}) +villas pipe -s config.json node1 < <(sleep 1; cat input.dat) wait $! -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? - -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} ${CONFIG_FILE2} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-loopback-zeromq.sh b/tests/integration/pipe-loopback-zeromq.sh index 1ba4dc1b9..6c8cea73d 100755 --- a/tests/integration/pipe-loopback-zeromq.sh +++ b/tests/integration/pipe-loopback-zeromq.sh @@ -3,7 +3,7 @@ # Integration loopback test for villas pipe. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,35 +22,39 @@ # along with this program. If not, see . ################################################################################## -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT NUM_SAMPLES=${NUM_SAMPLES:-10} - -# Generate test data -villas signal -l ${NUM_SAMPLES} -n -v 5 random > ${INPUT_FILE} VECTORIZE="10" FORMAT="protobuf" -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "node1" : { - "type" : "zeromq", + "nodes": { + "node1": { + "type": "zeromq", - "format" : "${FORMAT}", - "vectorize" : ${VECTORIZE}, - "pattern" : "pubsub", - "out" : { - "publish" : "tcp://127.0.0.1:12000" + "format": "${FORMAT}", + "vectorize": ${VECTORIZE}, + "pattern": "pubsub", + "out": { + "publish": "tcp://127.0.0.1:12000" }, - "in" : { - "subscribe" : "tcp://127.0.0.1:12000", - "signals" : { - "type" : "float", - "count" : 5 + "in": { + "subscribe": "tcp://127.0.0.1:12000", + "signals": { + "type": "float", + "count": 5 } } } @@ -58,12 +62,8 @@ cat > ${CONFIG_FILE} << EOF } EOF -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} node1 > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -n -v 5 random > input.dat -# Compare data -villas compare ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +villas pipe -l ${NUM_SAMPLES} config.json node1 > output.dat < input.dat -rm ${OUTPUT_FILE} ${INPUT_FILE} ${CONFIG_FILE} - -exit ${RC} +villas compare input.dat output.dat diff --git a/tests/integration/pipe-python-protobuf.sh b/tests/integration/pipe-python-protobuf.sh index 0f09167be..492c14b3e 100755 --- a/tests/integration/pipe-python-protobuf.sh +++ b/tests/integration/pipe-python-protobuf.sh @@ -3,7 +3,7 @@ # Test protobuf serialization with Python client # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -22,12 +22,19 @@ # along with this program. If not, see . ################################################################################## -# Test is broken +echo "Test is broken" exit 99 -CONFIG_FILE=$(mktemp) -INPUT_FILE=$(mktemp) -OUTPUT_FILE=$(mktemp) +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT LAYER="unix" FORMAT="protobuf" @@ -35,9 +42,6 @@ FORMAT="protobuf" NUM_SAMPLES=${NUM_SAMPLES:-20} NUM_VALUES=${NUM_VALUES:-5} -# Generate test data -villas signal -l ${NUM_SAMPLES} -v ${NUM_VALUES} -n random > ${INPUT_FILE} - case ${LAYER} in unix) LOCAL="/var/run/villas-node.server.sock" @@ -50,19 +54,19 @@ case ${LAYER} in ;; esac -cat > ${CONFIG_FILE} << EOF +cat > config.json << EOF { - "nodes" : { - "py-client" : { - "type" : "socket", + "nodes": { + "py-client": { + "type": "socket", "layer": "${LAYER}", - "format" : "${FORMAT}", + "format": "${FORMAT}", - "in" : { - "address" : "${LOCAL}" + "in": { + "address": "${LOCAL}" }, - "out" : { - "address" : "${REMOTE}" + "out": { + "address": "${REMOTE}" } } } @@ -73,7 +77,6 @@ export PYTHONPATH=${BUILDDIR}/python:${SRCDIR}/python # Start Python client in background python3 ${SRCDIR}/clients/python/client.py unix & -CPID=$! # Wait for client to be ready if [ "${LAYER}" = "unix" ]; then @@ -84,15 +87,11 @@ fi sleep 1 -villas pipe -l ${NUM_SAMPLES} ${CONFIG_FILE} py-client > ${OUTPUT_FILE} < ${INPUT_FILE} +villas signal -l ${NUM_SAMPLES} -v ${NUM_VALUES} -n random > input.dat -kill ${CPID} -wait ${CPID} +villas pipe -l ${NUM_SAMPLES} config.json py-client > output.dat < input.dat -# Compare data -villas compare ${CMPFLAGS} ${INPUT_FILE} ${OUTPUT_FILE} -RC=$? +kill %% +wait %% -rm ${CONFIG_FILE} ${INPUT_FILE} ${OUTPUT_FILE} - -exit ${RC} +villas compare ${CMPFLAGS} input.dat output.dat diff --git a/tests/integration/signal.sh b/tests/integration/signal.sh new file mode 100755 index 000000000..0daefcb19 --- /dev/null +++ b/tests/integration/signal.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# +# Integration test for villas signal tool +# +# @author Steffen Vogel +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC +# @license GNU General Public License (version 3) +# +# VILLASnode +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +################################################################################## + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > input.dat < output.dat + +villas compare -T input.dat output.dat diff --git a/tests/integration/test-config.sh b/tests/integration/test-config.sh index 417a1a69e..d7bb5e24f 100755 --- a/tests/integration/test-config.sh +++ b/tests/integration/test-config.sh @@ -4,7 +4,7 @@ # Test example configurations # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -29,6 +29,7 @@ CONFIGS=$(find ${SRCDIR}/etc/ -name '*.conf' -o -name '*.json') for CONFIG in ${CONFIGS}; do if [ "$(basename ${CONFIG})" == "opal.conf" ] || + [ "$(basename ${CONFIG})" == "fpga.conf" ] || [ "$(basename ${CONFIG})" == "paths.conf" ] || [ "$(basename ${CONFIG})" == "tricks.json" ] || [ "$(basename ${CONFIG})" == "tricks.conf" ] || diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 757109ea0..7232c053d 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tests/unit/config.cpp b/tests/unit/config.cpp index e9f8928d3..cec617934 100644 --- a/tests/unit/config.cpp +++ b/tests/unit/config.cpp @@ -1,7 +1,7 @@ /** Unit tests for config features. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,7 +25,7 @@ #include #include -#include +#include using namespace villas::node; diff --git a/tests/unit/config_json.cpp b/tests/unit/config_json.cpp index 2005beb73..c70bdec8f 100644 --- a/tests/unit/config_json.cpp +++ b/tests/unit/config_json.cpp @@ -1,7 +1,7 @@ /** Unit tests libconfig to jansson converters. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -30,6 +30,8 @@ #include #include +using namespace villas::node; + const char *cfg_example = "test : \n" "{\n" " hallo = 1L;\n" diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index 840bb0db4..724e7c706 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -1,7 +1,7 @@ /** Unit tests for formatters. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -28,10 +28,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -57,7 +57,7 @@ public: int bits; }; -void fill_sample_data(struct vlist *signals, struct sample *smps[], unsigned cnt) +void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], unsigned cnt) { struct timespec delta, now; @@ -65,17 +65,17 @@ void fill_sample_data(struct vlist *signals, struct sample *smps[], unsigned cnt delta = time_from_double(50e-6); for (unsigned i = 0; i < cnt; i++) { - struct sample *smp = smps[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 = vlist_length(signals); + 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 < vlist_length(signals); j++) { - struct signal *sig = (struct signal *) vlist_at(signals, j); - union signal_data *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: @@ -105,7 +105,7 @@ void fill_sample_data(struct vlist *signals, struct sample *smps[], unsigned cnt } } -void cr_assert_eq_sample(struct sample *a, struct sample *b, int flags) +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); @@ -148,7 +148,7 @@ void cr_assert_eq_sample(struct sample *a, struct sample *b, int flags) } } -void cr_assert_eq_sample_raw(struct sample *a, struct sample *b, int flags, int bits) +void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, int bits) { cr_assert_eq(a->length, b->length); @@ -232,18 +232,15 @@ ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); - struct pool pool; + struct Pool pool; Format *fmt; - struct vlist signals; - struct sample *smps[p->cnt]; - struct sample *smpt[p->cnt]; + 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 = vlist_init(&signals); - cr_assert_eq(ret, 0); - signal_list_generate(&signals, 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); @@ -251,7 +248,7 @@ ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) 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); @@ -259,7 +256,7 @@ ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) 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); @@ -319,11 +316,10 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) 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; - struct vlist signals; + struct Pool pool; Format *fmt; ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); @@ -335,11 +331,9 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) ret = sample_alloc_many(&pool, smpt, p->cnt); cr_assert_eq(ret, p->cnt); - ret = vlist_init(&signals); - cr_assert_eq(ret, 0); - signal_list_generate(&signals, 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]; @@ -357,7 +351,7 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) 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); diff --git a/tests/unit/json.cpp b/tests/unit/json.cpp index 8ac6a996d..ca88a9613 100644 --- a/tests/unit/json.cpp +++ b/tests/unit/json.cpp @@ -1,7 +1,7 @@ /** Unit tests for libjansson helpers * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -29,6 +29,8 @@ #include "helpers.hpp" +using namespace villas::node; + struct param { char *argv[32]; char *json; diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 008195229..0eea928e6 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -1,7 +1,7 @@ /** Custom main() for Criterion * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -20,10 +20,12 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include + +using namespace villas::node; void init_memory() { int ret __attribute__((unused)); - ret = memory_init(DEFAULT_NR_HUGEPAGES); + ret = memory::init(DEFAULT_NR_HUGEPAGES); } diff --git a/tests/unit/mapping.cpp b/tests/unit/mapping.cpp index 7e5ed3b5d..260da20e1 100644 --- a/tests/unit/mapping.cpp +++ b/tests/unit/mapping.cpp @@ -1,7 +1,7 @@ /** Unit tests for sample value mapping. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,79 +22,80 @@ #include -#include -#include -#include +#include +#include +#include #include -#include +#include using namespace villas; +using namespace villas::node; // cppcheck-suppress syntaxError Test(mapping, parse_nodes) { int ret; - struct mapping_entry m; + MappingEntry m; - ret = mapping_entry_parse_str(&m, "apple.ts.origin"); + ret = m.parseString("apple.ts.origin"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "apple"); - cr_assert_eq(m.type, MappingType::TIMESTAMP); - cr_assert_eq(m.timestamp.type, MappingTimestampType::ORIGIN); + 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 = mapping_entry_parse_str(&m, "cherry.stats.owd.mean"); + ret = m.parseString("cherry.stats.owd.mean"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "cherry"); - cr_assert_eq(m.type, MappingType::STATS); + 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 = mapping_entry_parse_str(&m, "carrot.data[1-2]"); + ret = m.parseString("carrot.data[1-2]"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot"); + ret = m.parseString("carrot"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot.data[sole]"); + ret = m.parseString("carrot.data[sole]"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot.sole"); + ret = m.parseString("carrot.sole"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot.data.sole"); + ret = m.parseString("carrot.data.sole"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot.data[sole-mio]"); + ret = m.parseString("carrot.data[sole-mio]"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 = mapping_entry_parse_str(&m, "carrot[sole-mio]"); + ret = m.parseString("carrot[sole-mio]"); cr_assert_eq(ret, 0); - cr_assert_str_eq(m.node_name, "carrot"); - cr_assert_eq(m.type, MappingType::DATA); + 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 7bd568d92..5ff3efb28 100644 --- a/tests/unit/memory.cpp +++ b/tests/unit/memory.cpp @@ -1,7 +1,7 @@ /** Unit tests for memory management * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,13 +25,15 @@ #include -#include +#include #include #include #include using namespace villas; +using namespace villas::node; + extern void init_memory(); #define PAGESIZE (1 << 12) @@ -40,29 +42,29 @@ extern void init_memory(); 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(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) { +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) + 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); + 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); #ifndef __APPLE__ - if (mt == &memory_mmap_hugetlb) { + if (mt == &memory::mmap_hugetlb) { cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE), "Memory at %p is not alligned to %#x byte bounary", ptr, HUGEPAGESIZE); } #endif - ret = memory_free(ptr); + 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)); } @@ -72,49 +74,49 @@ Test(memory, manager, .init = init_memory) { int ret; void *p, *p1, *p2, *p3; - struct memory_type *m; + struct memory::Type *m; total_size = 1 << 10; - max_block = total_size - sizeof(struct memory_type) - sizeof(struct memory_block); + max_block = total_size - sizeof(struct memory::Type) - sizeof(struct memory::Block); - p = memory_alloc(total_size, &memory_heap); + p = memory::alloc(total_size, &memory::heap); cr_assert_not_null(p); - m = memory_managed(p, total_size); + m = memory::managed(p, total_size); cr_assert_not_null(m); - p1 = memory_alloc(16, m); + p1 = memory::alloc(16, m); cr_assert_not_null(p1); - p2 = memory_alloc(32, m); + p2 = memory::alloc(32, m); cr_assert_not_null(p2); - ret = memory_free(p1); + ret = memory::free(p1); cr_assert(ret == 0); - p1 = memory_alloc_aligned(128, 128, m); + 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); + p3 = memory::alloc_aligned(128, 256, m); cr_assert(p3); cr_assert(IS_ALIGNED(p3, 256)); - ret = memory_free(p2); + ret = memory::free(p2); cr_assert(ret == 0); - ret = memory_free(p1); + ret = memory::free(p1); cr_assert(ret == 0); - ret = memory_free(p3); + ret = memory::free(p3); cr_assert(ret == 0); - p1 = memory_alloc(max_block, m); + p1 = memory::alloc(max_block, m); cr_assert_not_null(p1); - ret = memory_free(p1); + ret = memory::free(p1); cr_assert(ret == 0); - ret = memory_free(p); + ret = memory::free(p); cr_assert(ret == 0); } diff --git a/tests/unit/pool.cpp b/tests/unit/pool.cpp index bbbe15b4c..89aa560c6 100644 --- a/tests/unit/pool.cpp +++ b/tests/unit/pool.cpp @@ -1,7 +1,7 @@ /** Unit tests for memory pool * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -25,28 +25,30 @@ #include -#include +#include #include #include using namespace villas; +using namespace villas::node; + extern void init_memory(); struct param { int thread_count; int pool_size; size_t block_size; - struct memory_type *mt; + struct memory::Type *mt; }; ParameterizedTestParameters(pool, basic) { static struct param params[] = { - { 1, 4096, 150, &memory_heap }, - { 1, 128, 8, &memory_mmap }, - { 1, 4, 8192, &memory_mmap_hugetlb }, - { 1, 1 << 13, 4, &memory_mmap_hugetlb } + { 1, 4096, 150, &memory::heap }, + { 1, 128, 8, &memory::mmap }, + { 1, 4, 8192, &memory::mmap_hugetlb }, + { 1, 1 << 13, 4, &memory::mmap_hugetlb } }; return cr_make_param_array(struct param, params, ARRAY_LEN(params)); @@ -56,16 +58,15 @@ ParameterizedTestParameters(pool, basic) ParameterizedTest(struct param *p, pool, basic, .init = init_memory) { int ret; - struct pool pool; + struct Pool pool; // some strange LTO stuff is going on here.. - auto *m __attribute__((unused)) = &memory_mmap; + auto *m __attribute__((unused)) = &memory::mmap; void *ptr, *ptrs[p->pool_size]; - if (!utils::isPrivileged() && p->mt == &memory_mmap_hugetlb) { + 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"); diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index bb28b16af..11c414c60 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -1,7 +1,7 @@ /** Unit tests for queue * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -32,17 +32,18 @@ #include #include -#include -#include +#include +#include #include using namespace villas; +using namespace villas::node; extern void init_memory(); #define SIZE (1 << 10) -static struct queue q; +static struct CQueue q; #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 static pthread_barrier_t barrier; @@ -54,9 +55,9 @@ struct param { int thread_count; bool many; int batch_size; - struct memory_type *mt; + struct memory::Type *mt; volatile int start; - struct queue queue; + struct CQueue queue; }; /** Get thread id as integer @@ -231,7 +232,7 @@ Test(queue, single_threaded, .init = init_memory) p.queue_size = 1 << 10; p.start = 1; /* we start immeadiatly */ - ret = queue_init(&p.queue, p.queue_size, &memory_heap); + ret = queue_init(&p.queue, p.queue_size, &memory::heap); cr_assert_eq(ret, 0, "Failed to create queue"); producer(&p); @@ -253,35 +254,35 @@ ParameterizedTestParameters(queue, multi_threaded) .thread_count = 32, .many = true, .batch_size = 10, - .mt = &memory_heap + .mt = &memory::heap }, { .iter_count = 1 << 8, .queue_size = 1 << 9, .thread_count = 4, .many = true, .batch_size = 100, - .mt = &memory_heap + .mt = &memory::heap }, { .iter_count = 1 << 16, .queue_size = 1 << 14, .thread_count = 16, .many = true, .batch_size = 100, - .mt = &memory_heap + .mt = &memory::heap }, { .iter_count = 1 << 8, .queue_size = 1 << 9, .thread_count = 4, .many = true, .batch_size = 10, - .mt = &memory_heap + .mt = &memory::heap }, { .iter_count = 1 << 16, .queue_size = 1 << 9, .thread_count = 16, .many = false, .batch_size = 10, - .mt = &memory_mmap_hugetlb + .mt = &memory::mmap_hugetlb } }; @@ -291,11 +292,11 @@ ParameterizedTestParameters(queue, multi_threaded) ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, .init = init_memory) { int ret, cycpop; - struct tsc tsc; + struct Tsc tsc; Logger logger = logging.get("test:queue:multi_threaded"); - if (!utils::isPrivileged() && p->mt == &memory_mmap_hugetlb) + 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]; @@ -345,9 +346,9 @@ ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, .init = Test(queue, init_destroy, .init = init_memory) { int ret; - struct queue q; + struct CQueue q; - ret = queue_init(&q, 1024, &memory_heap); + ret = queue_init(&q, 1024, &memory::heap); cr_assert_eq(ret, 0); /* Should succeed */ ret = queue_destroy(&q); diff --git a/tests/unit/queue_signalled.cpp b/tests/unit/queue_signalled.cpp index 80acbd108..fbfbe6dbd 100644 --- a/tests/unit/queue_signalled.cpp +++ b/tests/unit/queue_signalled.cpp @@ -1,7 +1,7 @@ /** Unit tests for queue_signalled * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -27,9 +27,11 @@ #include #include -#include +#include #include +using namespace villas::node; + extern void init_memory(); #define NUM_ELEM 1000 @@ -43,7 +45,7 @@ struct param { static void * producer(void * ctx) { int ret; - struct queue_signalled *q = (struct queue_signalled *) ctx; + struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; for (intptr_t i = 0; i < NUM_ELEM; i++) { ret = queue_signalled_push(q, (void *) i); @@ -59,7 +61,7 @@ static void * producer(void * ctx) static void * consumer(void * ctx) { int ret; - struct queue_signalled *q = (struct queue_signalled *) ctx; + struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; void *data[NUM_ELEM]; @@ -80,7 +82,7 @@ static void * consumer(void * ctx) void * polled_consumer(void *ctx) { int ret, fd; - struct queue_signalled *q = (struct queue_signalled *) ctx; + struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; fd = queue_signalled_fd(q); cr_assert_geq(fd, 0); @@ -132,11 +134,11 @@ ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, .i { int ret; void *r1, *r2; - struct queue_signalled q; + struct CQueueSignalled q; pthread_t t1, t2; - ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory_heap, param->mode, param->flags); + 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); diff --git a/tests/unit/signal.cpp b/tests/unit/signal.cpp index c8c03544e..128a9a0f6 100644 --- a/tests/unit/signal.cpp +++ b/tests/unit/signal.cpp @@ -1,7 +1,7 @@ /** Unit tests for memory management * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode @@ -22,7 +22,9 @@ #include -#include +#include + +using namespace villas::node; extern void init_memory(); @@ -30,14 +32,14 @@ extern void init_memory(); Test(signal_data, parse, .init = init_memory) { int ret; enum SignalType type; - union signal_data sd; + union SignalData sd; const char *str; char *end; str = "1"; type = SignalType::INTEGER; - ret = signal_data_parse_str(&sd, type, str, &end); + ret = sd.parseString(type, str, &end); cr_assert_eq(ret, 0); cr_assert_eq(end, str + strlen(str)); cr_assert_eq(sd.i, 1); @@ -45,7 +47,7 @@ Test(signal_data, parse, .init = init_memory) { str = "1.2"; type = SignalType::FLOAT; - ret = signal_data_parse_str(&sd, type, str, &end); + 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); @@ -53,7 +55,7 @@ Test(signal_data, parse, .init = init_memory) { str = "1"; type = SignalType::BOOLEAN; - ret = signal_data_parse_str(&sd, type, str, &end); + ret = sd.parseString(type, str, &end); cr_assert_eq(ret, 0); cr_assert_eq(end, str + strlen(str)); cr_assert_eq(sd.b, 1); @@ -61,7 +63,7 @@ Test(signal_data, parse, .init = init_memory) { str = "1"; type = SignalType::COMPLEX; - ret = signal_data_parse_str(&sd, type, str, &end); + 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); @@ -70,7 +72,7 @@ Test(signal_data, parse, .init = init_memory) { str = "-1-3i"; type = SignalType::COMPLEX; - ret = signal_data_parse_str(&sd, type, str, &end); + 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); @@ -79,7 +81,7 @@ Test(signal_data, parse, .init = init_memory) { str = "-3i"; type = SignalType::COMPLEX; - ret = signal_data_parse_str(&sd, type, str, &end); + 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); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index fd5e39d69..ed3a5d3ea 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/docker-dev.sh b/tools/docker-dev.sh index fc7cdbf58..1fc45cec2 100755 --- a/tools/docker-dev.sh +++ b/tools/docker-dev.sh @@ -3,7 +3,7 @@ # Start a Docker based development environment # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/integration-tests.sh b/tools/integration-tests.sh index 7f83e8cd1..f07f79b9a 100755 --- a/tools/integration-tests.sh +++ b/tools/integration-tests.sh @@ -3,7 +3,7 @@ # Run integration tests # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode @@ -35,12 +35,13 @@ export PATH SRCDIR BUILDDIR LOGDIR # Default values VERBOSE=${VERBOSE:-0} +FAIL_FAST=${FAIL_FAST:-0} FILTER=${FILTER:-'*'} NUM_SAMPLES=${NUM_SAMPLES:-100} -TIMEOUT=${TIMEOUT:-2m} +TIMEOUT=${TIMEOUT:-1m} # Parse command line arguments -while getopts ":f:l:t:v" OPT; do +while getopts ":f:l:t:vg" OPT; do case ${OPT} in f) FILTER=${OPTARG} @@ -54,6 +55,9 @@ while getopts ":f:l:t:v" OPT; do t) TIMEOUT=${OPTARG} ;; + g) + FAIL_FAST=1 + ;; \?) echo "Invalid option: -${OPTARG}" >&2 ;; @@ -126,6 +130,10 @@ for TEST in ${TESTS}; do esac TOTAL=$((${TOTAL} + 1)) + + if (( ${RC} != 0 && ${RC} != 99 && ${FAIL_FAST} > 0 )); then + break + fi done # Show summary diff --git a/tools/rmsem.cpp b/tools/rmsem.cpp index cb9355187..9aea5d141 100644 --- a/tools/rmsem.cpp +++ b/tools/rmsem.cpp @@ -1,7 +1,7 @@ /** Delete semaphores. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/tools/rmshm.cpp b/tools/rmshm.cpp index f3e18fb86..2a254134f 100644 --- a/tools/rmshm.cpp +++ b/tools/rmshm.cpp @@ -1,7 +1,7 @@ /** Delete shared memory regions. * * @author Steffen Vogel - * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode diff --git a/tools/tc-dump.sh b/tools/tc-dump.sh index 9df3487d5..3ba807b28 100755 --- a/tools/tc-dump.sh +++ b/tools/tc-dump.sh @@ -3,7 +3,7 @@ # Dump Linux traffic control state to screen. # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/tc-netem.sh b/tools/tc-netem.sh index add3603ce..8bbd6ae1e 100755 --- a/tools/tc-netem.sh +++ b/tools/tc-netem.sh @@ -5,7 +5,7 @@ # Dependencies: iptables, ebtables and iproute2 # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/tc-netem2.sh b/tools/tc-netem2.sh index 7a6fc6cc7..b56165962 100755 --- a/tools/tc-netem2.sh +++ b/tools/tc-netem2.sh @@ -5,7 +5,7 @@ # Dependencies: iptables, ebtables and iproute2 # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/villas b/tools/villas index c5e27c0b4..81b92bd80 100755 --- a/tools/villas +++ b/tools/villas @@ -8,7 +8,7 @@ # $ make install # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode diff --git a/tools/villas-helper.sh b/tools/villas-helper.sh index c01c7375d..628979c64 100755 --- a/tools/villas-helper.sh +++ b/tools/villas-helper.sh @@ -3,7 +3,7 @@ # Some helper functions for our integration test suite # # @author Steffen Vogel -# @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2014-2021, Institute for Automation of Complex Power Systems, EONERC # @license GNU General Public License (version 3) # # VILLASnode