Compare commits

..

23 Commits

Author SHA1 Message Date
Dennis Klein
69faa63c5b docs: Update README 2022-03-21 18:22:07 +01:00
Dennis Klein
b7474ae138 build: Deprecate components dds_plugin, sdk, sdk_commands 2022-03-21 18:22:07 +01:00
Dennis Klein
b426bf39d7 fix: Update metadata 2022-03-21 18:22:07 +01:00
Dennis Klein
6780b7452c fix(control): Honor SIGINT and SIGTERM in more places
* Queue next transition for long-running states (fix #421)
* Add *OrCustom/Push/Locked family of functions to StateQueue to enable
  composition with custom signals
2022-03-21 16:28:43 +01:00
Dennis Klein
27277b11b4 fix(Device): Warning about narrowing conversion 2022-03-21 16:28:43 +01:00
Dennis Klein
cb5029f826 fix(Device): Spawn rate logger thread only if needed 2022-03-21 16:28:43 +01:00
Dennis Klein
5d45d89269 feat: Remove --max-run-time option
BREAKING CHANGE: was introduced in 1.4.0 release but appears unused
2022-03-21 16:28:43 +01:00
Dennis Klein
eb9ddc81cf ci: Run thread sanitizer with clang++ 2022-03-21 16:28:43 +01:00
Dennis Klein
f5891d5ae3 ci: Add thread sanitizer check and bump all checks to Fedora 35 2022-03-21 16:28:43 +01:00
Dennis Klein
3b2ad1f6f4 ci: Add Fedora 35 build 2022-03-21 16:28:43 +01:00
Giulio Eulisse
fa0bf96eb2 Skip error message only for tcp 2022-02-28 19:13:00 +01:00
Alexey Rybalchenko
29827f0426 Shm: bring back thread-safety for fRegions (intra-process) 2022-02-16 23:17:04 +01:00
Alexey Rybalchenko
8efe7adf0e Shm: fix number of region events 2022-02-16 23:17:04 +01:00
Alexey Rybalchenko
b747a8787c shm: check region size when opening existing 2022-02-08 09:09:25 +01:00
Alexey Rybalchenko
1a75141fc4 shm: allow monitor::ResetContent to cleanup after a crash 2022-02-02 10:49:00 +01:00
Alexey Rybalchenko
2f82eb4f09 shm: monitor: disable number of msgs in the ack queue output 2022-02-02 10:49:00 +01:00
Alexey Rybalchenko
92a56c26bc shm: remove UR queues on ResetContent 2022-02-02 10:49:00 +01:00
Alexey Rybalchenko
4f9aeda8ec shm: Add size to UnmanagedRegion debug output 2022-02-02 10:49:00 +01:00
Giulio Eulisse
ad894c79cf GUI Controller
provide a controller which can be used to control state
transitions from an external GUI.
2022-01-25 18:02:25 +01:00
Alexey Rybalchenko
5f33401d41 Parallelize more tests 2022-01-25 11:55:38 +01:00
Alexey Rybalchenko
f4d39d224b Avoid fixed ports in the test suites 2022-01-25 11:55:38 +01:00
Alexey Rybalchenko
bfd08bb33f Don't use to-be-deprecated names 2022-01-24 06:40:24 +01:00
Alexey Rybalchenko
f15f669853 use [[maybe_unused]] for values used in assertions 2022-01-24 06:40:24 +01:00
142 changed files with 1281 additions and 1166 deletions

View File

@@ -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 # # This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, # # GNU Lesser General Public Licence (LGPL) version 3, #
@@ -9,7 +9,7 @@
# Project ###################################################################### # Project ######################################################################
cmake_minimum_required(VERSION 3.15 FATAL_ERROR) 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) list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(GitHelper) include(GitHelper)

View File

@@ -4,19 +4,19 @@ Upstream-Contact: Mohammad Al-Turany <m.al-turany@gsi.de>
Source: https://github.com/FairRootGroup/FairMQ Source: https://github.com/FairRootGroup/FairMQ
Files: * Files: *
Copyright: 2012-2021, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH Copyright: 2012-2022, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright: 2012-2021, [see AUTHORS file] Copyright: 2012-2022, [see AUTHORS file]
Copyright: 2012-2021, [see CONTRIBUTORS file] Copyright: 2012-2022, [see CONTRIBUTORS file]
Comment: The copyright of individual contributors is documented in the Comment: The copyright of individual contributors is documented in the
Git history. Git history.
License: LGPL-3.0-only License: LGPL-3.0-only
Files: extern/googletest Files: extern/googletest
Copyright: 2008-2021, Google Inc. Copyright: 2008-2022, Google Inc.
License: GOOGLE License: GOOGLE
Files: extern/asio 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 License: BSL-1.0
Files: extern/PicoSHA2 Files: extern/PicoSHA2

View File

@@ -72,6 +72,9 @@ endif()
if(ENABLE_SANITIZER_THREAD) if(ENABLE_SANITIZER_THREAD)
list(APPEND options "-DENABLE_SANITIZER_THREAD=ON") list(APPEND options "-DENABLE_SANITIZER_THREAD=ON")
endif() endif()
if(CMAKE_CXX_COMPILER)
list(APPEND options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
endif()
if(CMAKE_CXX_FLAGS) if(CMAKE_CXX_FLAGS)
list(APPEND options "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}") list(APPEND options "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")
endif() endif()

6
Jenkinsfile vendored
View File

@@ -15,9 +15,9 @@ def jobMatrix(String type, List specs) {
ver = spec.ver ver = spec.ver
} else { // == 'check' } else { // == 'check'
job = "${spec.name}" job = "${spec.name}"
selector = 'fedora-34-x86_64' selector = 'fedora-35-x86_64'
os = 'fedora' os = 'fedora'
ver = '34' ver = '35'
} }
def label = "${job}" def label = "${job}"
@@ -96,6 +96,7 @@ pipeline{
[os: 'fedora', ver: '32', arch: 'x86_64', compiler: 'gcc-10', extra: all], [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: '33', arch: 'x86_64', compiler: 'gcc-10', extra: all],
[os: 'fedora', ver: '34', arch: 'x86_64', compiler: 'gcc-11', 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: 'x86_64', compiler: 'apple-clang-12', extra: '-DHAS_ASIO=ON'],
[os: 'macos', ver: '11', arch: 'arm64', compiler: 'apple-clang-13', 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: 'static-analyzers', extra: "${all_debug} -DRUN_STATIC_ANALYSIS=ON"],
[name: '{address,leak,ub}-sanitizers', [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'"], 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) parallel(builds + checks)

View File

@@ -1,12 +1,9 @@
<!-- {#mainpage} --> <!-- {#mainpage} -->
# FairMQ [![license](https://alfa-ci.gsi.de/shields/badge/license-LGPL--3.0-orange.svg)](COPYRIGHT) [![build status](https://alfa-ci.gsi.de/buildStatus/icon?job=FairRootGroup/FairMQ/dev)](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [![Coverity Badge](https://alfa-ci.gsi.de/shields/coverity/scan/fairrootgroup-fairmq.svg)](https://scan.coverity.com/projects/fairrootgroup-fairmq) # FairMQ [![license](https://alfa-ci.gsi.de/shields/badge/license-LGPL--3.0-orange.svg)](COPYRIGHT)
C++ Message Queuing Library and Framework C++ Message Queuing Library and Framework
| Release | Version | Docs | Docs: [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation)
| :---: | :--- | :--- |
| `stable` | [![release](https://alfa-ci.gsi.de/shields/github/release/FairRootGroup/FairMQ.svg)](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` | [![dev tag](https://alfa-ci.gsi.de/shields/github/tag/FairRootGroup/FairMQ.svg)](https://github.com/FairRootGroup/FairMQ/tags) | [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation) |
Find all FairMQ releases [here](https://github.com/FairRootGroup/FairMQ/releases). 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. `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). (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 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 are communicating through message passing. FairMQ does not only allow the user to use different transport
shapes the integration points for the user task. Devices also incorporate a plugin system for runtime configuration and control. but also to mix them; i.e: A Device can communicate using different transport on different channels at the
Next to the provided devices and plugins (e.g. [DDS](https://github.com/FairRootGroup/DDS)) same time. Device execution is modelled as a simple state machine that shapes the integration points for
the user can extend FairMQ by developing his own plugins to integrate his devices with external the user task. Devices also incorporate a plugin system for runtime configuration and control.
configuration and control services. 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) - FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
a simulation, reconstruction and analysis framework. 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. 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 ## Usage
FairMQ ships as a CMake package, so in your `CMakeLists.txt` you can discover it like this: FairMQ ships as a CMake package, so in your `CMakeLists.txt` you can discover it like this:
```cmake ```cmake
find_package(FairCMakeModules 0.2 REQUIRED) find_package(FairCMakeModules 1.0 REQUIRED)
include(FairFindPackage2) include(FairFindPackage2)
find_package2(FairMQ) find_package2(FairMQ)
find_package2_implicit_dependencies() 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: Optionally, you can require certain FairMQ package components and a minimum version:
```cmake ```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. When building FairMQ, CMake will print a summary table of all available package components.
## Dependencies ## Dependencies
* [asio](https://github.com/chriskohlhoff/asio) (optionally bundled) * [asio](https://github.com/chriskohlhoff/asio)
* [asiofi](https://github.com/FairRootGroup/asiofi) * [asiofi](https://github.com/FairRootGroup/asiofi)
* [Boost](https://www.boost.org/) * [Boost](https://www.boost.org/)
* [CMake](https://cmake.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/) * [Doxygen](http://www.doxygen.org/)
* [FairCMakeModules](https://github.com/FairRootGroup/FairCMakeModules) (optionally bundled) * [FairCMakeModules](https://github.com/FairRootGroup/FairCMakeModules) (optionally bundled)
* [FairLogger](https://github.com/FairRootGroup/FairLogger) * [FairLogger](https://github.com/FairRootGroup/FairLogger)
* [Flatbuffers](https://google.github.io/flatbuffers/)
* [GTest](https://github.com/google/googletest) (optionally bundled) * [GTest](https://github.com/google/googletest) (optionally bundled)
* [PMIx](https://pmix.org/) * [PMIx](https://pmix.org/)
* [ZeroMQ](http://zeromq.org/) * [ZeroMQ](http://zeromq.org/)
Which dependencies are required depends on which components are built. 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 ## CMake options
@@ -102,7 +103,6 @@ On command line:
* `-DBUILD_TESTING=OFF` disables building of tests. * `-DBUILD_TESTING=OFF` disables building of tests.
* `-DBUILD_EXAMPLES=OFF` disables building of examples. * `-DBUILD_EXAMPLES=OFF` disables building of examples.
* `-DBUILD_OFI_TRANSPORT=ON` enables building of the experimental OFI transport. * `-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_PMIX_PLUGIN=ON` enables building of the PMIx plugin.
* `-DBUILD_DOCS=ON` enables building of API docs. * `-DBUILD_DOCS=ON` enables building of API docs.
* You can hint non-system installations for dependent packages, see the #installation-from-source section above * You can hint non-system installations for dependent packages, see the #installation-from-source section above

View File

@@ -34,9 +34,9 @@ macro(fairmq_summary_components)
endif() endif()
message(STATUS " ${BWhite}ofi_transport${CR} ${ofi_summary}") message(STATUS " ${BWhite}ofi_transport${CR} ${ofi_summary}")
if(BUILD_DDS_PLUGIN) 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() 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() endif()
message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}") message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}")
if(BUILD_PMIX_PLUGIN) if(BUILD_PMIX_PLUGIN)
@@ -58,15 +58,15 @@ macro(fairmq_summary_components)
endif() endif()
message(STATUS " ${BWhite}docs${CR} ${docs_summary}") message(STATUS " ${BWhite}docs${CR} ${docs_summary}")
if(BUILD_SDK) 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() 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() endif()
message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}") message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}")
if(BUILD_SDK_COMMANDS) 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() 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() endif()
message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}") message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}")
if(BUILD_TIDY_TOOL) 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})") set(sdk_tidy_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_TIDY_TOOL=ON${CR})")
endif() endif()
message(STATUS " ${BWhite}tidy_tool${CR} ${sdk_tidy_summary}") 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() endmacro()
macro(fairmq_summary_static_analysis) macro(fairmq_summary_static_analysis)

View File

@@ -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` | | `transport` | at the end of `fair::mq::State::InitializingDevice` |
| `network-interface` | 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` | | `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-segment-size` | at the end of `fair::mq::State::InitializingDevice` |
| `shm-monitor` | 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` | | `ofi-size-hint` | at the end of `fair::mq::State::InitializingDevice` |

View File

@@ -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) 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) 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) 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 # install

View File

@@ -30,7 +30,7 @@ struct Sampler : fair::mq::Device
// create message object with a pointer to the data buffer, its size, // create message object with a pointer to the data buffer, its size,
// custom deletion function (called when transfer is done), // custom deletion function (called when transfer is done),
// and pointer to the object managing the data buffer // and pointer to the object managing the data buffer
FairMQMessagePtr msg(NewMessage( fair::mq::MessagePtr msg(NewMessage(
const_cast<char*>(text->c_str()), const_cast<char*>(text->c_str()),
text->length(), text->length(),
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },

View File

@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); 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()) << "\""; LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";

View File

@@ -8,20 +8,23 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi 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 # 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="fairmq-ex-1-1-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --rate 1" SAMPLER+=" --rate 1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $session"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -29,13 +32,16 @@ SINK="fairmq-ex-1-1-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --transport $transport" SINK+=" --transport $transport"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh"
SINK+=" --session $SESSION" SINK+=" --session $session"
SINK+=" --shm-segment-size 100000000"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
# wait for sampler and sink to finish # wait for sampler and sink to finish
wait $SAMPLER_PID wait $SAMPLER_PID
wait $SINK_PID wait $SINK_PID
rm $chanAddr

View File

@@ -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) 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) 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) 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 # install

View File

@@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
OnData("data1", &Processor::HandleData); OnData("data1", &Processor::HandleData);
} }
bool HandleData(FairMQMessagePtr& msg, int) bool HandleData(fair::mq::MessagePtr& msg, int)
{ {
LOG(info) << "Received data, processing..."; LOG(info) << "Received data, processing...";
@@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
// its size, // its size,
// custom deletion function (called when transfer is done), // custom deletion function (called when transfer is done),
// and pointer to the object managing the data buffer // 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(), text->length(),
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
text)); text));

View File

@@ -28,7 +28,7 @@ struct Sampler : fair::mq::Device
{ {
// Initializing message with NewStaticMessage will avoid copy // Initializing message with NewStaticMessage will avoid copy
// but won't delete the data after the sending is completed. // 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 << "\""; LOG(info) << "Sending \"" << fText << "\"";

View File

@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); 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()) << "\""; LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";

View File

@@ -8,20 +8,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi 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 # 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="fairmq-ex-1-n-1-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $session"
SAMPLER+=" --severity debug"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --max-iterations 2" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -29,10 +34,12 @@ PROCESSOR1="fairmq-ex-1-n-1-processor"
PROCESSOR1+=" --id processor1" PROCESSOR1+=" --id processor1"
PROCESSOR1+=" --transport $transport" PROCESSOR1+=" --transport $transport"
PROCESSOR1+=" --verbosity veryhigh" PROCESSOR1+=" --verbosity veryhigh"
PROCESSOR1+=" --session $SESSION" PROCESSOR1+=" --session $session"
PROCESSOR1+=" --severity debug"
PROCESSOR1+=" --shm-segment-size 100000000"
PROCESSOR1+=" --control static --color false" PROCESSOR1+=" --control static --color false"
PROCESSOR1+=" --mq-config $ex2config" PROCESSOR1+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
PROCESSOR1+=" --config-key processor" PROCESSOR1+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR1 & @CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR1 &
PROCESSOR1_PID=$! PROCESSOR1_PID=$!
@@ -40,10 +47,12 @@ PROCESSOR2="fairmq-ex-1-n-1-processor"
PROCESSOR2+=" --id processor2" PROCESSOR2+=" --id processor2"
PROCESSOR2+=" --transport $transport" PROCESSOR2+=" --transport $transport"
PROCESSOR2+=" --verbosity veryhigh" PROCESSOR2+=" --verbosity veryhigh"
PROCESSOR2+=" --session $SESSION" PROCESSOR2+=" --session $session"
PROCESSOR2+=" --severity debug"
PROCESSOR2+=" --shm-segment-size 100000000"
PROCESSOR2+=" --control static --color false" PROCESSOR2+=" --control static --color false"
PROCESSOR2+=" --mq-config $ex2config" PROCESSOR2+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
PROCESSOR2+=" --config-key processor" PROCESSOR2+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR2 & @CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR2 &
PROCESSOR2_PID=$! PROCESSOR2_PID=$!
@@ -51,10 +60,12 @@ SINK="fairmq-ex-1-n-1-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --transport $transport" SINK+=" --transport $transport"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh"
SINK+=" --session $SESSION" SINK+=" --session $session"
SINK+=" --severity debug"
SINK+=" --shm-segment-size 100000000"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --max-iterations 2" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
@@ -69,3 +80,5 @@ kill -SIGINT $PROCESSOR2_PID
# wait for everything to finish # wait for everything to finish
wait $PROCESSOR1_PID wait $PROCESSOR1_PID
wait $PROCESSOR2_PID wait $PROCESSOR2_PID
rm $chan1Addr; rm $chan2Addr

View File

@@ -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) 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) 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) 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) 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) 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 # install

View File

@@ -2,8 +2,6 @@
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@ export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
transport="zeromq" transport="zeromq"
multipart="false" multipart="false"
numParts="1" numParts="1"
@@ -20,8 +18,22 @@ if [[ $3 =~ ^[0-9]+$ ]]; then
numParts=$3 numParts=$3
fi 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 # 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="fairmq-bsampler"
SAMPLER+=" --id bsampler1" SAMPLER+=" --id bsampler1"
@@ -30,14 +42,15 @@ SAMPLER+=" --transport $transport"
SAMPLER+=" --color false" SAMPLER+=" --color false"
SAMPLER+=" --control static" SAMPLER+=" --control static"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --severity debug" SAMPLER+=" --severity debug"
SAMPLER+=" --msg-size 100000" SAMPLER+=" --msg-size 100000"
SAMPLER+=" --multipart $multipart" SAMPLER+=" --multipart $multipart"
SAMPLER+=" --num-parts $numParts" SAMPLER+=" --num-parts $numParts"
SAMPLER+=" --msg-rate 1" SAMPLER+=" --msg-rate 1"
SAMPLER+=" --max-iterations 0" SAMPLER+=" --max-iterations 0"
SAMPLER+=" --out-channel data1" SAMPLER+=" --out-channel $chan1"
SAMPLER+=" --channel-config name=data1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555" SAMPLER+=" --channel-config name=$chan1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
@FAIRMQ_BIN_DIR@/$SAMPLER & @FAIRMQ_BIN_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -48,11 +61,12 @@ SPLITTER+=" --transport $transport"
SPLITTER+=" --color false" SPLITTER+=" --color false"
SPLITTER+=" --control static" SPLITTER+=" --control static"
SPLITTER+=" --verbosity veryhigh" SPLITTER+=" --verbosity veryhigh"
SPLITTER+=" --shm-segment-size 100000000"
SPLITTER+=" --multipart $multipart" SPLITTER+=" --multipart $multipart"
SPLITTER+=" --in-channel data1" SPLITTER+=" --in-channel $chan1"
SPLITTER+=" --out-channel data2" SPLITTER+=" --out-channel $chan2"
SPLITTER+=" --channel-config name=data1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555" SPLITTER+=" --channel-config name=$chan1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
SPLITTER+=" name=data2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556,address=tcp://localhost:5557" SPLITTER+=" name=$chan2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1,address=ipc://$chan2Addr2"
@FAIRMQ_BIN_DIR@/$SPLITTER & @FAIRMQ_BIN_DIR@/$SPLITTER &
SPLITTER_PID=$! SPLITTER_PID=$!
@@ -63,11 +77,12 @@ PROXY1+=" --transport $transport"
PROXY1+=" --color false" PROXY1+=" --color false"
PROXY1+=" --control static" PROXY1+=" --control static"
PROXY1+=" --verbosity veryhigh" PROXY1+=" --verbosity veryhigh"
PROXY1+=" --shm-segment-size 100000000"
PROXY1+=" --multipart $multipart" PROXY1+=" --multipart $multipart"
PROXY1+=" --in-channel data2" PROXY1+=" --in-channel $chan2"
PROXY1+=" --out-channel data3" PROXY1+=" --out-channel $chan3"
PROXY1+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556" PROXY1+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1"
PROXY1+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558" PROXY1+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1"
@FAIRMQ_BIN_DIR@/$PROXY1 & @FAIRMQ_BIN_DIR@/$PROXY1 &
PROXY1_PID=$! PROXY1_PID=$!
@@ -78,11 +93,12 @@ PROXY2+=" --transport $transport"
PROXY2+=" --color false" PROXY2+=" --color false"
PROXY2+=" --control static" PROXY2+=" --control static"
PROXY2+=" --verbosity veryhigh" PROXY2+=" --verbosity veryhigh"
PROXY2+=" --shm-segment-size 100000000"
PROXY2+=" --multipart $multipart" PROXY2+=" --multipart $multipart"
PROXY2+=" --in-channel data2" PROXY2+=" --in-channel $chan2"
PROXY2+=" --out-channel data3" PROXY2+=" --out-channel $chan3"
PROXY2+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5557" PROXY2+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr2"
PROXY2+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5559" PROXY2+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr2"
@FAIRMQ_BIN_DIR@/$PROXY2 & @FAIRMQ_BIN_DIR@/$PROXY2 &
PROXY2_PID=$! PROXY2_PID=$!
@@ -93,11 +109,12 @@ MERGER+=" --transport $transport"
MERGER+=" --color false" MERGER+=" --color false"
MERGER+=" --control static" MERGER+=" --control static"
MERGER+=" --verbosity veryhigh" MERGER+=" --verbosity veryhigh"
MERGER+=" --shm-segment-size 100000000"
MERGER+=" --multipart $multipart" MERGER+=" --multipart $multipart"
MERGER+=" --in-channel data3" MERGER+=" --in-channel $chan3"
MERGER+=" --out-channel data4" MERGER+=" --out-channel $chan4"
MERGER+=" --channel-config name=data3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558,address=tcp://localhost:5559" MERGER+=" --channel-config name=$chan3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1,address=ipc://$chan3Addr2"
MERGER+=" name=data4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560" MERGER+=" name=$chan4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
@FAIRMQ_BIN_DIR@/$MERGER & @FAIRMQ_BIN_DIR@/$MERGER &
MERGER_PID=$! MERGER_PID=$!
@@ -108,11 +125,12 @@ MULTIPLIER+=" --transport $transport"
MULTIPLIER+=" --color false" MULTIPLIER+=" --color false"
MULTIPLIER+=" --control static" MULTIPLIER+=" --control static"
MULTIPLIER+=" --verbosity veryhigh" MULTIPLIER+=" --verbosity veryhigh"
MULTIPLIER+=" --shm-segment-size 100000000"
MULTIPLIER+=" --multipart $multipart" MULTIPLIER+=" --multipart $multipart"
MULTIPLIER+=" --in-channel data4" MULTIPLIER+=" --in-channel $chan4"
MULTIPLIER+=" --out-channel data5" MULTIPLIER+=" --out-channel $chan5"
MULTIPLIER+=" --channel-config name=data4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560" MULTIPLIER+=" --channel-config name=$chan4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
MULTIPLIER+=" name=data5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561,address=tcp://localhost:5561" MULTIPLIER+=" name=$chan5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr,address=ipc://$chan5Addr"
@FAIRMQ_BIN_DIR@/$MULTIPLIER & @FAIRMQ_BIN_DIR@/$MULTIPLIER &
MULTIPLIER_PID=$! MULTIPLIER_PID=$!
@@ -126,8 +144,8 @@ SINK+=" --verbosity veryhigh"
SINK+=" --severity debug" SINK+=" --severity debug"
SINK+=" --multipart $multipart" SINK+=" --multipart $multipart"
SINK+=" --max-iterations 2" SINK+=" --max-iterations 2"
SINK+=" --in-channel data5" SINK+=" --in-channel $chan5"
SINK+=" --channel-config name=data5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561" SINK+=" --channel-config name=$chan5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr"
@FAIRMQ_BIN_DIR@/$SINK & @FAIRMQ_BIN_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
@@ -146,3 +164,5 @@ wait $PROXY1_PID
wait $PROXY2_PID wait $PROXY2_PID
wait $MERGER_PID wait $MERGER_PID
wait $MULTIPLIER_PID wait $MULTIPLIER_PID
rm $chan1Addr; rm $chan2Addr1; rm $chan2Addr2; rm $chan3Addr1; rm $chan3Addr2; rm $chan4Addr; rm $chan5Addr

View File

@@ -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) 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) 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) 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 # install

View File

@@ -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). // 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 // 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) { for (int i = 0; i < fNumDataChannels - 1; ++i) {
FairMQMessagePtr msgCopy(NewMessage()); fair::mq::MessagePtr msgCopy(NewMessage());
msgCopy->Copy(*msg); msgCopy->Copy(*msg);
Send(msgCopy, "data", i); Send(msgCopy, "data", i);
} }

View File

@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); 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())) << "\""; LOG(info) << "Received message: \"" << *(static_cast<uint64_t*>(msg->GetData())) << "\"";

View File

@@ -8,19 +8,24 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi 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 # 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="fairmq-ex-copypush-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION" SAMPLER+=" --severity debug"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --session $session"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -28,10 +33,12 @@ SINK1="fairmq-ex-copypush-sink"
SINK1+=" --id sink1" SINK1+=" --id sink1"
SINK1+=" --transport $transport" SINK1+=" --transport $transport"
SINK1+=" --verbosity veryhigh" SINK1+=" --verbosity veryhigh"
SINK1+=" --session $SESSION" SINK1+=" --severity debug"
SINK1+=" --shm-segment-size 100000000"
SINK1+=" --session $session"
SINK1+=" --control static --color false" SINK1+=" --control static --color false"
SINK1+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK1 &
SINK1_PID=$! SINK1_PID=$!
@@ -39,10 +46,12 @@ SINK2="fairmq-ex-copypush-sink"
SINK2+=" --id sink2" SINK2+=" --id sink2"
SINK2+=" --transport $transport" SINK2+=" --transport $transport"
SINK2+=" --verbosity veryhigh" SINK2+=" --verbosity veryhigh"
SINK2+=" --session $SESSION" SINK2+=" --severity debug"
SINK2+=" --shm-segment-size 100000000"
SINK2+=" --session $session"
SINK2+=" --control static --color false" SINK2+=" --control static --color false"
SINK2+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK2 &
SINK2_PID=$! SINK2_PID=$!
@@ -50,3 +59,5 @@ SINK2_PID=$!
wait $SAMPLER_PID wait $SAMPLER_PID
wait $SINK1_PID wait $SINK1_PID
wait $SINK2_PID wait $SINK2_PID
rm $chanAddr1; rm $chanAddr2

View File

@@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
OnData("data1", &Processor::HandleData); OnData("data1", &Processor::HandleData);
} }
bool HandleData(FairMQMessagePtr& msg, int) bool HandleData(fair::mq::MessagePtr& msg, int)
{ {
LOG(info) << "Received data, processing..."; LOG(info) << "Received data, processing...";
@@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
// its size, // its size,
// custom deletion function (called when transfer is done), // custom deletion function (called when transfer is done),
// and pointer to the object managing the data buffer // 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(), text->length(),
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
text)); text));

View File

@@ -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). // 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 // 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\""; LOG(info) << "Sending \"Data\"";

View File

@@ -25,7 +25,7 @@ struct Sink : fair::mq::Device
fIterations = fConfig->GetValue<uint64_t>("iterations"); 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()) << "\""; LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";

View File

@@ -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) 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) 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) 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) if(BUILD_OFI_TRANSPORT)
add_test(NAME Example.Multipart.ofi COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh ofi) 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() endif()
# install # install

View File

@@ -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. 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. All parts are guaranteed to be delivered together. The Receive call in the sink will recive the entire parts structure.

View File

@@ -35,15 +35,15 @@ struct Sampler : fair::mq::Device
} }
LOG(info) << "Sending header with stopFlag: " << header.stopFlag; 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). // 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 // Should only be used for small data because of the cost of an additional copy
parts.AddPart(NewSimpleMessage(header)); parts.AddPart(NewSimpleMessage(header));
parts.AddPart(NewMessage(1000)); parts.AddPart(NewMessage(1000));
// create more data parts, testing the FairMQParts in-place constructor // create more data parts, testing the fair::mq::Parts in-place constructor
FairMQParts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) }; fair::mq::Parts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
assert(auxData.Size() == 3); assert(auxData.Size() == 3);
parts.AddPart(std::move(auxData)); parts.AddPart(std::move(auxData));
assert(auxData.Size() == 0); assert(auxData.Size() == 0);

View File

@@ -20,7 +20,7 @@ struct Sink : fair::mq::Device
OnData("data", &Sink::HandleData); OnData("data", &Sink::HandleData);
} }
bool HandleData(FairMQParts& parts, int) bool HandleData(fair::mq::Parts& parts, int)
{ {
LOG(info) << "Received message with " << parts.Size() << " parts"; LOG(info) << "Received message with " << parts.Size() << " parts";

View File

@@ -8,19 +8,28 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi 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 # 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="fairmq-ex-multipart-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $session"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --max-iterations 1" SAMPLER+=" --max-iterations 1"
SAMPLER+=" --control static --color false" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -28,11 +37,14 @@ SINK="fairmq-ex-multipart-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --transport $transport" SINK+=" --transport $transport"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh"
SINK+=" --session $SESSION" SINK+=" --session $session"
SINK+=" --shm-segment-size 100000000"
SINK+=" --control static --color false" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
wait $SAMPLER_PID wait $SAMPLER_PID
wait $SINK_PID wait $SINK_PID
rm $chanIpcFile

View File

@@ -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) 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) 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 # install

View File

@@ -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. 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`.

View File

@@ -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). // 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 // 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"; LOG(info) << "Sending OK";

View File

@@ -7,7 +7,7 @@
********************************************************************************/ ********************************************************************************/
#include <fairmq/Device.h> #include <fairmq/Device.h>
#include <FairMQPoller.h> #include <fairmq/Poller.h>
#include <fairmq/runDevice.h> #include <fairmq/runDevice.h>
#include <chrono> #include <chrono>
@@ -26,13 +26,13 @@ struct Sampler : fair::mq::Device
void Run() override void Run() override
{ {
FairMQPollerPtr poller(NewPoller("data", "broadcast")); fair::mq::PollerPtr poller(NewPoller("data", "broadcast"));
while (!NewStatePending()) { while (!NewStatePending()) {
poller->Poll(100); poller->Poll(100);
if (poller->CheckInput("broadcast", 0)) { if (poller->CheckInput("broadcast", 0)) {
FairMQMessagePtr msg(NewMessage()); fair::mq::MessagePtr msg(NewMessage());
if (Receive(msg, "broadcast") > 0) { if (Receive(msg, "broadcast") > 0) {
LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\""; 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)) { if (poller->CheckOutput("data", 0)) {
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
FairMQMessagePtr msg(NewSimpleMessage(fText)); fair::mq::MessagePtr msg(NewSimpleMessage(fText));
if (Send(msg, "data") > 0) { if (Send(msg, "data") > 0) {
LOG(info) << "Sent \"" << fText << "\""; LOG(info) << "Sent \"" << fText << "\"";

View File

@@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); 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()) << "\""; LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
fReceivedBroadcast = true; fReceivedBroadcast = true;
@@ -35,7 +35,7 @@ struct Sink : fair::mq::Device
return CheckIterations(); 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()) << "\""; LOG(info) << "Received message: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
fReceivedData = true; fReceivedData = true;

View File

@@ -8,18 +8,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi fi
# setup a trap to kill everything if the test fails/timeouts session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $BROADCASTER_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $BROADCASTER_PID;' TERM 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="fairmq-ex-multiple-channels-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --session $session"
SINK+=" --transport $transport" SINK+=" --transport $transport"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh --severity debug"
SINK+=" --shm-segment-size 100000000"
SINK+=" --max-iterations 1" SINK+=" --max-iterations 1"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5555" SINK+=" --channel-config name=$dataChan,type=pull,method=connect,rateLogging=0,address=ipc://$dataChanAddr"
SINK+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005" SINK+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
@CMAKE_CURRENT_BINARY_DIR@/$SINK & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
@@ -27,21 +34,25 @@ sleep 1
SAMPLER="fairmq-ex-multiple-channels-sampler" SAMPLER="fairmq-ex-multiple-channels-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --session $session"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh --severity debug"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --max-iterations 1" SAMPLER+=" --max-iterations 1"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --channel-config name=data,type=push,method=bind,rateLogging=0,address=tcp://*:5555" SAMPLER+=" --channel-config name=$dataChan,type=push,method=bind,rateLogging=0,address=ipc://$dataChanAddr"
SAMPLER+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005" SAMPLER+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
BROADCASTER="fairmq-ex-multiple-channels-broadcaster" BROADCASTER="fairmq-ex-multiple-channels-broadcaster"
BROADCASTER+=" --id broadcaster1" BROADCASTER+=" --id broadcaster1"
BROADCASTER+=" --session $session"
BROADCASTER+=" --transport $transport" BROADCASTER+=" --transport $transport"
BROADCASTER+=" --verbosity veryhigh" BROADCASTER+=" --verbosity veryhigh --severity debug"
BROADCASTER+=" --shm-segment-size 100000000"
BROADCASTER+=" --control static --color false" 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 & @CMAKE_CURRENT_BINARY_DIR@/$BROADCASTER &
BROADCASTER_PID=$! BROADCASTER_PID=$!
@@ -53,3 +64,5 @@ kill -SIGINT $BROADCASTER_PID
# wait for broadcaster to finish # wait for broadcaster to finish
wait $BROADCASTER_PID wait $BROADCASTER_PID
rm $dataChanAddr; rm $broadcastChanAddr

View File

@@ -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) 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) 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 # install

View File

@@ -28,7 +28,7 @@ struct Sampler1 : fair::mq::Device
bool ConditionalRun() override bool ConditionalRun() override
{ {
// Creates a message using the transport of channel data1 // 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 // 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). // 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; uint64_t numAcks = 0;
while (!NewStatePending()) { while (!NewStatePending()) {
FairMQMessagePtr ack(NewMessageFor("ack", 0)); fair::mq::MessagePtr ack(NewMessageFor("ack", 0));
if (Receive(ack, "ack") < 0) { if (Receive(ack, "ack") < 0) {
break; break;
} }

View File

@@ -22,7 +22,7 @@ struct Sampler2 : fair::mq::Device
bool ConditionalRun() override 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 // 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). // successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).

View File

@@ -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) // 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++; fNumIterations1++;
// Creates a message using the transport of channel ack // 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) { if (Send(ack, "ack") < 0) {
return false; 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) // 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++; fNumIterations2++;
// return true if want to be called again (otherwise go to IDLE state) // return true if want to be called again (otherwise go to IDLE state)

View File

@@ -2,46 +2,57 @@
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@ 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="fairmq-ex-multiple-transports-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh --severity debug"
SINK+=" --session $SESSION" SINK+=" --shm-segment-size 100000000"
SINK+=" --session $session"
SINK+=" --max-iterations 1" SINK+=" --max-iterations 1"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --transport shmem" SINK+=" --transport shmem"
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555" SINK+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr"
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=zeromq" SINK+=" name=$chan2,type=pull,method=connect,address=ipc://$chan2Addr,transport=zeromq"
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq" SINK+=" name=$ackChan,type=pub,method=connect,address=ipc://$ackChanAddr,transport=zeromq"
@CMAKE_CURRENT_BINARY_DIR@/$SINK & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
SAMPLER1="fairmq-ex-multiple-transports-sampler1" SAMPLER1="fairmq-ex-multiple-transports-sampler1"
SAMPLER1+=" --id sampler1" SAMPLER1+=" --id sampler1"
SAMPLER1+=" --session $SESSION" SAMPLER1+=" --session $session"
SAMPLER1+=" --verbosity veryhigh" SAMPLER1+=" --verbosity veryhigh --severity debug"
SAMPLER1+=" --shm-segment-size 100000000"
SAMPLER1+=" --max-iterations 1" SAMPLER1+=" --max-iterations 1"
SAMPLER1+=" --control static --color false" SAMPLER1+=" --control static --color false"
SAMPLER1+=" --transport shmem" SAMPLER1+=" --transport shmem"
SAMPLER1+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:5555" SAMPLER1+=" --channel-config name=$chan1,type=push,method=bind,address=ipc://$chan1Addr"
SAMPLER1+=" name=ack,type=sub,method=bind,address=tcp://127.0.0.1:5557,transport=zeromq" SAMPLER1+=" name=$ackChan,type=sub,method=bind,address=ipc://$ackChanAddr,transport=zeromq"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER1 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER1 &
SAMPLER1_PID=$! SAMPLER1_PID=$!
SAMPLER2="fairmq-ex-multiple-transports-sampler2" SAMPLER2="fairmq-ex-multiple-transports-sampler2"
SAMPLER2+=" --id sampler2" SAMPLER2+=" --id sampler2"
SAMPLER2+=" --session $SESSION" SAMPLER2+=" --session $session"
SAMPLER2+=" --verbosity veryhigh" SAMPLER2+=" --verbosity veryhigh --severity debug"
SAMPLER2+=" --shm-segment-size 100000000"
SAMPLER2+=" --max-iterations 1" SAMPLER2+=" --max-iterations 1"
SAMPLER2+=" --control static --color false" SAMPLER2+=" --control static --color false"
SAMPLER2+=" --transport zeromq" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 &
SAMPLER2_PID=$! SAMPLER2_PID=$!
wait $SAMPLER1_PID wait $SAMPLER1_PID
wait $SAMPLER2_PID wait $SAMPLER2_PID
wait $SINK_PID wait $SINK_PID
rm $chan1Addr; rm $chan2Addr; rm $ackChanAddr

View File

@@ -24,7 +24,7 @@ namespace bpo = boost::program_options;
struct TFBuffer struct TFBuffer
{ {
FairMQParts parts; fair::mq::Parts parts;
chrono::steady_clock::time_point start; chrono::steady_clock::time_point start;
chrono::steady_clock::time_point end; chrono::steady_clock::time_point end;
}; };
@@ -43,7 +43,7 @@ struct Receiver : fair::mq::Device
fMaxTimeframes = GetConfig()->GetValue<int>("max-timeframes"); 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())); Header& h = *(static_cast<Header*>(parts.At(0)->GetData()));
// LOG(info) << "Received sub-time frame #" << h.id << " from Sender" << h.senderIndex; // 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)"); ("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>(); return std::make_unique<Receiver>();
} }

View File

@@ -28,11 +28,11 @@ struct Sender : fair::mq::Device
void Run() override void Run() override
{ {
FairMQChannel& dataInChannel = GetChannel("sync", 0); fair::mq::Channel& dataInChannel = GetChannel("sync", 0);
while (!NewStatePending()) { while (!NewStatePending()) {
Header h; Header h;
FairMQMessagePtr id(NewMessage()); fair::mq::MessagePtr id(NewMessage());
if (dataInChannel.Receive(id) > 0) { if (dataInChannel.Receive(id) > 0) {
h.id = *(static_cast<uint16_t*>(id->GetData())); h.id = *(static_cast<uint16_t*>(id->GetData()));
h.senderIndex = fIndex; h.senderIndex = fIndex;
@@ -40,7 +40,7 @@ struct Sender : fair::mq::Device
continue; continue;
} }
FairMQParts parts; fair::mq::Parts parts;
parts.AddPart(NewSimpleMessage(h)); parts.AddPart(NewSimpleMessage(h));
parts.AddPart(NewMessage(fSubtimeframeSize)); 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") ("subtimeframe-size", bpo::value<int>()->default_value(1000), "Subtimeframe size in bytes")
("num-receivers", bpo::value<int>()->required(), "Number of EPNs"); ("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>(); return std::make_unique<Sender>();
} }

View File

@@ -19,7 +19,7 @@ struct Synchronizer : fair::mq::Device
{ {
bool ConditionalRun() override bool ConditionalRun() override
{ {
FairMQMessagePtr msg(NewSimpleMessage(fTimeframeId)); fair::mq::MessagePtr msg(NewSimpleMessage(fTimeframeId));
if (Send(msg, "sync") > 0) { if (Send(msg, "sync") > 0) {
if (++fTimeframeId == UINT16_MAX - 1) { if (++fTimeframeId == UINT16_MAX - 1) {
@@ -37,7 +37,7 @@ struct Synchronizer : fair::mq::Device
}; };
void addCustomOptions(bpo::options_description& /* options */) {} 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>(); return std::make_unique<Synchronizer>();
} }

View File

@@ -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) { if (fDoQC.load() == true) {
FairMQMessagePtr msgCopy(NewMessage()); fair::mq::MessagePtr msgCopy(NewMessage());
msgCopy->Copy(*msg); msgCopy->Copy(*msg);
if (Send(msg, "qc") < 0) { if (Send(msg, "qc") < 0) {
return false; return false;

View File

@@ -9,12 +9,12 @@
#include <fairmq/Device.h> #include <fairmq/Device.h>
#include <fairmq/runDevice.h> #include <fairmq/runDevice.h>
class QCTask : public FairMQDevice class QCTask : public fair::mq::Device
{ {
public: public:
QCTask() QCTask()
{ {
OnData("qc", [](FairMQMessagePtr& /*msg*/, int) { OnData("qc", [](fair::mq::MessagePtr& /*msg*/, int) {
LOG(info) << "received data"; LOG(info) << "received data";
return false; return false;
}); });

View File

@@ -16,7 +16,7 @@ struct Sampler : fair::mq::Device
{ {
bool ConditionalRun() override bool ConditionalRun() override
{ {
FairMQMessagePtr msg(NewMessage(1000)); fair::mq::MessagePtr msg(NewMessage(1000));
if (Send(msg, "data1") < 0) { if (Send(msg, "data1") < 0) {
return false; return false;

View File

@@ -14,7 +14,7 @@
struct Sink : fair::mq::Device struct Sink : fair::mq::Device
{ {
Sink() { OnData("data2", &Sink::HandleData); } 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; namespace bpo = boost::program_options;

View File

@@ -13,7 +13,7 @@
namespace bpo = boost::program_options; namespace bpo = boost::program_options;
class Builder : public FairMQDevice class Builder : public fair::mq::Device
{ {
public: public:
Builder() = default; Builder() = default;
@@ -24,7 +24,7 @@ class Builder : public FairMQDevice
OnData("rb", &Builder::HandleData); OnData("rb", &Builder::HandleData);
} }
bool HandleData(FairMQMessagePtr& msg, int /*index*/) bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
{ {
if (Send(msg, fOutputChannelName) < 0) { if (Send(msg, fOutputChannelName) < 0) {
return false; return false;

View File

@@ -18,9 +18,9 @@ struct Processor : fair::mq::Device
OnData("bp", &Processor::HandleData); 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) { if (Send(msg2, "ps") < 0) {
return false; return false;
} }

View File

@@ -22,7 +22,7 @@ struct Readout : fair::mq::Device
fMsgSize = fConfig->GetProperty<int>("msg-size"); fMsgSize = fConfig->GetProperty<int>("msg-size");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb", fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
0, 0,
10000000, 10000000,
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport [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 bool ConditionalRun() override
{ {
FairMQMessagePtr msg(NewMessageFor("rb", // channel fair::mq::MessagePtr msg(NewMessageFor("rb", // channel
0, // sub-channel 0, // sub-channel
fRegion, // region fRegion, // region
fRegion->GetData(), // ptr within region fRegion->GetData(), // ptr within region
@@ -71,7 +71,7 @@ struct Readout : fair::mq::Device
int fMsgSize = 10000; int fMsgSize = 10000;
uint64_t fMaxIterations = 0; uint64_t fMaxIterations = 0;
uint64_t fNumIterations = 0; uint64_t fNumIterations = 0;
FairMQUnmanagedRegionPtr fRegion = nullptr; fair::mq::UnmanagedRegionPtr fRegion = nullptr;
std::atomic<uint64_t> fNumUnackedMsgs = 0; std::atomic<uint64_t> fNumUnackedMsgs = 0;
}; };

View File

@@ -21,7 +21,7 @@ struct Sender : fair::mq::Device
OnData(fInputChannelName, &Sender::HandleData); OnData(fInputChannelName, &Sender::HandleData);
} }
bool HandleData(FairMQMessagePtr& msg, int /*index*/) bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
{ {
if (Send(msg, "sr") < 0) { if (Send(msg, "sr") < 0) {
return false; return false;

View File

@@ -26,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) 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) 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) 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 # install

View File

@@ -23,7 +23,7 @@ struct Sampler : fair::mq::Device
fLinger = fConfig->GetProperty<uint32_t>("region-linger"); fLinger = fConfig->GetProperty<uint32_t>("region-linger");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
GetChannel("data", 0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) { GetChannel("data", 0).Transport()->SubscribeToRegionEvents([](fair::mq::RegionInfo info) {
LOG(info) << "Region event: " << info.event << ": " LOG(info) << "Region event: " << info.event << ": "
<< (info.managed ? "managed" : "unmanaged") << (info.managed ? "managed" : "unmanaged")
<< ", id: " << info.id << ", id: " << info.id
@@ -36,7 +36,7 @@ struct Sampler : fair::mq::Device
regionCfg.linger = fLinger; // delay in ms before region destruction to collect outstanding events regionCfg.linger = fLinger; // delay in ms before region destruction to collect outstanding events
regionCfg.lock = true; // mlock region after creation regionCfg.lock = true; // mlock region after creation
regionCfg.zero = true; // zero region content after creation regionCfg.zero = true; // zero region content after creation
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data", // region is created using the transport of this channel... fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor("data", // region is created using the transport of this channel...
0, // ... and this sub-channel 0, // ... and this sub-channel
10000000, // region size 10000000, // region size
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport [this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
@@ -50,7 +50,7 @@ struct Sampler : fair::mq::Device
bool ConditionalRun() override bool ConditionalRun() override
{ {
FairMQMessagePtr msg(NewMessageFor("data", // channel fair::mq::MessagePtr msg(NewMessageFor("data", // channel
0, // sub-channel 0, // sub-channel
fRegion, // region fRegion, // region
fRegion->GetData(), // ptr within region fRegion->GetData(), // ptr within region
@@ -93,7 +93,7 @@ struct Sampler : fair::mq::Device
uint32_t fLinger = 100; uint32_t fLinger = 100;
uint64_t fMaxIterations = 0; uint64_t fMaxIterations = 0;
uint64_t fNumIterations = 0; uint64_t fNumIterations = 0;
FairMQUnmanagedRegionPtr fRegion = nullptr; fair::mq::UnmanagedRegionPtr fRegion = nullptr;
std::mutex fMtx; std::mutex fMtx;
uint64_t fNumUnackedMsgs = 0; uint64_t fNumUnackedMsgs = 0;
}; };

View File

@@ -9,22 +9,25 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
fi fi
msgSize="1000000" 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 # 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="fairmq-ex-region-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --severity debug" SAMPLER+=" --severity debug"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $session"
SAMPLER+=" --shm-segment-size 100000000"
SAMPLER+=" --verbosity veryhigh" SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --max-iterations 1" SAMPLER+=" --max-iterations 1"
SAMPLER+=" --msg-size $msgSize" SAMPLER+=" --msg-size $msgSize"
SAMPLER+=" --region-linger 500" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!
@@ -32,14 +35,17 @@ SINK="fairmq-ex-region-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --transport $transport" SINK+=" --transport $transport"
SINK+=" --severity debug" SINK+=" --severity debug"
SINK+=" --session $SESSION" SINK+=" --session $session"
SINK+=" --shm-segment-size 100000000"
SINK+=" --verbosity veryhigh" SINK+=" --verbosity veryhigh"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
# wait for sampler and sink to finish # wait for sampler and sink to finish
wait $SAMPLER_PID wait $SAMPLER_PID
wait $SINK_PID wait $SINK_PID
rm $chanAddr

View File

@@ -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) 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) 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) 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 # install

View File

@@ -32,11 +32,11 @@ struct Client : fair::mq::Device
// its size, // its size,
// custom deletion function (called when transfer is done), // custom deletion function (called when transfer is done),
// and pointer to the object managing the data buffer // 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 text->length(), // size
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
text)); // object that manages the data text)); // object that manages the data
FairMQMessagePtr rep(NewMessage()); fair::mq::MessagePtr rep(NewMessage());
LOG(info) << "Sending \"" << fText << "\" to server."; LOG(info) << "Sending \"" << fText << "\" to server.";

View File

@@ -26,7 +26,7 @@ struct Server : fair::mq::Device
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); 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()) << "\""; 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."; 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 text->length(), // size
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
text)); // object that manages the data text)); // object that manages the data

View File

@@ -8,19 +8,22 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1 transport=$1
fi 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 # 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="fairmq-ex-req-rep-client"
CLIENT+=" --id client" CLIENT+=" --id client"
CLIENT+=" --transport $transport" CLIENT+=" --transport $transport"
CLIENT+=" --verbosity veryhigh" CLIENT+=" --verbosity veryhigh"
CLIENT+=" --session $SESSION" CLIENT+=" --session $session"
CLIENT+=" --shm-segment-size 100000000"
CLIENT+=" --control static --color false" CLIENT+=" --control static --color false"
CLIENT+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$CLIENT &
CLIENT_PID=$! CLIENT_PID=$!
@@ -28,13 +31,16 @@ SERVER="fairmq-ex-req-rep-server"
SERVER+=" --id server" SERVER+=" --id server"
SERVER+=" --transport $transport" SERVER+=" --transport $transport"
SERVER+=" --verbosity veryhigh" SERVER+=" --verbosity veryhigh"
SERVER+=" --session $SESSION" SERVER+=" --session $session"
SERVER+=" --shm-segment-size 100000000"
SERVER+=" --control static --color false" SERVER+=" --control static --color false"
SERVER+=" --max-iterations 1" 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 & @CMAKE_CURRENT_BINARY_DIR@/$SERVER &
SERVER_PID=$! SERVER_PID=$!
# wait for everything to finish # wait for everything to finish
wait $CLIENT_PID wait $CLIENT_PID
wait $SERVER_PID wait $SERVER_PID
rm $chanAddr

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" * * 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 <boost/algorithm/string.hpp> // join/split
#include <chrono> #include <chrono>
#include <fairmq/Device.h> #include <fairmq/Device.h>
#include <fairmq/Tools.h> #include <fairmq/Tools.h>
#include <future>
#include <iomanip> #include <iomanip>
#include <list> #include <list>
#include <memory> // std::make_unique
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@@ -27,7 +27,6 @@ constexpr const char* Device::DefaultTransportName;
constexpr mq::Transport Device::DefaultTransportType; constexpr mq::Transport Device::DefaultTransportType;
constexpr const char* Device::DefaultNetworkInterface; constexpr const char* Device::DefaultNetworkInterface;
constexpr int Device::DefaultInitTimeout; constexpr int Device::DefaultInitTimeout;
constexpr uint64_t Device::DefaultMaxRunTime;
constexpr float Device::DefaultRate; constexpr float Device::DefaultRate;
constexpr const char* Device::DefaultSession; constexpr const char* Device::DefaultSession;
@@ -83,7 +82,6 @@ Device::Device(ProgOptions* config, tools::Version version)
, fMultitransportProceed(false) , fMultitransportProceed(false)
, fVersion(version) , fVersion(version)
, fRate(DefaultRate) , fRate(DefaultRate)
, fMaxRunRuntimeInS(DefaultMaxRunTime)
, fInitializationTimeoutInS(DefaultInitTimeout) , fInitializationTimeoutInS(DefaultInitTimeout)
, fTransitioning(false) , fTransitioning(false)
{ {
@@ -215,7 +213,6 @@ void Device::InitWrapper()
Init(); Init();
fRate = fConfig->GetProperty<float>("rate", DefaultRate); fRate = fConfig->GetProperty<float>("rate", DefaultRate);
fMaxRunRuntimeInS = fConfig->GetProperty<uint64_t>("max-run-time", DefaultMaxRunTime);
fInitializationTimeoutInS = fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout); fInitializationTimeoutInS = fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout);
try { try {
@@ -293,7 +290,9 @@ void Device::BindWrapper()
Bind(); Bind();
ChangeState(Transition::Auto); if (!NewStatePending()) {
ChangeState(Transition::Auto);
}
} }
void Device::ConnectWrapper() void Device::ConnectWrapper()
@@ -330,7 +329,9 @@ void Device::ConnectWrapper()
Connect(); Connect();
ChangeState(Transition::Auto); if (!NewStatePending()) {
ChangeState(Transition::Auto);
}
} }
void Device::AttachChannels(vector<Channel*>& chans) void Device::AttachChannels(vector<Channel*>& chans)
@@ -430,15 +431,28 @@ void Device::InitTaskWrapper()
{ {
InitTask(); InitTask();
ChangeState(Transition::Auto); if (!NewStatePending()) {
ChangeState(Transition::Auto);
}
} }
void Device::RunWrapper() void Device::RunWrapper()
{ {
LOG(info) << "fair::mq::Device running..."; LOG(info) << "fair::mq::Device running...";
// start the rate logger thread unique_ptr<thread> rateLogger;
future<void> rateLogger = async(launch::async, &Device::LogSocketRates, this); // 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(); }
});
// notify transports to resume transfers // notify transports to resume transfers
for (auto& t : fTransports) { for (auto& t : fTransports) {
@@ -481,8 +495,6 @@ void Device::RunWrapper()
PostRun(); PostRun();
cod.disable(); cod.disable();
rateLogger.get();
} }
void Device::HandleSingleChannelInput() void Device::HandleSingleChannelInput()
@@ -710,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> t0(chrono::high_resolution_clock::now());
chrono::time_point<chrono::high_resolution_clock> t1; chrono::time_point<chrono::high_resolution_clock> t1;
uint64_t secondsElapsed = 0;
while (!NewStatePending()) { while (!NewStatePending()) {
WaitFor(chrono::seconds(1)); WaitFor(chrono::seconds(1));
@@ -743,7 +754,7 @@ void Device::LogSocketRates()
bytesOut.at(i) = bytesOutNew.at(i); bytesOut.at(i) = bytesOutNew.at(i);
msgOut.at(i) = msgOutNew.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) " << "in: " << msgPerSecIn.at(i) << " (" << mbPerSecIn.at(i) << " MB) "
<< "out: " << msgPerSecOut.at(i) << " (" << mbPerSecOut.at(i) << " MB)"; << "out: " << msgPerSecOut.at(i) << " (" << mbPerSecOut.at(i) << " MB)";
} }
@@ -753,9 +764,6 @@ void Device::LogSocketRates()
} }
t0 = t1; t0 = t1;
if (fMaxRunRuntimeInS > 0 && ++secondsElapsed >= fMaxRunRuntimeInS) {
ChangeState(Transition::Stop);
}
} }
} }
@@ -770,7 +778,9 @@ void Device::ResetTaskWrapper()
{ {
ResetTask(); ResetTask();
ChangeState(Transition::Auto); if (!NewStatePending()) {
ChangeState(Transition::Auto);
}
} }
void Device::ResetWrapper() void Device::ResetWrapper()
@@ -784,7 +794,9 @@ void Device::ResetWrapper()
fChannels.clear(); fChannels.clear();
fTransports.clear(); fTransports.clear();
fTransportFactory.reset(); fTransportFactory.reset();
ChangeState(Transition::Auto); if (!NewStatePending()) {
ChangeState(Transition::Auto);
}
} }
Device::~Device() Device::~Device()

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -565,7 +565,6 @@ class Device
static constexpr mq::Transport DefaultTransportType = mq::Transport::ZMQ; static constexpr mq::Transport DefaultTransportType = mq::Transport::ZMQ;
static constexpr const char* DefaultNetworkInterface = "default"; static constexpr const char* DefaultNetworkInterface = "default";
static constexpr int DefaultInitTimeout = 120; static constexpr int DefaultInitTimeout = 120;
static constexpr uint64_t DefaultMaxRunTime = 0;
static constexpr float DefaultRate = 0.; static constexpr float DefaultRate = 0.;
static constexpr const char* DefaultSession = "default"; static constexpr const char* DefaultSession = "default";

View File

@@ -30,13 +30,13 @@
using namespace std; using namespace std;
using namespace fair::mq; using namespace fair::mq;
using namespace fair::mq::tools; using namespace tools;
using namespace boost::property_tree; using namespace boost::property_tree;
namespace fair::mq namespace fair::mq
{ {
fair::mq::Properties PtreeParser(const ptree& pt, const string& id) Properties PtreeParser(const ptree& pt, const string& id)
{ {
if (id.empty()) { if (id.empty()) {
throw ParserError("no device ID provided. Provide with `--id` cmd option"); 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); 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; ptree pt;
LOG(debug) << "Parsing JSON from " << filename << " ..."; LOG(debug) << "Parsing JSON from " << filename << " ...";
@@ -58,9 +58,9 @@ fair::mq::Properties JSONParser(const string& filename, const string& deviceId)
namespace helper 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) { for (const auto& node : fairMQOptions) {
if (node.first == "devices") { if (node.first == "devices") {
@@ -82,27 +82,27 @@ fair::mq::Properties DeviceParser(const ptree& fairMQOptions, const string& devi
return properties; return properties;
} }
void ChannelParser(const ptree& tree, fair::mq::Properties& properties) void ChannelParser(const ptree& tree, Properties& properties)
{ {
for (const auto& node : tree) { for (const auto& node : tree) {
if (node.first == "channels") { if (node.first == "channels") {
for (const auto& cn : node.second) { for (const auto& cn : node.second) {
fair::mq::Properties commonProperties; Properties commonProperties;
commonProperties.emplace("type", cn.second.get<string>("type", FairMQChannel::DefaultType)); commonProperties.emplace("type", cn.second.get<string>("type", Channel::DefaultType));
commonProperties.emplace("method", cn.second.get<string>("method", FairMQChannel::DefaultMethod)); commonProperties.emplace("method", cn.second.get<string>("method", Channel::DefaultMethod));
commonProperties.emplace("address", cn.second.get<string>("address", FairMQChannel::DefaultAddress)); commonProperties.emplace("address", cn.second.get<string>("address", Channel::DefaultAddress));
commonProperties.emplace("transport", cn.second.get<string>("transport", FairMQChannel::DefaultTransportName)); commonProperties.emplace("transport", cn.second.get<string>("transport", Channel::DefaultTransportName));
commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", FairMQChannel::DefaultSndBufSize)); commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", Channel::DefaultSndBufSize));
commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", FairMQChannel::DefaultRcvBufSize)); commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", Channel::DefaultRcvBufSize));
commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", FairMQChannel::DefaultSndKernelSize)); commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", Channel::DefaultSndKernelSize));
commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", FairMQChannel::DefaultRcvKernelSize)); commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", Channel::DefaultRcvKernelSize));
commonProperties.emplace("sndTimeoutMs", cn.second.get<int>("sndTimeoutMs", FairMQChannel::DefaultSndTimeoutMs)); commonProperties.emplace("sndTimeoutMs", cn.second.get<int>("sndTimeoutMs", Channel::DefaultSndTimeoutMs));
commonProperties.emplace("rcvTimeoutMs", cn.second.get<int>("rcvTimeoutMs", FairMQChannel::DefaultRcvTimeoutMs)); commonProperties.emplace("rcvTimeoutMs", cn.second.get<int>("rcvTimeoutMs", Channel::DefaultRcvTimeoutMs));
commonProperties.emplace("linger", cn.second.get<int>("linger", FairMQChannel::DefaultLinger)); commonProperties.emplace("linger", cn.second.get<int>("linger", Channel::DefaultLinger));
commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", FairMQChannel::DefaultRateLogging)); commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", Channel::DefaultRateLogging));
commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", FairMQChannel::DefaultPortRangeMin)); commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", Channel::DefaultPortRangeMin));
commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", FairMQChannel::DefaultPortRangeMax)); commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", Channel::DefaultPortRangeMax));
commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", FairMQChannel::DefaultAutoBind)); commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", Channel::DefaultAutoBind));
string name = cn.second.get<string>("name"); string name = cn.second.get<string>("name");
int numSockets = cn.second.get<int>("numSockets", 0); int numSockets = cn.second.get<int>("numSockets", 0);
@@ -128,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 // for each socket in channel
int i = 0; int i = 0;
@@ -137,7 +137,7 @@ void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties
if (node.first == "sockets") { if (node.first == "sockets") {
for (const auto& sn : node.second) { for (const auto& sn : node.second) {
// a sub-channel inherits relevant properties from the common channel ... // a sub-channel inherits relevant properties from the common channel ...
fair::mq::Properties newProperties(commonProperties); Properties newProperties(commonProperties);
// ... and adds/overwrites its own properties // ... and adds/overwrites its own properties
newProperties["type"] = sn.second.get<string>("type", boost::any_cast<string>(commonProperties.at("type"))); newProperties["type"] = sn.second.get<string>("type", boost::any_cast<string>(commonProperties.at("type")));
@@ -177,7 +177,7 @@ void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties
LOG(trace) << "\tNo sockets specified,"; LOG(trace) << "\tNo sockets specified,";
LOG(trace) << "\tapplying common settings to the channel:"; LOG(trace) << "\tapplying common settings to the channel:";
fair::mq::Properties newProperties(commonProperties); Properties newProperties(commonProperties);
for (auto& p : newProperties) { for (auto& p : newProperties) {
LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second; LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;

View File

@@ -12,7 +12,7 @@
/// ///
/// @author Mikolaj Krzewicki, mkrzewic@cern.ch /// @author Mikolaj Krzewicki, mkrzewic@cern.ch
#include <fairmq/FairMQTransportFactory.h> #include <fairmq/TransportFactory.h>
#include <fairmq/MemoryResources.h> #include <fairmq/MemoryResources.h>
namespace fair::mq namespace fair::mq
@@ -28,13 +28,13 @@ template<typename ContainerT>
// pmr::polymorphic_allocator<typename // pmr::polymorphic_allocator<typename
// ContainerT::value_type>, // ContainerT::value_type>,
// typename ContainerT::allocator_type>::value == true, // typename ContainerT::allocator_type>::value == true,
// FairMQMessagePtr>::type // MessagePtr>::type
FairMQMessagePtr getMessage(ContainerT &&container_, FairMQMemoryResource *targetResource = nullptr) MessagePtr getMessage(ContainerT &&container_, MemoryResource *targetResource = nullptr)
{ {
auto container = std::move(container_); auto container = std::move(container_);
auto alloc = container.get_allocator(); auto alloc = container.get_allocator();
auto resource = dynamic_cast<FairMQMemoryResource *>(alloc.resource()); auto resource = dynamic_cast<MemoryResource *>(alloc.resource());
if (!resource && !targetResource) { if (!resource && !targetResource) {
throw std::runtime_error("Neither the container or target resource specified"); throw std::runtime_error("Neither the container or target resource specified");
} }

View File

@@ -7,7 +7,7 @@
********************************************************************************/ ********************************************************************************/
#include <fairmq/Plugin.h> #include <fairmq/Plugin.h>
#include <FairMQLogger.h> #include <fairlogger/Logger.h>
#include <utility> #include <utility>
using namespace std; using namespace std;

View File

@@ -351,7 +351,7 @@ void ProgOptions::DeleteProperty(const string& key)
vm.erase(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); lock_guard<mutex> lock(fMtx);
unordered_map<string, int> existingChannels = GetChannelInfoImpl(); unordered_map<string, int> existingChannels = GetChannelInfoImpl();

View File

@@ -187,9 +187,7 @@ struct Machine_ : public state_machine_def<Machine_>
{ {
unique_lock<mutex> lock(fStateMtx); unique_lock<mutex> lock(fStateMtx);
while (!fNewStatePending) { fNewStatePendingCV.wait(lock, [this]{ return fNewStatePending.load(); });
fNewStatePendingCV.wait_for(lock, chrono::milliseconds(100));
}
LOG(state) << fState << " ---> " << fNewState; LOG(state) << fState << " ---> " << fNewState;
fState = static_cast<State>(fNewState); fState = static_cast<State>(fNewState);

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -9,16 +9,14 @@
#ifndef FAIRMQSTATEQUEUE_H_ #ifndef FAIRMQSTATEQUEUE_H_
#define FAIRMQSTATEQUEUE_H_ #define FAIRMQSTATEQUEUE_H_
#include <fairmq/States.h>
#include <queue>
#include <mutex>
#include <chrono> #include <chrono>
#include <utility> // pair
#include <condition_variable> #include <condition_variable>
#include <fairmq/States.h>
#include <mutex>
#include <queue>
#include <utility> // pair
namespace fair::mq namespace fair::mq {
{
class StateQueue class StateQueue
{ {
@@ -33,41 +31,47 @@ class StateQueue
fair::mq::State WaitForNext() fair::mq::State WaitForNext()
{ {
std::unique_lock<std::mutex> lock(fMtx); std::unique_lock<std::mutex> lock(fMtx);
while (fStates.empty()) { fCV.wait(lock, [this] { return Predicate(); });
fCV.wait_for(lock, std::chrono::milliseconds(50)); return 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;
} }
template<typename Rep, typename Period> template<typename Timeout>
std::pair<bool, fair::mq::State> WaitForNext(std::chrono::duration<Rep, Period> const& duration) std::pair<bool, fair::mq::State> WaitForNext(Timeout&& duration)
{ {
std::unique_lock<std::mutex> lock(fMtx); std::unique_lock<std::mutex> lock(fMtx);
fCV.wait_for(lock, duration); fCV.wait_for(lock, std::forward<Timeout>(duration), [this] { return Predicate(); });
return ReturnPairUnsafe();
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 };
} }
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) void Push(fair::mq::State state)
{ {
@@ -75,7 +79,35 @@ class StateQueue
std::lock_guard<std::mutex> lock(fMtx); std::lock_guard<std::mutex> lock(fMtx);
fStates.push(state); 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() void Clear()
@@ -88,8 +120,29 @@ class StateQueue
std::queue<fair::mq::State> fStates; std::queue<fair::mq::State> fStates;
std::mutex fMtx; std::mutex fMtx;
std::condition_variable fCV; 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_ */ #endif /* FAIRMQSTATEQUEUE_H_ */

View File

@@ -133,6 +133,7 @@ struct RegionConfig
bool removeOnDestruction = true; /// remove the region on object destruction bool removeOnDestruction = true; /// remove the region on object destruction
int creationFlags = 0; /// flags passed to the underlying transport on region creation 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 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::string path = ""; /// file path, if the region is backed by a file
std::optional<uint16_t> id = std::nullopt; /// region id std::optional<uint16_t> id = std::nullopt; /// region id
uint32_t linger = 100; /// delay in ms before region destruction to collect outstanding events uint32_t linger = 100; /// delay in ms before region destruction to collect outstanding events

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -21,7 +21,7 @@
#define FAIRMQ_GIT_DATE "@PROJECT_GIT_DATE@" #define FAIRMQ_GIT_DATE "@PROJECT_GIT_DATE@"
#define FAIRMQ_REPO_URL "https://github.com/FairRootGroup/FairMQ" #define FAIRMQ_REPO_URL "https://github.com/FairRootGroup/FairMQ"
#define FAIRMQ_LICENSE "LGPL-3.0" #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@" #define FAIRMQ_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
#endif // FAIR_MQ_VERSION_H #endif // FAIR_MQ_VERSION_H

View File

@@ -44,7 +44,7 @@ class BenchmarkSampler : public Device
void Run() override void Run() override
{ {
// store the channel reference to avoid traversing the map on every loop iteration // store the channel reference to avoid traversing the map on every loop iteration
FairMQChannel& dataOutChannel = GetChannel(fOutChannelName, 0); Channel& dataOutChannel = GetChannel(fOutChannelName, 0);
LOG(info) << "Starting the benchmark with message size of " << fMsgSize << " and " << fMaxIterations << " iterations."; LOG(info) << "Starting the benchmark with message size of " << fMsgSize << " and " << fMaxIterations << " iterations.";
auto tStart = std::chrono::high_resolution_clock::now(); auto tStart = std::chrono::high_resolution_clock::now();
@@ -53,7 +53,7 @@ class BenchmarkSampler : public Device
while (!NewStatePending()) { while (!NewStatePending()) {
if (fMultipart) { if (fMultipart) {
FairMQParts parts; Parts parts;
for (size_t i = 0; i < fNumParts; ++i) { for (size_t i = 0; i < fNumParts; ++i) {
parts.AddPart(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment})); parts.AddPart(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment}));
@@ -71,7 +71,7 @@ class BenchmarkSampler : public Device
++fNumIterations; ++fNumIterations;
} }
} else { } else {
FairMQMessagePtr msg(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment})); MessagePtr msg(dataOutChannel.NewMessage(fMsgSize, fair::mq::Alignment{fMsgAlignment}));
if (fMemSet) { if (fMemSet) {
std::memset(msg->GetData(), 0, msg->GetSize()); std::memset(msg->GetData(), 0, msg->GetSize());
} }

View File

@@ -9,7 +9,7 @@
#ifndef FAIR_MQ_MERGER_H #ifndef FAIR_MQ_MERGER_H
#define FAIR_MQ_MERGER_H #define FAIR_MQ_MERGER_H
#include <FairMQPoller.h> #include <fairmq/Poller.h>
#include <fairmq/Device.h> #include <fairmq/Device.h>
#include <fairlogger/Logger.h> #include <fairlogger/Logger.h>
@@ -45,13 +45,13 @@ class Merger : public Device
{ {
int numInputs = GetNumSubChannels(fInChannelName); int numInputs = GetNumSubChannels(fInChannelName);
std::vector<FairMQChannel*> chans; std::vector<Channel*> chans;
for (auto& chan : fChannels.at(fInChannelName)) { for (auto& chan : fChannels.at(fInChannelName)) {
chans.push_back(&chan); chans.push_back(&chan);
} }
FairMQPollerPtr poller(NewPoller(chans)); PollerPtr poller(NewPoller(chans));
if (fMultipart) { if (fMultipart) {
while (!NewStatePending()) { while (!NewStatePending()) {
@@ -61,7 +61,7 @@ class Merger : public Device
for (int i = 0; i < numInputs; ++i) { for (int i = 0; i < numInputs; ++i) {
// Check if the channel has data ready to be received. // Check if the channel has data ready to be received.
if (poller->CheckInput(i)) { if (poller->CheckInput(i)) {
FairMQParts payload; Parts payload;
if (Receive(payload, fInChannelName, i) >= 0) { if (Receive(payload, fInChannelName, i) >= 0) {
if (Send(payload, fOutChannelName) < 0) { if (Send(payload, fOutChannelName) < 0) {
@@ -83,7 +83,7 @@ class Merger : public Device
for (int i = 0; i < numInputs; ++i) { for (int i = 0; i < numInputs; ++i) {
// Check if the channel has data ready to be received. // Check if the channel has data ready to be received.
if (poller->CheckInput(i)) { if (poller->CheckInput(i)) {
FairMQMessagePtr payload(fTransportFactory->CreateMessage()); MessagePtr payload(fTransportFactory->CreateMessage());
if (Receive(payload, fInChannelName, i) >= 0) { if (Receive(payload, fInChannelName, i) >= 0) {
if (Send(payload, fOutChannelName) < 0) { if (Send(payload, fOutChannelName) < 0) {

View File

@@ -40,11 +40,11 @@ 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 i = 0; i < fOutChannelNames.size() - 1; ++i) { // all except last channel
for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage()); MessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(*payload); msgCopy->Copy(*payload);
Send(msgCopy, fOutChannelNames.at(i), j); Send(msgCopy, fOutChannelNames.at(i), j);
@@ -54,7 +54,7 @@ class Multiplier : public Device
unsigned int lastChannelSize = GetNumSubChannels(fOutChannelNames.back()); 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 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); msgCopy->Copy(*payload);
Send(msgCopy, fOutChannelNames.back(), i); Send(msgCopy, fOutChannelNames.back(), i);
@@ -65,14 +65,14 @@ class Multiplier : public Device
return true; 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 i = 0; i < fOutChannelNames.size() - 1; ++i) { // all except last channel
for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel
FairMQParts parts; Parts parts;
for (int k = 0; k < payload.Size(); ++k) { for (int k = 0; k < payload.Size(); ++k) {
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage()); MessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.AtRef(k)); msgCopy->Copy(payload.AtRef(k));
parts.AddPart(std::move(msgCopy)); parts.AddPart(std::move(msgCopy));
} }
@@ -84,10 +84,10 @@ class Multiplier : public Device
unsigned int lastChannelSize = GetNumSubChannels(fOutChannelNames.back()); 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 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) { for (int k = 0; k < payload.Size(); ++k) {
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage()); MessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.AtRef(k)); msgCopy->Copy(payload.AtRef(k));
parts.AddPart(std::move(msgCopy)); parts.AddPart(std::move(msgCopy));
} }

View File

@@ -34,7 +34,7 @@ class Proxy : public Device
{ {
if (fMultipart) { if (fMultipart) {
while (!NewStatePending()) { while (!NewStatePending()) {
FairMQParts payload; Parts payload;
if (Receive(payload, fInChannelName) >= 0) { if (Receive(payload, fInChannelName) >= 0) {
if (Send(payload, fOutChannelName) < 0) { if (Send(payload, fOutChannelName) < 0) {
LOG(debug) << "Transfer interrupted"; LOG(debug) << "Transfer interrupted";
@@ -47,7 +47,7 @@ class Proxy : public Device
} }
} else { } else {
while (!NewStatePending()) { while (!NewStatePending()) {
FairMQMessagePtr payload(fTransportFactory->CreateMessage()); MessagePtr payload(fTransportFactory->CreateMessage());
if (Receive(payload, fInChannelName) >= 0) { if (Receive(payload, fInChannelName) >= 0) {
if (Send(payload, fOutChannelName) < 0) { if (Send(payload, fOutChannelName) < 0) {
LOG(debug) << "Transfer interrupted"; LOG(debug) << "Transfer interrupted";

View File

@@ -9,7 +9,6 @@
#ifndef FAIR_MQ_SINK_H #ifndef FAIR_MQ_SINK_H
#define FAIR_MQ_SINK_H #define FAIR_MQ_SINK_H
#include <FairMQPoller.h>
#include <fairmq/Device.h> #include <fairmq/Device.h>
#include <fairmq/tools/Strings.h> #include <fairmq/tools/Strings.h>
@@ -48,7 +47,7 @@ class Sink : public Device
void Run() override void Run() override
{ {
// store the channel reference to avoid traversing the map on every loop iteration // store the channel reference to avoid traversing the map on every loop iteration
FairMQChannel& dataInChannel = GetChannel(fInChannelName, 0); Channel& dataInChannel = GetChannel(fInChannelName, 0);
LOG(info) << "Starting sink and expecting to receive " << fMaxIterations << " messages."; LOG(info) << "Starting sink and expecting to receive " << fMaxIterations << " messages.";
auto tStart = std::chrono::high_resolution_clock::now(); auto tStart = std::chrono::high_resolution_clock::now();
@@ -70,7 +69,7 @@ class Sink : public Device
while (!NewStatePending()) { while (!NewStatePending()) {
if (fMultipart) { if (fMultipart) {
FairMQParts parts; Parts parts;
if (dataInChannel.Receive(parts) < 0) { if (dataInChannel.Receive(parts) < 0) {
continue; continue;
} }
@@ -80,7 +79,7 @@ class Sink : public Device
} }
} }
} else { } else {
FairMQMessagePtr msg(dataInChannel.NewMessage()); MessagePtr msg(dataInChannel.NewMessage());
if (dataInChannel.Receive(msg) < 0) { if (dataInChannel.Receive(msg) < 0) {
continue; continue;
} }

View File

@@ -34,9 +34,9 @@ class Splitter : public Device
fDirection = 0; fDirection = 0;
if (fMultipart) { if (fMultipart) {
OnData(fInChannelName, &Splitter::HandleData<FairMQParts>); OnData(fInChannelName, &Splitter::HandleData<Parts>);
} else { } else {
OnData(fInChannelName, &Splitter::HandleData<FairMQMessagePtr>); OnData(fInChannelName, &Splitter::HandleData<MessagePtr>);
} }
} }

View File

@@ -10,7 +10,7 @@
#include <fairmq/ofi/Socket.h> #include <fairmq/ofi/Socket.h>
#include <fairmq/ofi/TransportFactory.h> #include <fairmq/ofi/TransportFactory.h>
#include <fairmq/tools/Strings.h> #include <fairmq/tools/Strings.h>
#include <FairMQLogger.h> #include <fairlogger/Logger.h>
#include <asiofi.hpp> #include <asiofi.hpp>
#include <asio/buffer.hpp> #include <asio/buffer.hpp>

View File

@@ -11,7 +11,7 @@
#include "PMIx.hpp" #include "PMIx.hpp"
#include <FairMQLogger.h> #include <fairlogger/Logger.h>
#include <fairmq/tools/Semaphore.h> #include <fairmq/tools/Semaphore.h>
#include <memory> // make_unique #include <memory> // make_unique
#include <string> #include <string>

View File

@@ -14,7 +14,7 @@
#include <fairmq/Plugin.h> #include <fairmq/Plugin.h>
#include <fairmq/Version.h> #include <fairmq/Version.h>
#include <FairMQLogger.h> #include <fairlogger/Logger.h>
#include <string> #include <string>
#include <sstream> #include <sstream>

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -62,7 +62,6 @@ Plugin::ProgOptions ConfigPluginProgramOptions()
("transport", po::value<string >()->default_value("zeromq"), "Transport ('zeromq'/'shmem').") ("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).") ("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).") ("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>)") ("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-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-allocation", po::value<string >()->default_value("rbtree_best_fit"), "Shared memory allocation algorithm: rbtree_best_fit/simple_seq_fit.")

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -36,7 +36,7 @@ REGISTER_FAIRMQ_PLUGIN(
config, // Plugin name config, // Plugin name
(Plugin::Version{FAIRMQ_VERSION_MAJOR, FAIRMQ_VERSION_MINOR, FAIRMQ_VERSION_PATCH}), (Plugin::Version{FAIRMQ_VERSION_MAJOR, FAIRMQ_VERSION_MINOR, FAIRMQ_VERSION_PATCH}),
"FairRootGroup <fairroot@gsi.de>", "FairRootGroup <fairroot@gsi.de>",
"https://github.com/FairRootGroup/FairRoot", "https://github.com/FairRootGroup/FairMQ",
ConfigPluginProgramOptions ConfigPluginProgramOptions
) )

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * 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) { SubscribeToDeviceStateChange([&](DeviceState newState) {
LOG(trace) << "control plugin notified on new state: " << newState; LOG(trace) << "control plugin notified on new state: " << newState;
fStateQueue.Push(newState);
if (newState == DeviceState::Error) { if (newState == DeviceState::Error) {
fPluginShutdownRequested = true; 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") { if (control == "static") {
LOG(debug) << "Running builtin controller: static"; LOG(debug) << "Running builtin controller: static";
fControllerThread = thread(&Control::StaticMode, this); 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") { } else if (control == "dynamic" || control == "external" || control == "interactive") {
LOG(debug) << "Running builtin controller: interactive"; LOG(debug) << "Running builtin controller: interactive";
fControllerThread = thread(&Control::InteractiveMode, this); fControllerThread = thread(&Control::InteractiveMode, this);
@@ -96,18 +99,42 @@ Control::Control(const string& name, Plugin::Version version, const string& main
auto Control::RunStartupSequence() -> void auto Control::RunStartupSequence() -> void
{ {
ChangeDeviceState(DeviceStateTransition::InitDevice); using Transition = DeviceStateTransition;
while (fStateQueue.WaitForNext() != DeviceState::InitializingDevice) {} using State = DeviceState;
ChangeDeviceState(DeviceStateTransition::CompleteInit); auto shutdownRequested = [this]{ return fDeviceShutdownRequested.load(); };
while (fStateQueue.WaitForNext() != DeviceState::Initialized) {}
ChangeDeviceState(DeviceStateTransition::Bind); ChangeDeviceState(Transition::InitDevice);
while (fStateQueue.WaitForNext() != DeviceState::Bound) {} fStateQueue.WaitForStateOrCustom(State::InitializingDevice, shutdownRequested);
ChangeDeviceState(DeviceStateTransition::Connect); if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
while (fStateQueue.WaitForNext() != DeviceState::DeviceReady) {}
ChangeDeviceState(DeviceStateTransition::InitTask); ChangeDeviceState(Transition::CompleteInit);
while (fStateQueue.WaitForNext() != DeviceState::Ready) {} fStateQueue.WaitForStateOrCustom(State::Initialized, shutdownRequested);
ChangeDeviceState(DeviceStateTransition::Run); if (fDeviceShutdownRequested) { return; /* --> shutdown sequence */ }
while (fStateQueue.WaitForNext() != DeviceState::Running) {}
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 auto ControlPluginProgramOptions() -> Plugin::ProgOptions
@@ -120,10 +147,8 @@ auto ControlPluginProgramOptions() -> Plugin::ProgOptions
return pluginOptions; return pluginOptions;
} }
auto Control::InteractiveMode() -> void auto Control::RunREPL() -> void
try { {
RunStartupSequence();
char input = 0; // hold the user console input char input = 0; // hold the user console input
pollfd cinfd[1]; pollfd cinfd[1];
cinfd[0].fd = fileno(stdin); cinfd[0].fd = fileno(stdin);
@@ -158,7 +183,7 @@ try {
case 'i': case 'i':
cout << "\n --> [i] init device\n\n" << flush; cout << "\n --> [i] init device\n\n" << flush;
if (ChangeDeviceState(DeviceStateTransition::InitDevice)) { if (ChangeDeviceState(DeviceStateTransition::InitDevice)) {
while (fStateQueue.WaitForNext() != DeviceState::InitializingDevice) {} fStateQueue.WaitForState(DeviceState::InitializingDevice);
ChangeDeviceState(DeviceStateTransition::CompleteInit); ChangeDeviceState(DeviceStateTransition::CompleteInit);
} }
break; break;
@@ -240,7 +265,19 @@ try {
} }
} }
RunShutdownSequence(); }
auto Control::InteractiveMode() -> void
try {
RunStartupSequence();
if(!fDeviceShutdownRequested) {
RunREPL();
}
if(!fDeviceShutdownRequested) {
RunShutdownSequence();
}
} catch (PluginServices::DeviceControlError& e) { } 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. // 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(); LOG(debug) << e.what();
@@ -363,16 +400,13 @@ auto Control::StaticMode() -> void
try { try {
RunStartupSequence(); RunStartupSequence();
{ // Wait for next state, which is DeviceState::Ready,
// Wait for next state, which is DeviceState::Ready, // or for device shutdown request (Ctrl-C)
// or for device shutdown request (Ctrl-C) fStateQueue.WaitForNextOrCustom([this]{ return fDeviceShutdownRequested.load(); });
pair<bool, fair::mq::State> result;
do {
result = fStateQueue.WaitForNext(chrono::milliseconds(50));
} while (result.first == false && !fDeviceShutdownRequested);
}
RunShutdownSequence(); if(!fDeviceShutdownRequested) {
RunShutdownSequence();
}
} catch (PluginServices::DeviceControlError& e) { } 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. // 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(); LOG(debug) << e.what();
@@ -380,6 +414,24 @@ try {
ReleaseDeviceControl(); 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 auto Control::SignalHandler() -> void
{ {
while (gSignalCount == 0 && !fPluginShutdownRequested) { 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."; LOG(info) << "Waiting for graceful device shutdown. Hit Ctrl-C again to abort immediately.";
// Signal and wait for controller thread, if we are controller // Signal and wait for controller thread, if we are controller
fDeviceShutdownRequested = true; fStateQueue.Notify([this] { fDeviceShutdownRequested = true; });
{ {
unique_lock<mutex> lock(fControllerMutex); unique_lock<mutex> lock(fControllerMutex);
if (fControllerThread.joinable()) fControllerThread.join(); if (fControllerThread.joinable()) { fControllerThread.join(); }
} }
if (!fDeviceHasShutdown) { if (!fDeviceHasShutdown) {
@@ -437,6 +489,12 @@ auto Control::RunShutdownSequence() -> void
case DeviceState::Running: case DeviceState::Running:
ChangeDeviceState(DeviceStateTransition::Stop); ChangeDeviceState(DeviceStateTransition::Stop);
break; break;
case DeviceState::Binding:
case DeviceState::Connecting:
case DeviceState::InitializingTask:
case DeviceState::ResettingTask:
case DeviceState::ResettingDevice:
ChangeDeviceState(DeviceStateTransition::Auto);
default: default:
// LOG(debug) << "Controller ignoring event: " << nextState; // LOG(debug) << "Controller ignoring event: " << nextState;
break; break;
@@ -456,9 +514,9 @@ Control::~Control()
{ {
unique_lock<mutex> lock(fControllerMutex); 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(); UnsubscribeFromDeviceStateChange();
} }

View File

@@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@@ -43,8 +43,10 @@ class Control : public Plugin
static auto PrintStateMachine() -> void; static auto PrintStateMachine() -> void;
auto PrintNumberOfConnectedPeers() -> void; auto PrintNumberOfConnectedPeers() -> void;
auto StaticMode() -> void; auto StaticMode() -> void;
auto GUIMode() -> void;
auto SignalHandler() -> void; auto SignalHandler() -> void;
auto RunShutdownSequence() -> void; auto RunShutdownSequence() -> void;
auto RunREPL() -> void;
auto RunStartupSequence() -> void; auto RunStartupSequence() -> void;
std::thread fControllerThread; std::thread fControllerThread;

View File

@@ -11,7 +11,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
using FairMQDevicePtr = FairMQDevice*; using FairMQDevicePtr = fair::mq::Device*;
// to be implemented by the user to return a child class of FairMQDevice // to be implemented by the user to return a child class of FairMQDevice
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& config); FairMQDevicePtr getDevice(const fair::mq::ProgOptions& config);
@@ -45,7 +45,7 @@ int main(int argc, char* argv[])
// }); // });
runner.AddHook<InstantiateDevice>([](DeviceRunner& r){ 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(); return runner.Run();

View File

@@ -28,6 +28,8 @@
namespace fair::mq::shmem namespace fair::mq::shmem
{ {
static constexpr uint64_t kManagementSegmentSize = 6553600;
struct SharedMemoryError : std::runtime_error { using std::runtime_error::runtime_error; }; struct SharedMemoryError : std::runtime_error { using std::runtime_error::runtime_error; };
using SimpleSeqFitSegment = boost::interprocess::basic_managed_shared_memory<char, using SimpleSeqFitSegment = boost::interprocess::basic_managed_shared_memory<char,
@@ -58,19 +60,22 @@ struct RegionInfo
: fPath("", alloc) : fPath("", alloc)
, fCreationFlags(0) , fCreationFlags(0)
, fUserFlags(0) , fUserFlags(0)
, fSize(0)
, fDestroyed(false) , fDestroyed(false)
{} {}
RegionInfo(const char* path, const int flags, const uint64_t userFlags, const VoidAlloc& alloc) RegionInfo(const char* path, int flags, uint64_t userFlags, uint64_t size, const VoidAlloc& alloc)
: fPath(path, alloc) : fPath(path, alloc)
, fCreationFlags(flags) , fCreationFlags(flags)
, fUserFlags(userFlags) , fUserFlags(userFlags)
, fSize(size)
, fDestroyed(false) , fDestroyed(false)
{} {}
Str fPath; Str fPath;
int fCreationFlags; int fCreationFlags;
uint64_t fUserFlags; uint64_t fUserFlags;
uint64_t fSize;
bool fDestroyed; bool fDestroyed;
}; };

View File

@@ -132,7 +132,7 @@ class Manager
: fShmId64(config ? config->GetProperty<uint64_t>("shmid", makeShmIdUint64(sessionName)) : makeShmIdUint64(sessionName)) : fShmId64(config ? config->GetProperty<uint64_t>("shmid", makeShmIdUint64(sessionName)) : makeShmIdUint64(sessionName))
, fShmId(makeShmIdStr(fShmId64)) , fShmId(makeShmIdStr(fShmId64))
, fSegmentId(config ? config->GetProperty<uint16_t>("shm-segment-id", 0) : 0) , fSegmentId(config ? config->GetProperty<uint16_t>("shm-segment-id", 0) : 0)
, fManagementSegment(boost::interprocess::open_or_create, std::string("fmq_" + fShmId + "_mng").c_str(), 6553600) , fManagementSegment(boost::interprocess::open_or_create, std::string("fmq_" + fShmId + "_mng").c_str(), kManagementSegmentSize)
, fShmVoidAlloc(fManagementSegment.get_segment_manager()) , fShmVoidAlloc(fManagementSegment.get_segment_manager())
, fShmMtx(fManagementSegment.find_or_construct<boost::interprocess::interprocess_mutex>(boost::interprocess::unique_instance)()) , fShmMtx(fManagementSegment.find_or_construct<boost::interprocess::interprocess_mutex>(boost::interprocess::unique_instance)())
, fNumObservedEvents(0) , fNumObservedEvents(0)
@@ -228,6 +228,8 @@ class Manager
fShmSegments = fManagementSegment.find_or_construct<Uint16SegmentInfoHashMap>(unique_instance)(fShmVoidAlloc); fShmSegments = fManagementSegment.find_or_construct<Uint16SegmentInfoHashMap>(unique_instance)(fShmVoidAlloc);
fShmRegions = fManagementSegment.find_or_construct<Uint16RegionInfoHashMap>(unique_instance)(fShmVoidAlloc); fShmRegions = fManagementSegment.find_or_construct<Uint16RegionInfoHashMap>(unique_instance)(fShmVoidAlloc);
bool createdSegment = false;
try { try {
std::string segmentName("fmq_" + fShmId + "_m_" + std::to_string(fSegmentId)); std::string segmentName("fmq_" + fShmId + "_m_" + std::to_string(fSegmentId));
auto it = fShmSegments->find(fSegmentId); auto it = fShmSegments->find(fSegmentId);
@@ -246,6 +248,7 @@ class Manager
if (zeroSegmentOnCreation) { if (zeroSegmentOnCreation) {
ZeroSegment(fSegmentId); ZeroSegment(fSegmentId);
} }
createdSegment = true;
} else { } else {
// found segment with the given id, opening // found segment with the given id, opening
if (it->second.fAllocationAlgorithm == AllocationAlgorithm::rbtree_best_fit) { if (it->second.fAllocationAlgorithm == AllocationAlgorithm::rbtree_best_fit) {
@@ -278,7 +281,9 @@ class Manager
ZeroSegment(fSegmentId); ZeroSegment(fSegmentId);
} }
(fEventCounter->fCount)++; if (createdSegment) {
(fEventCounter->fCount)++;
}
#ifdef FAIRMQ_DEBUG_MODE #ifdef FAIRMQ_DEBUG_MODE
fMsgDebug = fManagementSegment.find_or_construct<Uint16MsgDebugMapHashMap>(unique_instance)(fShmVoidAlloc); fMsgDebug = fManagementSegment.find_or_construct<Uint16MsgDebugMapHashMap>(unique_instance)(fShmVoidAlloc);
@@ -360,7 +365,7 @@ class Manager
} }
bool Interrupted() { return fInterrupted.load(); } bool Interrupted() { return fInterrupted.load(); }
std::pair<UnmanagedRegion*, uint16_t> CreateRegion(const size_t size, std::pair<UnmanagedRegion*, uint16_t> CreateRegion(size_t size,
RegionCallback callback, RegionCallback callback,
RegionBulkCallback bulkCallback, RegionBulkCallback bulkCallback,
RegionConfig cfg) RegionConfig cfg)
@@ -370,7 +375,7 @@ class Manager
std::pair<UnmanagedRegion*, uint16_t> result; std::pair<UnmanagedRegion*, uint16_t> result;
{ {
boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(*fShmMtx); boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> shmLock(*fShmMtx);
if (!cfg.id.has_value()) { if (!cfg.id.has_value()) {
RegionCounter* rc = fManagementSegment.find<RegionCounter>(unique_instance).first; RegionCounter* rc = fManagementSegment.find<RegionCounter>(unique_instance).first;
@@ -390,23 +395,28 @@ class Manager
const uint16_t id = cfg.id.value(); const uint16_t id = cfg.id.value();
auto res = fRegions.emplace(id, std::make_unique<UnmanagedRegion>(fShmId, size, false, cfg)); UnmanagedRegion* region = nullptr;
bool newRegionCreated = res.second; bool newRegionCreated = false;
UnmanagedRegion& region = *(res.first->second); {
std::lock_guard<std::mutex> lock(fLocalRegionsMtx);
auto res = fRegions.emplace(id, std::make_unique<UnmanagedRegion>(fShmId, size, false, cfg));
newRegionCreated = res.second;
region = res.first->second.get();
}
// LOG(debug) << "Created region with id '" << id << "', path: '" << cfg.path << "', flags: '" << cfg.creationFlags << "'"; // LOG(debug) << "Created region with id '" << id << "', path: '" << cfg.path << "', flags: '" << cfg.creationFlags << "'";
if (!newRegionCreated) { if (!newRegionCreated) {
region.fRemote = false; // TODO: this should be more clear, refactor it. region->fRemote = false; // TODO: this should be more clear, refactor it.
} }
// start ack receiver only if a callback has been provided. // start ack receiver only if a callback has been provided.
if (callback || bulkCallback) { if (callback || bulkCallback) {
region.SetCallbacks(callback, bulkCallback); region->SetCallbacks(callback, bulkCallback);
region.InitializeQueues(); region->InitializeQueues();
region.StartAckSender(); region->StartAckSender();
region.StartAckReceiver(); region->StartAckReceiver();
} }
result.first = &(region); result.first = region;
result.second = id; result.second = id;
} }
fRegionsGen += 1; // signal TL cache invalidation fRegionsGen += 1; // signal TL cache invalidation
@@ -419,7 +429,7 @@ class Manager
} }
} }
UnmanagedRegion* GetRegion(const uint16_t id) UnmanagedRegion* GetRegion(uint16_t id)
{ {
// NOTE: gcc optimizations. Prevent loading tls addresses many times in the fast path // NOTE: gcc optimizations. Prevent loading tls addresses many times in the fast path
const auto &lTlCache = fTlRegionCache; const auto &lTlCache = fTlRegionCache;
@@ -439,13 +449,14 @@ class Manager
fTlRegionCache.fRegionsTLCache.clear(); fTlRegionCache.fRegionsTLCache.clear();
} }
std::lock_guard<std::mutex> lock(fLocalRegionsMtx);
auto* lRegion = GetRegionUnsafe(id, shmLock); auto* lRegion = GetRegionUnsafe(id, shmLock);
fTlRegionCache.fRegionsTLCache.emplace_back(std::make_tuple(lRegion, id, fShmId64)); fTlRegionCache.fRegionsTLCache.emplace_back(std::make_tuple(lRegion, id, fShmId64));
fTlRegionCache.fRegionsTLCacheGen = fRegionsGen; fTlRegionCache.fRegionsTLCacheGen = fRegionsGen;
return lRegion; return lRegion;
} }
UnmanagedRegion* GetRegionUnsafe(const uint16_t id, boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex>& lockedShmLock) UnmanagedRegion* GetRegionUnsafe(uint16_t id, boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex>& lockedShmLock)
{ {
// remote region could actually be a local one if a message originates from this device (has been sent out and returned) // remote region could actually be a local one if a message originates from this device (has been sent out and returned)
auto it = fRegions.find(id); auto it = fRegions.find(id);
@@ -479,12 +490,13 @@ class Manager
} }
} }
void RemoveRegion(const uint16_t id) void RemoveRegion(uint16_t id)
{ {
try { try {
std::lock_guard<std::mutex> lock(fLocalRegionsMtx);
fRegions.at(id)->StopAcks(); fRegions.at(id)->StopAcks();
{ {
boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(*fShmMtx); boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> shmLock(*fShmMtx);
if (fRegions.at(id)->RemoveOnDestruction()) { if (fRegions.at(id)->RemoveOnDestruction()) {
fShmRegions->at(id).fDestroyed = true; fShmRegions->at(id).fDestroyed = true;
(fEventCounter->fCount)++; (fEventCounter->fCount)++;
@@ -800,6 +812,7 @@ class Manager
VoidAlloc fShmVoidAlloc; VoidAlloc fShmVoidAlloc;
boost::interprocess::interprocess_mutex* fShmMtx; boost::interprocess::interprocess_mutex* fShmMtx;
std::mutex fLocalRegionsMtx;
std::mutex fRegionEventsMtx; std::mutex fRegionEventsMtx;
std::condition_variable fRegionEventsCV; std::condition_variable fRegionEventsCV;
std::thread fRegionEventThread; std::thread fRegionEventThread;

View File

@@ -35,7 +35,7 @@ class Message final : public fair::mq::Message
friend class Socket; friend class Socket;
public: public:
Message(Manager& manager, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -46,7 +46,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, Alignment alignment, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, Alignment alignment, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -58,7 +58,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, const size_t size, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, const size_t size, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -70,7 +70,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, const size_t size, Alignment alignment, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, const size_t size, Alignment alignment, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -83,7 +83,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, void* data, const size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -102,7 +102,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, UnmanagedRegionPtr& region, void* data, const size_t size, void* hint = 0, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, UnmanagedRegionPtr& region, void* data, const size_t size, void* hint = 0, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -125,7 +125,7 @@ class Message final : public fair::mq::Message
fManager.IncrementMsgCounter(); fManager.IncrementMsgCounter();
} }
Message(Manager& manager, MetaHeader& hdr, FairMQTransportFactory* factory = nullptr) Message(Manager& manager, MetaHeader& hdr, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fManager(manager) , fManager(manager)
, fQueued(false) , fQueued(false)
@@ -169,7 +169,7 @@ class Message final : public fair::mq::Message
InitializeChunk(size, fAlignment); InitializeChunk(size, fAlignment);
} }
void Rebuild(void* data, size_t size, fairmq_free_fn* ffn, void* hint = nullptr) override void Rebuild(void* data, size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr) override
{ {
CloseMessage(); CloseMessage();
fQueued = false; fQueued = false;

View File

@@ -6,9 +6,10 @@
* copied verbatim in the file "LICENSE" * * copied verbatim in the file "LICENSE" *
********************************************************************************/ ********************************************************************************/
#include "Monitor.h"
#include "Common.h" #include "Common.h"
#include "UnmanagedRegion.h" #include "Monitor.h"
#include "Segment.h"
#include <fairmq/shmem/UnmanagedRegion.h>
#include <fairmq/tools/IO.h> #include <fairmq/tools/IO.h>
#include <fairmq/tools/Strings.h> #include <fairmq/tools/Strings.h>
@@ -267,13 +268,14 @@ bool Monitor::PrintShm(const ShmId& shmId)
ss << "\n unmanaged regions:"; ss << "\n unmanaged regions:";
for (const auto& r : *shmRegions) { for (const auto& r : *shmRegions) {
ss << "\n [" << r.first << "]: " << (r.second.fDestroyed ? "destroyed" : "alive"); ss << "\n [" << r.first << "]: " << (r.second.fDestroyed ? "destroyed" : "alive");
ss << ", size: " << r.second.fSize;
try { // try {
boost::interprocess::message_queue q(open_only, std::string("fmq_" + std::string(shmId) + "_rgq_" + to_string(r.first)).c_str()); // boost::interprocess::message_queue q(open_only, std::string("fmq_" + std::string(shmId) + "_rgq_" + to_string(r.first)).c_str());
ss << ", ack queue: " << q.get_num_msg() << " messages"; // ss << ", ack queue: " << q.get_num_msg() << " messages";
} catch (bie&) { // } catch (bie&) {
ss << ", ack queue: not found"; // ss << ", ack queue: not found";
} // }
} }
} }
LOGV(info, user1) << ss.str(); LOGV(info, user1) << ss.str();
@@ -414,24 +416,28 @@ void Monitor::PrintDebugInfo(const ShmId& shmId __attribute__((unused)))
size_t numMessages = 0; size_t numMessages = 0;
for (const auto& e : *debug) { if (debug) {
numMessages += e.second.size(); for (const auto& e : *debug) {
} numMessages += e.second.size();
LOG(info) << endl << "found " << numMessages << " messages.";
for (const auto& s : *debug) {
for (const auto& e : s.second) {
using time_point = chrono::system_clock::time_point;
time_point tmpt{chrono::duration_cast<time_point::duration>(chrono::nanoseconds(e.second.fCreationTime))};
time_t t = chrono::system_clock::to_time_t(tmpt);
uint64_t ms = e.second.fCreationTime % 1000000;
auto tm = localtime(&t);
LOG(info) << "segment: " << setw(3) << setfill(' ') << s.first
<< ", offset: " << setw(12) << setfill(' ') << e.first
<< ", size: " << setw(10) << setfill(' ') << e.second.fSize
<< ", creator PID: " << e.second.fPid << setfill('0')
<< ", at: " << setw(2) << tm->tm_hour << ":" << setw(2) << tm->tm_min << ":" << setw(2) << tm->tm_sec << "." << setw(6) << ms;
} }
LOG(info) << endl << "found " << numMessages << " messages.";
for (const auto& s : *debug) {
for (const auto& e : s.second) {
using time_point = chrono::system_clock::time_point;
time_point tmpt{chrono::duration_cast<time_point::duration>(chrono::nanoseconds(e.second.fCreationTime))};
time_t t = chrono::system_clock::to_time_t(tmpt);
uint64_t ms = e.second.fCreationTime % 1000000;
auto tm = localtime(&t);
LOG(info) << "segment: " << setw(3) << setfill(' ') << s.first
<< ", offset: " << setw(12) << setfill(' ') << e.first
<< ", size: " << setw(10) << setfill(' ') << e.second.fSize
<< ", creator PID: " << e.second.fPid << setfill('0')
<< ", at: " << setw(2) << tm->tm_hour << ":" << setw(2) << tm->tm_min << ":" << setw(2) << tm->tm_sec << "." << setw(6) << ms;
}
}
} else {
LOG(info) << "no debug data found";
} }
} catch (bie&) { } catch (bie&) {
LOG(info) << "no segments found"; LOG(info) << "no segments found";
@@ -462,11 +468,16 @@ unordered_map<uint16_t, std::vector<BufferDebugInfo>> Monitor::GetDebugInfo(cons
result.reserve(debug->size()); result.reserve(debug->size());
for (const auto& s : *debug) {
result[s.first].reserve(s.second.size()); if (debug) {
for (const auto& e : s.second) { for (const auto& s : *debug) {
result[s.first][e.first] = BufferDebugInfo(e.first, e.second.fPid, e.second.fSize, e.second.fCreationTime); result[s.first].reserve(s.second.size());
for (const auto& e : s.second) {
result[s.first][e.first] = BufferDebugInfo(e.first, e.second.fPid, e.second.fSize, e.second.fCreationTime);
}
} }
} else {
LOG(info) << "no debug data found";
} }
} catch (bie&) { } catch (bie&) {
LOG(info) << "no segments found"; LOG(info) << "no segments found";
@@ -552,15 +563,16 @@ std::pair<std::string, bool> Remove(const std::string& name, bool verbose)
} }
} }
std::vector<std::pair<std::string, bool>> Monitor::Cleanup(const ShmId& shmId, bool verbose /* = true */) std::vector<std::pair<std::string, bool>> Monitor::Cleanup(const ShmId& shmIdT, bool verbose /* = true */)
{ {
std::string shmId = shmIdT.shmId;
std::vector<std::pair<std::string, bool>> result; std::vector<std::pair<std::string, bool>> result;
if (verbose) { if (verbose) {
LOG(info) << "Cleaning up for shared memory id '" << shmId.shmId << "'..."; LOG(info) << "Cleaning up for shared memory id '" << shmId << "'...";
} }
string managementSegmentName("fmq_" + shmId.shmId + "_mng"); string managementSegmentName("fmq_" + shmId + "_mng");
try { try {
bipc::managed_shared_memory managementSegment(bipc::open_only, managementSegmentName.c_str()); bipc::managed_shared_memory managementSegment(bipc::open_only, managementSegmentName.c_str());
@@ -578,22 +590,21 @@ std::vector<std::pair<std::string, bool>> Monitor::Cleanup(const ShmId& shmId, b
LOG(info) << "Found RegionInfo with path: '" << path << "', flags: " << flags << ", fDestroyed: " << info.fDestroyed << "."; LOG(info) << "Found RegionInfo with path: '" << path << "', flags: " << flags << ", fDestroyed: " << info.fDestroyed << ".";
} }
if (!path.empty()) { if (!path.empty()) {
result.emplace_back(Remove<bipc::file_mapping>(path + "fmq_" + shmId.shmId + "_rg_" + to_string(id), verbose)); result.emplace_back(Remove<bipc::file_mapping>(path + "fmq_" + shmId + "_rg_" + to_string(id), verbose));
} else { } else {
result.emplace_back(Remove<bipc::shared_memory_object>("fmq_" + shmId.shmId + "_rg_" + to_string(id), verbose)); result.emplace_back(Remove<bipc::shared_memory_object>("fmq_" + shmId + "_rg_" + to_string(id), verbose));
} }
result.emplace_back(Remove<bipc::message_queue>("fmq_" + shmId.shmId + "_rgq_" + to_string(id), verbose)); result.emplace_back(Remove<bipc::message_queue>("fmq_" + shmId + "_rgq_" + to_string(id), verbose));
} }
} }
Uint16SegmentInfoHashMap* shmSegments = managementSegment.find<Uint16SegmentInfoHashMap>(bipc::unique_instance).first; Uint16SegmentInfoHashMap* shmSegments = managementSegment.find<Uint16SegmentInfoHashMap>(bipc::unique_instance).first;
if (shmSegments) { if (shmSegments) {
if (verbose) { if (verbose) {
LOG(info) << "Found " << shmSegments->size() << " managed segments..."; LOG(info) << "Found " << shmSegments->size() << " managed segments...";
} }
for (const auto& segment : *shmSegments) { for (const auto& segment : *shmSegments) {
result.emplace_back(Remove<bipc::shared_memory_object>("fmq_" + shmId.shmId + "_m_" + to_string(segment.first), verbose)); result.emplace_back(Remove<bipc::shared_memory_object>("fmq_" + shmId + "_m_" + to_string(segment.first), verbose));
} }
} else { } else {
if (verbose) { if (verbose) {
@@ -636,41 +647,49 @@ std::vector<std::pair<std::string, bool>> Monitor::CleanupFull(const SessionId&
return CleanupFull(shmId, verbose); return CleanupFull(shmId, verbose);
} }
void Monitor::ResetContent(const ShmId& shmId, bool verbose /* = true */) void Monitor::ResetContent(const ShmId& shmIdT, bool verbose /* = true */)
{ {
std::string shmId = shmIdT.shmId;
if (verbose) { if (verbose) {
cout << "Resetting segments content for shared memory id '" << shmId.shmId << "'..." << endl; cout << "Resetting segments content for shared memory id '" << shmId << "'..." << endl;
} }
string managementSegmentName("fmq_" + shmId.shmId + "_mng"); string managementSegmentName("fmq_" + shmId + "_mng");
try { try {
using namespace boost::interprocess; using namespace boost::interprocess;
managed_shared_memory managementSegment(open_only, managementSegmentName.c_str()); managed_shared_memory managementSegment(open_only, managementSegmentName.c_str());
Uint16SegmentInfoHashMap* segmentInfos = managementSegment.find<Uint16SegmentInfoHashMap>(unique_instance).first; Uint16SegmentInfoHashMap* segmentInfos = managementSegment.find<Uint16SegmentInfoHashMap>(unique_instance).first;
for (const auto& s : *segmentInfos) { for (const auto& s : *segmentInfos) {
if (verbose) { if (verbose) {
cout << "Resetting content of segment '" << "fmq_" << shmId.shmId << "_m_" << s.first << "'..." << endl; cout << "Resetting content of segment '" << "fmq_" << shmId << "_m_" << s.first << "'..." << endl;
} }
try { try {
if (s.second.fAllocationAlgorithm == AllocationAlgorithm::rbtree_best_fit) { if (s.second.fAllocationAlgorithm == AllocationAlgorithm::rbtree_best_fit) {
RBTreeBestFitSegment segment(open_only, std::string("fmq_" + shmId.shmId + "_m_" + to_string(s.first)).c_str()); RBTreeBestFitSegment segment(open_only, std::string("fmq_" + shmId + "_m_" + to_string(s.first)).c_str());
void* ptr = segment.get_segment_manager(); void* ptr = segment.get_segment_manager();
size_t size = segment.get_segment_manager()->get_size(); size_t size = segment.get_segment_manager()->get_size();
new(ptr) segment_manager<char, rbtree_best_fit<mutex_family, offset_ptr<void>>, null_index>(size); new(ptr) segment_manager<char, rbtree_best_fit<mutex_family, offset_ptr<void>>, null_index>(size);
} else { } else {
SimpleSeqFitSegment segment(open_only, std::string("fmq_" + shmId.shmId + "_m_" + to_string(s.first)).c_str()); SimpleSeqFitSegment segment(open_only, std::string("fmq_" + shmId + "_m_" + to_string(s.first)).c_str());
void* ptr = segment.get_segment_manager(); void* ptr = segment.get_segment_manager();
size_t size = segment.get_segment_manager()->get_size(); size_t size = segment.get_segment_manager()->get_size();
new(ptr) segment_manager<char, simple_seq_fit<mutex_family, offset_ptr<void>>, null_index>(size); new(ptr) segment_manager<char, simple_seq_fit<mutex_family, offset_ptr<void>>, null_index>(size);
} }
} catch (bie& e) { } catch (bie& e) {
if (verbose) { if (verbose) {
cout << "Error resetting content of segment '" << std::string("fmq_" + shmId.shmId + "_m_" + to_string(s.first)) << "': " << e.what() << endl; cout << "Error resetting content of segment '" << std::string("fmq_" + shmId + "_m_" + to_string(s.first)) << "': " << e.what() << endl;
} }
} }
} }
Uint16RegionInfoHashMap* shmRegions = managementSegment.find<Uint16RegionInfoHashMap>(bipc::unique_instance).first;
if (shmRegions) {
for (const auto& region : *shmRegions) {
uint16_t id = region.first;
Remove<bipc::message_queue>("fmq_" + shmId + "_rgq_" + to_string(id), verbose);
}
}
} catch (bie& e) { } catch (bie& e) {
if (verbose) { if (verbose) {
cout << "Could not find '" << managementSegmentName << "' segment. Nothing to cleanup." << endl; cout << "Could not find '" << managementSegmentName << "' segment. Nothing to cleanup." << endl;
@@ -679,7 +698,7 @@ void Monitor::ResetContent(const ShmId& shmId, bool verbose /* = true */)
} }
if (verbose) { if (verbose) {
cout << "Done resetting segment content for shared memory id '" << shmId.shmId << "'." << endl; cout << "Done resetting segment content for shared memory id '" << shmId << "'." << endl;
} }
} }
@@ -692,6 +711,43 @@ void Monitor::ResetContent(const SessionId& sessionId, bool verbose /* = true */
ResetContent(shmId, verbose); ResetContent(shmId, verbose);
} }
void Monitor::ResetContent(const ShmId& shmIdT, const std::vector<SegmentConfig>& segmentCfgs, const std::vector<RegionConfig>& regionCfgs, bool verbose /* = true */)
{
using namespace boost::interprocess;
std::string shmId = shmIdT.shmId;
std::string managementSegmentName("fmq_" + shmId + "_mng");
// reset managed segments
ResetContent(shmIdT, verbose);
// delete management segment
Remove<bipc::shared_memory_object>(managementSegmentName, verbose);
// recreate management segment
managed_shared_memory mngSegment(create_only, managementSegmentName.c_str(), kManagementSegmentSize);
// fill management segment with segment & region infos
for (const auto& s : segmentCfgs) {
if (s.allocationAlgorithm == "rbtree_best_fit") {
Segment::Register(shmId, s.id, AllocationAlgorithm::rbtree_best_fit);
} else if (s.allocationAlgorithm == "simple_seq_fit") {
Segment::Register(shmId, s.id, AllocationAlgorithm::simple_seq_fit);
} else {
LOG(error) << "Unknown allocation algorithm provided: " << s.allocationAlgorithm;
throw MonitorError("Unknown allocation algorithm provided: " + s.allocationAlgorithm);
}
}
for (const auto& r : regionCfgs) {
fair::mq::shmem::UnmanagedRegion::Register(shmId, r);
}
}
void Monitor::ResetContent(const SessionId& sessionId, const std::vector<SegmentConfig>& segmentCfgs, const std::vector<RegionConfig>& regionCfgs, bool verbose /* = true */)
{
ShmId shmId{makeShmIdStr(sessionId.sessionId)};
if (verbose) {
cout << "ResetContent called with session id '" << sessionId.sessionId << "', translating to shared memory id '" << shmId.shmId << "'" << endl;
}
ResetContent(shmId, segmentCfgs, regionCfgs, verbose);
}
Monitor::~Monitor() Monitor::~Monitor()
{ {
if (fSignalThread.joinable()) { if (fSignalThread.joinable()) {

View File

@@ -8,6 +8,8 @@
#ifndef FAIR_MQ_SHMEM_MONITOR_H_ #ifndef FAIR_MQ_SHMEM_MONITOR_H_
#define FAIR_MQ_SHMEM_MONITOR_H_ #define FAIR_MQ_SHMEM_MONITOR_H_
#include <fairmq/UnmanagedRegion.h>
#include <fairlogger/Logger.h> #include <fairlogger/Logger.h>
#include <thread> #include <thread>
@@ -49,6 +51,13 @@ struct BufferDebugInfo
uint64_t fCreationTime; uint64_t fCreationTime;
}; };
struct SegmentConfig
{
uint16_t id;
uint64_t size;
std::string allocationAlgorithm;
};
class Monitor class Monitor
{ {
public: public:
@@ -88,6 +97,14 @@ class Monitor
/// @param sessionId session id /// @param sessionId session id
/// Only call this when segment is not in use /// Only call this when segment is not in use
static void ResetContent(const SessionId& sessionId, bool verbose = true); static void ResetContent(const SessionId& sessionId, bool verbose = true);
/// @brief [EXPERIMENTAL] cleanup the content of the shem segment, without recreating it
/// @param shmId shared memory id
/// Only call this when segment is not in use
static void ResetContent(const ShmId& shmId, const std::vector<SegmentConfig>& segmentCfgs, const std::vector<RegionConfig>& regionCfgs, bool verbose = true);
/// @brief [EXPERIMENTAL] cleanup the content of the shem segment, without recreating it
/// @param sessionId session id
/// Only call this when segment is not in use
static void ResetContent(const SessionId& sessionId, const std::vector<SegmentConfig>& segmentCfgs, const std::vector<RegionConfig>& regionCfgs, bool verbose = true);
/// @brief Outputs list of messages in shmem (if compiled with FAIRMQ_DEBUG_MODE=ON) /// @brief Outputs list of messages in shmem (if compiled with FAIRMQ_DEBUG_MODE=ON)
/// @param shmId shmem id /// @param shmId shmem id

View File

@@ -26,6 +26,8 @@ static const RBTreeBestFit rbTreeBestFit = RBTreeBestFit();
struct Segment struct Segment
{ {
friend class Monitor;
Segment(const std::string& shmId, uint16_t id, size_t size, SimpleSeqFit) Segment(const std::string& shmId, uint16_t id, size_t size, SimpleSeqFit)
: fSegment(SimpleSeqFitSegment(boost::interprocess::open_or_create, : fSegment(SimpleSeqFitSegment(boost::interprocess::open_or_create,
std::string("fmq_" + shmId + "_m_" + std::to_string(id)).c_str(), std::string("fmq_" + shmId + "_m_" + std::to_string(id)).c_str(),
@@ -66,15 +68,12 @@ struct Segment
static void Register(const std::string& shmId, uint16_t id, AllocationAlgorithm allocAlgo) static void Register(const std::string& shmId, uint16_t id, AllocationAlgorithm allocAlgo)
{ {
using namespace boost::interprocess; using namespace boost::interprocess;
managed_shared_memory mngSegment(open_or_create, std::string("fmq_" + shmId + "_mng").c_str(), 6553600); managed_shared_memory mngSegment(open_or_create, std::string("fmq_" + shmId + "_mng").c_str(), kManagementSegmentSize);
VoidAlloc alloc(mngSegment.get_segment_manager()); VoidAlloc alloc(mngSegment.get_segment_manager());
Uint16SegmentInfoHashMap* shmSegments = mngSegment.find_or_construct<Uint16SegmentInfoHashMap>(unique_instance)(alloc); Uint16SegmentInfoHashMap* shmSegments = mngSegment.find_or_construct<Uint16SegmentInfoHashMap>(unique_instance)(alloc);
EventCounter* eventCounter = mngSegment.find<EventCounter>(unique_instance).first; EventCounter* eventCounter = mngSegment.find_or_construct<EventCounter>(unique_instance)(0);
if (!eventCounter) {
eventCounter = mngSegment.construct<EventCounter>(unique_instance)(0);
}
bool newSegmentRegistered = shmSegments->emplace(id, allocAlgo).second; bool newSegmentRegistered = shmSegments->emplace(id, allocAlgo).second;
if (newSegmentRegistered) { if (newSegmentRegistered) {

View File

@@ -51,7 +51,7 @@ struct ZMsg
class Socket final : public fair::mq::Socket class Socket final : public fair::mq::Socket
{ {
public: public:
Socket(Manager& manager, const std::string& type, const std::string& name, const std::string& id, void* context, FairMQTransportFactory* fac = nullptr) Socket(Manager& manager, const std::string& type, const std::string& name, const std::string& id, void* context, fair::mq::TransportFactory* fac = nullptr)
: fair::mq::Socket(fac) : fair::mq::Socket(fac)
, fManager(manager) , fManager(manager)
, fId(id + "." + name + "." + type) , fId(id + "." + name + "." + type)

View File

@@ -113,7 +113,7 @@ class TransportFactory final : public fair::mq::TransportFactory
return std::make_unique<Message>(*fManager, size, alignment, this); return std::make_unique<Message>(*fManager, size, alignment, this);
} }
MessagePtr CreateMessage(void* data, size_t size, fairmq_free_fn* ffn, void* hint = nullptr) override MessagePtr CreateMessage(void* data, size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr) override
{ {
return std::make_unique<Message>(*fManager, data, size, ffn, hint, this); return std::make_unique<Message>(*fManager, data, size, ffn, hint, this);
} }
@@ -128,17 +128,17 @@ class TransportFactory final : public fair::mq::TransportFactory
return std::make_unique<Socket>(*fManager, type, name, GetId(), fZmqCtx, this); return std::make_unique<Socket>(*fManager, type, name, GetId(), fZmqCtx, this);
} }
PollerPtr CreatePoller(const std::vector<FairMQChannel>& channels) const override PollerPtr CreatePoller(const std::vector<Channel>& channels) const override
{ {
return std::make_unique<Poller>(channels); return std::make_unique<Poller>(channels);
} }
PollerPtr CreatePoller(const std::vector<FairMQChannel*>& channels) const override PollerPtr CreatePoller(const std::vector<Channel*>& channels) const override
{ {
return std::make_unique<Poller>(channels); return std::make_unique<Poller>(channels);
} }
PollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const override PollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<Channel>>& channelsMap, const std::vector<std::string>& channelList) const override
{ {
return std::make_unique<Poller>(channelsMap, channelList); return std::make_unique<Poller>(channelsMap, channelList);
} }

View File

@@ -41,6 +41,7 @@ struct UnmanagedRegion
{ {
friend class Message; friend class Message;
friend class Manager; friend class Manager;
friend class Monitor;
UnmanagedRegion(const std::string& shmId, uint16_t id, uint64_t size) UnmanagedRegion(const std::string& shmId, uint16_t id, uint64_t size)
: UnmanagedRegion(shmId, size, false, makeRegionConfig(id)) : UnmanagedRegion(shmId, size, false, makeRegionConfig(id))
@@ -50,6 +51,10 @@ struct UnmanagedRegion
: UnmanagedRegion(shmId, size, false, std::move(cfg)) : UnmanagedRegion(shmId, size, false, std::move(cfg))
{} {}
UnmanagedRegion(const std::string& shmId, RegionConfig cfg)
: UnmanagedRegion(shmId, cfg.size, false, std::move(cfg))
{}
UnmanagedRegion(const std::string& shmId, uint64_t size, bool remote, RegionConfig cfg) UnmanagedRegion(const std::string& shmId, uint64_t size, bool remote, RegionConfig cfg)
: fRemote(remote) : fRemote(remote)
, fRemoveOnDestruction(cfg.removeOnDestruction) , fRemoveOnDestruction(cfg.removeOnDestruction)
@@ -66,6 +71,9 @@ struct UnmanagedRegion
{ {
using namespace boost::interprocess; using namespace boost::interprocess;
// TODO: refactor this
cfg.size = size;
if (!cfg.path.empty()) { if (!cfg.path.empty()) {
fName = std::string(cfg.path + fName); fName = std::string(cfg.path + fName);
@@ -91,16 +99,25 @@ struct UnmanagedRegion
fRegion = mapped_region(fFileMapping, read_write, 0, size, 0, cfg.creationFlags); fRegion = mapped_region(fFileMapping, read_write, 0, size, 0, cfg.creationFlags);
} else { } else {
try { try {
fShmemObject = shared_memory_object(open_or_create, fName.c_str(), read_write); // if opening fails, create
if (size != 0) { try {
fShmemObject = shared_memory_object(open_only, fName.c_str(), read_write);
} catch (interprocess_exception& e) {
LOG(debug) << "Could not open " << (remote ? "remote" : "local") << " shared_memory_object for region id '" << cfg.id.value() << "': " << e.what() << ", creating...";
fShmemObject = shared_memory_object(create_only, fName.c_str(), read_write);
fShmemObject.truncate(size); fShmemObject.truncate(size);
} }
} catch (interprocess_exception& e) { } catch (interprocess_exception& e) {
LOG(error) << "Failed " << (remote ? "opening" : "creating") << " shared_memory_object for region id '" << cfg.id.value() << "': " << e.what(); LOG(error) << "Failed " << (remote ? "opening" : "creating") << " shared_memory_object for region id '" << cfg.id.value() << "': " << e.what();
throw; throw;
} }
try { try {
fRegion = mapped_region(fShmemObject, read_write, 0, 0, 0, cfg.creationFlags); fRegion = mapped_region(fShmemObject, read_write, 0, 0, 0, cfg.creationFlags);
if (size != 0 && size != fRegion.get_size()) {
LOG(error) << "Created/opened region size (" << fRegion.get_size() << ") does not match configured size (" << size << ")";
throw TransportError(tools::ToString("Created/opened region size (", fRegion.get_size(), ") does not match configured size (", size, ")"));
}
} catch (interprocess_exception& e) { } catch (interprocess_exception& e) {
LOG(error) << "Failed mapping shared_memory_object for region id '" << cfg.id.value() << "': " << e.what(); LOG(error) << "Failed mapping shared_memory_object for region id '" << cfg.id.value() << "': " << e.what();
throw; throw;
@@ -223,20 +240,17 @@ struct UnmanagedRegion
return regionCfg; return regionCfg;
} }
static void Register(const std::string& shmId, RegionConfig& cfg) static void Register(const std::string& shmId, const RegionConfig& cfg)
{ {
using namespace boost::interprocess; using namespace boost::interprocess;
managed_shared_memory mngSegment(open_or_create, std::string("fmq_" + shmId + "_mng").c_str(), 6553600); managed_shared_memory mngSegment(open_or_create, std::string("fmq_" + shmId + "_mng").c_str(), kManagementSegmentSize);
VoidAlloc alloc(mngSegment.get_segment_manager()); VoidAlloc alloc(mngSegment.get_segment_manager());
Uint16RegionInfoHashMap* shmRegions = mngSegment.find_or_construct<Uint16RegionInfoHashMap>(unique_instance)(alloc); Uint16RegionInfoHashMap* shmRegions = mngSegment.find_or_construct<Uint16RegionInfoHashMap>(unique_instance)(alloc);
EventCounter* eventCounter = mngSegment.find<EventCounter>(unique_instance).first; EventCounter* eventCounter = mngSegment.find_or_construct<EventCounter>(unique_instance)(0);
if (!eventCounter) {
eventCounter = mngSegment.construct<EventCounter>(unique_instance)(0);
}
bool newShmRegionCreated = shmRegions->emplace(cfg.id.value(), RegionInfo(cfg.path.c_str(), cfg.creationFlags, cfg.userFlags, alloc)).second; bool newShmRegionCreated = shmRegions->emplace(cfg.id.value(), RegionInfo(cfg.path.c_str(), cfg.creationFlags, cfg.userFlags, cfg.size, alloc)).second;
if (newShmRegionCreated) { if (newShmRegionCreated) {
(eventCounter->fCount)++; (eventCounter->fCount)++;
} }

View File

@@ -34,7 +34,7 @@ class UnmanagedRegionImpl final : public fair::mq::UnmanagedRegion
RegionCallback callback, RegionCallback callback,
RegionBulkCallback bulkCallback, RegionBulkCallback bulkCallback,
fair::mq::RegionConfig cfg, fair::mq::RegionConfig cfg,
FairMQTransportFactory* factory) fair::mq::TransportFactory* factory)
: fair::mq::UnmanagedRegion(factory) : fair::mq::UnmanagedRegion(factory)
, fManager(manager) , fManager(manager)
, fRegion(nullptr) , fRegion(nullptr)

View File

@@ -27,7 +27,11 @@ inline bool Bind(void* socket, const std::string& address, const std::string& id
if (errno == EADDRINUSE) { if (errno == EADDRINUSE) {
// do not print error in this case, this is handled upstream in case no // do not print error in this case, this is handled upstream in case no
// connection could be established after trying a number of random ports from a range. // connection could be established after trying a number of random ports from a range.
return false; size_t protocolPos = address.find(':');
std::string protocol = address.substr(0, protocolPos);
if (protocol == "tcp") {
return false;
}
} else if (errno == EACCES) { } else if (errno == EACCES) {
// check if TCP port 1 was given, if yes then it will be handeled upstream, print debug only // check if TCP port 1 was given, if yes then it will be handeled upstream, print debug only
size_t protocolPos = address.find(':'); size_t protocolPos = address.find(':');
@@ -141,7 +145,7 @@ inline auto makeMonitorSocket(void* zmqCtx, void* socketToMonitor, std::string_v
// the FD is still valid by the time your code receives this event. // the FD is still valid by the time your code receives this event.
// ZMQ_EVENT_DISCONNECTED - The socket was disconnected unexpectedly. The event value is the // ZMQ_EVENT_DISCONNECTED - The socket was disconnected unexpectedly. The event value is the
// FD of the underlying network socket. Warning: this socket will be closed. // FD of the underlying network socket. Warning: this socket will be closed.
auto const rc = [[maybe_unused]] auto const rc =
zmq_socket_monitor(socketToMonitor, zmq_socket_monitor(socketToMonitor,
address.c_str(), address.c_str(),
ZMQ_EVENT_CONNECTED | ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED); ZMQ_EVENT_CONNECTED | ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
@@ -156,11 +160,11 @@ inline auto makeMonitorSocket(void* zmqCtx, void* socketToMonitor, std::string_v
// Progress only happens, when a user calls GetNumberOfConnectedPeers()`. // Progress only happens, when a user calls GetNumberOfConnectedPeers()`.
// The assumption here is, that not too many events will pile up anyways. // The assumption here is, that not too many events will pile up anyways.
int const unlimited(0); int const unlimited(0);
auto const rc = zmq_setsockopt(mon, ZMQ_RCVHWM, &unlimited, sizeof(unlimited)); [[maybe_unused]] auto const rc = zmq_setsockopt(mon, ZMQ_RCVHWM, &unlimited, sizeof(unlimited));
assertm(rc == 0, "Setting rcv queue size to unlimited succeeded"); // NOLINT assertm(rc == 0, "Setting rcv queue size to unlimited succeeded"); // NOLINT
} }
{ // Connect the reading monitor socket { // Connect the reading monitor socket
auto const rc = zmq_connect(mon, address.c_str()); [[maybe_unused]] auto const rc = zmq_connect(mon, address.c_str());
assertm(rc == 0, "Connecting reading monitor socket succeeded"); // NOLINT assertm(rc == 0, "Connecting reading monitor socket succeeded"); // NOLINT
} }
return mon; return mon;
@@ -192,7 +196,7 @@ inline auto getMonitorEvent(void* monitorSocket) -> int
assertm(zmq_msg_more(&msg), "A second frame is pending"); // NOLINT assertm(zmq_msg_more(&msg), "A second frame is pending"); // NOLINT
zmq_msg_init(&msg); zmq_msg_init(&msg);
{ {
auto const rc = zmq_msg_recv(&msg, monitorSocket, 0); [[maybe_unused]] auto const rc = zmq_msg_recv(&msg, monitorSocket, 0);
assertm(rc >= 0, "second monitor event frame successfully received"); // NOLINT assertm(rc >= 0, "second monitor event frame successfully received"); // NOLINT
} }
assertm(!zmq_msg_more(&msg), "No more frames are pending"); // NOLINT assertm(!zmq_msg_more(&msg), "No more frames are pending"); // NOLINT

View File

@@ -10,8 +10,9 @@
#define FAIR_MQ_ZMQ_CONTEXT_H_ #define FAIR_MQ_ZMQ_CONTEXT_H_
#include <fairmq/tools/Strings.h> #include <fairmq/tools/Strings.h>
#include <FairMQLogger.h> #include <fairmq/UnmanagedRegion.h>
#include <FairMQUnmanagedRegion.h>
#include <fairlogger/Logger.h>
#include <zmq.h> #include <zmq.h>

View File

@@ -10,9 +10,10 @@
#define FAIR_MQ_ZMQ_MESSAGE_H #define FAIR_MQ_ZMQ_MESSAGE_H
#include <fairmq/zeromq/UnmanagedRegion.h> #include <fairmq/zeromq/UnmanagedRegion.h>
#include <FairMQLogger.h> #include <fairmq/Message.h>
#include <FairMQMessage.h> #include <fairmq/UnmanagedRegion.h>
#include <FairMQUnmanagedRegion.h>
#include <fairlogger/Logger.h>
#include <zmq.h> #include <zmq.h>
@@ -38,7 +39,7 @@ class Message final : public fair::mq::Message
Message& operator=(const Message&) = delete; Message& operator=(const Message&) = delete;
Message& operator=(Message&&) = delete; Message& operator=(Message&&) = delete;
Message(FairMQTransportFactory* factory = nullptr) Message(fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
{ {
@@ -47,7 +48,7 @@ class Message final : public fair::mq::Message
} }
} }
Message(Alignment alignment, FairMQTransportFactory* factory = nullptr) Message(Alignment alignment, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fAlignment(alignment.alignment) , fAlignment(alignment.alignment)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
@@ -57,7 +58,7 @@ class Message final : public fair::mq::Message
} }
} }
Message(const size_t size, FairMQTransportFactory* factory = nullptr) Message(const size_t size, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
{ {
@@ -80,7 +81,7 @@ class Message final : public fair::mq::Message
return {static_cast<void*>(fullBufferPtr), static_cast<void*>(alignedPartPtr)}; return {static_cast<void*>(fullBufferPtr), static_cast<void*>(alignedPartPtr)};
} }
Message(const size_t size, Alignment alignment, FairMQTransportFactory* factory = nullptr) Message(const size_t size, Alignment alignment, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fAlignment(alignment.alignment) , fAlignment(alignment.alignment)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
@@ -97,7 +98,7 @@ class Message final : public fair::mq::Message
} }
} }
Message(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr, FairMQTransportFactory* factory = nullptr) Message(void* data, const size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
{ {
@@ -106,7 +107,7 @@ class Message final : public fair::mq::Message
} }
} }
Message(UnmanagedRegionPtr& region, void* data, const size_t size, void* hint = 0, FairMQTransportFactory* factory = nullptr) Message(UnmanagedRegionPtr& region, void* data, const size_t size, void* hint = 0, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Message(factory) : fair::mq::Message(factory)
, fMsg(std::make_unique<zmq_msg_t>()) , fMsg(std::make_unique<zmq_msg_t>())
{ {
@@ -184,7 +185,7 @@ class Message final : public fair::mq::Message
} }
} }
void Rebuild(void* data, size_t size, fairmq_free_fn* ffn, void* hint = nullptr) override void Rebuild(void* data, size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr) override
{ {
CloseMessage(); CloseMessage();
fMsg = std::make_unique<zmq_msg_t>(); fMsg = std::make_unique<zmq_msg_t>();

View File

@@ -9,14 +9,15 @@
#ifndef FAIR_MQ_ZMQ_SOCKET_H #ifndef FAIR_MQ_ZMQ_SOCKET_H
#define FAIR_MQ_ZMQ_SOCKET_H #define FAIR_MQ_ZMQ_SOCKET_H
#include <FairMQLogger.h> #include <fairmq/Message.h>
#include <FairMQMessage.h> #include <fairmq/Socket.h>
#include <FairMQSocket.h>
#include <fairmq/tools/Strings.h> #include <fairmq/tools/Strings.h>
#include <fairmq/zeromq/Common.h> #include <fairmq/zeromq/Common.h>
#include <fairmq/zeromq/Context.h> #include <fairmq/zeromq/Context.h>
#include <fairmq/zeromq/Message.h> #include <fairmq/zeromq/Message.h>
#include <fairlogger/Logger.h>
#include <zmq.h> #include <zmq.h>
#include <atomic> #include <atomic>
@@ -30,7 +31,7 @@ namespace fair::mq::zmq
class Socket final : public fair::mq::Socket class Socket final : public fair::mq::Socket
{ {
public: public:
Socket(Context& ctx, const std::string& type, const std::string& name, const std::string& id, FairMQTransportFactory* factory = nullptr) Socket(Context& ctx, const std::string& type, const std::string& name, const std::string& id, fair::mq::TransportFactory* factory = nullptr)
: fair::mq::Socket(factory) : fair::mq::Socket(factory)
, fCtx(ctx) , fCtx(ctx)
, fId(id + "." + name + "." + type) , fId(id + "." + name + "." + type)
@@ -219,7 +220,7 @@ class Socket final : public fair::mq::Socket
bool repeat = false; bool repeat = false;
do { do {
FairMQMessagePtr part = std::make_unique<Message>(GetTransport()); fair::mq::MessagePtr part = std::make_unique<Message>(GetTransport());
int nbytes = zmq_msg_recv(static_cast<Message*>(part.get())->GetMessage(), fSocket, flags); int nbytes = zmq_msg_recv(static_cast<Message*>(part.get())->GetMessage(), fSocket, flags);
if (nbytes >= 0) { if (nbytes >= 0) {

View File

@@ -14,7 +14,7 @@
#include <fairmq/zeromq/Socket.h> #include <fairmq/zeromq/Socket.h>
#include <fairmq/zeromq/Poller.h> #include <fairmq/zeromq/Poller.h>
#include <fairmq/zeromq/UnmanagedRegion.h> #include <fairmq/zeromq/UnmanagedRegion.h>
#include <FairMQTransportFactory.h> #include <fairmq/TransportFactory.h>
#include <fairmq/ProgOptions.h> #include <fairmq/ProgOptions.h>
#include <memory> // unique_ptr, make_unique #include <memory> // unique_ptr, make_unique
@@ -24,11 +24,11 @@
namespace fair::mq::zmq namespace fair::mq::zmq
{ {
class TransportFactory final : public FairMQTransportFactory class TransportFactory final : public fair::mq::TransportFactory
{ {
public: public:
TransportFactory(const std::string& id = "", const ProgOptions* config = nullptr) TransportFactory(const std::string& id = "", const ProgOptions* config = nullptr)
: FairMQTransportFactory(id) : fair::mq::TransportFactory(id)
, fCtx(nullptr) , fCtx(nullptr)
{ {
int major = 0, minor = 0, patch = 0; int major = 0, minor = 0, patch = 0;
@@ -68,7 +68,7 @@ class TransportFactory final : public FairMQTransportFactory
return std::make_unique<Message>(size, alignment, this); return std::make_unique<Message>(size, alignment, this);
} }
MessagePtr CreateMessage(void* data, size_t size, fairmq_free_fn* ffn, void* hint = nullptr) override MessagePtr CreateMessage(void* data, size_t size, fair::mq::FreeFn* ffn, void* hint = nullptr) override
{ {
return std::make_unique<Message>(data, size, ffn, hint, this); return std::make_unique<Message>(data, size, ffn, hint, this);
} }
@@ -83,17 +83,17 @@ class TransportFactory final : public FairMQTransportFactory
return std::make_unique<Socket>(*fCtx, type, name, GetId(), this); return std::make_unique<Socket>(*fCtx, type, name, GetId(), this);
} }
PollerPtr CreatePoller(const std::vector<FairMQChannel>& channels) const override PollerPtr CreatePoller(const std::vector<Channel>& channels) const override
{ {
return std::make_unique<Poller>(channels); return std::make_unique<Poller>(channels);
} }
PollerPtr CreatePoller(const std::vector<FairMQChannel*>& channels) const override PollerPtr CreatePoller(const std::vector<Channel*>& channels) const override
{ {
return std::make_unique<Poller>(channels); return std::make_unique<Poller>(channels);
} }
PollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const override PollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<Channel>>& channelsMap, const std::vector<std::string>& channelList) const override
{ {
return std::make_unique<Poller>(channelsMap, channelList); return std::make_unique<Poller>(channelsMap, channelList);
} }

View File

@@ -10,8 +10,9 @@
#define FAIR_MQ_ZMQ_UNMANAGEDREGION_H #define FAIR_MQ_ZMQ_UNMANAGEDREGION_H
#include <fairmq/zeromq/Context.h> #include <fairmq/zeromq/Context.h>
#include <FairMQUnmanagedRegion.h> #include <fairmq/UnmanagedRegion.h>
#include <FairMQLogger.h>
#include <fairlogger/Logger.h>
#include <cstddef> // size_t #include <cstddef> // size_t
#include <string> #include <string>
@@ -33,7 +34,7 @@ class UnmanagedRegion final : public fair::mq::UnmanagedRegion
int64_t userFlags, int64_t userFlags,
RegionCallback callback, RegionCallback callback,
RegionBulkCallback bulkCallback, RegionBulkCallback bulkCallback,
FairMQTransportFactory* factory, fair::mq::TransportFactory* factory,
fair::mq::RegionConfig cfg) fair::mq::RegionConfig cfg)
: fair::mq::UnmanagedRegion(factory) : fair::mq::UnmanagedRegion(factory)
, fCtx(ctx) , fCtx(ctx)

View File

@@ -45,11 +45,9 @@ add_testhelper(runTestDevice
${definitions} ${definitions}
) )
set(MQ_CONFIG "${CMAKE_BINARY_DIR}/test/testsuite_FairMQ.IOPatterns_config.json")
set(RUN_TEST_DEVICE "${CMAKE_BINARY_DIR}/test/testhelper_runTestDevice") set(RUN_TEST_DEVICE "${CMAKE_BINARY_DIR}/test/testhelper_runTestDevice")
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq) set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
set(SDK_TESTSUITE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk) set(SDK_TESTSUITE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protocols/config.json.in ${MQ_CONFIG})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/runner.cxx.in ${CMAKE_CURRENT_BINARY_DIR}/runner.cxx) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/runner.cxx.in ${CMAKE_CURRENT_BINARY_DIR}/runner.cxx)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TestEnvironment.h.in ${CMAKE_CURRENT_BINARY_DIR}/TestEnvironment.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TestEnvironment.h.in ${CMAKE_CURRENT_BINARY_DIR}/TestEnvironment.h)
@@ -68,7 +66,6 @@ add_testsuite(Protocols
${CMAKE_CURRENT_SOURCE_DIR}/protocols ${CMAKE_CURRENT_SOURCE_DIR}/protocols
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
TIMEOUT 5 TIMEOUT 5
RUN_SERIAL ON
${definitions} ${definitions}
) )
@@ -131,7 +128,6 @@ add_testsuite(Device
${CMAKE_CURRENT_SOURCE_DIR}/device ${CMAKE_CURRENT_SOURCE_DIR}/device
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
TIMEOUT 5 TIMEOUT 5
# RUN_SERIAL ON
) )
set(VERSION_MAJOR 1) set(VERSION_MAJOR 1)
@@ -282,7 +278,6 @@ add_testsuite(Poller
INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
TIMEOUT 5 TIMEOUT 5
RUN_SERIAL ON
${definitions} ${definitions}
) )

Some files were not shown because too many files have changed in this diff Show More