mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-15 17:41:45 +00:00
Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d105960444 | ||
|
3aae5bae58 | ||
|
9031029d2c | ||
|
d478e050ba | ||
|
06b2b9b01f | ||
|
b3fa4f6e7e | ||
|
da5cb34416 | ||
|
226733c653 | ||
|
b06efc401e | ||
|
2500771689 | ||
|
d2aa3b6bb0 | ||
|
00df117c7c | ||
|
69faa63c5b | ||
|
b7474ae138 | ||
|
b426bf39d7 | ||
|
6780b7452c | ||
|
27277b11b4 | ||
|
cb5029f826 | ||
|
5d45d89269 | ||
|
eb9ddc81cf | ||
|
f5891d5ae3 | ||
|
3b2ad1f6f4 | ||
|
fa0bf96eb2 | ||
|
29827f0426 | ||
|
8efe7adf0e | ||
|
b747a8787c | ||
|
1a75141fc4 | ||
|
2f82eb4f09 | ||
|
92a56c26bc | ||
|
4f9aeda8ec | ||
|
ad894c79cf | ||
|
5f33401d41 | ||
|
f4d39d224b | ||
|
bfd08bb33f | ||
|
f15f669853 | ||
|
f6bade32bb | ||
|
ddf9bc7272 | ||
|
f79a0714b4 | ||
|
c04958e2a4 | ||
|
692576a5b1 | ||
|
eb4620b1ec | ||
|
9f9583eb55 | ||
|
08ba068791 | ||
|
1839f7e8c0 | ||
|
80ed45df63 | ||
|
eef42d2dea | ||
|
d630fbb1e4 | ||
|
acfb495411 | ||
|
953c4a75c8 | ||
|
f24dee33c2 | ||
|
856780f88a | ||
|
dbdf17c661 | ||
|
a3bb5fb4b0 | ||
|
0eaea3c66f |
86
.zenodo.json
Normal file
86
.zenodo.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"creators": [
|
||||
{
|
||||
"name": "Al-Turany, Mohammad"
|
||||
},
|
||||
{
|
||||
"orcid": "0000-0003-3787-1910",
|
||||
"name": "Klein, Dennis"
|
||||
},
|
||||
{
|
||||
"name": "Kollegger, Thorsten"
|
||||
},
|
||||
{
|
||||
"name": "Rybalchenko, Alexey"
|
||||
},
|
||||
{
|
||||
"name": "Winckler, Nicolas"
|
||||
}
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Aphecetche, Laurent"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Binet, Sebastien"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Eulisse, Giulio"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Karabowicz, Radoslaw"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Kretz, Matthias"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Krzewicki, Mikolaj"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Lebedev, Andrey"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Mrnjavac, Teo"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Neskovic, Gvozden"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Richter, Matthias"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"orcid": "0000-0002-5321-8404",
|
||||
"name": "Tacke, Christian"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Uhlig, Florian"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Wenzel, Sandro"
|
||||
}
|
||||
],
|
||||
"description": "<p>C++ Message Queuing Library and Framework</p>",
|
||||
"related_identifiers": [
|
||||
{
|
||||
"identifier": "https://github.com/FairRootGroup/FairMQ/",
|
||||
"relation": "isSupplementTo",
|
||||
"resource_type": "software",
|
||||
"scheme": "url"
|
||||
}
|
||||
],
|
||||
"title": "FairMQ",
|
||||
"license": "LGPL-3.0-only"
|
||||
}
|
2
AUTHORS
2
AUTHORS
@@ -1,5 +1,5 @@
|
||||
Al-Turany, Mohammad
|
||||
Klein, Dennis
|
||||
Klein, Dennis [https://orcid.org/0000-0003-3787-1910]
|
||||
Kollegger, Thorsten
|
||||
Rybalchenko, Alexey
|
||||
Winckler, Nicolas
|
||||
|
@@ -1,5 +1,5 @@
|
||||
################################################################################
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# Project ######################################################################
|
||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
cmake_policy(VERSION 3.15...3.20)
|
||||
cmake_policy(VERSION 3.15...3.22)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
include(GitHelper)
|
||||
|
@@ -3,11 +3,11 @@ Binet, Sebastien
|
||||
Eulisse, Giulio
|
||||
Karabowicz, Radoslaw
|
||||
Kretz, Matthias <kretz@kde.org>
|
||||
Krzewicki, Mikolaj
|
||||
Krzewicki, Mikolaj
|
||||
Lebedev, Andrey
|
||||
Mrnjavac, Teo <teo.m@cern.ch>
|
||||
Neskovic, Gvozden
|
||||
Richter, Matthias
|
||||
Tacke, Christian
|
||||
Tacke, Christian [https://orcid.org/0000-0002-5321-8404]
|
||||
Uhlig, Florian
|
||||
Wenzel, Sandro
|
||||
|
10
COPYRIGHT
10
COPYRIGHT
@@ -4,19 +4,19 @@ Upstream-Contact: Mohammad Al-Turany <m.al-turany@gsi.de>
|
||||
Source: https://github.com/FairRootGroup/FairMQ
|
||||
|
||||
Files: *
|
||||
Copyright: 2012-2021, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
Copyright: 2012-2021, [see AUTHORS file]
|
||||
Copyright: 2012-2021, [see CONTRIBUTORS file]
|
||||
Copyright: 2012-2022, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
Copyright: 2012-2022, [see AUTHORS file]
|
||||
Copyright: 2012-2022, [see CONTRIBUTORS file]
|
||||
Comment: The copyright of individual contributors is documented in the
|
||||
Git history.
|
||||
License: LGPL-3.0-only
|
||||
|
||||
Files: extern/googletest
|
||||
Copyright: 2008-2021, Google Inc.
|
||||
Copyright: 2008-2022, Google Inc.
|
||||
License: GOOGLE
|
||||
|
||||
Files: extern/asio
|
||||
Copyright: 2003-2021, Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
Copyright: 2003-2022, Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
License: BSL-1.0
|
||||
|
||||
Files: extern/PicoSHA2
|
||||
|
@@ -72,6 +72,9 @@ endif()
|
||||
if(ENABLE_SANITIZER_THREAD)
|
||||
list(APPEND options "-DENABLE_SANITIZER_THREAD=ON")
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER)
|
||||
list(APPEND options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
if(CMAKE_CXX_FLAGS)
|
||||
list(APPEND options "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
6
Jenkinsfile
vendored
6
Jenkinsfile
vendored
@@ -15,9 +15,9 @@ def jobMatrix(String type, List specs) {
|
||||
ver = spec.ver
|
||||
} else { // == 'check'
|
||||
job = "${spec.name}"
|
||||
selector = 'fedora-34-x86_64'
|
||||
selector = 'fedora-35-x86_64'
|
||||
os = 'fedora'
|
||||
ver = '34'
|
||||
ver = '35'
|
||||
}
|
||||
|
||||
def label = "${job}"
|
||||
@@ -96,6 +96,7 @@ pipeline{
|
||||
[os: 'fedora', ver: '32', arch: 'x86_64', compiler: 'gcc-10', extra: all],
|
||||
[os: 'fedora', ver: '33', arch: 'x86_64', compiler: 'gcc-10', extra: all],
|
||||
[os: 'fedora', ver: '34', arch: 'x86_64', compiler: 'gcc-11', extra: all],
|
||||
[os: 'fedora', ver: '35', arch: 'x86_64', compiler: 'gcc-11', extra: all],
|
||||
[os: 'macos', ver: '11', arch: 'x86_64', compiler: 'apple-clang-12', extra: '-DHAS_ASIO=ON'],
|
||||
[os: 'macos', ver: '11', arch: 'arm64', compiler: 'apple-clang-13', extra: '-DHAS_ASIO=ON'],
|
||||
])
|
||||
@@ -106,6 +107,7 @@ pipeline{
|
||||
[name: 'static-analyzers', extra: "${all_debug} -DRUN_STATIC_ANALYSIS=ON"],
|
||||
[name: '{address,leak,ub}-sanitizers',
|
||||
extra: "${all_debug} -DENABLE_SANITIZER_ADDRESS=ON -DENABLE_SANITIZER_LEAK=ON -DENABLE_SANITIZER_UNDEFINED_BEHAVIOUR=ON -DCMAKE_CXX_FLAGS='-O1 -fno-omit-frame-pointer'"],
|
||||
[name: 'thread-sanitizer', extra: "${all_debug} -DENABLE_SANITIZER_THREAD=ON -DCMAKE_CXX_COMPILER=clang++"],
|
||||
])
|
||||
|
||||
parallel(builds + checks)
|
||||
|
32
README.md
32
README.md
@@ -1,12 +1,9 @@
|
||||
<!-- {#mainpage} -->
|
||||
# FairMQ [](COPYRIGHT) [](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [](https://scan.coverity.com/projects/fairrootgroup-fairmq)
|
||||
# FairMQ [](COPYRIGHT)
|
||||
|
||||
C++ Message Queuing Library and Framework
|
||||
|
||||
| Release | Version | Docs |
|
||||
| :---: | :--- | :--- |
|
||||
| `stable` | [](https://github.com/FairRootGroup/FairMQ/releases/latest) | [API](https://fairrootgroup.github.io/FairMQ/latest), [Book](https://github.com/FairRootGroup/FairMQ/blob/master/README.md#documentation) |
|
||||
| `testing` | [](https://github.com/FairRootGroup/FairMQ/tags) | [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation) |
|
||||
Docs: [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation)
|
||||
|
||||
Find all FairMQ releases [here](https://github.com/FairRootGroup/FairMQ/releases).
|
||||
|
||||
@@ -24,11 +21,13 @@ FairMQ provides multiple implementations for its API (so-called "transports",
|
||||
e.g. `zeromq`, `shmem` and `ofi` (in development)) to cover a variety of use cases
|
||||
(e.g. inter-thread, inter-process, inter-node communication) and machines (e.g. Ethernet, Infiniband).
|
||||
In addition to this core functionality FairMQ provides a framework for creating "devices" - actors which
|
||||
are communicating through message passing. FairMQ does not only allow the user to use different transport but also to mix them; i.e: A Device can communicate using different transport on different channels at the same time. Device execution is modelled as a simple state machine that
|
||||
shapes the integration points for the user task. Devices also incorporate a plugin system for runtime configuration and control.
|
||||
Next to the provided devices and plugins (e.g. [DDS](https://github.com/FairRootGroup/DDS))
|
||||
the user can extend FairMQ by developing his own plugins to integrate his devices with external
|
||||
configuration and control services.
|
||||
are communicating through message passing. FairMQ does not only allow the user to use different transport
|
||||
but also to mix them; i.e: A Device can communicate using different transport on different channels at the
|
||||
same time. Device execution is modelled as a simple state machine that shapes the integration points for
|
||||
the user task. Devices also incorporate a plugin system for runtime configuration and control.
|
||||
Next to the provided [devices](https://github.com/FairRootGroup/FairMQ/tree/master/fairmq/devices) and
|
||||
[plugins](https://github.com/FairRootGroup/FairMQ/tree/master/fairmq/plugins) the user can extend FairMQ
|
||||
by developing his own plugins to integrate his devices with external configuration and control services.
|
||||
|
||||
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
|
||||
a simulation, reconstruction and analysis framework.
|
||||
@@ -47,14 +46,15 @@ cmake --build fairmq_build --target install
|
||||
|
||||
Please consult the [manpages of your CMake version](https://cmake.org/cmake/help/latest/manual/cmake.1.html) for more options.
|
||||
|
||||
If dependencies are not installed in standard system directories, you can hint the installation location via `-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...`. `{DEPENDENCY}` can be `GTEST`, `BOOST`, `FAIRLOGGER`, `ZEROMQ`, `OFI`, `PMIX`, `ASIO`, `ASIOFI` or `DDS` (`*_ROOT` variables can also be environment variables).
|
||||
If dependencies are not installed in standard system directories, you can hint the installation location via
|
||||
`-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...` (`*_ROOT` variables can also be environment variables).
|
||||
|
||||
## Usage
|
||||
|
||||
FairMQ ships as a CMake package, so in your `CMakeLists.txt` you can discover it like this:
|
||||
|
||||
```cmake
|
||||
find_package(FairCMakeModules 0.2 REQUIRED)
|
||||
find_package(FairCMakeModules 1.0 REQUIRED)
|
||||
include(FairFindPackage2)
|
||||
find_package2(FairMQ)
|
||||
find_package2_implicit_dependencies()
|
||||
@@ -71,14 +71,14 @@ list(PREPEND CMAKE_PREFIX_PATH /path/to/fairmq_install)
|
||||
Optionally, you can require certain FairMQ package components and a minimum version:
|
||||
|
||||
```cmake
|
||||
find_package(FairMQ 1.4.0 COMPONENTS dds_plugin)
|
||||
find_package(FairMQ 1.4.50 COMPONENTS ofi_transport)
|
||||
```
|
||||
|
||||
When building FairMQ, CMake will print a summary table of all available package components.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [asio](https://github.com/chriskohlhoff/asio) (optionally bundled)
|
||||
* [asio](https://github.com/chriskohlhoff/asio)
|
||||
* [asiofi](https://github.com/FairRootGroup/asiofi)
|
||||
* [Boost](https://www.boost.org/)
|
||||
* [CMake](https://cmake.org/)
|
||||
@@ -86,13 +86,14 @@ When building FairMQ, CMake will print a summary table of all available package
|
||||
* [Doxygen](http://www.doxygen.org/)
|
||||
* [FairCMakeModules](https://github.com/FairRootGroup/FairCMakeModules) (optionally bundled)
|
||||
* [FairLogger](https://github.com/FairRootGroup/FairLogger)
|
||||
* [Flatbuffers](https://google.github.io/flatbuffers/)
|
||||
* [GTest](https://github.com/google/googletest) (optionally bundled)
|
||||
* [PMIx](https://pmix.org/)
|
||||
* [ZeroMQ](http://zeromq.org/)
|
||||
|
||||
Which dependencies are required depends on which components are built.
|
||||
|
||||
Supported platforms: Linux and MacOS.
|
||||
Supported platform is Linux. macOS is supported on a best-effort basis.
|
||||
|
||||
## CMake options
|
||||
|
||||
@@ -102,7 +103,6 @@ On command line:
|
||||
* `-DBUILD_TESTING=OFF` disables building of tests.
|
||||
* `-DBUILD_EXAMPLES=OFF` disables building of examples.
|
||||
* `-DBUILD_OFI_TRANSPORT=ON` enables building of the experimental OFI transport.
|
||||
* `-DBUILD_DDS_PLUGIN=ON` enables building of the DDS plugin.
|
||||
* `-DBUILD_PMIX_PLUGIN=ON` enables building of the PMIx plugin.
|
||||
* `-DBUILD_DOCS=ON` enables building of API docs.
|
||||
* You can hint non-system installations for dependent packages, see the #installation-from-source section above
|
||||
|
@@ -34,9 +34,9 @@ macro(fairmq_summary_components)
|
||||
endif()
|
||||
message(STATUS " ${BWhite}ofi_transport${CR} ${ofi_summary}")
|
||||
if(BUILD_DDS_PLUGIN)
|
||||
set(dds_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_DDS_PLUGIN=OFF${CR})")
|
||||
set(dds_summary "${BGreen}YES${CR} DEPRECATED (disable with ${BMagenta}-DBUILD_DDS_PLUGIN=OFF${CR})")
|
||||
else()
|
||||
set(dds_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_DDS_PLUGIN=ON${CR})")
|
||||
set(dds_summary "${BRed} NO${CR} DEPRECATED (default, enable with ${BMagenta}-DBUILD_DDS_PLUGIN=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}")
|
||||
if(BUILD_PMIX_PLUGIN)
|
||||
@@ -58,15 +58,15 @@ macro(fairmq_summary_components)
|
||||
endif()
|
||||
message(STATUS " ${BWhite}docs${CR} ${docs_summary}")
|
||||
if(BUILD_SDK)
|
||||
set(sdk_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})")
|
||||
set(sdk_summary "${BGreen}YES${CR} DEPRECATED (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})")
|
||||
else()
|
||||
set(sdk_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})")
|
||||
set(sdk_summary "${BRed} NO${CR} DEPRECATED (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}")
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
set(sdk_commands_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_SDK_COMMANDS=OFF${CR})")
|
||||
set(sdk_commands_summary "${BGreen}YES${CR} DEPRECATED (disable with ${BMagenta}-DBUILD_SDK_COMMANDS=OFF${CR})")
|
||||
else()
|
||||
set(sdk_commands_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_SDK_COMMANDS=ON${CR})")
|
||||
set(sdk_commands_summary "${BRed} NO${CR} DEPRECATED (default, enable with ${BMagenta}-DBUILD_SDK_COMMANDS=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}")
|
||||
if(BUILD_TIDY_TOOL)
|
||||
@@ -75,6 +75,21 @@ macro(fairmq_summary_components)
|
||||
set(sdk_tidy_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_TIDY_TOOL=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}tidy_tool${CR} ${sdk_tidy_summary}")
|
||||
|
||||
set(_deprecated)
|
||||
if(BUILD_SDK)
|
||||
list(APPEND _deprecated sdk)
|
||||
endif()
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
list(APPEND _deprecated sdk_commands)
|
||||
endif()
|
||||
if(BUILD_DDS_PLUGIN)
|
||||
list(APPEND _deprecated dds_plugin)
|
||||
endif()
|
||||
list(JOIN _deprecated ", " _deprecated)
|
||||
if(_deprecated)
|
||||
message(DEPRECATION "You have selected to build deprecated components '${_deprecated}' which will be removed in a future release. See https://github.com/FairRootGroup/FairMQ/discussions/392 for more information. Use '-Wno-deprecated' to silence deprecation warnings.")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(fairmq_summary_static_analysis)
|
||||
|
@@ -18,7 +18,8 @@
|
||||
{
|
||||
"@type": "Person",
|
||||
"givenName": "Dennis",
|
||||
"familyName": "Klein"
|
||||
"familyName": "Klein",
|
||||
"@id": "https://orcid.org/0000-0003-3787-1910"
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
@@ -92,7 +93,8 @@
|
||||
{
|
||||
"@type": "Person",
|
||||
"givenName": "Christian",
|
||||
"familyName": "Tacke"
|
||||
"familyName": "Tacke",
|
||||
"@id": "https://orcid.org/0000-0002-5321-8404"
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
|
@@ -26,7 +26,6 @@ Here is an overview of the device/channel options and when they are applied:
|
||||
| `transport` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `network-interface` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `init-timeout` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `max-run-time` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `shm-segment-size` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `shm-monitor` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `ofi-size-hint` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
|
@@ -23,10 +23,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-1.sh.in ${CMAKE_CUR
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh)
|
||||
|
||||
add_test(NAME Example.1-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh zeromq)
|
||||
set_tests_properties(Example.1-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
set_tests_properties(Example.1-1.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
add_test(NAME Example.1-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh shmem)
|
||||
set_tests_properties(Example.1-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
set_tests_properties(Example.1-1.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -30,7 +30,7 @@ struct Sampler : fair::mq::Device
|
||||
// create message object with a pointer to the data buffer, its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
FairMQMessagePtr msg(NewMessage(
|
||||
fair::mq::MessagePtr msg(NewMessage(
|
||||
const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
|
@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
@@ -8,20 +8,23 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; rm $chanAddr' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-1-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --rate 1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://*:5555,rateLogging=0"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,address=ipc://$chanAddr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -29,13 +32,16 @@ SINK="fairmq-ex-1-1-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://localhost:5555,rateLogging=0"
|
||||
SINK+=" --channel-config name=$chan,type=pull,method=connect,address=ipc://$chanAddr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
# wait for sampler and sink to finish
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
rm $chanAddr
|
||||
|
@@ -29,10 +29,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-1-n-1.json ${CMAKE_CURRENT_BINARY_
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-n-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh)
|
||||
|
||||
add_test(NAME Example.1-n-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh zeromq)
|
||||
set_tests_properties(Example.1-n-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
set_tests_properties(Example.1-n-1.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
add_test(NAME Example.1-n-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh shmem)
|
||||
set_tests_properties(Example.1-n-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
set_tests_properties(Example.1-n-1.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
|
||||
OnData("data1", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received data, processing...";
|
||||
|
||||
@@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
|
||||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
FairMQMessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
fair::mq::MessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
text));
|
||||
|
@@ -28,7 +28,7 @@ struct Sampler : fair::mq::Device
|
||||
{
|
||||
// Initializing message with NewStaticMessage will avoid copy
|
||||
// but won't delete the data after the sending is completed.
|
||||
FairMQMessagePtr msg(NewStaticMessage(fText));
|
||||
fair::mq::MessagePtr msg(NewStaticMessage(fText));
|
||||
|
||||
LOG(info) << "Sending \"" << fText << "\"";
|
||||
|
||||
|
@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
@@ -8,20 +8,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
ex2config="@CMAKE_CURRENT_BINARY_DIR@/ex-1-n-1.json"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan1="data1"
|
||||
chan2="data2"
|
||||
chan1Addr="/tmp/fmq_$session""_""$chan1""_""$transport"
|
||||
chan2Addr="/tmp/fmq_$session""_""$chan2""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $PROCESSOR1_PID; kill -TERM $PROCESSOR2_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $PROCESSOR1_PID; wait $PROCESSOR2_PID;' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $PROCESSOR1_PID; kill -TERM $PROCESSOR2_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $PROCESSOR1_PID; wait $PROCESSOR2_PID; rm $chan1Addr; rm $chan2Addr' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-1-n-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 2"
|
||||
SAMPLER+=" --mq-config $ex2config"
|
||||
SAMPLER+=" --channel-config name=$chan1,type=push,method=bind,address=ipc://$chan1Addr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -29,10 +34,12 @@ PROCESSOR1="fairmq-ex-1-n-1-processor"
|
||||
PROCESSOR1+=" --id processor1"
|
||||
PROCESSOR1+=" --transport $transport"
|
||||
PROCESSOR1+=" --verbosity veryhigh"
|
||||
PROCESSOR1+=" --session $SESSION"
|
||||
PROCESSOR1+=" --session $session"
|
||||
PROCESSOR1+=" --severity debug"
|
||||
PROCESSOR1+=" --shm-segment-size 100000000"
|
||||
PROCESSOR1+=" --control static --color false"
|
||||
PROCESSOR1+=" --mq-config $ex2config"
|
||||
PROCESSOR1+=" --config-key processor"
|
||||
PROCESSOR1+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
|
||||
PROCESSOR1+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR1 &
|
||||
PROCESSOR1_PID=$!
|
||||
|
||||
@@ -40,10 +47,12 @@ PROCESSOR2="fairmq-ex-1-n-1-processor"
|
||||
PROCESSOR2+=" --id processor2"
|
||||
PROCESSOR2+=" --transport $transport"
|
||||
PROCESSOR2+=" --verbosity veryhigh"
|
||||
PROCESSOR2+=" --session $SESSION"
|
||||
PROCESSOR2+=" --session $session"
|
||||
PROCESSOR2+=" --severity debug"
|
||||
PROCESSOR2+=" --shm-segment-size 100000000"
|
||||
PROCESSOR2+=" --control static --color false"
|
||||
PROCESSOR2+=" --mq-config $ex2config"
|
||||
PROCESSOR2+=" --config-key processor"
|
||||
PROCESSOR2+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
|
||||
PROCESSOR2+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR2 &
|
||||
PROCESSOR2_PID=$!
|
||||
|
||||
@@ -51,10 +60,12 @@ SINK="fairmq-ex-1-n-1-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 2"
|
||||
SINK+=" --mq-config $ex2config"
|
||||
SINK+=" --channel-config name=$chan2,type=pull,method=bind,address=ipc://$chan2Addr,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
@@ -69,3 +80,5 @@ kill -SIGINT $PROCESSOR2_PID
|
||||
# wait for everything to finish
|
||||
wait $PROCESSOR1_PID
|
||||
wait $PROCESSOR2_PID
|
||||
|
||||
rm $chan1Addr; rm $chan2Addr
|
||||
|
@@ -15,16 +15,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-builtin-devices.sh.in
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-builtin-devices.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh)
|
||||
|
||||
add_test(NAME Example.BuiltinDevices.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq)
|
||||
set_tests_properties(Example.BuiltinDevices.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
set_tests_properties(Example.BuiltinDevices.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
|
||||
add_test(NAME Example.BuiltinDevices.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem)
|
||||
set_tests_properties(Example.BuiltinDevices.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
set_tests_properties(Example.BuiltinDevices.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
|
||||
add_test(NAME Example.BuiltinDevices.multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq true 2)
|
||||
set_tests_properties(Example.BuiltinDevices.multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
set_tests_properties(Example.BuiltinDevices.multipart.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
|
||||
add_test(NAME Example.BuiltinDevices.multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem true 2)
|
||||
set_tests_properties(Example.BuiltinDevices.multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
set_tests_properties(Example.BuiltinDevices.multipart.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
transport="zeromq"
|
||||
multipart="false"
|
||||
numParts="1"
|
||||
@@ -20,8 +18,22 @@ if [[ $3 =~ ^[0-9]+$ ]]; then
|
||||
numParts=$3
|
||||
fi
|
||||
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan1="data1"
|
||||
chan2="data2"
|
||||
chan3="data3"
|
||||
chan4="data4"
|
||||
chan5="data5"
|
||||
chan1Addr="/tmp/fmq_$session""_""$chan1""_""$transport"
|
||||
chan2Addr1="/tmp/fmq_$session""_""$chan2""_1""_""$transport"
|
||||
chan2Addr2="/tmp/fmq_$session""_""$chan2""_2""_""$transport"
|
||||
chan3Addr1="/tmp/fmq_$session""_""$chan3""_1""_""$transport"
|
||||
chan3Addr2="/tmp/fmq_$session""_""$chan3""_2""_""$transport"
|
||||
chan4Addr="/tmp/fmq_$session""_""$chan4""_""$transport"
|
||||
chan5Addr="/tmp/fmq_$session""_""$chan5""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SPLITTER_PID; kill -TERM $PROXY1_PID; kill -TERM $PROXY2_PID; kill -TERM $MERGER_PID; kill -TERM $MULTIPLIER_PID; kill -TERM $SINK_PID;' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SPLITTER_PID; kill -TERM $PROXY1_PID; kill -TERM $PROXY2_PID; kill -TERM $MERGER_PID; kill -TERM $MULTIPLIER_PID; kill -TERM $SINK_PID; rm $chan1Addr; rm $chan2Addr1; rm $chan2Addr2; rm $chan3Addr1; rm $chan3Addr2; rm $chan4Addr; rm $chan5Addr' TERM
|
||||
|
||||
SAMPLER="fairmq-bsampler"
|
||||
SAMPLER+=" --id bsampler1"
|
||||
@@ -30,14 +42,15 @@ SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --color false"
|
||||
SAMPLER+=" --control static"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --msg-size 100000"
|
||||
SAMPLER+=" --multipart $multipart"
|
||||
SAMPLER+=" --num-parts $numParts"
|
||||
SAMPLER+=" --msg-rate 1"
|
||||
SAMPLER+=" --max-iterations 0"
|
||||
SAMPLER+=" --out-channel data1"
|
||||
SAMPLER+=" --channel-config name=data1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555"
|
||||
SAMPLER+=" --out-channel $chan1"
|
||||
SAMPLER+=" --channel-config name=$chan1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
|
||||
@FAIRMQ_BIN_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -48,11 +61,12 @@ SPLITTER+=" --transport $transport"
|
||||
SPLITTER+=" --color false"
|
||||
SPLITTER+=" --control static"
|
||||
SPLITTER+=" --verbosity veryhigh"
|
||||
SPLITTER+=" --shm-segment-size 100000000"
|
||||
SPLITTER+=" --multipart $multipart"
|
||||
SPLITTER+=" --in-channel data1"
|
||||
SPLITTER+=" --out-channel data2"
|
||||
SPLITTER+=" --channel-config name=data1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555"
|
||||
SPLITTER+=" name=data2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556,address=tcp://localhost:5557"
|
||||
SPLITTER+=" --in-channel $chan1"
|
||||
SPLITTER+=" --out-channel $chan2"
|
||||
SPLITTER+=" --channel-config name=$chan1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
|
||||
SPLITTER+=" name=$chan2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1,address=ipc://$chan2Addr2"
|
||||
@FAIRMQ_BIN_DIR@/$SPLITTER &
|
||||
SPLITTER_PID=$!
|
||||
|
||||
@@ -63,11 +77,12 @@ PROXY1+=" --transport $transport"
|
||||
PROXY1+=" --color false"
|
||||
PROXY1+=" --control static"
|
||||
PROXY1+=" --verbosity veryhigh"
|
||||
PROXY1+=" --shm-segment-size 100000000"
|
||||
PROXY1+=" --multipart $multipart"
|
||||
PROXY1+=" --in-channel data2"
|
||||
PROXY1+=" --out-channel data3"
|
||||
PROXY1+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556"
|
||||
PROXY1+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558"
|
||||
PROXY1+=" --in-channel $chan2"
|
||||
PROXY1+=" --out-channel $chan3"
|
||||
PROXY1+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1"
|
||||
PROXY1+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1"
|
||||
@FAIRMQ_BIN_DIR@/$PROXY1 &
|
||||
PROXY1_PID=$!
|
||||
|
||||
@@ -78,11 +93,12 @@ PROXY2+=" --transport $transport"
|
||||
PROXY2+=" --color false"
|
||||
PROXY2+=" --control static"
|
||||
PROXY2+=" --verbosity veryhigh"
|
||||
PROXY2+=" --shm-segment-size 100000000"
|
||||
PROXY2+=" --multipart $multipart"
|
||||
PROXY2+=" --in-channel data2"
|
||||
PROXY2+=" --out-channel data3"
|
||||
PROXY2+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5557"
|
||||
PROXY2+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5559"
|
||||
PROXY2+=" --in-channel $chan2"
|
||||
PROXY2+=" --out-channel $chan3"
|
||||
PROXY2+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr2"
|
||||
PROXY2+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr2"
|
||||
@FAIRMQ_BIN_DIR@/$PROXY2 &
|
||||
PROXY2_PID=$!
|
||||
|
||||
@@ -93,11 +109,12 @@ MERGER+=" --transport $transport"
|
||||
MERGER+=" --color false"
|
||||
MERGER+=" --control static"
|
||||
MERGER+=" --verbosity veryhigh"
|
||||
MERGER+=" --shm-segment-size 100000000"
|
||||
MERGER+=" --multipart $multipart"
|
||||
MERGER+=" --in-channel data3"
|
||||
MERGER+=" --out-channel data4"
|
||||
MERGER+=" --channel-config name=data3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558,address=tcp://localhost:5559"
|
||||
MERGER+=" name=data4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560"
|
||||
MERGER+=" --in-channel $chan3"
|
||||
MERGER+=" --out-channel $chan4"
|
||||
MERGER+=" --channel-config name=$chan3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1,address=ipc://$chan3Addr2"
|
||||
MERGER+=" name=$chan4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
|
||||
@FAIRMQ_BIN_DIR@/$MERGER &
|
||||
MERGER_PID=$!
|
||||
|
||||
@@ -108,11 +125,12 @@ MULTIPLIER+=" --transport $transport"
|
||||
MULTIPLIER+=" --color false"
|
||||
MULTIPLIER+=" --control static"
|
||||
MULTIPLIER+=" --verbosity veryhigh"
|
||||
MULTIPLIER+=" --shm-segment-size 100000000"
|
||||
MULTIPLIER+=" --multipart $multipart"
|
||||
MULTIPLIER+=" --in-channel data4"
|
||||
MULTIPLIER+=" --out-channel data5"
|
||||
MULTIPLIER+=" --channel-config name=data4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560"
|
||||
MULTIPLIER+=" name=data5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561,address=tcp://localhost:5561"
|
||||
MULTIPLIER+=" --in-channel $chan4"
|
||||
MULTIPLIER+=" --out-channel $chan5"
|
||||
MULTIPLIER+=" --channel-config name=$chan4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
|
||||
MULTIPLIER+=" name=$chan5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr,address=ipc://$chan5Addr"
|
||||
@FAIRMQ_BIN_DIR@/$MULTIPLIER &
|
||||
MULTIPLIER_PID=$!
|
||||
|
||||
@@ -126,8 +144,8 @@ SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --multipart $multipart"
|
||||
SINK+=" --max-iterations 2"
|
||||
SINK+=" --in-channel data5"
|
||||
SINK+=" --channel-config name=data5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561"
|
||||
SINK+=" --in-channel $chan5"
|
||||
SINK+=" --channel-config name=$chan5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr"
|
||||
@FAIRMQ_BIN_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
@@ -146,3 +164,5 @@ wait $PROXY1_PID
|
||||
wait $PROXY2_PID
|
||||
wait $MERGER_PID
|
||||
wait $MULTIPLIER_PID
|
||||
|
||||
rm $chan1Addr; rm $chan2Addr1; rm $chan2Addr2; rm $chan3Addr1; rm $chan3Addr2; rm $chan4Addr; rm $chan5Addr
|
||||
|
@@ -24,10 +24,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-copypush.sh.in ${CMAK
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-copypush.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh)
|
||||
|
||||
add_test(NAME Example.CopyPush.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh zeromq)
|
||||
set_tests_properties(Example.CopyPush.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
set_tests_properties(Example.CopyPush.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
|
||||
add_test(NAME Example.CopyPush.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh shmem)
|
||||
set_tests_properties(Example.CopyPush.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
set_tests_properties(Example.CopyPush.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -19,7 +19,7 @@ struct Sampler : fair::mq::Device
|
||||
{
|
||||
void InitTask() override
|
||||
{
|
||||
fNumDataChannels = fChannels.at("data").size();
|
||||
fNumDataChannels = GetNumSubChannels("data");
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ struct Sampler : fair::mq::Device
|
||||
{
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fCounter++));
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fCounter++));
|
||||
|
||||
for (int i = 0; i < fNumDataChannels - 1; ++i) {
|
||||
FairMQMessagePtr msgCopy(NewMessage());
|
||||
fair::mq::MessagePtr msgCopy(NewMessage());
|
||||
msgCopy->Copy(*msg);
|
||||
Send(msgCopy, "data", i);
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received message: \"" << *(static_cast<uint64_t*>(msg->GetData())) << "\"";
|
||||
|
||||
|
@@ -8,19 +8,24 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr1="/tmp/fmq_$session""_""$chan""_1""_""$transport"
|
||||
chanAddr2="/tmp/fmq_$session""_""$chan""_2""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK1_PID; kill -TERM $SINK2_PID; wait $SAMPLER_PID; wait $SINK1_PID; wait $SINK2_PID;' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK1_PID; kill -TERM $SINK2_PID; wait $SAMPLER_PID; wait $SINK1_PID; wait $SINK2_PID; rm $chanAddr1; rm $chanAddr2' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-copypush-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,rateLogging=0,address=tcp://*:5555,address=tcp://*:5556"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,rateLogging=0,address=ipc://$chanAddr1,address=ipc://$chanAddr2"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -28,10 +33,12 @@ SINK1="fairmq-ex-copypush-sink"
|
||||
SINK1+=" --id sink1"
|
||||
SINK1+=" --transport $transport"
|
||||
SINK1+=" --verbosity veryhigh"
|
||||
SINK1+=" --session $SESSION"
|
||||
SINK1+=" --severity debug"
|
||||
SINK1+=" --shm-segment-size 100000000"
|
||||
SINK1+=" --session $session"
|
||||
SINK1+=" --control static --color false"
|
||||
SINK1+=" --max-iterations 1"
|
||||
SINK1+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5555"
|
||||
SINK1+=" --channel-config name=$chan,type=pull,method=connect,rateLogging=0,address=ipc://$chanAddr1"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK1 &
|
||||
SINK1_PID=$!
|
||||
|
||||
@@ -39,10 +46,12 @@ SINK2="fairmq-ex-copypush-sink"
|
||||
SINK2+=" --id sink2"
|
||||
SINK2+=" --transport $transport"
|
||||
SINK2+=" --verbosity veryhigh"
|
||||
SINK2+=" --session $SESSION"
|
||||
SINK2+=" --severity debug"
|
||||
SINK2+=" --shm-segment-size 100000000"
|
||||
SINK2+=" --session $session"
|
||||
SINK2+=" --control static --color false"
|
||||
SINK2+=" --max-iterations 1"
|
||||
SINK2+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5556"
|
||||
SINK2+=" --channel-config name=$chan,type=pull,method=connect,rateLogging=0,address=ipc://$chanAddr2"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK2 &
|
||||
SINK2_PID=$!
|
||||
|
||||
@@ -50,3 +59,5 @@ SINK2_PID=$!
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK1_PID
|
||||
wait $SINK2_PID
|
||||
|
||||
rm $chanAddr1; rm $chanAddr2
|
||||
|
@@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
|
||||
OnData("data1", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received data, processing...";
|
||||
|
||||
@@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
|
||||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
FairMQMessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
fair::mq::MessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
text));
|
||||
|
@@ -24,7 +24,7 @@ struct Sampler : fair::mq::Device
|
||||
{
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
FairMQMessagePtr msg(NewSimpleMessage("Data"));
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage("Data"));
|
||||
|
||||
LOG(info) << "Sending \"Data\"";
|
||||
|
||||
|
@@ -25,7 +25,7 @@ struct Sink : fair::mq::Device
|
||||
fIterations = fConfig->GetValue<uint64_t>("iterations");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
@@ -23,14 +23,14 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multipart.sh.in ${CMA
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh)
|
||||
|
||||
add_test(NAME Example.Multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh zeromq)
|
||||
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
|
||||
add_test(NAME Example.Multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh shmem)
|
||||
set_tests_properties(Example.Multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
set_tests_properties(Example.Multipart.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
add_test(NAME Example.Multipart.ofi COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh ofi)
|
||||
set_tests_properties(Example.Multipart.ofi PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
set_tests_properties(Example.Multipart.ofi PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
endif()
|
||||
|
||||
# install
|
||||
|
@@ -5,7 +5,7 @@ A topology of two devices - Sampler and Sink, communicating with PUSH-PULL patte
|
||||
|
||||
The Sampler sends a multipart message to the Sink, consisting of two message parts - header and body.
|
||||
|
||||
Each message part is a regular FairMQMessage. To combine them into a multi-part message use `FairMQParts`. Add messages to `FairMQParts` with `AddPart` method.
|
||||
Each message part is a regular fair::mq::Message. To combine them into a multi-part message use `fair::mq::Parts`. Add messages to `fair::mq::Parts` with `AddPart` method.
|
||||
|
||||
All parts are guaranteed to be delivered together. The Receive call in the sink will recive the entire parts structure.
|
||||
|
||||
|
@@ -35,15 +35,15 @@ struct Sampler : fair::mq::Device
|
||||
}
|
||||
LOG(info) << "Sending header with stopFlag: " << header.stopFlag;
|
||||
|
||||
FairMQParts parts;
|
||||
fair::mq::Parts parts;
|
||||
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
parts.AddPart(NewSimpleMessage(header));
|
||||
parts.AddPart(NewMessage(1000));
|
||||
|
||||
// create more data parts, testing the FairMQParts in-place constructor
|
||||
FairMQParts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
|
||||
// create more data parts, testing the fair::mq::Parts in-place constructor
|
||||
fair::mq::Parts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
|
||||
assert(auxData.Size() == 3);
|
||||
parts.AddPart(std::move(auxData));
|
||||
assert(auxData.Size() == 0);
|
||||
|
@@ -20,7 +20,7 @@ struct Sink : fair::mq::Device
|
||||
OnData("data", &Sink::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQParts& parts, int)
|
||||
bool HandleData(fair::mq::Parts& parts, int)
|
||||
{
|
||||
LOG(info) << "Received message with " << parts.Size() << " parts";
|
||||
|
||||
|
@@ -8,19 +8,28 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr=""
|
||||
chanIpcFile="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
if [ $transport = "ofi" ]; then
|
||||
chanAddr="tcp://127.0.0.1:5656"
|
||||
else
|
||||
chanAddr="ipc://""$chanIpcFile"
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; rm $chanIpcFile' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-multipart-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --channel-config name=data,type=pair,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555,linger=1000"
|
||||
SAMPLER+=" --channel-config name=$chan,type=pair,method=connect,rateLogging=0,address=$chanAddr,linger=1000"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -28,11 +37,14 @@ SINK="fairmq-ex-multipart-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --channel-config name=data,type=pair,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
|
||||
SINK+=" --channel-config name=$chan,type=pair,method=bind,rateLogging=0,address=$chanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
rm $chanIpcFile
|
||||
|
@@ -26,7 +26,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-channels.sh.
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-channels.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh)
|
||||
|
||||
add_test(NAME Example.MultipleChannels.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh zeromq)
|
||||
set_tests_properties(Example.MultipleChannels.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
set_tests_properties(Example.MultipleChannels.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -5,4 +5,4 @@ This example demonstrates how to work with multiple channels and multiplex betwe
|
||||
|
||||
A topology of three devices - **Sampler**, **Sink** and **Broadcaster**. The Sampler sends data to the Sink via the PUSH-PULL pattern. The Broadcaster device sends a message to both Sampler and Sink containing a string "OK" every second. The Broadcaster sends the message via PUB pattern. Both Sampler and Sink, besides doing their PUSH-PULL job, listen via SUB to the Broadcaster.
|
||||
|
||||
The multiplexing between their data channels and the broadcast channels happens with `FairMQPoller`.
|
||||
The multiplexing between their data channels and the broadcast channels happens with `fair::mq::Poller`.
|
||||
|
@@ -22,7 +22,7 @@ struct Broadcaster : fair::mq::Device
|
||||
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
FairMQMessagePtr msg(NewSimpleMessage("OK"));
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage("OK"));
|
||||
|
||||
LOG(info) << "Sending OK";
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include <fairmq/Device.h>
|
||||
#include <FairMQPoller.h>
|
||||
#include <fairmq/Poller.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
|
||||
#include <chrono>
|
||||
@@ -26,13 +26,13 @@ struct Sampler : fair::mq::Device
|
||||
|
||||
void Run() override
|
||||
{
|
||||
FairMQPollerPtr poller(NewPoller("data", "broadcast"));
|
||||
fair::mq::PollerPtr poller(NewPoller("data", "broadcast"));
|
||||
|
||||
while (!NewStatePending()) {
|
||||
poller->Poll(100);
|
||||
|
||||
if (poller->CheckInput("broadcast", 0)) {
|
||||
FairMQMessagePtr msg(NewMessage());
|
||||
fair::mq::MessagePtr msg(NewMessage());
|
||||
|
||||
if (Receive(msg, "broadcast") > 0) {
|
||||
LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
@@ -42,7 +42,7 @@ struct Sampler : fair::mq::Device
|
||||
if (poller->CheckOutput("data", 0)) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fText));
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fText));
|
||||
|
||||
if (Send(msg, "data") > 0) {
|
||||
LOG(info) << "Sent \"" << fText << "\"";
|
||||
|
@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleBroadcast(FairMQMessagePtr& msg, int /*index*/)
|
||||
bool HandleBroadcast(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
{
|
||||
LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
fReceivedBroadcast = true;
|
||||
@@ -35,7 +35,7 @@ struct Sink : fair::mq::Device
|
||||
return CheckIterations();
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
{
|
||||
LOG(info) << "Received message: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
fReceivedData = true;
|
||||
|
@@ -8,18 +8,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $BROADCASTER_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $BROADCASTER_PID;' TERM
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
dataChan="data"
|
||||
broadcastChan="broadcast"
|
||||
dataChanAddr="/tmp/fmq_$session""_""$dataChan""_""$transport"
|
||||
broadcastChanAddr="/tmp/fmq_$session""_""$broadcastChan""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $BROADCASTER_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $BROADCASTER_PID; rm $dataChanAddr; rm $broadcastChanAddr' TERM
|
||||
|
||||
SINK="fairmq-ex-multiple-channels-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --verbosity veryhigh --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5555"
|
||||
SINK+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005"
|
||||
SINK+=" --channel-config name=$dataChan,type=pull,method=connect,rateLogging=0,address=ipc://$dataChanAddr"
|
||||
SINK+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
@@ -27,21 +34,25 @@ sleep 1
|
||||
|
||||
SAMPLER="fairmq-ex-multiple-channels-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,rateLogging=0,address=tcp://*:5555"
|
||||
SAMPLER+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005"
|
||||
SAMPLER+=" --channel-config name=$dataChan,type=push,method=bind,rateLogging=0,address=ipc://$dataChanAddr"
|
||||
SAMPLER+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
BROADCASTER="fairmq-ex-multiple-channels-broadcaster"
|
||||
BROADCASTER+=" --id broadcaster1"
|
||||
BROADCASTER+=" --session $session"
|
||||
BROADCASTER+=" --transport $transport"
|
||||
BROADCASTER+=" --verbosity veryhigh"
|
||||
BROADCASTER+=" --verbosity veryhigh --severity debug"
|
||||
BROADCASTER+=" --shm-segment-size 100000000"
|
||||
BROADCASTER+=" --control static --color false"
|
||||
BROADCASTER+=" --channel-config name=broadcast,type=pub,method=bind,rateLogging=0,address=tcp://*:5005"
|
||||
BROADCASTER+=" --channel-config name=$broadcastChan,type=pub,method=bind,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$BROADCASTER &
|
||||
BROADCASTER_PID=$!
|
||||
|
||||
@@ -53,3 +64,5 @@ kill -SIGINT $BROADCASTER_PID
|
||||
|
||||
# wait for broadcaster to finish
|
||||
wait $BROADCASTER_PID
|
||||
|
||||
rm $dataChanAddr; rm $broadcastChanAddr
|
||||
|
@@ -25,7 +25,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-transports.s
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
|
||||
add_test(NAME Example.MultipleTransports COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
|
||||
set_tests_properties(Example.MultipleTransports PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
set_tests_properties(Example.MultipleTransports PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -28,7 +28,7 @@ struct Sampler1 : fair::mq::Device
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
// Creates a message using the transport of channel data1
|
||||
FairMQMessagePtr msg(NewMessageFor("data1", 0, 1000000));
|
||||
fair::mq::MessagePtr msg(NewMessageFor("data1", 0, 1000000));
|
||||
|
||||
// in case of error or transfer interruption, return false to go to IDLE state
|
||||
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
|
||||
@@ -54,7 +54,7 @@ struct Sampler1 : fair::mq::Device
|
||||
uint64_t numAcks = 0;
|
||||
|
||||
while (!NewStatePending()) {
|
||||
FairMQMessagePtr ack(NewMessageFor("ack", 0));
|
||||
fair::mq::MessagePtr ack(NewMessageFor("ack", 0));
|
||||
if (Receive(ack, "ack") < 0) {
|
||||
break;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ struct Sampler2 : fair::mq::Device
|
||||
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
FairMQMessagePtr msg(NewMessage(1000));
|
||||
fair::mq::MessagePtr msg(NewMessage(1000));
|
||||
|
||||
// in case of error or transfer interruption, return false to go to IDLE state
|
||||
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
|
||||
|
@@ -26,11 +26,11 @@ struct Sink : fair::mq::Device
|
||||
}
|
||||
|
||||
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
|
||||
bool HandleData1(FairMQMessagePtr& /*msg*/, int /*index*/)
|
||||
bool HandleData1(fair::mq::MessagePtr& /*msg*/, int /*index*/)
|
||||
{
|
||||
fNumIterations1++;
|
||||
// Creates a message using the transport of channel ack
|
||||
FairMQMessagePtr ack(NewMessageFor("ack", 0));
|
||||
fair::mq::MessagePtr ack(NewMessageFor("ack", 0));
|
||||
if (Send(ack, "ack") < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ struct Sink : fair::mq::Device
|
||||
}
|
||||
|
||||
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
|
||||
bool HandleData2(FairMQMessagePtr& /*msg*/, int /*index*/)
|
||||
bool HandleData2(fair::mq::MessagePtr& /*msg*/, int /*index*/)
|
||||
{
|
||||
fNumIterations2++;
|
||||
// return true if want to be called again (otherwise go to IDLE state)
|
||||
|
@@ -2,46 +2,57 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan1="data1"
|
||||
chan2="data2"
|
||||
ackChan="ack"
|
||||
chan1Addr="/tmp/fmq_$session""_""$chan1"
|
||||
chan2Addr="/tmp/fmq_$session""_""$chan2"
|
||||
ackChanAddr="/tmp/fmq_$session""_""$ackChan"
|
||||
|
||||
trap 'kill -TERM $SAMPLER1_PID; kill -TERM $SAMPLER2_PID; kill -TERM $SINK_PID; wait $SAMPLER1_PID; wait $SAMPLER2_PID; wait $SINK_PID; @CMAKE_BINARY_DIR@/fairmq/fairmq-shmmonitor --cleanup --session $SESSION;' TERM
|
||||
trap 'kill -TERM $SAMPLER1_PID; kill -TERM $SAMPLER2_PID; kill -TERM $SINK_PID; wait $SAMPLER1_PID; wait $SAMPLER2_PID; wait $SINK_PID; @CMAKE_BINARY_DIR@/fairmq/fairmq-shmmonitor --cleanup --session $SESSION; rm $chan1Addr; rm $chan2Addr; rm $ackChanAddr' TERM
|
||||
|
||||
SINK="fairmq-ex-multiple-transports-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --verbosity veryhigh --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --transport shmem"
|
||||
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
|
||||
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=zeromq"
|
||||
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
|
||||
SINK+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr"
|
||||
SINK+=" name=$chan2,type=pull,method=connect,address=ipc://$chan2Addr,transport=zeromq"
|
||||
SINK+=" name=$ackChan,type=pub,method=connect,address=ipc://$ackChanAddr,transport=zeromq"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
SAMPLER1="fairmq-ex-multiple-transports-sampler1"
|
||||
SAMPLER1+=" --id sampler1"
|
||||
SAMPLER1+=" --session $SESSION"
|
||||
SAMPLER1+=" --verbosity veryhigh"
|
||||
SAMPLER1+=" --session $session"
|
||||
SAMPLER1+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER1+=" --shm-segment-size 100000000"
|
||||
SAMPLER1+=" --max-iterations 1"
|
||||
SAMPLER1+=" --control static --color false"
|
||||
SAMPLER1+=" --transport shmem"
|
||||
SAMPLER1+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:5555"
|
||||
SAMPLER1+=" name=ack,type=sub,method=bind,address=tcp://127.0.0.1:5557,transport=zeromq"
|
||||
SAMPLER1+=" --channel-config name=$chan1,type=push,method=bind,address=ipc://$chan1Addr"
|
||||
SAMPLER1+=" name=$ackChan,type=sub,method=bind,address=ipc://$ackChanAddr,transport=zeromq"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER1 &
|
||||
SAMPLER1_PID=$!
|
||||
|
||||
SAMPLER2="fairmq-ex-multiple-transports-sampler2"
|
||||
SAMPLER2+=" --id sampler2"
|
||||
SAMPLER2+=" --session $SESSION"
|
||||
SAMPLER2+=" --verbosity veryhigh"
|
||||
SAMPLER2+=" --session $session"
|
||||
SAMPLER2+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER2+=" --shm-segment-size 100000000"
|
||||
SAMPLER2+=" --max-iterations 1"
|
||||
SAMPLER2+=" --control static --color false"
|
||||
SAMPLER2+=" --transport zeromq"
|
||||
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
|
||||
SAMPLER2+=" --channel-config name=$chan2,type=push,method=bind,address=ipc://$chan2Addr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 &
|
||||
SAMPLER2_PID=$!
|
||||
|
||||
wait $SAMPLER1_PID
|
||||
wait $SAMPLER2_PID
|
||||
wait $SINK_PID
|
||||
|
||||
rm $chan1Addr; rm $chan2Addr; rm $ackChanAddr
|
||||
|
@@ -24,7 +24,7 @@ namespace bpo = boost::program_options;
|
||||
|
||||
struct TFBuffer
|
||||
{
|
||||
FairMQParts parts;
|
||||
fair::mq::Parts parts;
|
||||
chrono::steady_clock::time_point start;
|
||||
chrono::steady_clock::time_point end;
|
||||
};
|
||||
@@ -43,7 +43,7 @@ struct Receiver : fair::mq::Device
|
||||
fMaxTimeframes = GetConfig()->GetValue<int>("max-timeframes");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQParts& parts, int /* index */)
|
||||
bool HandleData(fair::mq::Parts& parts, int /* index */)
|
||||
{
|
||||
Header& h = *(static_cast<Header*>(parts.At(0)->GetData()));
|
||||
// LOG(info) << "Received sub-time frame #" << h.id << " from Sender" << h.senderIndex;
|
||||
@@ -107,7 +107,7 @@ void addCustomOptions(bpo::options_description& options)
|
||||
("max-timeframes", bpo::value<int>()->default_value(0), "Maximum number of timeframes to receive (0 - unlimited)");
|
||||
}
|
||||
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Receiver>();
|
||||
}
|
||||
|
@@ -28,11 +28,11 @@ struct Sender : fair::mq::Device
|
||||
|
||||
void Run() override
|
||||
{
|
||||
FairMQChannel& dataInChannel = fChannels.at("sync").at(0);
|
||||
fair::mq::Channel& dataInChannel = GetChannel("sync", 0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
Header h;
|
||||
FairMQMessagePtr id(NewMessage());
|
||||
fair::mq::MessagePtr id(NewMessage());
|
||||
if (dataInChannel.Receive(id) > 0) {
|
||||
h.id = *(static_cast<uint16_t*>(id->GetData()));
|
||||
h.senderIndex = fIndex;
|
||||
@@ -40,7 +40,7 @@ struct Sender : fair::mq::Device
|
||||
continue;
|
||||
}
|
||||
|
||||
FairMQParts parts;
|
||||
fair::mq::Parts parts;
|
||||
parts.AddPart(NewSimpleMessage(h));
|
||||
parts.AddPart(NewMessage(fSubtimeframeSize));
|
||||
|
||||
@@ -66,7 +66,7 @@ void addCustomOptions(bpo::options_description& options)
|
||||
("subtimeframe-size", bpo::value<int>()->default_value(1000), "Subtimeframe size in bytes")
|
||||
("num-receivers", bpo::value<int>()->required(), "Number of EPNs");
|
||||
}
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Sender>();
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ struct Synchronizer : fair::mq::Device
|
||||
{
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fTimeframeId));
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fTimeframeId));
|
||||
|
||||
if (Send(msg, "sync") > 0) {
|
||||
if (++fTimeframeId == UINT16_MAX - 1) {
|
||||
@@ -37,7 +37,7 @@ struct Synchronizer : fair::mq::Device
|
||||
};
|
||||
|
||||
void addCustomOptions(bpo::options_description& /* options */) {}
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Synchronizer>();
|
||||
}
|
||||
|
@@ -30,10 +30,10 @@ struct QCDispatcher : fair::mq::Device
|
||||
});
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
{
|
||||
if (fDoQC.load() == true) {
|
||||
FairMQMessagePtr msgCopy(NewMessage());
|
||||
fair::mq::MessagePtr msgCopy(NewMessage());
|
||||
msgCopy->Copy(*msg);
|
||||
if (Send(msg, "qc") < 0) {
|
||||
return false;
|
||||
|
@@ -9,12 +9,12 @@
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
|
||||
class QCTask : public FairMQDevice
|
||||
class QCTask : public fair::mq::Device
|
||||
{
|
||||
public:
|
||||
QCTask()
|
||||
{
|
||||
OnData("qc", [](FairMQMessagePtr& /*msg*/, int) {
|
||||
OnData("qc", [](fair::mq::MessagePtr& /*msg*/, int) {
|
||||
LOG(info) << "received data";
|
||||
return false;
|
||||
});
|
||||
|
@@ -16,7 +16,7 @@ struct Sampler : fair::mq::Device
|
||||
{
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
FairMQMessagePtr msg(NewMessage(1000));
|
||||
fair::mq::MessagePtr msg(NewMessage(1000));
|
||||
|
||||
if (Send(msg, "data1") < 0) {
|
||||
return false;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
struct Sink : fair::mq::Device
|
||||
{
|
||||
Sink() { OnData("data2", &Sink::HandleData); }
|
||||
bool HandleData(FairMQMessagePtr& /*msg*/, int /*index*/) { return true; }
|
||||
bool HandleData(fair::mq::MessagePtr& /*msg*/, int /*index*/) { return true; }
|
||||
};
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
class Builder : public FairMQDevice
|
||||
class Builder : public fair::mq::Device
|
||||
{
|
||||
public:
|
||||
Builder() = default;
|
||||
@@ -24,7 +24,7 @@ class Builder : public FairMQDevice
|
||||
OnData("rb", &Builder::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
{
|
||||
if (Send(msg, fOutputChannelName) < 0) {
|
||||
return false;
|
||||
|
@@ -18,9 +18,9 @@ struct Processor : fair::mq::Device
|
||||
OnData("bp", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
{
|
||||
FairMQMessagePtr msg2(NewMessageFor("ps", 0, msg->GetSize()));
|
||||
fair::mq::MessagePtr msg2(NewMessageFor("ps", 0, msg->GetSize()));
|
||||
if (Send(msg2, "ps") < 0) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ struct Readout : fair::mq::Device
|
||||
fMsgSize = fConfig->GetProperty<int>("msg-size");
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
|
||||
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
|
||||
fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
|
||||
0,
|
||||
10000000,
|
||||
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
|
||||
@@ -36,7 +36,7 @@ struct Readout : fair::mq::Device
|
||||
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
FairMQMessagePtr msg(NewMessageFor("rb", // channel
|
||||
fair::mq::MessagePtr msg(NewMessageFor("rb", // channel
|
||||
0, // sub-channel
|
||||
fRegion, // region
|
||||
fRegion->GetData(), // ptr within region
|
||||
@@ -71,7 +71,7 @@ struct Readout : fair::mq::Device
|
||||
int fMsgSize = 10000;
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
FairMQUnmanagedRegionPtr fRegion = nullptr;
|
||||
fair::mq::UnmanagedRegionPtr fRegion = nullptr;
|
||||
std::atomic<uint64_t> fNumUnackedMsgs = 0;
|
||||
};
|
||||
|
||||
|
@@ -26,7 +26,7 @@ struct Receiver : Device
|
||||
|
||||
void Run() override
|
||||
{
|
||||
Channel& dataInChannel = fChannels.at("sr").at(0);
|
||||
Channel& dataInChannel = GetChannel("sr", 0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
auto msg(dataInChannel.NewMessage());
|
||||
|
@@ -21,7 +21,7 @@ struct Sender : fair::mq::Device
|
||||
OnData(fInputChannelName, &Sender::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
{
|
||||
if (Send(msg, "sr") < 0) {
|
||||
return false;
|
||||
|
@@ -12,7 +12,10 @@ target_link_libraries(fairmq-ex-region-sampler PRIVATE FairMQ)
|
||||
add_executable(fairmq-ex-region-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-region-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleRegion DEPENDS fairmq-ex-region-sampler fairmq-ex-region-sink)
|
||||
add_executable(fairmq-ex-region-keep-alive keep-alive.cxx)
|
||||
target_link_libraries(fairmq-ex-region-keep-alive PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleRegion DEPENDS fairmq-ex-region-sampler fairmq-ex-region-sink fairmq-ex-region-keep-alive)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
@@ -23,10 +26,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-region.sh.in ${CMAKE_
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh)
|
||||
|
||||
add_test(NAME Example.Region.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh zeromq)
|
||||
set_tests_properties(Example.Region.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
|
||||
set_tests_properties(Example.Region.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
|
||||
|
||||
add_test(NAME Example.Region.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh shmem)
|
||||
set_tests_properties(Example.Region.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
|
||||
set_tests_properties(Example.Region.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
|
||||
|
||||
# install
|
||||
|
||||
|
221
examples/region/keep-alive.cxx
Normal file
221
examples/region/keep-alive.cxx
Normal file
@@ -0,0 +1,221 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
#include <fairmq/shmem/Common.h>
|
||||
#include <fairmq/shmem/Monitor.h>
|
||||
#include <fairmq/shmem/Segment.h>
|
||||
#include <fairmq/shmem/UnmanagedRegion.h>
|
||||
#include <fairmq/tools/Unique.h>
|
||||
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::program_options;
|
||||
|
||||
namespace {
|
||||
volatile sig_atomic_t gStopping = 0;
|
||||
volatile sig_atomic_t gResetContent = 0;
|
||||
} // namespace
|
||||
|
||||
void signalHandler(int /* signal */) { gStopping = 1; }
|
||||
|
||||
void resetContentHandler(int /* signal */) { gResetContent = 1; }
|
||||
|
||||
struct ShmManager
|
||||
{
|
||||
ShmManager(uint64_t _shmId, const vector<string>& _segments, const vector<string>& _regions, bool zero = true)
|
||||
: shmId(fair::mq::shmem::makeShmIdStr(_shmId))
|
||||
{
|
||||
LOG(info) << "Starting ShmManager for shmId: " << shmId;
|
||||
LOG(info) << "Performing full reset...";
|
||||
FullReset();
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Adding managed segments...";
|
||||
AddSegments(_segments, zero);
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Adding unmanaged regions...";
|
||||
AddRegions(_regions, zero);
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Shared memory is ready for use.";
|
||||
}
|
||||
|
||||
void AddSegments(const vector<string>& _segments, bool zero)
|
||||
{
|
||||
for (const auto& s : _segments) {
|
||||
vector<string> conf;
|
||||
boost::algorithm::split(conf, s, boost::algorithm::is_any_of(","));
|
||||
if (conf.size() != 3) {
|
||||
LOG(error) << "incorrect format for --segments. Expecting pairs of <id>,<size><numaid>.";
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
throw runtime_error("incorrect format for --segments. Expecting pairs of <id>,<size>,<numaid>.");
|
||||
}
|
||||
uint16_t id = stoi(conf.at(0));
|
||||
uint64_t size = stoull(conf.at(1));
|
||||
segmentCfgs.emplace_back(fair::mq::shmem::SegmentConfig{id, size, "rbtree_best_fit"});
|
||||
|
||||
auto ret = segments.emplace(id, fair::mq::shmem::Segment(shmId, id, size, fair::mq::shmem::rbTreeBestFit));
|
||||
fair::mq::shmem::Segment& segment = ret.first->second;
|
||||
LOG(info) << "Created segment " << id << " of size " << segment.GetSize()
|
||||
<< ", starting at " << segment.GetData() << ". Locking...";
|
||||
segment.Lock();
|
||||
LOG(info) << "Done.";
|
||||
if (zero) {
|
||||
LOG(info) << "Zeroing...";
|
||||
segment.Zero();
|
||||
LOG(info) << "Done.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddRegions(const vector<string>& _regions, bool zero)
|
||||
{
|
||||
for (const auto& r : _regions) {
|
||||
vector<string> conf;
|
||||
boost::algorithm::split(conf, r, boost::algorithm::is_any_of(","));
|
||||
if (conf.size() != 3) {
|
||||
LOG(error) << "incorrect format for --regions. Expecting pairs of <id>,<size>,<numaid>.";
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
throw runtime_error("incorrect format for --regions. Expecting pairs of <id>,<size>,<numaid>.");
|
||||
}
|
||||
uint16_t id = stoi(conf.at(0));
|
||||
uint64_t size = stoull(conf.at(1));
|
||||
fair::mq::RegionConfig cfg;
|
||||
cfg.id = id;
|
||||
cfg.size = size;
|
||||
regionCfgs.push_back(cfg);
|
||||
|
||||
auto ret = regions.emplace(id, make_unique<fair::mq::shmem::UnmanagedRegion>(shmId, id, size));
|
||||
fair::mq::shmem::UnmanagedRegion& region = *(ret.first->second);
|
||||
LOG(info) << "Created unamanged region " << id << " of size " << region.GetSize()
|
||||
<< ", starting at " << region.GetData() << ". Locking...";
|
||||
region.Lock();
|
||||
LOG(info) << "Done.";
|
||||
if (zero) {
|
||||
LOG(info) << "Zeroing...";
|
||||
region.Zero();
|
||||
LOG(info) << "Done.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckPresence()
|
||||
{
|
||||
for (const auto& sc : segmentCfgs) {
|
||||
if (!(fair::mq::shmem::Monitor::SegmentIsPresent(fair::mq::shmem::ShmId{shmId}, sc.id))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const auto& rc : regionCfgs) {
|
||||
if (!(fair::mq::shmem::Monitor::RegionIsPresent(fair::mq::shmem::ShmId{shmId}, rc.id.value()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetContent()
|
||||
{
|
||||
fair::mq::shmem::Monitor::ResetContent(fair::mq::shmem::ShmId{shmId}, segmentCfgs, regionCfgs);
|
||||
}
|
||||
|
||||
void FullReset()
|
||||
{
|
||||
segments.clear();
|
||||
regions.clear();
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
}
|
||||
|
||||
~ShmManager()
|
||||
{
|
||||
// clean all segments, regions and any other shmem objects belonging to this shmId
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
}
|
||||
|
||||
std::string shmId;
|
||||
map<uint16_t, fair::mq::shmem::Segment> segments;
|
||||
map<uint16_t, unique_ptr<fair::mq::shmem::UnmanagedRegion>> regions;
|
||||
std::vector<fair::mq::shmem::SegmentConfig> segmentCfgs;
|
||||
std::vector<fair::mq::RegionConfig> regionCfgs;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
fair::Logger::SetConsoleColor(true);
|
||||
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
signal(SIGUSR1, resetContentHandler);
|
||||
|
||||
try {
|
||||
bool nozero = false;
|
||||
bool checkPresence = true;
|
||||
uint64_t shmId = 0;
|
||||
vector<string> segments;
|
||||
vector<string> regions;
|
||||
|
||||
options_description desc("Options");
|
||||
desc.add_options()
|
||||
("shmid", value<uint64_t>(&shmId)->required(), "Shm id")
|
||||
("segments", value<vector<string>>(&segments)->multitoken()->composing(), "Segments, as <id>,<size>,<numaid> <id>,<size>,<numaid> <id>,<size>,<numaid> ... (numaid: -2 disabled, -1 interleave, >=0 node)")
|
||||
("regions", value<vector<string>>(®ions)->multitoken()->composing(), "Regions, as <id>,<size> <id>,<size>,<numaid> <id>,<size>,<numaid> ...")
|
||||
("nozero", value<bool>(&nozero)->default_value(false)->implicit_value(true), "Do not zero segments after initialization")
|
||||
("check-presence", value<bool>(&checkPresence)->default_value(true)->implicit_value(true), "Check periodically if configured segments/regions are still present, and cleanup and leave if they are not")
|
||||
("help,h", "Print help");
|
||||
|
||||
variables_map vm;
|
||||
store(parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
LOG(info) << "ShmManager" << "\n" << desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
notify(vm);
|
||||
|
||||
ShmManager shmManager(shmId, segments, regions, !nozero);
|
||||
|
||||
std::thread resetContentThread([&shmManager]() {
|
||||
while (!gStopping) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
if (gResetContent == 1) {
|
||||
LOG(info) << "Resetting content for shmId " << shmManager.shmId;
|
||||
shmManager.ResetContent();
|
||||
gResetContent = 0;
|
||||
LOG(info) << "Done resetting content for shmId " << shmManager.shmId;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (checkPresence) {
|
||||
while (!gStopping) {
|
||||
if (shmManager.CheckPresence() == false) {
|
||||
LOG(error) << "Failed to find segments, exiting.";
|
||||
gStopping = true;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
}
|
||||
|
||||
resetContentThread.join();
|
||||
|
||||
LOG(info) << "stopping.";
|
||||
} catch (exception& e) {
|
||||
LOG(error) << "Exception reached the top of main: " << e.what() << ", exiting";
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -23,7 +23,7 @@ struct Sampler : fair::mq::Device
|
||||
fLinger = fConfig->GetProperty<uint32_t>("region-linger");
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
|
||||
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) {
|
||||
GetChannel("data", 0).Transport()->SubscribeToRegionEvents([](fair::mq::RegionInfo info) {
|
||||
LOG(info) << "Region event: " << info.event << ": "
|
||||
<< (info.managed ? "managed" : "unmanaged")
|
||||
<< ", id: " << info.id
|
||||
@@ -32,27 +32,25 @@ struct Sampler : fair::mq::Device
|
||||
<< ", flags: " << info.flags;
|
||||
});
|
||||
|
||||
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data", // region is created using the transport of this channel...
|
||||
fair::mq::RegionConfig regionCfg;
|
||||
regionCfg.linger = fLinger; // delay in ms before region destruction to collect outstanding events
|
||||
regionCfg.lock = true; // mlock region after creation
|
||||
regionCfg.zero = true; // zero region content after creation
|
||||
fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor("data", // region is created using the transport of this channel...
|
||||
0, // ... and this sub-channel
|
||||
10000000, // region size
|
||||
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fNumUnackedMsgs -= blocks.size();
|
||||
|
||||
if (fMaxIterations > 0) {
|
||||
LOG(info) << "Received " << blocks.size() << " acks";
|
||||
}
|
||||
},
|
||||
"", // path, if a region is backed by a file
|
||||
0, // flags that are passed for region creation
|
||||
fair::mq::RegionConfig{true, true} // additional config: { call mlock on the region, zero the region memory }
|
||||
));
|
||||
fRegion->SetLinger(fLinger);
|
||||
}, regionCfg));
|
||||
}
|
||||
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
FairMQMessagePtr msg(NewMessageFor("data", // channel
|
||||
fair::mq::MessagePtr msg(NewMessageFor("data", // channel
|
||||
0, // sub-channel
|
||||
fRegion, // region
|
||||
fRegion->GetData(), // ptr within region
|
||||
@@ -78,6 +76,8 @@ struct Sampler : fair::mq::Device
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
// give some time for acks to be received
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
fRegion.reset();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
@@ -87,7 +87,7 @@ struct Sampler : fair::mq::Device
|
||||
LOG(info) << "All acknowledgements received.";
|
||||
}
|
||||
}
|
||||
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
|
||||
GetChannel("data", 0).Transport()->UnsubscribeFromRegionEvents();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -95,7 +95,7 @@ struct Sampler : fair::mq::Device
|
||||
uint32_t fLinger = 100;
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
FairMQUnmanagedRegionPtr fRegion = nullptr;
|
||||
fair::mq::UnmanagedRegionPtr fRegion = nullptr;
|
||||
std::mutex fMtx;
|
||||
uint64_t fNumUnackedMsgs = 0;
|
||||
};
|
||||
|
@@ -22,7 +22,7 @@ struct Sink : Device
|
||||
{
|
||||
// Get the fMaxIterations value from the command line options (via fConfig)
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](RegionInfo info) {
|
||||
GetChannel("data", 0).Transport()->SubscribeToRegionEvents([](RegionInfo info) {
|
||||
LOG(info) << "Region event: " << info.event << ": "
|
||||
<< (info.managed ? "managed" : "unmanaged") << ", id: " << info.id
|
||||
<< ", ptr: " << info.ptr << ", size: " << info.size
|
||||
@@ -32,7 +32,7 @@ struct Sink : Device
|
||||
|
||||
void Run() override
|
||||
{
|
||||
Channel& dataInChannel = fChannels.at("data").at(0);
|
||||
Channel& dataInChannel = GetChannel("data", 0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
auto msg(dataInChannel.Transport()->CreateMessage());
|
||||
@@ -51,7 +51,7 @@ struct Sink : Device
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
|
||||
GetChannel("data", 0).Transport()->UnsubscribeFromRegionEvents();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -9,22 +9,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
fi
|
||||
|
||||
msgSize="1000000"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; @CMAKE_BINARY_DIR@/fairmq/fairmq-shmmonitor --cleanup --session $SESSION' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; @CMAKE_BINARY_DIR@/fairmq/fairmq-shmmonitor --cleanup --session $SESSION; rm $chanAddr' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --msg-size $msgSize"
|
||||
SAMPLER+=" --region-linger 500"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,address=ipc://$chanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
@@ -32,14 +35,17 @@ SINK="fairmq-ex-region-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
SINK+=" --channel-config name=$chan,type=pull,method=connect,address=ipc://$chanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
# wait for sampler and sink to finish
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
rm $chanAddr
|
||||
|
@@ -24,10 +24,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-req-rep.sh.in ${CMAKE
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-req-rep.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh)
|
||||
|
||||
add_test(NAME Example.ReqRep.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh zeromq)
|
||||
set_tests_properties(Example.ReqRep.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
set_tests_properties(Example.ReqRep.zeromq PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
|
||||
add_test(NAME Example.ReqRep.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh shmem)
|
||||
set_tests_properties(Example.ReqRep.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
set_tests_properties(Example.ReqRep.shmem PROPERTIES TIMEOUT "30" PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -32,11 +32,11 @@ struct Client : fair::mq::Device
|
||||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
FairMQMessagePtr req(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
fair::mq::MessagePtr req(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
text->length(), // size
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
|
||||
text)); // object that manages the data
|
||||
FairMQMessagePtr rep(NewMessage());
|
||||
fair::mq::MessagePtr rep(NewMessage());
|
||||
|
||||
LOG(info) << "Sending \"" << fText << "\" to server.";
|
||||
|
||||
|
@@ -26,7 +26,7 @@ struct Server : fair::mq::Device
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(FairMQMessagePtr& req, int)
|
||||
bool HandleData(fair::mq::MessagePtr& req, int)
|
||||
{
|
||||
LOG(info) << "Received request from client: \"" << std::string(static_cast<char*>(req->GetData()), req->GetSize()) << "\"";
|
||||
|
||||
@@ -34,7 +34,7 @@ struct Server : fair::mq::Device
|
||||
|
||||
LOG(info) << "Sending reply to client.";
|
||||
|
||||
FairMQMessagePtr rep(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
fair::mq::MessagePtr rep(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
text->length(), // size
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
|
||||
text)); // object that manages the data
|
||||
|
@@ -8,19 +8,22 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $CLIENT_PID; kill -TERM $SERVER_PID; wait $CLIENT_PID; wait $SERVER_PID;' TERM
|
||||
trap 'kill -TERM $CLIENT_PID; kill -TERM $SERVER_PID; wait $CLIENT_PID; wait $SERVER_PID; rm $chanAddr' TERM
|
||||
|
||||
CLIENT="fairmq-ex-req-rep-client"
|
||||
CLIENT+=" --id client"
|
||||
CLIENT+=" --transport $transport"
|
||||
CLIENT+=" --verbosity veryhigh"
|
||||
CLIENT+=" --session $SESSION"
|
||||
CLIENT+=" --session $session"
|
||||
CLIENT+=" --shm-segment-size 100000000"
|
||||
CLIENT+=" --control static --color false"
|
||||
CLIENT+=" --max-iterations 1"
|
||||
CLIENT+=" --channel-config name=data,type=req,method=connect,rateLogging=0,address=tcp://127.0.0.1:5005"
|
||||
CLIENT+=" --channel-config name=$chan,type=req,method=connect,rateLogging=0,address=ipc://$chanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$CLIENT &
|
||||
CLIENT_PID=$!
|
||||
|
||||
@@ -28,13 +31,16 @@ SERVER="fairmq-ex-req-rep-server"
|
||||
SERVER+=" --id server"
|
||||
SERVER+=" --transport $transport"
|
||||
SERVER+=" --verbosity veryhigh"
|
||||
SERVER+=" --session $SESSION"
|
||||
SERVER+=" --session $session"
|
||||
SERVER+=" --shm-segment-size 100000000"
|
||||
SERVER+=" --control static --color false"
|
||||
SERVER+=" --max-iterations 1"
|
||||
SERVER+=" --channel-config name=data,type=rep,method=bind,rateLogging=0,address=tcp://127.0.0.1:5005"
|
||||
SERVER+=" --channel-config name=$chan,type=rep,method=bind,rateLogging=0,address=ipc://$chanAddr"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SERVER &
|
||||
SERVER_PID=$!
|
||||
|
||||
# wait for everything to finish
|
||||
wait $CLIENT_PID
|
||||
wait $SERVER_PID
|
||||
|
||||
rm $chanAddr
|
||||
|
@@ -30,6 +30,7 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
|
||||
|
||||
set(TOOLS_PUBLIC_HEADER_FILES
|
||||
tools/CppSTL.h
|
||||
tools/Exceptions.h
|
||||
tools/InstanceLimit.h
|
||||
tools/IO.h
|
||||
tools/Network.h
|
||||
@@ -191,6 +192,9 @@ if(BUILD_FAIRMQ)
|
||||
runDevice.h
|
||||
runFairMQDevice.h
|
||||
shmem/Monitor.h
|
||||
shmem/Common.h
|
||||
shmem/UnmanagedRegion.h
|
||||
shmem/Segment.h
|
||||
)
|
||||
|
||||
set(FAIRMQ_PRIVATE_HEADER_FILES
|
||||
@@ -205,12 +209,10 @@ if(BUILD_FAIRMQ)
|
||||
plugins/control/Control.h
|
||||
shmem/Message.h
|
||||
shmem/Poller.h
|
||||
shmem/UnmanagedRegion.h
|
||||
shmem/UnmanagedRegionImpl.h
|
||||
shmem/Socket.h
|
||||
shmem/TransportFactory.h
|
||||
shmem/Common.h
|
||||
shmem/Manager.h
|
||||
shmem/Region.h
|
||||
zeromq/Common.h
|
||||
zeromq/Context.h
|
||||
zeromq/Message.h
|
||||
@@ -248,6 +250,7 @@ if(BUILD_FAIRMQ)
|
||||
TransportFactory.cxx
|
||||
plugins/config/Config.cxx
|
||||
plugins/control/Control.cxx
|
||||
shmem/Common.cxx
|
||||
shmem/Manager.cxx
|
||||
shmem/Monitor.cxx
|
||||
)
|
||||
@@ -384,7 +387,7 @@ if(BUILD_FAIRMQ)
|
||||
fairmq_target_tidy(TARGET fairmq-splitter)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
|
||||
add_executable(fairmq-shmmonitor shmem/Common.cxx shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
|
||||
target_compile_features(fairmq-shmmonitor PUBLIC cxx_std_17)
|
||||
target_compile_definitions(fairmq-shmmonitor PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
|
||||
if(FAIRMQ_DEBUG_MODE)
|
||||
|
@@ -39,6 +39,8 @@ constexpr int Channel::DefaultSndBufSize;
|
||||
constexpr int Channel::DefaultRcvBufSize;
|
||||
constexpr int Channel::DefaultSndKernelSize;
|
||||
constexpr int Channel::DefaultRcvKernelSize;
|
||||
constexpr int Channel::DefaultSndTimeoutMs;
|
||||
constexpr int Channel::DefaultRcvTimeoutMs;
|
||||
constexpr int Channel::DefaultLinger;
|
||||
constexpr int Channel::DefaultRateLogging;
|
||||
constexpr int Channel::DefaultPortRangeMin;
|
||||
@@ -73,6 +75,8 @@ Channel::Channel(string name, string type, string method, string address, shared
|
||||
, fRcvBufSize(DefaultRcvBufSize)
|
||||
, fSndKernelSize(DefaultSndKernelSize)
|
||||
, fRcvKernelSize(DefaultRcvKernelSize)
|
||||
, fSndTimeoutMs(DefaultSndTimeoutMs)
|
||||
, fRcvTimeoutMs(DefaultRcvTimeoutMs)
|
||||
, fLinger(DefaultLinger)
|
||||
, fRateLogging(DefaultRateLogging)
|
||||
, fPortRangeMin(DefaultPortRangeMin)
|
||||
@@ -97,6 +101,8 @@ Channel::Channel(const string& name, int index, const Properties& properties)
|
||||
fRcvBufSize = GetPropertyOrDefault(properties, string(prefix + "rcvBufSize"), DefaultRcvBufSize);
|
||||
fSndKernelSize = GetPropertyOrDefault(properties, string(prefix + "sndKernelSize"), DefaultSndKernelSize);
|
||||
fRcvKernelSize = GetPropertyOrDefault(properties, string(prefix + "rcvKernelSize"), DefaultRcvKernelSize);
|
||||
fSndTimeoutMs = GetPropertyOrDefault(properties, string(prefix + "sndTimeoutMs"), DefaultSndTimeoutMs);
|
||||
fRcvTimeoutMs = GetPropertyOrDefault(properties, string(prefix + "rcvTimeoutMs"), DefaultRcvTimeoutMs);
|
||||
fLinger = GetPropertyOrDefault(properties, string(prefix + "linger"), DefaultLinger);
|
||||
fRateLogging = GetPropertyOrDefault(properties, string(prefix + "rateLogging"), DefaultRateLogging);
|
||||
fPortRangeMin = GetPropertyOrDefault(properties, string(prefix + "portRangeMin"), DefaultPortRangeMin);
|
||||
@@ -120,6 +126,8 @@ Channel::Channel(const Channel& chan, string newName)
|
||||
, fRcvBufSize(chan.fRcvBufSize)
|
||||
, fSndKernelSize(chan.fSndKernelSize)
|
||||
, fRcvKernelSize(chan.fRcvKernelSize)
|
||||
, fSndTimeoutMs(chan.fSndTimeoutMs)
|
||||
, fRcvTimeoutMs(chan.fRcvTimeoutMs)
|
||||
, fLinger(chan.fLinger)
|
||||
, fRateLogging(chan.fRateLogging)
|
||||
, fPortRangeMin(chan.fPortRangeMin)
|
||||
@@ -146,6 +154,8 @@ Channel& Channel::operator=(const Channel& chan)
|
||||
fRcvBufSize = chan.fRcvBufSize;
|
||||
fSndKernelSize = chan.fSndKernelSize;
|
||||
fRcvKernelSize = chan.fRcvKernelSize;
|
||||
fSndTimeoutMs = chan.fSndTimeoutMs;
|
||||
fRcvTimeoutMs = chan.fRcvTimeoutMs;
|
||||
fLinger = chan.fLinger;
|
||||
fRateLogging = chan.fRateLogging;
|
||||
fPortRangeMin = chan.fPortRangeMin;
|
||||
|
114
fairmq/Channel.h
114
fairmq/Channel.h
@@ -166,6 +166,14 @@ class Channel
|
||||
/// @return Returns socket kernel transmit receive buffer size (in bytes)
|
||||
int GetRcvKernelSize() const { return fRcvKernelSize; }
|
||||
|
||||
/// Get socket default send timeout (in ms)
|
||||
/// @return Returns socket default send timeout (in ms)
|
||||
int GetSndTimeout() const { return fSndTimeoutMs; }
|
||||
|
||||
/// Get socket default receive timeout (in ms)
|
||||
/// @return Returns socket default receive timeout (in ms)
|
||||
int GetRcvTimeout() const { return fRcvTimeoutMs; }
|
||||
|
||||
/// Get linger duration (in milliseconds)
|
||||
/// @return Returns linger duration (in milliseconds)
|
||||
int GetLinger() const { return fLinger; }
|
||||
@@ -230,6 +238,14 @@ class Channel
|
||||
/// @param rcvKernelSize Socket receive buffer size (in bytes)
|
||||
void UpdateRcvKernelSize(int rcvKernelSize) { fRcvKernelSize = rcvKernelSize; Invalidate(); }
|
||||
|
||||
/// Set socket default send timeout (in ms)
|
||||
/// @param sndTimeoutMs Socket default send timeout (in ms)
|
||||
void UpdateSndTimeout(int sndTimeoutMs) { fSndTimeoutMs = sndTimeoutMs; Invalidate(); }
|
||||
|
||||
/// Set socket default receive timeout (in ms)
|
||||
/// @param rcvTimeoutMs Socket default receive timeout (in ms)
|
||||
void UpdateRcvTimeout(int rcvTimeoutMs) { fRcvTimeoutMs = rcvTimeoutMs; Invalidate(); }
|
||||
|
||||
/// Set linger duration (in milliseconds)
|
||||
/// @param duration linger duration (in milliseconds)
|
||||
void UpdateLinger(int duration) { fLinger = duration; Invalidate(); }
|
||||
@@ -267,62 +283,52 @@ class Channel
|
||||
/// invalidates the channel (requires validation to be used again).
|
||||
void Invalidate() { fValid = false; }
|
||||
|
||||
/// Sends a message to the socket queue.
|
||||
/// @param msg Constant reference of unique_ptr to a Message
|
||||
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of bytes that have been queued, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Send(MessagePtr& msg, int sndTimeoutInMs = -1)
|
||||
/// Send message(s) to the socket queue.
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param sndTimeoutMs send timeout in ms.
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot send).
|
||||
/// If not provided, default timeout will be taken.
|
||||
/// @return Number of bytes that have been queued,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M, typename... Timeout>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, Timeout&&... sndTimeoutMs)
|
||||
{
|
||||
CheckSendCompatibility(msg);
|
||||
return fSocket->Send(msg, sndTimeoutInMs);
|
||||
static_assert(sizeof...(sndTimeoutMs) <= 1, "Send called with too many arguments");
|
||||
|
||||
CheckSendCompatibility(m);
|
||||
int t = fSndTimeoutMs;
|
||||
if constexpr (sizeof...(sndTimeoutMs) == 1) {
|
||||
t = {sndTimeoutMs...};
|
||||
}
|
||||
return fSocket->Send(m, t);
|
||||
}
|
||||
|
||||
/// Receives a message from the socket queue.
|
||||
/// @param msg Constant reference of unique_ptr to a Message
|
||||
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of bytes that have been received, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Receive(MessagePtr& msg, int rcvTimeoutInMs = -1)
|
||||
/// Receive message(s) from the socket queue.
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param rcvTimeoutMs receive timeout in ms.
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot receive).
|
||||
/// If not provided, default timeout will be taken.
|
||||
/// @return Number of bytes that have been received,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M, typename... Timeout>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, Timeout&&... rcvTimeoutMs)
|
||||
{
|
||||
CheckReceiveCompatibility(msg);
|
||||
return fSocket->Receive(msg, rcvTimeoutInMs);
|
||||
}
|
||||
static_assert(sizeof...(rcvTimeoutMs) <= 1, "Receive called with too many arguments");
|
||||
|
||||
/// Send a vector of messages
|
||||
/// @param msgVec message vector reference
|
||||
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of bytes that have been queued, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Send(std::vector<MessagePtr>& msgVec, int sndTimeoutInMs = -1)
|
||||
{
|
||||
CheckSendCompatibility(msgVec);
|
||||
return fSocket->Send(msgVec, sndTimeoutInMs);
|
||||
}
|
||||
|
||||
/// Receive a vector of messages
|
||||
/// @param msgVec message vector reference
|
||||
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of bytes that have been received, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Receive(std::vector<MessagePtr>& msgVec, int rcvTimeoutInMs = -1)
|
||||
{
|
||||
CheckReceiveCompatibility(msgVec);
|
||||
return fSocket->Receive(msgVec, rcvTimeoutInMs);
|
||||
}
|
||||
|
||||
/// Send Parts
|
||||
/// @param parts Parts reference
|
||||
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of bytes that have been queued, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Send(Parts& parts, int sndTimeoutInMs = -1)
|
||||
{
|
||||
return Send(parts.fParts, sndTimeoutInMs);
|
||||
}
|
||||
|
||||
/// Receive Parts
|
||||
/// @param parts Parts reference
|
||||
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of bytes that have been received, TransferCode::timeout if timed out, TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
int64_t Receive(Parts& parts, int rcvTimeoutInMs = -1)
|
||||
{
|
||||
return Receive(parts.fParts, rcvTimeoutInMs);
|
||||
CheckReceiveCompatibility(m);
|
||||
int t = fRcvTimeoutMs;
|
||||
if constexpr (sizeof...(rcvTimeoutMs) == 1) {
|
||||
t = {rcvTimeoutMs...};
|
||||
}
|
||||
return fSocket->Receive(m, t);
|
||||
}
|
||||
|
||||
unsigned long GetBytesTx() const { return fSocket->GetBytesTx(); }
|
||||
@@ -366,6 +372,8 @@ class Channel
|
||||
static constexpr int DefaultRcvBufSize = 1000;
|
||||
static constexpr int DefaultSndKernelSize = 0;
|
||||
static constexpr int DefaultRcvKernelSize = 0;
|
||||
static constexpr int DefaultSndTimeoutMs = -1;
|
||||
static constexpr int DefaultRcvTimeoutMs = -1;
|
||||
static constexpr int DefaultLinger = 500;
|
||||
static constexpr int DefaultRateLogging = 1;
|
||||
static constexpr int DefaultPortRangeMin = 22000;
|
||||
@@ -385,6 +393,8 @@ class Channel
|
||||
int fRcvBufSize;
|
||||
int fSndKernelSize;
|
||||
int fRcvKernelSize;
|
||||
int fSndTimeoutMs;
|
||||
int fRcvTimeoutMs;
|
||||
int fLinger;
|
||||
int fRateLogging;
|
||||
int fPortRangeMin;
|
||||
@@ -414,6 +424,7 @@ class Channel
|
||||
}
|
||||
}
|
||||
|
||||
void CheckSendCompatibility(Parts& parts) { CheckSendCompatibility(parts.fParts); }
|
||||
void CheckSendCompatibility(std::vector<MessagePtr>& msgVec)
|
||||
{
|
||||
for (auto& msg : msgVec) {
|
||||
@@ -443,6 +454,7 @@ class Channel
|
||||
}
|
||||
}
|
||||
|
||||
void CheckReceiveCompatibility(Parts& parts) { CheckReceiveCompatibility(parts.fParts); }
|
||||
void CheckReceiveCompatibility(std::vector<MessagePtr>& msgVec)
|
||||
{
|
||||
for (auto& msg : msgVec) {
|
||||
|
@@ -1,19 +1,19 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2012-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2012-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include <algorithm> // std::max
|
||||
#include <algorithm> // std::max, std::any_of
|
||||
#include <boost/algorithm/string.hpp> // join/split
|
||||
#include <chrono>
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <future>
|
||||
#include <iomanip>
|
||||
#include <list>
|
||||
#include <memory> // std::make_unique
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
@@ -27,7 +27,6 @@ constexpr const char* Device::DefaultTransportName;
|
||||
constexpr mq::Transport Device::DefaultTransportType;
|
||||
constexpr const char* Device::DefaultNetworkInterface;
|
||||
constexpr int Device::DefaultInitTimeout;
|
||||
constexpr uint64_t Device::DefaultMaxRunTime;
|
||||
constexpr float Device::DefaultRate;
|
||||
constexpr const char* Device::DefaultSession;
|
||||
|
||||
@@ -83,7 +82,6 @@ Device::Device(ProgOptions* config, tools::Version version)
|
||||
, fMultitransportProceed(false)
|
||||
, fVersion(version)
|
||||
, fRate(DefaultRate)
|
||||
, fMaxRunRuntimeInS(DefaultMaxRunTime)
|
||||
, fInitializationTimeoutInS(DefaultInitTimeout)
|
||||
, fTransitioning(false)
|
||||
{
|
||||
@@ -215,7 +213,6 @@ void Device::InitWrapper()
|
||||
Init();
|
||||
|
||||
fRate = fConfig->GetProperty<float>("rate", DefaultRate);
|
||||
fMaxRunRuntimeInS = fConfig->GetProperty<uint64_t>("max-run-time", DefaultMaxRunTime);
|
||||
fInitializationTimeoutInS = fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout);
|
||||
|
||||
try {
|
||||
@@ -293,7 +290,9 @@ void Device::BindWrapper()
|
||||
|
||||
Bind();
|
||||
|
||||
ChangeState(Transition::Auto);
|
||||
if (!NewStatePending()) {
|
||||
ChangeState(Transition::Auto);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::ConnectWrapper()
|
||||
@@ -330,7 +329,9 @@ void Device::ConnectWrapper()
|
||||
|
||||
Connect();
|
||||
|
||||
ChangeState(Transition::Auto);
|
||||
if (!NewStatePending()) {
|
||||
ChangeState(Transition::Auto);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::AttachChannels(vector<Channel*>& chans)
|
||||
@@ -430,62 +431,70 @@ void Device::InitTaskWrapper()
|
||||
{
|
||||
InitTask();
|
||||
|
||||
ChangeState(Transition::Auto);
|
||||
if (!NewStatePending()) {
|
||||
ChangeState(Transition::Auto);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::RunWrapper()
|
||||
{
|
||||
LOG(info) << "DEVICE: Running...";
|
||||
LOG(info) << "fair::mq::Device running...";
|
||||
|
||||
unique_ptr<thread> rateLogger;
|
||||
// Check if rate logging thread is needed
|
||||
const bool rateLogging = any_of(fChannels.cbegin(), fChannels.cend(), [](auto ch) {
|
||||
return any_of(ch.second.cbegin(), ch.second.cend(), [](auto sub) { return sub.fRateLogging > 0; });
|
||||
});
|
||||
|
||||
if (rateLogging) {
|
||||
rateLogger = make_unique<thread>(&Device::LogSocketRates, this);
|
||||
}
|
||||
tools::CallOnDestruction joinRateLogger([&](){
|
||||
if (rateLogging && rateLogger->joinable()) { rateLogger->join(); }
|
||||
});
|
||||
|
||||
// start the rate logger thread
|
||||
future<void> rateLogger = async(launch::async, &Device::LogSocketRates, this);
|
||||
|
||||
// notify transports to resume transfers
|
||||
for (auto& t : fTransports) {
|
||||
t.second->Resume();
|
||||
}
|
||||
|
||||
try {
|
||||
PreRun();
|
||||
// change to Error state in case of an exception, to release LogSocketRates
|
||||
tools::CallOnDestruction cod([&](){
|
||||
ChangeState(Transition::ErrorFound);
|
||||
});
|
||||
|
||||
// process either data callbacks or ConditionalRun/Run
|
||||
if (fDataCallbacks) {
|
||||
// if only one input channel, do lightweight handling without additional polling.
|
||||
if (fInputChannelKeys.size() == 1 && fChannels.at(fInputChannelKeys.at(0)).size() == 1) {
|
||||
HandleSingleChannelInput();
|
||||
} else {// otherwise do full handling with polling
|
||||
HandleMultipleChannelInput();
|
||||
PreRun();
|
||||
|
||||
// process either data callbacks or ConditionalRun/Run
|
||||
if (fDataCallbacks) {
|
||||
// if only one input channel, do lightweight handling without additional polling.
|
||||
if (fInputChannelKeys.size() == 1 && fChannels.at(fInputChannelKeys.at(0)).size() == 1) {
|
||||
HandleSingleChannelInput();
|
||||
} else {// otherwise do full handling with polling
|
||||
HandleMultipleChannelInput();
|
||||
}
|
||||
} else {
|
||||
tools::RateLimiter rateLimiter(fRate);
|
||||
|
||||
while (!NewStatePending() && ConditionalRun()) {
|
||||
if (fRate > 0.001) {
|
||||
rateLimiter.maybe_sleep();
|
||||
}
|
||||
} else {
|
||||
tools::RateLimiter rateLimiter(fRate);
|
||||
|
||||
while (!NewStatePending() && ConditionalRun()) {
|
||||
if (fRate > 0.001) {
|
||||
rateLimiter.maybe_sleep();
|
||||
}
|
||||
}
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
// if Run() exited and the state is still RUNNING, transition to READY.
|
||||
if (!NewStatePending()) {
|
||||
UnblockTransports();
|
||||
ChangeState(Transition::Stop);
|
||||
}
|
||||
|
||||
PostRun();
|
||||
} catch (const out_of_range& oor) {
|
||||
LOG(error) << "out of range: " << oor.what();
|
||||
LOG(error) << "incorrect/incomplete channel configuration?";
|
||||
ChangeState(Transition::ErrorFound);
|
||||
throw;
|
||||
} catch (...) {
|
||||
ChangeState(Transition::ErrorFound);
|
||||
throw;
|
||||
Run();
|
||||
}
|
||||
|
||||
rateLogger.get();
|
||||
// if Run() exited and the state is still RUNNING, transition to READY.
|
||||
if (!NewStatePending()) {
|
||||
UnblockTransports();
|
||||
ChangeState(Transition::Stop);
|
||||
}
|
||||
|
||||
PostRun();
|
||||
|
||||
cod.disable();
|
||||
}
|
||||
|
||||
void Device::HandleSingleChannelInput()
|
||||
@@ -713,7 +722,6 @@ void Device::LogSocketRates()
|
||||
|
||||
chrono::time_point<chrono::high_resolution_clock> t0(chrono::high_resolution_clock::now());
|
||||
chrono::time_point<chrono::high_resolution_clock> t1;
|
||||
uint64_t secondsElapsed = 0;
|
||||
|
||||
while (!NewStatePending()) {
|
||||
WaitFor(chrono::seconds(1));
|
||||
@@ -746,7 +754,7 @@ void Device::LogSocketRates()
|
||||
bytesOut.at(i) = bytesOutNew.at(i);
|
||||
msgOut.at(i) = msgOutNew.at(i);
|
||||
|
||||
LOG(info) << setw(chanNameLen) << filteredChannelNames.at(i) << ": "
|
||||
LOG(info) << setw(static_cast<int>(chanNameLen)) << filteredChannelNames.at(i) << ": "
|
||||
<< "in: " << msgPerSecIn.at(i) << " (" << mbPerSecIn.at(i) << " MB) "
|
||||
<< "out: " << msgPerSecOut.at(i) << " (" << mbPerSecOut.at(i) << " MB)";
|
||||
}
|
||||
@@ -756,9 +764,6 @@ void Device::LogSocketRates()
|
||||
}
|
||||
|
||||
t0 = t1;
|
||||
if (fMaxRunRuntimeInS > 0 && ++secondsElapsed >= fMaxRunRuntimeInS) {
|
||||
ChangeState(Transition::Stop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +778,9 @@ void Device::ResetTaskWrapper()
|
||||
{
|
||||
ResetTask();
|
||||
|
||||
ChangeState(Transition::Auto);
|
||||
if (!NewStatePending()) {
|
||||
ChangeState(Transition::Auto);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::ResetWrapper()
|
||||
@@ -787,7 +794,9 @@ void Device::ResetWrapper()
|
||||
fChannels.clear();
|
||||
fTransports.clear();
|
||||
fTransportFactory.reset();
|
||||
ChangeState(Transition::Auto);
|
||||
if (!NewStatePending()) {
|
||||
ChangeState(Transition::Auto);
|
||||
}
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
|
110
fairmq/Device.h
110
fairmq/Device.h
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2021-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -81,72 +81,70 @@ class Device
|
||||
Deserializer().Deserialize(msg, std::forward<DataType>(data), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Shorthand method to send `msg` on `chan` at index `i`
|
||||
/// @param msg message reference
|
||||
/// Send `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via
|
||||
/// state change)), 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of bytes that have been queued, TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by
|
||||
/// requested state change)
|
||||
int64_t Send(MessagePtr& msg,
|
||||
const std::string& channel,
|
||||
const int index = 0,
|
||||
int sndTimeoutInMs = -1)
|
||||
/// @return Number of queued bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, const std::string& channel, const int index = 0)
|
||||
{
|
||||
return GetChannel(channel, index).Send(msg, sndTimeoutInMs);
|
||||
return GetChannel(channel, index).Send(m);
|
||||
}
|
||||
|
||||
/// Shorthand method to receive `msg` on `chan` at index `i`
|
||||
/// @param msg message reference
|
||||
/// Receive `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g.
|
||||
/// via state change)), 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of bytes that have been received, TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by
|
||||
/// requested state change)
|
||||
int64_t Receive(MessagePtr& msg,
|
||||
const std::string& channel,
|
||||
const int index = 0,
|
||||
int rcvTimeoutInMs = -1)
|
||||
/// @return Number of received bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, const std::string& channel, const int index = 0)
|
||||
{
|
||||
return GetChannel(channel, index).Receive(msg, rcvTimeoutInMs);
|
||||
return GetChannel(channel, index).Receive(m);
|
||||
}
|
||||
|
||||
/// Shorthand method to send Parts on `chan` at index `i`
|
||||
/// @param parts parts reference
|
||||
/// Send `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via
|
||||
/// state change)), 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of bytes that have been queued, TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by
|
||||
/// requested state change)
|
||||
int64_t Send(Parts& parts,
|
||||
const std::string& channel,
|
||||
const int index = 0,
|
||||
int sndTimeoutInMs = -1)
|
||||
/// @param sndTimeoutMs send timeout in ms,
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of queued bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, const std::string& channel, const int index, int sndTimeoutMs)
|
||||
{
|
||||
return GetChannel(channel, index).Send(parts.fParts, sndTimeoutInMs);
|
||||
return GetChannel(channel, index).Send(m, sndTimeoutMs);
|
||||
}
|
||||
|
||||
/// Shorthand method to receive Parts on `chan` at index `i`
|
||||
/// @param parts parts reference
|
||||
/// Receive `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g.
|
||||
/// via state change)), 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of bytes that have been received, TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error, TransferCode::interrupted if interrupted (e.g. by
|
||||
/// requested state change)
|
||||
int64_t Receive(Parts& parts,
|
||||
const std::string& channel,
|
||||
const int index = 0,
|
||||
int rcvTimeoutInMs = -1)
|
||||
/// @param rcvTimeoutMs receive timeout in ms,
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change),
|
||||
/// 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of received bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, const std::string& channel, const int index, int rcvTimeoutMs)
|
||||
{
|
||||
return GetChannel(channel, index).Receive(parts.fParts, rcvTimeoutInMs);
|
||||
return GetChannel(channel, index).Receive(m, rcvTimeoutMs);
|
||||
}
|
||||
|
||||
/// @brief Getter for default transport factory
|
||||
@@ -320,10 +318,15 @@ class Device
|
||||
try {
|
||||
return fChannels.at(channelName).at(index);
|
||||
} catch (const std::out_of_range& oor) {
|
||||
LOG(error)
|
||||
<< "requested channel has not been configured? check channel names/configuration.";
|
||||
LOG(error) << "channel: " << channelName << ", index: " << index;
|
||||
LOG(error) << "out of range: " << oor.what();
|
||||
LOG(error) << "GetChannel(): '" << channelName << "[" << index << "]' does not exist.";
|
||||
throw;
|
||||
}
|
||||
|
||||
size_t GetNumSubChannels(const std::string& channelName)
|
||||
try {
|
||||
return fChannels.at(channelName).size();
|
||||
} catch (const std::out_of_range& oor) {
|
||||
LOG(error) << "GetNumSubChannels(): '" << channelName << "' does not exist.";
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -562,7 +565,6 @@ class Device
|
||||
static constexpr mq::Transport DefaultTransportType = mq::Transport::ZMQ;
|
||||
static constexpr const char* DefaultNetworkInterface = "default";
|
||||
static constexpr int DefaultInitTimeout = 120;
|
||||
static constexpr uint64_t DefaultMaxRunTime = 0;
|
||||
static constexpr float DefaultRate = 0.;
|
||||
static constexpr const char* DefaultSession = "default";
|
||||
|
||||
|
@@ -128,7 +128,7 @@ auto DeviceRunner::Run() -> int
|
||||
|
||||
fConfig.ParseAll(fRawCmdLineArgs, true);
|
||||
|
||||
if (!HandleGeneralOptions(fConfig)) {
|
||||
if (!HandleGeneralOptions(fConfig, fPrintLogo)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -30,13 +30,13 @@
|
||||
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
using namespace fair::mq::tools;
|
||||
using namespace tools;
|
||||
using namespace boost::property_tree;
|
||||
|
||||
namespace fair::mq
|
||||
{
|
||||
|
||||
fair::mq::Properties PtreeParser(const ptree& pt, const string& id)
|
||||
Properties PtreeParser(const ptree& pt, const string& id)
|
||||
{
|
||||
if (id.empty()) {
|
||||
throw ParserError("no device ID provided. Provide with `--id` cmd option");
|
||||
@@ -47,7 +47,7 @@ fair::mq::Properties PtreeParser(const ptree& pt, const string& id)
|
||||
return helper::DeviceParser(pt.get_child("fairMQOptions"), id);
|
||||
}
|
||||
|
||||
fair::mq::Properties JSONParser(const string& filename, const string& deviceId)
|
||||
Properties JSONParser(const string& filename, const string& deviceId)
|
||||
{
|
||||
ptree pt;
|
||||
LOG(debug) << "Parsing JSON from " << filename << " ...";
|
||||
@@ -58,9 +58,9 @@ fair::mq::Properties JSONParser(const string& filename, const string& deviceId)
|
||||
namespace helper
|
||||
{
|
||||
|
||||
fair::mq::Properties DeviceParser(const ptree& fairMQOptions, const string& deviceId)
|
||||
Properties DeviceParser(const ptree& fairMQOptions, const string& deviceId)
|
||||
{
|
||||
fair::mq::Properties properties;
|
||||
Properties properties;
|
||||
|
||||
for (const auto& node : fairMQOptions) {
|
||||
if (node.first == "devices") {
|
||||
@@ -82,25 +82,27 @@ fair::mq::Properties DeviceParser(const ptree& fairMQOptions, const string& devi
|
||||
return properties;
|
||||
}
|
||||
|
||||
void ChannelParser(const ptree& tree, fair::mq::Properties& properties)
|
||||
void ChannelParser(const ptree& tree, Properties& properties)
|
||||
{
|
||||
for (const auto& node : tree) {
|
||||
if (node.first == "channels") {
|
||||
for (const auto& cn : node.second) {
|
||||
fair::mq::Properties commonProperties;
|
||||
commonProperties.emplace("type", cn.second.get<string>("type", FairMQChannel::DefaultType));
|
||||
commonProperties.emplace("method", cn.second.get<string>("method", FairMQChannel::DefaultMethod));
|
||||
commonProperties.emplace("address", cn.second.get<string>("address", FairMQChannel::DefaultAddress));
|
||||
commonProperties.emplace("transport", cn.second.get<string>("transport", FairMQChannel::DefaultTransportName));
|
||||
commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", FairMQChannel::DefaultSndBufSize));
|
||||
commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", FairMQChannel::DefaultRcvBufSize));
|
||||
commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", FairMQChannel::DefaultSndKernelSize));
|
||||
commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", FairMQChannel::DefaultRcvKernelSize));
|
||||
commonProperties.emplace("linger", cn.second.get<int>("linger", FairMQChannel::DefaultLinger));
|
||||
commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", FairMQChannel::DefaultRateLogging));
|
||||
commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", FairMQChannel::DefaultPortRangeMin));
|
||||
commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", FairMQChannel::DefaultPortRangeMax));
|
||||
commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", FairMQChannel::DefaultAutoBind));
|
||||
Properties commonProperties;
|
||||
commonProperties.emplace("type", cn.second.get<string>("type", Channel::DefaultType));
|
||||
commonProperties.emplace("method", cn.second.get<string>("method", Channel::DefaultMethod));
|
||||
commonProperties.emplace("address", cn.second.get<string>("address", Channel::DefaultAddress));
|
||||
commonProperties.emplace("transport", cn.second.get<string>("transport", Channel::DefaultTransportName));
|
||||
commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", Channel::DefaultSndBufSize));
|
||||
commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", Channel::DefaultRcvBufSize));
|
||||
commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", Channel::DefaultSndKernelSize));
|
||||
commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", Channel::DefaultRcvKernelSize));
|
||||
commonProperties.emplace("sndTimeoutMs", cn.second.get<int>("sndTimeoutMs", Channel::DefaultSndTimeoutMs));
|
||||
commonProperties.emplace("rcvTimeoutMs", cn.second.get<int>("rcvTimeoutMs", Channel::DefaultRcvTimeoutMs));
|
||||
commonProperties.emplace("linger", cn.second.get<int>("linger", Channel::DefaultLinger));
|
||||
commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", Channel::DefaultRateLogging));
|
||||
commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", Channel::DefaultPortRangeMin));
|
||||
commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", Channel::DefaultPortRangeMax));
|
||||
commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", Channel::DefaultAutoBind));
|
||||
|
||||
string name = cn.second.get<string>("name");
|
||||
int numSockets = cn.second.get<int>("numSockets", 0);
|
||||
@@ -126,7 +128,7 @@ void ChannelParser(const ptree& tree, fair::mq::Properties& properties)
|
||||
}
|
||||
}
|
||||
|
||||
void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties, const string& channelName, const fair::mq::Properties& commonProperties)
|
||||
void SubChannelParser(const ptree& channelTree, Properties& properties, const string& channelName, const Properties& commonProperties)
|
||||
{
|
||||
// for each socket in channel
|
||||
int i = 0;
|
||||
@@ -135,7 +137,7 @@ void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties
|
||||
if (node.first == "sockets") {
|
||||
for (const auto& sn : node.second) {
|
||||
// a sub-channel inherits relevant properties from the common channel ...
|
||||
fair::mq::Properties newProperties(commonProperties);
|
||||
Properties newProperties(commonProperties);
|
||||
|
||||
// ... and adds/overwrites its own properties
|
||||
newProperties["type"] = sn.second.get<string>("type", boost::any_cast<string>(commonProperties.at("type")));
|
||||
@@ -146,6 +148,8 @@ void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties
|
||||
newProperties["rcvBufSize"] = sn.second.get<int>("rcvBufSize", boost::any_cast<int>(commonProperties.at("rcvBufSize")));
|
||||
newProperties["sndKernelSize"] = sn.second.get<int>("sndKernelSize", boost::any_cast<int>(commonProperties.at("sndKernelSize")));
|
||||
newProperties["rcvKernelSize"] = sn.second.get<int>("rcvKernelSize", boost::any_cast<int>(commonProperties.at("rcvKernelSize")));
|
||||
newProperties["sndTimeoutMs"] = sn.second.get<int>("sndTimeoutMs", boost::any_cast<int>(commonProperties.at("sndTimeoutMs")));
|
||||
newProperties["rcvTimeoutMs"] = sn.second.get<int>("rcvTimeoutMs", boost::any_cast<int>(commonProperties.at("rcvTimeoutMs")));
|
||||
newProperties["linger"] = sn.second.get<int>("linger", boost::any_cast<int>(commonProperties.at("linger")));
|
||||
newProperties["rateLogging"] = sn.second.get<int>("rateLogging", boost::any_cast<int>(commonProperties.at("rateLogging")));
|
||||
newProperties["portRangeMin"] = sn.second.get<int>("portRangeMin", boost::any_cast<int>(commonProperties.at("portRangeMin")));
|
||||
@@ -173,7 +177,7 @@ void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties
|
||||
LOG(trace) << "\tNo sockets specified,";
|
||||
LOG(trace) << "\tapplying common settings to the channel:";
|
||||
|
||||
fair::mq::Properties newProperties(commonProperties);
|
||||
Properties newProperties(commonProperties);
|
||||
|
||||
for (auto& p : newProperties) {
|
||||
LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
///
|
||||
/// @author Mikolaj Krzewicki, mkrzewic@cern.ch
|
||||
|
||||
#include <fairmq/FairMQTransportFactory.h>
|
||||
#include <fairmq/TransportFactory.h>
|
||||
#include <fairmq/MemoryResources.h>
|
||||
|
||||
namespace fair::mq
|
||||
@@ -28,13 +28,13 @@ template<typename ContainerT>
|
||||
// pmr::polymorphic_allocator<typename
|
||||
// ContainerT::value_type>,
|
||||
// typename ContainerT::allocator_type>::value == true,
|
||||
// FairMQMessagePtr>::type
|
||||
FairMQMessagePtr getMessage(ContainerT &&container_, FairMQMemoryResource *targetResource = nullptr)
|
||||
// MessagePtr>::type
|
||||
MessagePtr getMessage(ContainerT &&container_, MemoryResource *targetResource = nullptr)
|
||||
{
|
||||
auto container = std::move(container_);
|
||||
auto alloc = container.get_allocator();
|
||||
|
||||
auto resource = dynamic_cast<FairMQMemoryResource *>(alloc.resource());
|
||||
auto resource = dynamic_cast<MemoryResource *>(alloc.resource());
|
||||
if (!resource && !targetResource) {
|
||||
throw std::runtime_error("Neither the container or target resource specified");
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <FairMQLogger.h>
|
||||
#include <fairlogger/Logger.h>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
@@ -351,7 +351,7 @@ void ProgOptions::DeleteProperty(const string& key)
|
||||
vm.erase(key);
|
||||
}
|
||||
|
||||
void ProgOptions::AddChannel(const string& name, const FairMQChannel& channel)
|
||||
void ProgOptions::AddChannel(const string& name, const Channel& channel)
|
||||
{
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
unordered_map<string, int> existingChannels = GetChannelInfoImpl();
|
||||
|
@@ -10,9 +10,12 @@
|
||||
#define FAIR_MQ_SOCKET_H
|
||||
|
||||
#include <fairmq/Message.h>
|
||||
#include <fairmq/Parts.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace fair::mq {
|
||||
@@ -27,6 +30,12 @@ enum class TransferCode : int
|
||||
interrupted = -3
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_transferrable : std::disjunction<std::is_same<T, MessagePtr>,
|
||||
std::is_same<T, std::vector<MessagePtr>>,
|
||||
std::is_same<T, fair::mq::Parts>>
|
||||
{};
|
||||
|
||||
struct Socket
|
||||
{
|
||||
Socket() = default;
|
||||
@@ -45,6 +54,8 @@ struct Socket
|
||||
virtual int64_t Receive(MessagePtr& msg, int timeout = -1) = 0;
|
||||
virtual int64_t Send(std::vector<std::unique_ptr<Message>>& msgVec, int timeout = -1) = 0;
|
||||
virtual int64_t Receive(std::vector<std::unique_ptr<Message>>& msgVec, int timeout = -1) = 0;
|
||||
virtual int64_t Send(Parts& parts, int timeout = -1) { return Send(parts.fParts, timeout); }
|
||||
virtual int64_t Receive(Parts& parts, int timeout = -1) { return Receive(parts.fParts, timeout); }
|
||||
|
||||
[[deprecated("Use Socket::~Socket() instead.")]]
|
||||
virtual void Close() = 0;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include <fairmq/StateMachine.h>
|
||||
#include <fairmq/tools/Exceptions.h>
|
||||
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
@@ -186,9 +187,7 @@ struct Machine_ : public state_machine_def<Machine_>
|
||||
{
|
||||
unique_lock<mutex> lock(fStateMtx);
|
||||
|
||||
while (!fNewStatePending) {
|
||||
fNewStatePendingCV.wait_for(lock, chrono::milliseconds(100));
|
||||
}
|
||||
fNewStatePendingCV.wait(lock, [this]{ return fNewStatePending.load(); });
|
||||
|
||||
LOG(state) << fState << " ---> " << fNewState;
|
||||
fState = static_cast<State>(fNewState);
|
||||
@@ -204,6 +203,7 @@ struct Machine_ : public state_machine_def<Machine_>
|
||||
}
|
||||
|
||||
if (fState == State::Error) {
|
||||
LOG(trace) << "Device transitioned to error state";
|
||||
throw StateMachine::ErrorStateException("Device transitioned to error state");
|
||||
}
|
||||
}
|
||||
@@ -366,20 +366,18 @@ void StateMachine::ProcessWork()
|
||||
{
|
||||
auto fsm = static_pointer_cast<FairMQFSM>(fFsm);
|
||||
|
||||
try {
|
||||
fsm->CallStateChangeCallbacks(State::Idle);
|
||||
fsm->ProcessWork();
|
||||
} catch(ErrorStateException& ese) {
|
||||
LOG(trace) << "ErrorStateException caught in ProcessWork(), rethrowing";
|
||||
throw;
|
||||
} catch(...) {
|
||||
LOG(debug) << "Exception caught in ProcessWork(), going to Error state and rethrowing";
|
||||
fair::mq::tools::CallOnDestruction cod([&](){
|
||||
LOG(debug) << "Exception caught in ProcessWork(), going to Error state";
|
||||
{
|
||||
lock_guard<mutex> lock(fsm->fStateMtx);
|
||||
fsm->fState = State::Error;
|
||||
fsm->CallStateChangeCallbacks(State::Error);
|
||||
}
|
||||
ChangeState(Transition::ErrorFound);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
fsm->CallStateChangeCallbacks(State::Idle);
|
||||
fsm->ProcessWork();
|
||||
|
||||
cod.disable();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2019-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -9,16 +9,14 @@
|
||||
#ifndef FAIRMQSTATEQUEUE_H_
|
||||
#define FAIRMQSTATEQUEUE_H_
|
||||
|
||||
#include <fairmq/States.h>
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <utility> // pair
|
||||
#include <condition_variable>
|
||||
#include <fairmq/States.h>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <utility> // pair
|
||||
|
||||
namespace fair::mq
|
||||
{
|
||||
namespace fair::mq {
|
||||
|
||||
class StateQueue
|
||||
{
|
||||
@@ -33,41 +31,47 @@ class StateQueue
|
||||
fair::mq::State WaitForNext()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
while (fStates.empty()) {
|
||||
fCV.wait_for(lock, std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
fair::mq::State state = fStates.front();
|
||||
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
|
||||
fStates.pop();
|
||||
return state;
|
||||
fCV.wait(lock, [this] { return Predicate(); });
|
||||
return PopFrontUnsafe();
|
||||
}
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
std::pair<bool, fair::mq::State> WaitForNext(std::chrono::duration<Rep, Period> const& duration)
|
||||
template<typename Timeout>
|
||||
std::pair<bool, fair::mq::State> WaitForNext(Timeout&& duration)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait_for(lock, duration);
|
||||
|
||||
if (fStates.empty()) {
|
||||
return { false, fair::mq::State::Ok };
|
||||
}
|
||||
|
||||
fair::mq::State state = fStates.front();
|
||||
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
|
||||
fStates.pop();
|
||||
return { true, state };
|
||||
fCV.wait_for(lock, std::forward<Timeout>(duration), [this] { return Predicate(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
void WaitForState(fair::mq::State state) { while (WaitForNext() != state) {} }
|
||||
template<typename CustomPredicate>
|
||||
std::pair<bool, fair::mq::State> WaitForNextOrCustom(CustomPredicate&& customPredicate)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait(lock, [this, cp = std::move(customPredicate)] { return Predicate() || cp(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
template<typename CustomPredicate>
|
||||
std::pair<bool, fair::mq::State> WaitForCustom(CustomPredicate&& customPredicate)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait(lock, [cp = std::move(customPredicate)] { return cp(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
void WaitForState(fair::mq::State state)
|
||||
{
|
||||
while (WaitForNext() != state) {}
|
||||
}
|
||||
|
||||
template<typename CustomPredicate>
|
||||
void WaitForStateOrCustom(fair::mq::State state, CustomPredicate customPredicate)
|
||||
{
|
||||
auto next = WaitForNextOrCustom(customPredicate);
|
||||
while (!customPredicate() && (next.first && next.second != state)) {
|
||||
next = WaitForNextOrCustom(customPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
void Push(fair::mq::State state)
|
||||
{
|
||||
@@ -75,7 +79,35 @@ class StateQueue
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fStates.push(state);
|
||||
}
|
||||
fCV.notify_all();
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Push(fair::mq::State state, CustomSignal&& signal)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fStates.push(state);
|
||||
signal();
|
||||
}
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Notify(CustomSignal&& signal)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
signal();
|
||||
}
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Locked(CustomSignal&& signal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
signal();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
@@ -88,8 +120,29 @@ class StateQueue
|
||||
std::queue<fair::mq::State> fStates;
|
||||
std::mutex fMtx;
|
||||
std::condition_variable fCV;
|
||||
|
||||
// must be called under locked fMtx
|
||||
fair::mq::State PopFrontUnsafe()
|
||||
{
|
||||
fair::mq::State state = fStates.front();
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
fStates.pop();
|
||||
return state;
|
||||
}
|
||||
|
||||
// must be called under locked fMtx
|
||||
std::pair<bool, fair::mq::State> ReturnPairUnsafe()
|
||||
{
|
||||
auto const pred = Predicate();
|
||||
return {pred, pred ? PopFrontUnsafe() : fair::mq::State::Ok};
|
||||
}
|
||||
|
||||
// must be called under locked fMtx
|
||||
bool Predicate() { return !fStates.empty(); }
|
||||
};
|
||||
|
||||
} // namespace fair::mq
|
||||
} // namespace fair::mq
|
||||
|
||||
#endif /* FAIRMQSTATEQUEUE_H_ */
|
||||
|
@@ -38,6 +38,8 @@ enum channelOptionKeyIds
|
||||
RCVBUFSIZE, // size of the receive queue
|
||||
SNDKERNELSIZE,
|
||||
RCVKERNELSIZE,
|
||||
SNDTIMEOUTMS,
|
||||
RCVTIMEOUTMS,
|
||||
LINGER,
|
||||
RATELOGGING, // logging rate
|
||||
PORTRANGEMIN,
|
||||
@@ -57,6 +59,8 @@ constexpr static const char* channelOptionKeys[] = {
|
||||
/*[RCVBUFSIZE] = */ "rcvBufSize",
|
||||
/*[SNDKERNELSIZE] = */ "sndKernelSize",
|
||||
/*[RCVKERNELSIZE] = */ "rcvKernelSize",
|
||||
/*[SNDTIMEOUTMS] = */ "sndTimeoutMs",
|
||||
/*[RCVTIMEOUTMS] = */ "rcvTimeoutMs",
|
||||
/*[LINGER] = */ "linger",
|
||||
/*[RATELOGGING] = */ "rateLogging",
|
||||
/*[PORTRANGEMIN] = */ "portRangeMin",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
#include <fairmq/tools/CppSTL.h>
|
||||
#include <fairmq/tools/Exceptions.h>
|
||||
#include <fairmq/tools/InstanceLimit.h>
|
||||
#include <fairmq/tools/Network.h>
|
||||
#include <fairmq/tools/Process.h>
|
||||
|
@@ -109,13 +109,15 @@ class TransportFactory
|
||||
/// @param path optional parameter to pass to the underlying transport
|
||||
/// @param flags optional parameter to pass to the underlying transport
|
||||
/// @return pointer to UnmanagedRegion
|
||||
// [[deprecated("Use CreateUnmanagedRegion(size_t size, RegionCallback callback, RegionConfig cfg)")]]
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size,
|
||||
RegionCallback callback = nullptr,
|
||||
const std::string& path = "",
|
||||
int flags = 0,
|
||||
RegionConfig cfg = RegionConfig()) = 0;
|
||||
// [[deprecated("Use CreateUnmanagedRegion(size_t size, RegionCallback callback, RegionConfig cfg)")]]
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size,
|
||||
RegionBulkCallback callback = nullptr,
|
||||
RegionBulkCallback bulkCallback = nullptr,
|
||||
const std::string& path = "",
|
||||
int flags = 0,
|
||||
RegionConfig cfg = RegionConfig()) = 0;
|
||||
@@ -128,19 +130,35 @@ class TransportFactory
|
||||
/// @param path optional parameter to pass to the underlying transport
|
||||
/// @param flags optional parameter to pass to the underlying transport
|
||||
/// @return pointer to UnmanagedRegion
|
||||
// [[deprecated("Use CreateUnmanagedRegion(size_t size, RegionCallback callback, RegionConfig cfg)")]]
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size,
|
||||
int64_t userFlags,
|
||||
RegionCallback callback = nullptr,
|
||||
const std::string& path = "",
|
||||
int flags = 0,
|
||||
RegionConfig cfg = RegionConfig()) = 0;
|
||||
// [[deprecated("Use CreateUnmanagedRegion(size_t size, RegionCallback callback, RegionConfig cfg)")]]
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size,
|
||||
int64_t userFlags,
|
||||
RegionBulkCallback callback = nullptr,
|
||||
RegionBulkCallback bulkCallback = nullptr,
|
||||
const std::string& path = "",
|
||||
int flags = 0,
|
||||
RegionConfig cfg = RegionConfig()) = 0;
|
||||
|
||||
/// @brief Create new UnmanagedRegion
|
||||
/// @param size size of the region
|
||||
/// @param callback callback to be called when a message belonging to this region is no longer needed by the transport
|
||||
/// @param cfg region configuration
|
||||
/// @return pointer to UnmanagedRegion
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size, RegionCallback callback, RegionConfig cfg) = 0;
|
||||
|
||||
/// @brief Create new UnmanagedRegion
|
||||
/// @param size size of the region
|
||||
/// @param bulkCallback callback to be called when message(s) belonging to this region is no longer needed by the transport
|
||||
/// @param cfg region configuration
|
||||
/// @return pointer to UnmanagedRegion
|
||||
virtual UnmanagedRegionPtr CreateUnmanagedRegion(size_t size, RegionBulkCallback bulkCallback, RegionConfig cfg) = 0;
|
||||
|
||||
/// @brief Subscribe to region events (creation, destruction, ...)
|
||||
/// @param callback the callback that is called when a region event occurs
|
||||
virtual void SubscribeToRegionEvents(RegionEventCallback callback) = 0;
|
||||
|
@@ -9,12 +9,16 @@
|
||||
#ifndef FAIR_MQ_UNMANAGEDREGION_H
|
||||
#define FAIR_MQ_UNMANAGEDREGION_H
|
||||
|
||||
#include <fairmq/Transports.h>
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint32_t
|
||||
#include <fairmq/Transports.h>
|
||||
|
||||
#include <functional> // std::function
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <ostream> // std::ostream
|
||||
#include <optional> // std::optional
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fair::mq {
|
||||
@@ -119,13 +123,20 @@ struct RegionConfig
|
||||
{
|
||||
RegionConfig() = default;
|
||||
|
||||
RegionConfig(bool l, bool z)
|
||||
: lock(l)
|
||||
, zero(z)
|
||||
RegionConfig(bool _lock, bool _zero)
|
||||
: lock(_lock)
|
||||
, zero(_zero)
|
||||
{}
|
||||
|
||||
bool lock = false;
|
||||
bool zero = false;
|
||||
bool lock = false; /// mlock region after creation
|
||||
bool zero = false; /// zero region content after creation
|
||||
bool removeOnDestruction = true; /// remove the region on object destruction
|
||||
int creationFlags = 0; /// flags passed to the underlying transport on region creation
|
||||
int64_t userFlags = 0; /// custom flags that have no effect on the transport, but can be retrieved from the region by the user
|
||||
uint64_t size = 0; /// region size
|
||||
std::string path = ""; /// file path, if the region is backed by a file
|
||||
std::optional<uint16_t> id = std::nullopt; /// region id
|
||||
uint32_t linger = 100; /// delay in ms before region destruction to collect outstanding events
|
||||
};
|
||||
|
||||
} // namespace fair::mq
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2018-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -21,7 +21,7 @@
|
||||
#define FAIRMQ_GIT_DATE "@PROJECT_GIT_DATE@"
|
||||
#define FAIRMQ_REPO_URL "https://github.com/FairRootGroup/FairMQ"
|
||||
#define FAIRMQ_LICENSE "LGPL-3.0"
|
||||
#define FAIRMQ_COPYRIGHT "2012-2021 GSI"
|
||||
#define FAIRMQ_COPYRIGHT "2012-2022 GSI"
|
||||
#define FAIRMQ_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
|
||||
|
||||
#endif // FAIR_MQ_VERSION_H
|
||||
|
@@ -44,7 +44,7 @@ class BenchmarkSampler : public Device
|
||||
void Run() override
|
||||
{
|
||||
// store the channel reference to avoid traversing the map on every loop iteration
|
||||
FairMQChannel& dataOutChannel = fChannels.at(fOutChannelName).at(0);
|
||||
Channel& dataOutChannel = GetChannel(fOutChannelName, 0);
|
||||
|
||||
LOG(info) << "Starting the benchmark with message size of " << fMsgSize << " and " << fMaxIterations << " iterations.";
|
||||
auto tStart = std::chrono::high_resolution_clock::now();
|
||||
@@ -53,7 +53,7 @@ class BenchmarkSampler : public Device
|
||||
|
||||
while (!NewStatePending()) {
|
||||
if (fMultipart) {
|
||||
FairMQParts parts;
|
||||
Parts parts;
|
||||
|
||||
for (size_t i = 0; i < fNumParts; ++i) {
|
||||
parts.AddPart(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment}));
|
||||
@@ -71,7 +71,7 @@ class BenchmarkSampler : public Device
|
||||
++fNumIterations;
|
||||
}
|
||||
} else {
|
||||
FairMQMessagePtr msg(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment}));
|
||||
MessagePtr msg(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment}));
|
||||
if (fMemSet) {
|
||||
std::memset(msg->GetData(), 0, msg->GetSize());
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#ifndef FAIR_MQ_MERGER_H
|
||||
#define FAIR_MQ_MERGER_H
|
||||
|
||||
#include <FairMQPoller.h>
|
||||
#include <fairmq/Poller.h>
|
||||
#include <fairmq/Device.h>
|
||||
|
||||
#include <fairlogger/Logger.h>
|
||||
@@ -43,15 +43,15 @@ class Merger : public Device
|
||||
|
||||
void Run() override
|
||||
{
|
||||
int numInputs = fChannels.at(fInChannelName).size();
|
||||
int numInputs = GetNumSubChannels(fInChannelName);
|
||||
|
||||
std::vector<FairMQChannel*> chans;
|
||||
std::vector<Channel*> chans;
|
||||
|
||||
for (auto& chan : fChannels.at(fInChannelName)) {
|
||||
chans.push_back(&chan);
|
||||
}
|
||||
|
||||
FairMQPollerPtr poller(NewPoller(chans));
|
||||
PollerPtr poller(NewPoller(chans));
|
||||
|
||||
if (fMultipart) {
|
||||
while (!NewStatePending()) {
|
||||
@@ -61,7 +61,7 @@ class Merger : public Device
|
||||
for (int i = 0; i < numInputs; ++i) {
|
||||
// Check if the channel has data ready to be received.
|
||||
if (poller->CheckInput(i)) {
|
||||
FairMQParts payload;
|
||||
Parts payload;
|
||||
|
||||
if (Receive(payload, fInChannelName, i) >= 0) {
|
||||
if (Send(payload, fOutChannelName) < 0) {
|
||||
@@ -83,7 +83,7 @@ class Merger : public Device
|
||||
for (int i = 0; i < numInputs; ++i) {
|
||||
// Check if the channel has data ready to be received.
|
||||
if (poller->CheckInput(i)) {
|
||||
FairMQMessagePtr payload(fTransportFactory->CreateMessage());
|
||||
MessagePtr payload(fTransportFactory->CreateMessage());
|
||||
|
||||
if (Receive(payload, fInChannelName, i) >= 0) {
|
||||
if (Send(payload, fOutChannelName) < 0) {
|
||||
|
@@ -30,7 +30,7 @@ class Multiplier : public Device
|
||||
fMultipart = fConfig->GetProperty<bool>("multipart");
|
||||
fInChannelName = fConfig->GetProperty<std::string>("in-channel");
|
||||
fOutChannelNames = fConfig->GetProperty<std::vector<std::string>>("out-channel");
|
||||
fNumOutputs = fChannels.at(fOutChannelNames.at(0)).size();
|
||||
fNumOutputs = GetNumSubChannels(fOutChannelNames.at(0));
|
||||
|
||||
if (fMultipart) {
|
||||
OnData(fInChannelName, &Multiplier::HandleMultipartData);
|
||||
@@ -40,21 +40,21 @@ class Multiplier : public Device
|
||||
}
|
||||
|
||||
|
||||
bool HandleSingleData(std::unique_ptr<FairMQMessage>& payload, int)
|
||||
bool HandleSingleData(std::unique_ptr<Message>& payload, int)
|
||||
{
|
||||
for (unsigned int i = 0; i < fOutChannelNames.size() - 1; ++i) { // all except last channel
|
||||
for (unsigned int j = 0; j < fChannels.at(fOutChannelNames.at(i)).size(); ++j) { // all subChannels in a channel
|
||||
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel
|
||||
MessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
msgCopy->Copy(*payload);
|
||||
|
||||
Send(msgCopy, fOutChannelNames.at(i), j);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int lastChannelSize = fChannels.at(fOutChannelNames.back()).size();
|
||||
unsigned int lastChannelSize = GetNumSubChannels(fOutChannelNames.back());
|
||||
|
||||
for (unsigned int i = 0; i < lastChannelSize - 1; ++i) { // iterate over all except last subChannels of the last channel
|
||||
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
MessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
msgCopy->Copy(*payload);
|
||||
|
||||
Send(msgCopy, fOutChannelNames.back(), i);
|
||||
@@ -65,14 +65,14 @@ class Multiplier : public Device
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleMultipartData(FairMQParts& payload, int)
|
||||
bool HandleMultipartData(Parts& payload, int)
|
||||
{
|
||||
for (unsigned int i = 0; i < fOutChannelNames.size() - 1; ++i) { // all except last channel
|
||||
for (unsigned int j = 0; j < fChannels.at(fOutChannelNames.at(i)).size(); ++j) { // all subChannels in a channel
|
||||
FairMQParts parts;
|
||||
for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel
|
||||
Parts parts;
|
||||
|
||||
for (int k = 0; k < payload.Size(); ++k) {
|
||||
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
MessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
msgCopy->Copy(payload.AtRef(k));
|
||||
parts.AddPart(std::move(msgCopy));
|
||||
}
|
||||
@@ -81,13 +81,13 @@ class Multiplier : public Device
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int lastChannelSize = fChannels.at(fOutChannelNames.back()).size();
|
||||
unsigned int lastChannelSize = GetNumSubChannels(fOutChannelNames.back());
|
||||
|
||||
for (unsigned int i = 0; i < lastChannelSize - 1; ++i) { // iterate over all except last subChannels of the last channel
|
||||
FairMQParts parts;
|
||||
Parts parts;
|
||||
|
||||
for (int k = 0; k < payload.Size(); ++k) {
|
||||
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
MessagePtr msgCopy(fTransportFactory->CreateMessage());
|
||||
msgCopy->Copy(payload.AtRef(k));
|
||||
parts.AddPart(std::move(msgCopy));
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ class Proxy : public Device
|
||||
{
|
||||
if (fMultipart) {
|
||||
while (!NewStatePending()) {
|
||||
FairMQParts payload;
|
||||
Parts payload;
|
||||
if (Receive(payload, fInChannelName) >= 0) {
|
||||
if (Send(payload, fOutChannelName) < 0) {
|
||||
LOG(debug) << "Transfer interrupted";
|
||||
@@ -47,7 +47,7 @@ class Proxy : public Device
|
||||
}
|
||||
} else {
|
||||
while (!NewStatePending()) {
|
||||
FairMQMessagePtr payload(fTransportFactory->CreateMessage());
|
||||
MessagePtr payload(fTransportFactory->CreateMessage());
|
||||
if (Receive(payload, fInChannelName) >= 0) {
|
||||
if (Send(payload, fOutChannelName) < 0) {
|
||||
LOG(debug) << "Transfer interrupted";
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#ifndef FAIR_MQ_SINK_H
|
||||
#define FAIR_MQ_SINK_H
|
||||
|
||||
#include <FairMQPoller.h>
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/tools/Strings.h>
|
||||
|
||||
@@ -48,7 +47,7 @@ class Sink : public Device
|
||||
void Run() override
|
||||
{
|
||||
// store the channel reference to avoid traversing the map on every loop iteration
|
||||
FairMQChannel& dataInChannel = fChannels.at(fInChannelName).at(0);
|
||||
Channel& dataInChannel = GetChannel(fInChannelName, 0);
|
||||
|
||||
LOG(info) << "Starting sink and expecting to receive " << fMaxIterations << " messages.";
|
||||
auto tStart = std::chrono::high_resolution_clock::now();
|
||||
@@ -70,7 +69,7 @@ class Sink : public Device
|
||||
|
||||
while (!NewStatePending()) {
|
||||
if (fMultipart) {
|
||||
FairMQParts parts;
|
||||
Parts parts;
|
||||
if (dataInChannel.Receive(parts) < 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -80,7 +79,7 @@ class Sink : public Device
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FairMQMessagePtr msg(dataInChannel.NewMessage());
|
||||
MessagePtr msg(dataInChannel.NewMessage());
|
||||
if (dataInChannel.Receive(msg) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
@@ -30,13 +30,13 @@ class Splitter : public Device
|
||||
fMultipart = fConfig->GetProperty<bool>("multipart");
|
||||
fInChannelName = fConfig->GetProperty<std::string>("in-channel");
|
||||
fOutChannelName = fConfig->GetProperty<std::string>("out-channel");
|
||||
fNumOutputs = fChannels.at(fOutChannelName).size();
|
||||
fNumOutputs = GetNumSubChannels(fOutChannelName);
|
||||
fDirection = 0;
|
||||
|
||||
if (fMultipart) {
|
||||
OnData(fInChannelName, &Splitter::HandleData<FairMQParts>);
|
||||
OnData(fInChannelName, &Splitter::HandleData<Parts>);
|
||||
} else {
|
||||
OnData(fInChannelName, &Splitter::HandleData<FairMQMessagePtr>);
|
||||
OnData(fInChannelName, &Splitter::HandleData<MessagePtr>);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#include <fairmq/ofi/Socket.h>
|
||||
#include <fairmq/ofi/TransportFactory.h>
|
||||
#include <fairmq/tools/Strings.h>
|
||||
#include <FairMQLogger.h>
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
#include <asiofi.hpp>
|
||||
#include <asio/buffer.hpp>
|
||||
|
@@ -166,6 +166,22 @@ struct TransportFactory final : mq::TransportFactory
|
||||
throw std::runtime_error("Not yet implemented UMR.");
|
||||
}
|
||||
|
||||
auto CreateUnmanagedRegion(std::size_t /*size*/,
|
||||
RegionCallback /*callback*/,
|
||||
RegionConfig /*cfg*/)
|
||||
-> std::unique_ptr<mq::UnmanagedRegion> override
|
||||
{
|
||||
throw std::runtime_error("Not yet implemented UMR.");
|
||||
}
|
||||
|
||||
auto CreateUnmanagedRegion(std::size_t /*size*/,
|
||||
RegionBulkCallback /*callback*/,
|
||||
RegionConfig /*cfg*/)
|
||||
-> std::unique_ptr<mq::UnmanagedRegion> override
|
||||
{
|
||||
throw std::runtime_error("Not yet implemented UMR.");
|
||||
}
|
||||
|
||||
auto SubscribeToRegionEvents(RegionEventCallback /*callback*/) -> void override
|
||||
{
|
||||
throw std::runtime_error("Not yet implemented.");
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "PMIx.hpp"
|
||||
|
||||
#include <FairMQLogger.h>
|
||||
#include <fairlogger/Logger.h>
|
||||
#include <fairmq/tools/Semaphore.h>
|
||||
#include <memory> // make_unique
|
||||
#include <string>
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <fairmq/Version.h>
|
||||
#include <FairMQLogger.h>
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -40,7 +40,7 @@ Config::Config(const string& name, Plugin::Version version, const string& mainta
|
||||
LOG(debug) << "channel-config: Parsing channel configuration";
|
||||
SetProperties(SuboptParser(GetProperty<vector<string>>("channel-config"), idForParser));
|
||||
} else {
|
||||
LOG(warn) << "fair::mq::plugins::Config: no channels configuration provided via --mq-config or --channel-config";
|
||||
LOG(info) << "fair::mq::plugins::Config: no channels configuration provided via --mq-config or --channel-config";
|
||||
}
|
||||
} catch (exception& e) {
|
||||
LOG(error) << e.what();
|
||||
@@ -62,11 +62,11 @@ Plugin::ProgOptions ConfigPluginProgramOptions()
|
||||
("transport", po::value<string >()->default_value("zeromq"), "Transport ('zeromq'/'shmem').")
|
||||
("network-interface", po::value<string >()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).")
|
||||
("init-timeout", po::value<int >()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).")
|
||||
("max-run-time", po::value<uint64_t >()->default_value(0), "Maximum runtime for the Running state handler, after which state will change to Ready (in seconds, 0 for no limit).")
|
||||
("print-channels", po::value<bool >()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (<channel name>:<min num subchannels>:<max num subchannels>)")
|
||||
("shm-segment-size", po::value<size_t >()->default_value(2ULL << 30), "Shared memory: size of the shared memory segment (in bytes).")
|
||||
("shm-allocation", po::value<string >()->default_value("rbtree_best_fit"), "Shared memory allocation algorithm: rbtree_best_fit/simple_seq_fit.")
|
||||
("shm-segment-id", po::value<uint16_t >()->default_value(0), "EXPERIMENTAL: Shared memory segment id for message creation.")
|
||||
("shmid", po::value<uint64_t >(), "EXPERIMENTAL: Fixed shmid to use instead of deriving it from the session name.")
|
||||
("shm-mlock-segment", po::value<bool >()->default_value(false), "Shared memory: mlock the shared memory segment after initialization (opened or created).")
|
||||
("shm-mlock-segment-on-creation", po::value<bool >()->default_value(false), "Shared memory: mlock the shared memory segment only once when created.")
|
||||
("shm-zero-segment", po::value<bool >()->default_value(false), "Shared memory: zero the shared memory segment memory after initialization (opened or created).")
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -36,7 +36,7 @@ REGISTER_FAIRMQ_PLUGIN(
|
||||
config, // Plugin name
|
||||
(Plugin::Version{FAIRMQ_VERSION_MAJOR, FAIRMQ_VERSION_MINOR, FAIRMQ_VERSION_PATCH}),
|
||||
"FairRootGroup <fairroot@gsi.de>",
|
||||
"https://github.com/FairRootGroup/FairRoot",
|
||||
"https://github.com/FairRootGroup/FairMQ",
|
||||
ConfigPluginProgramOptions
|
||||
)
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -56,11 +56,11 @@ Control::Control(const string& name, Plugin::Version version, const string& main
|
||||
SubscribeToDeviceStateChange([&](DeviceState newState) {
|
||||
LOG(trace) << "control plugin notified on new state: " << newState;
|
||||
|
||||
fStateQueue.Push(newState);
|
||||
|
||||
if (newState == DeviceState::Error) {
|
||||
fPluginShutdownRequested = true;
|
||||
fDeviceShutdownRequested = true;
|
||||
fStateQueue.Push(newState, [this]{ fDeviceShutdownRequested = true; });
|
||||
} else {
|
||||
fStateQueue.Push(newState);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -72,6 +72,9 @@ Control::Control(const string& name, Plugin::Version version, const string& main
|
||||
if (control == "static") {
|
||||
LOG(debug) << "Running builtin controller: static";
|
||||
fControllerThread = thread(&Control::StaticMode, this);
|
||||
} else if (control == "gui") {
|
||||
LOG(debug) << "Running builtin controller: gui";
|
||||
fControllerThread = thread(&Control::GUIMode, this);
|
||||
} else if (control == "dynamic" || control == "external" || control == "interactive") {
|
||||
LOG(debug) << "Running builtin controller: interactive";
|
||||
fControllerThread = thread(&Control::InteractiveMode, this);
|
||||
@@ -96,18 +99,42 @@ Control::Control(const string& name, Plugin::Version version, const string& main
|
||||
|
||||
auto Control::RunStartupSequence() -> void
|
||||
{
|
||||
ChangeDeviceState(DeviceStateTransition::InitDevice);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::InitializingDevice) {}
|
||||
ChangeDeviceState(DeviceStateTransition::CompleteInit);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::Initialized) {}
|
||||
ChangeDeviceState(DeviceStateTransition::Bind);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::Bound) {}
|
||||
ChangeDeviceState(DeviceStateTransition::Connect);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::DeviceReady) {}
|
||||
ChangeDeviceState(DeviceStateTransition::InitTask);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::Ready) {}
|
||||
ChangeDeviceState(DeviceStateTransition::Run);
|
||||
while (fStateQueue.WaitForNext() != DeviceState::Running) {}
|
||||
using Transition = DeviceStateTransition;
|
||||
using State = DeviceState;
|
||||
auto shutdownRequested = [this]{ return fDeviceShutdownRequested.load(); };
|
||||
|
||||
ChangeDeviceState(Transition::InitDevice);
|
||||
fStateQueue.WaitForStateOrCustom(State::InitializingDevice, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
ChangeDeviceState(Transition::CompleteInit);
|
||||
fStateQueue.WaitForStateOrCustom(State::Initialized, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
ChangeDeviceState(Transition::Bind);
|
||||
fStateQueue.WaitForStateOrCustom(State::Binding, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
fStateQueue.WaitForStateOrCustom(State::Bound, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
ChangeDeviceState(Transition::Connect);
|
||||
fStateQueue.WaitForStateOrCustom(State::Connecting, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
fStateQueue.WaitForStateOrCustom(State::DeviceReady, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
ChangeDeviceState(Transition::InitTask);
|
||||
fStateQueue.WaitForStateOrCustom(State::InitializingTask, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
fStateQueue.WaitForStateOrCustom(State::Ready, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
|
||||
ChangeDeviceState(Transition::Run);
|
||||
fStateQueue.WaitForStateOrCustom(State::Running, shutdownRequested);
|
||||
if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
|
||||
}
|
||||
|
||||
auto ControlPluginProgramOptions() -> Plugin::ProgOptions
|
||||
@@ -120,10 +147,8 @@ auto ControlPluginProgramOptions() -> Plugin::ProgOptions
|
||||
return pluginOptions;
|
||||
}
|
||||
|
||||
auto Control::InteractiveMode() -> void
|
||||
try {
|
||||
RunStartupSequence();
|
||||
|
||||
auto Control::RunREPL() -> void
|
||||
{
|
||||
char input = 0; // hold the user console input
|
||||
pollfd cinfd[1];
|
||||
cinfd[0].fd = fileno(stdin);
|
||||
@@ -158,7 +183,7 @@ try {
|
||||
case 'i':
|
||||
cout << "\n --> [i] init device\n\n" << flush;
|
||||
if (ChangeDeviceState(DeviceStateTransition::InitDevice)) {
|
||||
while (fStateQueue.WaitForNext() != DeviceState::InitializingDevice) {}
|
||||
fStateQueue.WaitForState(DeviceState::InitializingDevice);
|
||||
ChangeDeviceState(DeviceStateTransition::CompleteInit);
|
||||
}
|
||||
break;
|
||||
@@ -240,7 +265,19 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
RunShutdownSequence();
|
||||
}
|
||||
|
||||
auto Control::InteractiveMode() -> void
|
||||
try {
|
||||
RunStartupSequence();
|
||||
|
||||
if(!fDeviceShutdownRequested) {
|
||||
RunREPL();
|
||||
}
|
||||
|
||||
if(!fDeviceShutdownRequested) {
|
||||
RunShutdownSequence();
|
||||
}
|
||||
} catch (PluginServices::DeviceControlError& e) {
|
||||
// If we are here, it means another plugin has taken control. That's fine, just print the exception message and do nothing else.
|
||||
LOG(debug) << e.what();
|
||||
@@ -363,16 +400,13 @@ auto Control::StaticMode() -> void
|
||||
try {
|
||||
RunStartupSequence();
|
||||
|
||||
{
|
||||
// Wait for next state, which is DeviceState::Ready,
|
||||
// or for device shutdown request (Ctrl-C)
|
||||
pair<bool, fair::mq::State> result;
|
||||
do {
|
||||
result = fStateQueue.WaitForNext(chrono::milliseconds(50));
|
||||
} while (result.first == false && !fDeviceShutdownRequested);
|
||||
}
|
||||
// Wait for next state, which is DeviceState::Ready,
|
||||
// or for device shutdown request (Ctrl-C)
|
||||
fStateQueue.WaitForNextOrCustom([this]{ return fDeviceShutdownRequested.load(); });
|
||||
|
||||
RunShutdownSequence();
|
||||
if(!fDeviceShutdownRequested) {
|
||||
RunShutdownSequence();
|
||||
}
|
||||
} catch (PluginServices::DeviceControlError& e) {
|
||||
// If we are here, it means another plugin has taken control. That's fine, just print the exception message and do nothing else.
|
||||
LOG(debug) << e.what();
|
||||
@@ -380,6 +414,24 @@ try {
|
||||
ReleaseDeviceControl();
|
||||
}
|
||||
|
||||
auto Control::GUIMode() -> void
|
||||
try {
|
||||
RunStartupSequence();
|
||||
|
||||
// Wait for device shutdown request (Ctrl-C)
|
||||
fStateQueue.WaitForCustom([this]{ return fDeviceShutdownRequested.load(); });
|
||||
|
||||
if(!fDeviceShutdownRequested) {
|
||||
RunShutdownSequence();
|
||||
}
|
||||
} catch (PluginServices::DeviceControlError& e) {
|
||||
// If we are here, it means another plugin has taken control. That's fine, just print the
|
||||
// exception message and do nothing else.
|
||||
LOG(debug) << e.what();
|
||||
} catch (DeviceErrorState&) {
|
||||
ReleaseDeviceControl();
|
||||
}
|
||||
|
||||
auto Control::SignalHandler() -> void
|
||||
{
|
||||
while (gSignalCount == 0 && !fPluginShutdownRequested) {
|
||||
@@ -391,10 +443,10 @@ auto Control::SignalHandler() -> void
|
||||
LOG(info) << "Waiting for graceful device shutdown. Hit Ctrl-C again to abort immediately.";
|
||||
|
||||
// Signal and wait for controller thread, if we are controller
|
||||
fDeviceShutdownRequested = true;
|
||||
fStateQueue.Notify([this] { fDeviceShutdownRequested = true; });
|
||||
{
|
||||
unique_lock<mutex> lock(fControllerMutex);
|
||||
if (fControllerThread.joinable()) fControllerThread.join();
|
||||
if (fControllerThread.joinable()) { fControllerThread.join(); }
|
||||
}
|
||||
|
||||
if (!fDeviceHasShutdown) {
|
||||
@@ -437,6 +489,12 @@ auto Control::RunShutdownSequence() -> void
|
||||
case DeviceState::Running:
|
||||
ChangeDeviceState(DeviceStateTransition::Stop);
|
||||
break;
|
||||
case DeviceState::Binding:
|
||||
case DeviceState::Connecting:
|
||||
case DeviceState::InitializingTask:
|
||||
case DeviceState::ResettingTask:
|
||||
case DeviceState::ResettingDevice:
|
||||
ChangeDeviceState(DeviceStateTransition::Auto);
|
||||
default:
|
||||
// LOG(debug) << "Controller ignoring event: " << nextState;
|
||||
break;
|
||||
@@ -456,9 +514,9 @@ Control::~Control()
|
||||
|
||||
{
|
||||
unique_lock<mutex> lock(fControllerMutex);
|
||||
if (fControllerThread.joinable()) fControllerThread.join();
|
||||
if (fControllerThread.joinable()) { fControllerThread.join(); }
|
||||
}
|
||||
if (fSignalHandlerThread.joinable()) fSignalHandlerThread.join();
|
||||
if (fSignalHandlerThread.joinable()) { fSignalHandlerThread.join(); }
|
||||
|
||||
UnsubscribeFromDeviceStateChange();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -43,8 +43,10 @@ class Control : public Plugin
|
||||
static auto PrintStateMachine() -> void;
|
||||
auto PrintNumberOfConnectedPeers() -> void;
|
||||
auto StaticMode() -> void;
|
||||
auto GUIMode() -> void;
|
||||
auto SignalHandler() -> void;
|
||||
auto RunShutdownSequence() -> void;
|
||||
auto RunREPL() -> void;
|
||||
auto RunStartupSequence() -> void;
|
||||
|
||||
std::thread fControllerThread;
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using FairMQDevicePtr = FairMQDevice*;
|
||||
using FairMQDevicePtr = fair::mq::Device*;
|
||||
|
||||
// to be implemented by the user to return a child class of FairMQDevice
|
||||
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& config);
|
||||
@@ -45,7 +45,7 @@ int main(int argc, char* argv[])
|
||||
// });
|
||||
|
||||
runner.AddHook<InstantiateDevice>([](DeviceRunner& r){
|
||||
r.fDevice = std::unique_ptr<FairMQDevice>{getDevice(r.fConfig)};
|
||||
r.fDevice = std::unique_ptr<fair::mq::Device>{getDevice(r.fConfig)};
|
||||
});
|
||||
|
||||
return runner.Run();
|
||||
|
56
fairmq/shmem/Common.cxx
Normal file
56
fairmq/shmem/Common.cxx
Normal file
@@ -0,0 +1,56 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <picosha2.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace fair::mq::shmem
|
||||
{
|
||||
|
||||
std::string makeShmIdStr(const std::string& sessionId, const std::string& userId)
|
||||
{
|
||||
std::string seed(userId + sessionId);
|
||||
// generate a 8-digit hex value out of sha256 hash
|
||||
std::vector<unsigned char> hash(4);
|
||||
picosha2::hash256(seed.begin(), seed.end(), hash.begin(), hash.end());
|
||||
|
||||
return picosha2::bytes_to_hex_string(hash.begin(), hash.end());
|
||||
}
|
||||
|
||||
std::string makeShmIdStr(const std::string& sessionId)
|
||||
{
|
||||
return makeShmIdStr(sessionId, std::to_string(geteuid()));
|
||||
}
|
||||
|
||||
uint64_t makeShmIdUint64(const std::string& sessionId)
|
||||
{
|
||||
std::string shmId = makeShmIdStr(sessionId);
|
||||
uint64_t id = 0;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << shmId;
|
||||
ss >> id;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string makeShmIdStr(uint64_t val)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::setfill('0') << std::setw(8) << std::hex << val;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace fair::mq::shmem
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user