mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-14 17:16:47 +00:00
Compare commits
No commits in common. "master" and "v1.4.39" have entirely different histories.
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"image": "ghcr.io/fairrootgroup/fairmq-dev/fedora-38:latest",
|
||||
"features": {
|
||||
}
|
||||
}
|
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
|
@ -1,12 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
target-branch: "dev"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
- package-ecosystem: "gitsubmodule"
|
||||
directory: "/"
|
||||
target-branch: "dev"
|
||||
schedule:
|
||||
interval: "monthly"
|
29
.github/workflows/check_metadata.yaml
vendored
29
.github/workflows/check_metadata.yaml
vendored
|
@ -1,29 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH, Darmstadt, Germany
|
||||
#
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
name: Check AUTHORS and CONTRIBUTORS in metadata
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- AUTHORS
|
||||
- CONTRIBUTORS
|
||||
- codemeta.json
|
||||
- .zenodo.json
|
||||
pull_request:
|
||||
paths:
|
||||
- AUTHORS
|
||||
- CONTRIBUTORS
|
||||
- codemeta.json
|
||||
- .zenodo.json
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Try updating metadata
|
||||
run: python meta_update.py
|
||||
- name: Check for Updates
|
||||
run: git diff --exit-code
|
21
.github/workflows/codemeta_validate.yaml
vendored
21
.github/workflows/codemeta_validate.yaml
vendored
|
@ -1,21 +0,0 @@
|
|||
name: validate codemeta
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- codemeta.json
|
||||
- .github/workflows/codemeta_validate.yaml
|
||||
pull_request:
|
||||
paths:
|
||||
- codemeta.json
|
||||
- .github/workflows/codemeta_validate.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: gitlab-registry.in2p3.fr/escape2020/wp3/eossr:v1.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: validate codemeta
|
||||
run: eossr-metadata-validator codemeta.json
|
16
.github/workflows/fair-software.yml
vendored
16
.github/workflows/fair-software.yml
vendored
|
@ -1,16 +0,0 @@
|
|||
name: fair-software
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: "fair-software"
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'FairRootGroup/FairMQ'
|
||||
steps:
|
||||
- uses: fair-software/howfairis-github-action@0.2.1
|
||||
name: Measure compliance with fair-software.eu recommendations
|
||||
env:
|
||||
PYCHARM_HOSTED: "Trick colorama into displaying colored output"
|
||||
with:
|
||||
MY_REPO_URL: "https://github.com/${{ github.repository }}"
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,8 +1,5 @@
|
|||
build
|
||||
install
|
||||
|
||||
.DS_Store
|
||||
|
||||
.vscode
|
||||
/compile_commands.json
|
||||
.cache
|
||||
.spack-env
|
||||
spack.lock
|
||||
|
|
88
.zenodo.json
88
.zenodo.json
|
@ -1,88 +0,0 @@
|
|||
{
|
||||
"creators": [
|
||||
{
|
||||
"orcid": "0000-0002-8071-4497",
|
||||
"name": "Al-Turany, Mohammad"
|
||||
},
|
||||
{
|
||||
"orcid": "0000-0003-3787-1910",
|
||||
"name": "Klein, Dennis"
|
||||
},
|
||||
{
|
||||
"name": "Kollegger, Thorsten"
|
||||
},
|
||||
{
|
||||
"orcid": "0000-0002-6249-155X",
|
||||
"name": "Rybalchenko, Alexey"
|
||||
},
|
||||
{
|
||||
"name": "Winckler, Nicolas"
|
||||
}
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Aphecetche, Laurent"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Binet, Sebastien"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Eulisse, Giulio"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Karabowicz, Radoslaw"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Kretz, Matthias"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Krzewicki, Mikolaj"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Lebedev, Andrey"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Mrnjavac, Teo"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Neskovic, Gvozden"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Richter, Matthias"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"orcid": "0000-0002-5321-8404",
|
||||
"name": "Tacke, Christian"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Uhlig, Florian"
|
||||
},
|
||||
{
|
||||
"type": "Other",
|
||||
"name": "Wenzel, Sandro"
|
||||
}
|
||||
],
|
||||
"description": "<p>C++ Message Queuing Library and Framework</p>",
|
||||
"related_identifiers": [
|
||||
{
|
||||
"identifier": "https://github.com/FairRootGroup/FairMQ/",
|
||||
"relation": "isSupplementTo",
|
||||
"resource_type": "software",
|
||||
"scheme": "url"
|
||||
}
|
||||
],
|
||||
"title": "FairMQ",
|
||||
"license": "LGPL-3.0-only"
|
||||
}
|
6
AUTHORS
6
AUTHORS
|
@ -1,5 +1,5 @@
|
|||
Al-Turany, Mohammad [https://orcid.org/0000-0002-8071-4497]
|
||||
Klein, Dennis [https://orcid.org/0000-0003-3787-1910]
|
||||
Al-Turany, Mohammad
|
||||
Klein, Dennis
|
||||
Kollegger, Thorsten
|
||||
Rybalchenko, Alexey [https://orcid.org/0000-0002-6249-155X]
|
||||
Rybalchenko, Alexey
|
||||
Winckler, Nicolas
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -8,7 +8,8 @@
|
|||
|
||||
|
||||
# Project ######################################################################
|
||||
cmake_minimum_required(VERSION 3.15...3.30 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
cmake_policy(VERSION 3.15...3.20)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
include(GitHelper)
|
||||
|
@ -26,10 +27,18 @@ fairmq_build_option(BUILD_FAIRMQ "Build FairMQ library and devices."
|
|||
DEFAULT ON)
|
||||
fairmq_build_option(BUILD_TESTING "Build tests."
|
||||
DEFAULT OFF REQUIRES "BUILD_FAIRMQ")
|
||||
fairmq_build_option(BUILD_OFI_TRANSPORT "Build experimental OFI transport."
|
||||
DEFAULT OFF REQUIRES "BUILD_FAIRMQ")
|
||||
fairmq_build_option(BUILD_SDK_COMMANDS "Build the FairMQ SDK commands."
|
||||
DEFAULT OFF)
|
||||
fairmq_build_option(BUILD_DDS_PLUGIN "Build DDS plugin."
|
||||
DEFAULT OFF REQUIRES "BUILD_FAIRMQ;BUILD_SDK_COMMANDS")
|
||||
fairmq_build_option(BUILD_PMIX_PLUGIN "Build PMIx plugin."
|
||||
DEFAULT OFF REQUIRES "BUILD_FAIRMQ;BUILD_SDK_COMMANDS")
|
||||
fairmq_build_option(BUILD_EXAMPLES "Build FairMQ examples."
|
||||
DEFAULT ON REQUIRES "BUILD_FAIRMQ")
|
||||
fairmq_build_option(BUILD_TIDY_TOOL "Build the fairmq-tidy tool."
|
||||
DEFAULT OFF)
|
||||
fairmq_build_option(BUILD_SDK "Build the FairMQ controller SDK."
|
||||
DEFAULT OFF REQUIRES "BUILD_DDS_PLUGIN;BUILD_SDK_COMMANDS")
|
||||
fairmq_build_option(BUILD_DOCS "Build FairMQ documentation."
|
||||
DEFAULT OFF)
|
||||
fairmq_build_option(USE_EXTERNAL_GTEST "Do not use bundled GTest. Not recommended."
|
||||
|
@ -46,7 +55,7 @@ include(FairMQDependencies)
|
|||
|
||||
|
||||
# Targets ######################################################################
|
||||
if(BUILD_FAIRMQ)
|
||||
if(BUILD_FAIRMQ OR BUILD_SDK)
|
||||
add_subdirectory(fairmq)
|
||||
endif()
|
||||
|
||||
|
@ -67,10 +76,6 @@ if(BUILD_DOCS)
|
|||
doxygen_add_docs(doxygen README.md fairmq)
|
||||
add_custom_target(docs ALL DEPENDS doxygen)
|
||||
endif()
|
||||
|
||||
if(BUILD_TIDY_TOOL)
|
||||
add_subdirectory(fairmq/tidy)
|
||||
endif()
|
||||
################################################################################
|
||||
|
||||
|
||||
|
@ -81,14 +86,26 @@ endif()
|
|||
if(BUILD_TESTING)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS tests)
|
||||
endif()
|
||||
if(BUILD_DDS_PLUGIN)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS dds_plugin)
|
||||
endif()
|
||||
if(BUILD_PMIX_PLUGIN)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS pmix_plugin)
|
||||
endif()
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS ofi_transport)
|
||||
endif()
|
||||
if(BUILD_EXAMPLES)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS examples)
|
||||
endif()
|
||||
if(BUILD_DOCS)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS docs)
|
||||
endif()
|
||||
if(BUILD_TIDY_TOOL)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS tidy_tool)
|
||||
if(BUILD_SDK)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk)
|
||||
endif()
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk_commands)
|
||||
endif()
|
||||
################################################################################
|
||||
|
||||
|
@ -99,16 +116,16 @@ if(BUILD_FAIRMQ)
|
|||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
)
|
||||
endif()
|
||||
if(BUILD_SDK OR BUILD_DDS_PLUGIN)
|
||||
install(FILES cmake/Findasio.cmake
|
||||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
)
|
||||
endif()
|
||||
if(BUILD_DOCS)
|
||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/doxygen/html
|
||||
DESTINATION ${PROJECT_INSTALL_DATADIR}/docs
|
||||
)
|
||||
endif()
|
||||
if(BUILD_TIDY_TOOL)
|
||||
install(FILES cmake/FairMQTidy.cmake
|
||||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
include(FairMQPackage)
|
||||
install_cmake_package()
|
||||
|
@ -126,6 +143,5 @@ fairmq_summary_components()
|
|||
fairmq_summary_static_analysis()
|
||||
fairmq_summary_install_prefix()
|
||||
fairmq_summary_debug_mode()
|
||||
fairmq_summary_compile_definitions()
|
||||
message(STATUS " ")
|
||||
################################################################################
|
||||
|
|
|
@ -8,6 +8,6 @@ Lebedev, Andrey
|
|||
Mrnjavac, Teo <teo.m@cern.ch>
|
||||
Neskovic, Gvozden
|
||||
Richter, Matthias
|
||||
Tacke, Christian [https://orcid.org/0000-0002-5321-8404]
|
||||
Tacke, Christian
|
||||
Uhlig, Florian
|
||||
Wenzel, Sandro
|
||||
|
|
10
COPYRIGHT
10
COPYRIGHT
|
@ -4,19 +4,19 @@ Upstream-Contact: Mohammad Al-Turany <m.al-turany@gsi.de>
|
|||
Source: https://github.com/FairRootGroup/FairMQ
|
||||
|
||||
Files: *
|
||||
Copyright: 2012-2022, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
Copyright: 2012-2022, [see AUTHORS file]
|
||||
Copyright: 2012-2022, [see CONTRIBUTORS file]
|
||||
Copyright: 2012-2021, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
Copyright: 2012-2021, [see AUTHORS file]
|
||||
Copyright: 2012-2021, [see CONTRIBUTORS file]
|
||||
Comment: The copyright of individual contributors is documented in the
|
||||
Git history.
|
||||
License: LGPL-3.0-only
|
||||
|
||||
Files: extern/googletest
|
||||
Copyright: 2008-2022, Google Inc.
|
||||
Copyright: 2008-2021, Google Inc.
|
||||
License: GOOGLE
|
||||
|
||||
Files: extern/asio
|
||||
Copyright: 2003-2022, Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
Copyright: 2003-2021, Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
License: BSL-1.0
|
||||
|
||||
Files: extern/PicoSHA2
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2021-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -42,6 +42,15 @@ endif()
|
|||
ctest_start(Continuous)
|
||||
|
||||
list(APPEND options "-DDISABLE_COLOR=ON" "-DBUILD_EXAMPLES=ON" "-DBUILD_TESTING=ON")
|
||||
if(HAS_ASIO AND HAS_DDS)
|
||||
list(APPEND options "-DBUILD_SDK_COMMANDS=ON" "-DBUILD_SDK=ON" "-DBUILD_DDS_PLUGIN=ON")
|
||||
endif()
|
||||
if(HAS_PMIX)
|
||||
list(APPEND options "-DBUILD_SDK_COMMANDS=ON" "-DBUILD_PMIX_PLUGIN=ON")
|
||||
endif()
|
||||
if(HAS_ASIO AND HAS_ASIOFI)
|
||||
list(APPEND options "-DBUILD_OFI_TRANSPORT=ON")
|
||||
endif()
|
||||
if(RUN_STATIC_ANALYSIS)
|
||||
list(APPEND options "-DRUN_STATIC_ANALYSIS=ON")
|
||||
endif()
|
||||
|
@ -63,9 +72,6 @@ endif()
|
|||
if(ENABLE_SANITIZER_THREAD)
|
||||
list(APPEND options "-DENABLE_SANITIZER_THREAD=ON")
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER)
|
||||
list(APPEND options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
if(CMAKE_CXX_FLAGS)
|
||||
list(APPEND options "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
@ -81,7 +87,7 @@ ctest_submit()
|
|||
|
||||
if(NOT RUN_STATIC_ANALYSIS)
|
||||
ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}"
|
||||
PARALLEL_LEVEL ${NCPUS}
|
||||
PARALLEL_LEVEL 1
|
||||
SCHEDULE_RANDOM ON
|
||||
RETURN_VALUE _ctest_test_ret_val)
|
||||
|
||||
|
|
46
Jenkinsfile
vendored
46
Jenkinsfile
vendored
|
@ -4,21 +4,20 @@ def jobMatrix(String type, List specs) {
|
|||
def nodes = [:]
|
||||
for (spec in specs) {
|
||||
def job = ""
|
||||
def selector = "slurm"
|
||||
def selector = ""
|
||||
def os = ""
|
||||
def ver = ""
|
||||
|
||||
if (type == 'build') {
|
||||
job = "${spec.os}-${spec.ver}-${spec.arch}-${spec.compiler}"
|
||||
if (spec.os =~ /^macos/) {
|
||||
selector = "${spec.os}-${spec.ver}-${spec.arch}"
|
||||
}
|
||||
os = spec.os
|
||||
ver = spec.ver
|
||||
} else { // == 'check'
|
||||
job = "${spec.name}"
|
||||
selector = 'fedora-34-x86_64'
|
||||
os = 'fedora'
|
||||
ver = '36'
|
||||
ver = '34'
|
||||
}
|
||||
|
||||
def label = "${job}"
|
||||
|
@ -37,14 +36,14 @@ def jobMatrix(String type, List specs) {
|
|||
sh "echo \"export LABEL=\\\"\${JOB_BASE_NAME} ${label}\\\"\" >> ${jobscript}"
|
||||
if (selector =~ /^macos/) {
|
||||
sh """\
|
||||
echo \"export DDS_ROOT=\\\"\\\$(brew --prefix dds)\\\"\" >> ${jobscript}
|
||||
echo \"export PATH=\\\"\\\$(brew --prefix dds)/bin:\\\$PATH\\\"\" >> ${jobscript}
|
||||
echo \"${ctestcmd}\" >> ${jobscript}
|
||||
"""
|
||||
sh "cat ${jobscript}"
|
||||
sh "bash ${jobscript}"
|
||||
} else { // selector == "slurm"
|
||||
def imageurl = "oras://ghcr.io/fairrootgroup/fairmq-dev/${os}-${ver}-sif:latest"
|
||||
def execopts = "--ipc --uts --pid -B/shared"
|
||||
def containercmd = "singularity exec ${execopts} ${imageurl} bash -l -c \\\"${ctestcmd} ${extra}\\\""
|
||||
} else {
|
||||
def containercmd = "singularity exec --net --ipc --uts --pid -B/shared ${env.SINGULARITY_CONTAINER_ROOT}/fairmq/${os}.${ver}.sif bash -l -c \\\"${ctestcmd} ${extra}\\\""
|
||||
sh """\
|
||||
echo \"echo \\\"*** Job started at .......: \\\$(date -R)\\\"\" >> ${jobscript}
|
||||
echo \"echo \\\"*** Job ID ...............: \\\${SLURM_JOB_ID}\\\"\" >> ${jobscript}
|
||||
|
@ -68,6 +67,12 @@ def jobMatrix(String type, List specs) {
|
|||
deleteDir()
|
||||
githubNotify(context: "${label}", description: 'Success', status: 'SUCCESS')
|
||||
} catch (e) {
|
||||
def tarball = "${type}_${job}_dds_logs.tar.gz"
|
||||
if (fileExists("build/test/.DDS")) {
|
||||
sh "tar czvf ${tarball} -C \${WORKSPACE}/build/test .DDS/"
|
||||
archiveArtifacts tarball
|
||||
}
|
||||
|
||||
deleteDir()
|
||||
githubNotify(context: "${label}", description: 'Error', status: 'ERROR')
|
||||
throw e
|
||||
|
@ -84,30 +89,23 @@ pipeline{
|
|||
stage("CI") {
|
||||
steps{
|
||||
script {
|
||||
def all = '-DHAS_ASIO=ON -DHAS_DDS=ON -DHAS_PMIX=ON'
|
||||
|
||||
def builds = jobMatrix('build', [
|
||||
[os: 'ubuntu', ver: '20.04', arch: 'x86_64', compiler: 'gcc-9'],
|
||||
[os: 'ubuntu', ver: '22.04', arch: 'x86_64', compiler: 'gcc-11'],
|
||||
[os: 'ubuntu', ver: '24.04', arch: 'x86_64', compiler: 'gcc-13'],
|
||||
[os: 'fedora', ver: '33', arch: 'x86_64', compiler: 'gcc-10'],
|
||||
[os: 'fedora', ver: '34', arch: 'x86_64', compiler: 'gcc-11'],
|
||||
[os: 'fedora', ver: '35', arch: 'x86_64', compiler: 'gcc-11'],
|
||||
[os: 'fedora', ver: '36', arch: 'x86_64', compiler: 'gcc-12'],
|
||||
[os: 'fedora', ver: '37', arch: 'x86_64', compiler: 'gcc-12'],
|
||||
[os: 'fedora', ver: '38', arch: 'x86_64', compiler: 'gcc-13'],
|
||||
[os: 'fedora', ver: '39', arch: 'x86_64', compiler: 'gcc-13'],
|
||||
[os: 'fedora', ver: '40', arch: 'x86_64', compiler: 'gcc-14'],
|
||||
[os: 'macos', ver: '14', arch: 'x86_64', compiler: 'apple-clang-16'],
|
||||
[os: 'macos', ver: '15', arch: 'x86_64', compiler: 'apple-clang-16'],
|
||||
[os: 'macos', ver: '15', arch: 'arm64', compiler: 'apple-clang-16'],
|
||||
[os: 'ubuntu', ver: '20.04', arch: 'x86_64', compiler: 'gcc-9', 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: '34', arch: 'x86_64', compiler: 'gcc-11', extra: all],
|
||||
[os: 'macos', ver: '11', arch: 'x86_64', compiler: 'apple-clang-12',
|
||||
extra: '-DHAS_ASIO=ON -DHAS_DDS=ON'],
|
||||
])
|
||||
|
||||
def all_debug = "-DCMAKE_BUILD_TYPE=Debug"
|
||||
def all_debug = "${all} -DCMAKE_BUILD_TYPE=Debug"
|
||||
|
||||
def checks = jobMatrix('check', [
|
||||
[name: 'static-analyzers', extra: "${all_debug} -DRUN_STATIC_ANALYSIS=ON"],
|
||||
[name: '{address,leak,ub}-sanitizers',
|
||||
extra: "${all_debug} -DENABLE_SANITIZER_ADDRESS=ON -DENABLE_SANITIZER_LEAK=ON -DENABLE_SANITIZER_UNDEFINED_BEHAVIOUR=ON -DCMAKE_CXX_FLAGS='-O1 -fno-omit-frame-pointer'"],
|
||||
[name: 'thread-sanitizer', extra: "${all_debug} -DENABLE_SANITIZER_THREAD=ON -DCMAKE_CXX_COMPILER=clang++"],
|
||||
])
|
||||
|
||||
parallel(builds + checks)
|
||||
|
|
83
README.md
83
README.md
|
@ -1,15 +1,12 @@
|
|||
<!-- {#mainpage} -->
|
||||
# FairMQ
|
||||
|
||||
[](COPYRIGHT)
|
||||
[](https://doi.org/10.5281/zenodo.1689985)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6915)
|
||||
[](https://github.com/FairRootGroup/FairMQ/actions/workflows/fair-software.yml)
|
||||
[](https://repology.org/project/fairmq/versions)
|
||||
# FairMQ [](COPYRIGHT) [](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [](https://scan.coverity.com/projects/fairrootgroup-fairmq)
|
||||
|
||||
C++ Message Queuing Library and Framework
|
||||
|
||||
Docs: [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation)
|
||||
| Release | Version | Docs |
|
||||
| :---: | :--- | :--- |
|
||||
| `stable` | [](https://github.com/FairRootGroup/FairMQ/releases/latest) | [API](https://fairrootgroup.github.io/FairMQ/latest), [Book](https://github.com/FairRootGroup/FairMQ/blob/master/README.md#documentation) |
|
||||
| `testing` | [](https://github.com/FairRootGroup/FairMQ/tags) | [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation) |
|
||||
|
||||
Find all FairMQ releases [here](https://github.com/FairRootGroup/FairMQ/releases).
|
||||
|
||||
|
@ -24,17 +21,14 @@ FairMQ is designed to help implementing large-scale data processing workflows ne
|
|||
The core of FairMQ provides an abstract asynchronous message passing API with scalability protocols
|
||||
inspired by [ZeroMQ](https://github.com/zeromq/libzmq) (e.g. PUSH/PULL, PUB/SUB).
|
||||
FairMQ provides multiple implementations for its API (so-called "transports",
|
||||
e.g. `zeromq` and `shmem` (latest release of the `ofi` transport in v1.4.56, removed since v1.5+)) 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).
|
||||
In addition to this core functionality FairMQ provides a framework for creating "devices" - actors which
|
||||
are communicating through message passing. FairMQ does not only allow the user to use different transport
|
||||
but also to mix them; i.e: A Device can communicate using different transport on different channels at the
|
||||
same time. Device execution is modelled as a simple state machine that shapes the integration points for
|
||||
the user task. Devices also incorporate a plugin system for runtime configuration and control.
|
||||
Next to the provided [devices](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.
|
||||
are communicating through message passing. FairMQ does not only allow the user to use different transport but also to mix them; i.e: A Device can communicate using different transport on different channels at the same time. Device execution is modelled as a simple state machine that
|
||||
shapes the integration points for the user task. Devices also incorporate a plugin system for runtime configuration and control.
|
||||
Next to the provided devices and plugins (e.g. [DDS](https://github.com/FairRootGroup/DDS))
|
||||
the user can extend FairMQ by developing his own plugins to integrate his devices with external
|
||||
configuration and control services.
|
||||
|
||||
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
|
||||
a simulation, reconstruction and analysis framework.
|
||||
|
@ -45,42 +39,22 @@ Recommended:
|
|||
|
||||
```bash
|
||||
git clone https://github.com/FairRootGroup/FairMQ fairmq_source
|
||||
cmake -S fairmq_source -B fairmq_build -GNinja -DCMAKE_BUILD_TYPE=Release [-DBUILD_TESTING=ON]
|
||||
cmake -S fairmq_source -B fairmq_build -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=fairmq_install
|
||||
cmake --build fairmq_build
|
||||
[ctest --test-dir fairmq_build --output-on-failure --schedule-random -j<ncpus>] # needs -DBUILD_TESTING=ON
|
||||
cmake --install fairmq_build --prefix $(pwd)/fairmq_install
|
||||
cmake --build fairmq_build --target test
|
||||
cmake --build fairmq_build --target install
|
||||
```
|
||||
|
||||
Please consult the [manpages of your CMake version](https://cmake.org/cmake/help/latest/manual/cmake.1.html) for more options.
|
||||
|
||||
If dependencies are not installed in standard system directories, you can hint the installation location via
|
||||
`-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...` (`*_ROOT` variables can also be environment variables).
|
||||
|
||||
## Installation via Spack
|
||||
|
||||
Prerequisite: [Spack](https://spack.readthedocs.io/en/latest/getting_started.html)
|
||||
|
||||
```bash
|
||||
spack info fairmq # inspect build options
|
||||
spack install fairmq # build latest packaged version with default options
|
||||
```
|
||||
|
||||
Build FairMQ's dependencies via Spack for development:
|
||||
```bash
|
||||
git clone -b dev https://github.com/FairRootGroup/FairMQ fairmq_source
|
||||
spack --env fairmq_source install # installs deps declared in fairmq_source/spack.yaml
|
||||
spack env activate fairmq_source # sets $CMAKE_PREFIX_PATH which is used by CMake to find FairMQ's deps
|
||||
cmake -S fairmq_source -B fairmq_build -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
|
||||
# develop, compile, test
|
||||
spack env deactivate # at end of dev session, or simply close the shell
|
||||
```
|
||||
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).
|
||||
|
||||
## Usage
|
||||
|
||||
FairMQ ships as a CMake package, so in your `CMakeLists.txt` you can discover it like this:
|
||||
|
||||
```cmake
|
||||
find_package(FairCMakeModules 1.0 REQUIRED)
|
||||
find_package(FairCMakeModules 0.2 REQUIRED)
|
||||
include(FairFindPackage2)
|
||||
find_package2(FairMQ)
|
||||
find_package2_implicit_dependencies()
|
||||
|
@ -94,19 +68,31 @@ If FairMQ is not installed in system directories, you can hint the installation:
|
|||
list(PREPEND CMAKE_PREFIX_PATH /path/to/fairmq_install)
|
||||
```
|
||||
|
||||
Optionally, you can require certain FairMQ package components and a minimum version:
|
||||
|
||||
```cmake
|
||||
find_package(FairMQ 1.4.0 COMPONENTS dds_plugin)
|
||||
```
|
||||
|
||||
When building FairMQ, CMake will print a summary table of all available package components.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [asio](https://github.com/chriskohlhoff/asio) (optionally bundled)
|
||||
* [asiofi](https://github.com/FairRootGroup/asiofi)
|
||||
* [Boost](https://www.boost.org/)
|
||||
* [CMake](https://cmake.org/)
|
||||
* [DDS](http://dds.gsi.de)
|
||||
* [Doxygen](http://www.doxygen.org/)
|
||||
* [FairCMakeModules](https://github.com/FairRootGroup/FairCMakeModules) (optionally bundled)
|
||||
* [FairLogger](https://github.com/FairRootGroup/FairLogger)
|
||||
* [GTest](https://github.com/google/googletest) (optionally bundled)
|
||||
* [PMIx](https://pmix.org/)
|
||||
* [ZeroMQ](http://zeromq.org/)
|
||||
|
||||
Which dependencies are required depends on which components are built.
|
||||
|
||||
Supported platform is Linux. macOS is supported on a best-effort basis.
|
||||
Supported platforms: Linux and MacOS.
|
||||
|
||||
## CMake options
|
||||
|
||||
|
@ -115,8 +101,10 @@ On command line:
|
|||
* `-DDISABLE_COLOR=ON` disables coloured console output.
|
||||
* `-DBUILD_TESTING=OFF` disables building of tests.
|
||||
* `-DBUILD_EXAMPLES=OFF` disables building of examples.
|
||||
* `-DBUILD_OFI_TRANSPORT=ON` enables building of the experimental OFI transport.
|
||||
* `-DBUILD_DDS_PLUGIN=ON` enables building of the DDS plugin.
|
||||
* `-DBUILD_PMIX_PLUGIN=ON` enables building of the PMIx plugin.
|
||||
* `-DBUILD_DOCS=ON` enables building of API docs.
|
||||
* `-DFAIRMQ_CHANNEL_DEFAULT_AUTOBIND=OFF` disable channel `autoBind` by default
|
||||
* You can hint non-system installations for dependent packages, see the #installation-from-source section above
|
||||
|
||||
After the `find_package(FairMQ)` call the following CMake variables are defined:
|
||||
|
@ -159,9 +147,6 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
|
|||
3. [Introspection](docs/Configuration.md#33-introspection)
|
||||
4. [Development](docs/Development.md#4-development)
|
||||
1. [Testing](docs/Development.md#41-testing)
|
||||
2. [Static Analysis](docs/Development.md#42-static-analysis)
|
||||
1. [CMake Integration](docs/Development.md#421-cmake-integration)
|
||||
2. [Extra Compiler Arguments](docs/Development.md#422-extra-compiler-arguments)
|
||||
5. [Logging](docs/Logging.md#5-logging)
|
||||
1. [Log severity](docs/Logging.md#51-log-severity)
|
||||
2. [Log verbosity](docs/Logging.md#52-log-verbosity)
|
||||
|
@ -173,4 +158,6 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
|
|||
1. [Usage](docs/Plugins.md#71-usage)
|
||||
2. [Development](docs/Plugins.md#72-development)
|
||||
3. [Provided Plugins](docs/Plugins.md#73-provided-plugins)
|
||||
1. [PMIx](docs/Plugins.md#731-pmix)
|
||||
1. [DDS](docs/Plugins.md#731-dds)
|
||||
2. [PMIx](docs/Plugins.md#732-pmix)
|
||||
8. [Controller SDK](docs/SDK.md)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2025 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -12,19 +12,46 @@ include(FairCMakeModules)
|
|||
include(FairFindPackage2)
|
||||
include(FairMQBundlePackageHelper)
|
||||
|
||||
if(BUILD_FAIRMQ)
|
||||
if(BUILD_FAIRMQ OR BUILD_SDK)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package2(PUBLIC Threads REQUIRED)
|
||||
set(Threads_PREFIX "<system>")
|
||||
set(Threads_PREFIX "<unknown system prefix>")
|
||||
endif()
|
||||
|
||||
if(BUILD_FAIRMQ OR BUILD_TIDY_TOOL)
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
find_package2(PRIVATE asiofi REQUIRED VERSION 0.5)
|
||||
find_package2(PRIVATE OFI REQUIRED)
|
||||
endif()
|
||||
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
find_package2(PRIVATE Flatbuffers REQUIRED)
|
||||
endif()
|
||||
|
||||
if(BUILD_DDS_PLUGIN OR BUILD_SDK)
|
||||
find_package2(PRIVATE DDS REQUIRED VERSION 3.5.13.7)
|
||||
set(DDS_Boost_COMPONENTS system log log_setup regex filesystem thread)
|
||||
set(DDS_Boost_VERSION 1.67)
|
||||
endif()
|
||||
|
||||
if(BUILD_PMIX_PLUGIN)
|
||||
find_package2(PRIVATE PMIx REQUIRED VERSION 2.1.4)
|
||||
endif()
|
||||
|
||||
if(BUILD_FAIRMQ OR BUILD_SDK)
|
||||
find_package2(PUBLIC FairLogger REQUIRED VERSION 1.6.0)
|
||||
find_package2(PUBLIC Boost REQUIRED VERSION 1.66
|
||||
COMPONENTS container program_options filesystem date_time regex
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BUILD_OFI_TRANSPORT OR BUILD_SDK OR BUILD_DDS_PLUGIN)
|
||||
set(__old ${CMAKE_FIND_PACKAGE_PREFER_CONFIG})
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
||||
find_package2(PUBLIC asio REQUIRED VERSION 1.18)
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ${__old})
|
||||
unset(__old)
|
||||
endif()
|
||||
|
||||
if(BUILD_FAIRMQ)
|
||||
find_package2(PRIVATE ZeroMQ REQUIRED VERSION 4.1.4)
|
||||
if(NOT PicoSHA2_BUNDLED)
|
||||
|
@ -32,7 +59,6 @@ if(BUILD_FAIRMQ)
|
|||
endif()
|
||||
find_package2(BUNDLED PicoSHA2 REQUIRED)
|
||||
set(PicoSHA2_VERSION "1.0.0")
|
||||
set(PicoSHA2_PREFIX "<bundled>")
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
|
@ -41,8 +67,7 @@ if(BUILD_TESTING)
|
|||
endif()
|
||||
find_package2(BUNDLED GTest REQUIRED)
|
||||
if(GTest_BUNDLED)
|
||||
set(GTest_VERSION "Dec 26 2024 @7d76a23")
|
||||
set(GTest_PREFIX "<bundled>")
|
||||
set(GTest_VERSION "Apr 28 2021 @f5e592d8")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -52,13 +77,6 @@ if(BUILD_DOCS)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(BUILD_TIDY_TOOL)
|
||||
find_package2(PRIVATE LLVM REQUIRED)
|
||||
find_package2(PRIVATE Clang REQUIRED)
|
||||
set(Clang_VERSION ${LLVM_VERSION})
|
||||
find_package2(PRIVATE CLI11 REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package2_implicit_dependencies() # Always call last after latest find_package2
|
||||
|
||||
if(PROJECT_PACKAGE_DEPENDENCIES)
|
||||
|
@ -70,6 +88,12 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
|
|||
if(NOT FairLogger_PREFIX AND FairLogger_ROOT)
|
||||
set(FairLogger_PREFIX ${FairLogger_ROOT})
|
||||
endif()
|
||||
elseif(${dep} STREQUAL asiofi)
|
||||
if(NOT asiofi_PREFIX AND asiofi_ROOT)
|
||||
set(asiofi_PREFIX ${asiofi_ROOT})
|
||||
endif()
|
||||
elseif(${dep} STREQUAL DDS)
|
||||
set(DDS_PREFIX "${DDS_INSTALL_PREFIX}")
|
||||
elseif(${dep} STREQUAL Boost)
|
||||
if(TARGET Boost::headers)
|
||||
get_target_property(boost_include Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
|
||||
|
@ -83,6 +107,14 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
|
|||
get_filename_component(Doxygen_PREFIX ${doxygen_bin} DIRECTORY)
|
||||
get_filename_component(Doxygen_PREFIX ${Doxygen_PREFIX}/.. ABSOLUTE)
|
||||
unset(doxygen_bin)
|
||||
elseif(${dep} STREQUAL Flatbuffers)
|
||||
if(TARGET flatbuffers::flatbuffers)
|
||||
get_target_property(flatbuffers_include flatbuffers::flatbuffers INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
get_target_property(flatbuffers_include flatbuffers::flatbuffers_shared INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
||||
get_filename_component(Flatbuffers_PREFIX ${flatbuffers_include}/.. ABSOLUTE)
|
||||
unset(flatbuffers_include)
|
||||
elseif(NOT ${dep}_PREFIX)
|
||||
# try to guess
|
||||
if(TARGET ${dep}::${dep})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -34,6 +34,8 @@ endfunction()
|
|||
|
||||
# Configure/Install CMake package
|
||||
macro(install_cmake_package)
|
||||
list(SORT PROJECT_PACKAGE_DEPENDENCIES)
|
||||
list(SORT PROJECT_INTERFACE_PACKAGE_DEPENDENCIES)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(PACKAGE_INSTALL_DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -114,16 +114,16 @@ endif()
|
|||
set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo")
|
||||
set(_warnings "-Wshadow -Wall -Wextra -Wpedantic")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g ${_warnings} ${_sanitizers}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g ${_warnings} -DNDEBUG ${_sanitizers}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${_warnings} -DNDEBUG ${_sanitizers}")
|
||||
unset(_warnings)
|
||||
unset(_sanitizers)
|
||||
|
||||
if(DISABLE_COLOR)
|
||||
set(CMAKE_COLOR_MAKEFILE OFF)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=never")
|
||||
else()
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
||||
endif()
|
||||
|
||||
|
@ -168,22 +168,9 @@ if(CMAKE_GENERATOR STREQUAL Ninja AND ENABLE_CCACHE)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FAIRMQ_HAS_STD_FILESYSTEM)
|
||||
if( ( CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
||||
if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
||||
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
|
||||
OR ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9))
|
||||
set(FAIRMQ_HAS_STD_FILESYSTEM 0)
|
||||
else()
|
||||
set(FAIRMQ_HAS_STD_FILESYSTEM 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FAIRMQ_HAS_STD_PMR)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Clang (to be more precise: libc++) currently does not implement <memory_resource>
|
||||
set(FAIRMQ_HAS_STD_PMR 0)
|
||||
else()
|
||||
set(FAIRMQ_HAS_STD_PMR 1)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -27,6 +27,24 @@ macro(fairmq_summary_components)
|
|||
set(tests_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_TESTING=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}tests${CR} ${tests_summary}")
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
set(ofi_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_OFI_TRANSPORT=OFF${CR})")
|
||||
else()
|
||||
set(ofi_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_OFI_TRANSPORT=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}ofi_transport${CR} ${ofi_summary}")
|
||||
if(BUILD_DDS_PLUGIN)
|
||||
set(dds_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_DDS_PLUGIN=OFF${CR})")
|
||||
else()
|
||||
set(dds_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_DDS_PLUGIN=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}")
|
||||
if(BUILD_PMIX_PLUGIN)
|
||||
set(pmix_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_PMIX_PLUGIN=OFF${CR})")
|
||||
else()
|
||||
set(pmix_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_PMIX_PLUGIN=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}pmix_plugin${CR} ${pmix_summary}")
|
||||
if(BUILD_EXAMPLES)
|
||||
set(examples_summary "${BGreen}YES${CR} (default, disable with ${BMagenta}-DBUILD_EXAMPLES=OFF${CR})")
|
||||
else()
|
||||
|
@ -39,12 +57,18 @@ macro(fairmq_summary_components)
|
|||
set(docs_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_DOCS=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}docs${CR} ${docs_summary}")
|
||||
if(BUILD_TIDY_TOOL)
|
||||
set(sdk_tidy_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_TIDY_TOOL=OFF${CR})")
|
||||
if(BUILD_SDK)
|
||||
set(sdk_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})")
|
||||
else()
|
||||
set(sdk_tidy_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_TIDY_TOOL=ON${CR})")
|
||||
set(sdk_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}tidy_tool${CR} ${sdk_tidy_summary}")
|
||||
message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}")
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
set(sdk_commands_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_SDK_COMMANDS=OFF${CR})")
|
||||
else()
|
||||
set(sdk_commands_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_SDK_COMMANDS=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}")
|
||||
endmacro()
|
||||
|
||||
macro(fairmq_summary_static_analysis)
|
||||
|
@ -67,17 +91,9 @@ macro(fairmq_summary_static_analysis)
|
|||
endforeach()
|
||||
set(static_ana_summary "${BWhite}(${CR}${analyser_list}${BWhite})${CR} (disable with ${BMagenta}-DRUN_STATIC_ANALYSIS=OFF${CR})")
|
||||
else()
|
||||
set(static_ana_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DRUN_STATIC_ANALYSIS=ON${CR})")
|
||||
set(static_ana_summary "${BRed}OFF${CR} (default, enable with ${BMagenta}-DRUN_STATIC_ANALYSIS=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${Cyan}RUN STATIC ANALYSIS ${static_ana_summary}")
|
||||
if(BUILD_TIDY_TOOL)
|
||||
if(RUN_FAIRMQ_TIDY)
|
||||
set(tidy_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DRUN_FAIRMQ_TIDY=OFF${CR})")
|
||||
else()
|
||||
set(tidy_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DRUN_FAIRMQ_TIDY=ON${CR})")
|
||||
endif()
|
||||
message(STATUS " ${Cyan}RUN fairmq-tidy ${tidy_summary}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(fairmq_summary_install_prefix)
|
||||
|
@ -93,13 +109,3 @@ macro(fairmq_summary_debug_mode)
|
|||
message(STATUS " ${Cyan}DEBUG MODE${CR} ${BRed}${FAIRMQ_DEBUG_MODE}${CR} (enable with ${BMagenta}-DFAIRMQ_DEBUG_MODE=ON${CR})")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(fairmq_summary_compile_definitions)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}COMPILE DEFINITION VALUE${CR}")
|
||||
message(STATUS " ${BWhite}FAIRMQ_HAS_STD_FILESYSTEM${CR} ${FAIRMQ_HAS_STD_FILESYSTEM} (overridable with ${BMagenta}-DFAIRMQ_HAS_STD_FILESYSTEM=0|1${CR})")
|
||||
message(STATUS " ${BWhite}FAIRMQ_HAS_STD_PMR${CR} ${FAIRMQ_HAS_STD_PMR} (overridable with ${BMagenta}-DFAIRMQ_HAS_STD_PMR=0|1${CR})")
|
||||
if(DEFINED FAIRMQ_CHANNEL_DEFAULT_AUTOBIND)
|
||||
message(STATUS " ${BWhite}FAIRMQ_CHANNEL_DEFAULT_AUTOBIND${CR} ${FAIRMQ_CHANNEL_DEFAULT_AUTOBIND}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
include_guard(GLOBAL)
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
|
||||
``fairmq_target_tidy()``
|
||||
========================
|
||||
|
||||
Runs the FairMQ static analyzer ``fairmq-tidy`` on source files in given
|
||||
target.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
fairmq_target_tidy(TARGET <target> [EXTRA_ARGS <args>]
|
||||
[CLANG_EXECUTABLE <clang>])
|
||||
|
||||
Registers a custom command that depends on ``<target>`` which runs ``fairmq-tidy``
|
||||
on the source files that belong to ``<target>``. Optional extra arguments
|
||||
``<args>`` are passed to the ``fairmq-tidy`` command-line.
|
||||
|
||||
Requires ``CMAKE_EXPORT_COMPILE_COMMANDS`` to be enabled.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
function(fairmq_target_tidy)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "TARGET;EXTRA_ARGS;CLANG_EXECUTABLE" "")
|
||||
|
||||
if(NOT CMAKE_EXPORT_COMPILE_COMMANDS)
|
||||
message(AUTHOR_WARNING "CMAKE_EXPORT_COMPILE_COMMANDS is not enabled. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT ARG_TARGET)
|
||||
message(AUTHOR_WARNING "TARGET argument is required. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT TARGET ${ARG_TARGET})
|
||||
message(AUTHOR_WARNING "Given TARGET argument `${ARG_TARGET}` is not a target. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(NOT fairmq_tidy_clang_resource_dir)
|
||||
if(ARG_CLANG_EXECUTABLE)
|
||||
set(clang_exe ${ARG_CLANG_EXECUTABLE})
|
||||
else()
|
||||
if(TARGET clang)
|
||||
get_property(clang_exe TARGET clang PROPERTY LOCATION)
|
||||
else()
|
||||
set(clang_exe "clang")
|
||||
endif()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${clang_exe} -print-resource-dir
|
||||
OUTPUT_VARIABLE clang_resource_dir
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(fairmq_tidy_clang_resource_dir ${clang_resource_dir}
|
||||
CACHE PATH "fairmq_target_tidy() internal state" FORCE)
|
||||
endif()
|
||||
list(APPEND ARG_EXTRA_ARGS
|
||||
"--extra-arg-before=-I${fairmq_tidy_clang_resource_dir}/include")
|
||||
endif()
|
||||
|
||||
if(ARG_EXTRA_ARGS)
|
||||
set(extra 1)
|
||||
else()
|
||||
set(extra 0)
|
||||
endif()
|
||||
|
||||
get_target_property(sources ${ARG_TARGET} SOURCES)
|
||||
list(FILTER sources INCLUDE REGEX "\.(cpp|cxx)$")
|
||||
string(REPLACE ":" "-" target_nocolon "${ARG_TARGET}")
|
||||
|
||||
set(src_deps)
|
||||
foreach(source IN LISTS sources)
|
||||
string(REPLACE "\/" "-" source_noslash "${source}")
|
||||
set(src_stamp "${CMAKE_CURRENT_BINARY_DIR}/${target_nocolon}-${source_noslash}.fairmq-tidy")
|
||||
add_custom_command(
|
||||
OUTPUT ${src_stamp}
|
||||
COMMAND $<TARGET_FILE:FairMQ::fairmq-tidy> -p=${CMAKE_BINARY_DIR}
|
||||
$<${extra}:${ARG_EXTRA_ARGS}> ${source}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${src_stamp}
|
||||
COMMENT "fairmq-tidy: Analyzing source file '${source}' of target '${ARG_TARGET}'"
|
||||
DEPENDS ${ARG_TARGET}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND_EXPAND_LISTS VERBATIM
|
||||
)
|
||||
list(APPEND src_deps ${src_stamp})
|
||||
endforeach()
|
||||
|
||||
if(src_deps)
|
||||
add_custom_target("fairmq-tidy-${target_nocolon}" ALL DEPENDS ${src_deps})
|
||||
endif()
|
||||
endfunction()
|
74
cmake/FindPMIx.cmake
Normal file
74
cmake/FindPMIx.cmake
Normal file
|
@ -0,0 +1,74 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
|
||||
# The "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix" part in all
|
||||
# the PATH_SUFFIXES is here to be able to find Debian's
|
||||
# libpmix-dev package. It installs everything below
|
||||
# /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix
|
||||
|
||||
|
||||
find_path(PMIx_INCLUDE_DIR
|
||||
NAMES pmix.h
|
||||
HINTS ${PMIX_ROOT} $ENV{PMIX_ROOT}
|
||||
PATH_SUFFIXES include lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix/include
|
||||
)
|
||||
|
||||
find_path(PMIx_LIBRARY_DIR
|
||||
NAMES libpmix.dylib libpmix.so
|
||||
HINTS ${PMIX_ROOT} $ENV{PMIX_ROOT}
|
||||
PATH_SUFFIXES lib lib64 lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix/lib
|
||||
)
|
||||
|
||||
find_library(PMIx_LIBRARY_SHARED
|
||||
NAMES libpmix.dylib libpmix.so
|
||||
HINTS ${PMIX_ROOT} $ENV{PMIX_ROOT}
|
||||
PATH_SUFFIXES lib lib64 lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix/lib
|
||||
)
|
||||
|
||||
find_file(PMIx_VERSION_FILE
|
||||
NAMES pmix_version.h
|
||||
HINTS ${PMIX_ROOT} $ENV{PMIX_ROOT}
|
||||
PATH_SUFFIXES include lib/${CMAKE_LIBRARY_ARCHITECTURE}/pmix/include
|
||||
)
|
||||
|
||||
file(READ "${PMIx_VERSION_FILE}" __version_raw)
|
||||
string(REGEX MATCH "#define PMIX_VERSION_MAJOR ([0-9]?)L?"
|
||||
__version_major_raw "${__version_raw}"
|
||||
)
|
||||
set(PMIx_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "#define PMIX_VERSION_MINOR ([0-9]?)L?"
|
||||
__version_minor_raw "${__version_raw}"
|
||||
)
|
||||
set(PMIx_VERSION_MINOR "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "#define PMIX_VERSION_RELEASE ([0-9]?)L?"
|
||||
__version_patch_raw "${__version_raw}"
|
||||
)
|
||||
set(PMIx_VERSION_PATCH "${CMAKE_MATCH_1}")
|
||||
|
||||
set(PMIx_VERSION "${PMIx_VERSION_MAJOR}.${PMIx_VERSION_MINOR}.${PMIx_VERSION_PATCH}")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PMIx
|
||||
REQUIRED_VARS
|
||||
PMIx_INCLUDE_DIR
|
||||
PMIx_LIBRARY_DIR
|
||||
PMIx_LIBRARY_SHARED
|
||||
|
||||
VERSION_VAR PMIx_VERSION
|
||||
)
|
||||
|
||||
if(NOT TARGET PMIx::libpmix AND PMIx_FOUND)
|
||||
add_library(PMIx::libpmix SHARED IMPORTED)
|
||||
set_target_properties(PMIx::libpmix PROPERTIES
|
||||
IMPORTED_LOCATION ${PMIx_LIBRARY_SHARED}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${PMIx_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
|
@ -1,5 +1,5 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2017-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
|
@ -20,7 +20,6 @@
|
|||
# [DEPENDS dep1 [dep2 ...]]
|
||||
# [LINKS linklib1 [linklib2 ...]
|
||||
# [INCLUDES dir1 [dir2 ...]
|
||||
# [ENVIRONMENT var1=op:val1[;var2=op:val2 ...]]
|
||||
# [TIMEOUT seconds]
|
||||
# [RUN_SERIAL ON/OFF])
|
||||
#
|
||||
|
@ -49,15 +48,12 @@
|
|||
#
|
||||
|
||||
include(GoogleTest)
|
||||
if(BUILD_TIDY_TOOL)
|
||||
include(FairMQTidy)
|
||||
endif()
|
||||
|
||||
function(add_testsuite suitename)
|
||||
cmake_parse_arguments(testsuite
|
||||
""
|
||||
"TIMEOUT;RUN_SERIAL"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES;DEFINITIONS;ENVIRONMENT"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES;DEFINITIONS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
|
@ -78,12 +74,6 @@ function(add_testsuite suitename)
|
|||
if(testsuite_DEFINITIONS)
|
||||
target_compile_definitions("${target}" PUBLIC ${testsuite_DEFINITIONS})
|
||||
endif()
|
||||
if(testsuite_ENVIRONMENT AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22)
|
||||
set(env "ENVIRONMENT_MODIFICATION" ${testsuite_ENVIRONMENT})
|
||||
endif()
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET ${target})
|
||||
endif()
|
||||
|
||||
# add_test(NAME "${suitename}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${target})
|
||||
if(testsuite_TIMEOUT)
|
||||
|
@ -101,7 +91,6 @@ function(add_testsuite suitename)
|
|||
TEST_PREFIX ${suitename}.
|
||||
PROPERTIES RUN_SERIAL ${testsuite_RUN_SERIAL}
|
||||
TIMEOUT ${testsuite_TIMEOUT}
|
||||
${env}
|
||||
)
|
||||
|
||||
list(APPEND ALL_TEST_TARGETS ${target})
|
||||
|
@ -131,9 +120,6 @@ function(add_testhelper helpername)
|
|||
if(testhelper_DEFINITIONS)
|
||||
target_compile_definitions(${target} PUBLIC ${testhelper_DEFINITIONS})
|
||||
endif()
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET ${target})
|
||||
endif()
|
||||
|
||||
list(APPEND ALL_TEST_TARGETS ${target})
|
||||
set(ALL_TEST_TARGETS ${ALL_TEST_TARGETS} PARENT_SCOPE)
|
||||
|
@ -168,9 +154,6 @@ function(add_testlib libname)
|
|||
if(testlib_DEFINITIONS)
|
||||
target_compile_definitions(${target} PUBLIC ${testlib_DEFINITIONS})
|
||||
endif()
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET ${target})
|
||||
endif()
|
||||
|
||||
list(APPEND ALL_TEST_TARGETS ${target})
|
||||
set(ALL_TEST_TARGETS ${ALL_TEST_TARGETS} PARENT_SCOPE)
|
||||
|
|
|
@ -6,29 +6,17 @@
|
|||
"license": "./COPYRIGHT",
|
||||
"datePublished": "2018-04-15",
|
||||
"developmentStatus": "active",
|
||||
"softwareVersion": "master",
|
||||
"releaseNotes": "https://github.com/FairRootGroup/FairMQ/releases",
|
||||
"codeRepository": "https://github.com/FairRootGroup/FairMQ/",
|
||||
"readme": "https://github.com/FairRootGroup/FairMQ/#readme",
|
||||
"issueTracker": "https://github.com/FairRootGroup/FairMQ/issues",
|
||||
"identifier": "https://doi.org/10.5281/zenodo.1689985",
|
||||
"maintainer": [
|
||||
{
|
||||
"@type": "ResearchOrganisation",
|
||||
"@id": "https://ror.org/02k8cbn47",
|
||||
"name": "GSI Helmholtz Centre for Heavy Ion Research"
|
||||
}
|
||||
],
|
||||
"author": [
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0002-8071-4497",
|
||||
"givenName": "Mohammad",
|
||||
"familyName": "Al-Turany"
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0003-3787-1910",
|
||||
"givenName": "Dennis",
|
||||
"familyName": "Klein"
|
||||
},
|
||||
|
@ -39,7 +27,6 @@
|
|||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0002-6249-155X",
|
||||
"givenName": "Alexey",
|
||||
"familyName": "Rybalchenko"
|
||||
},
|
||||
|
@ -104,7 +91,6 @@
|
|||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0002-5321-8404",
|
||||
"givenName": "Christian",
|
||||
"familyName": "Tacke"
|
||||
},
|
||||
|
|
83
codemeta_update.py
Executable file
83
codemeta_update.py
Executable file
|
@ -0,0 +1,83 @@
|
|||
#! /usr/bin/env python3
|
||||
# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
class CodeMetaManipulator(object):
|
||||
def load(self, filename='codemeta.json'):
|
||||
with open(filename, 'rb') as fp:
|
||||
self.data = json.load(fp, object_pairs_hook=OrderedDict)
|
||||
|
||||
@staticmethod
|
||||
def _dict_entry_cmp(dict1, dict2, field):
|
||||
if (field in dict1) and (field in dict2):
|
||||
return dict1[field] == dict2[field]
|
||||
else:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def find_person_entry(cls, person_list, matchdict):
|
||||
for entry in person_list:
|
||||
if cls._dict_entry_cmp(entry, matchdict, 'email'):
|
||||
return entry
|
||||
if cls._dict_entry_cmp(entry, matchdict, 'familyName') \
|
||||
and cls._dict_entry_cmp(entry, matchdict, 'givenName'):
|
||||
return entry
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def update_person_entry(entry, matchdict):
|
||||
if entry is None:
|
||||
entry = OrderedDict()
|
||||
entry['@type'] = 'Person'
|
||||
for field in ('givenName', 'familyName', 'email'):
|
||||
val = matchdict.get(field, None)
|
||||
if val is not None:
|
||||
entry[field] = val
|
||||
return entry
|
||||
|
||||
def handle_person_list_file(self, filename, cm_field_name):
|
||||
fp = open(filename, 'r', encoding='utf8')
|
||||
findregex = re.compile(r'^(?P<familyName>[-\w\s]*[-\w]),\s*'
|
||||
r'(?P<givenName>[-\w\s]*[-\w])\s*'
|
||||
r'(?:<(?P<email>\S+@\S+)>)?$')
|
||||
person_list = self.data.setdefault(cm_field_name, [])
|
||||
for line in fp:
|
||||
line = line.strip()
|
||||
m = findregex.match(line)
|
||||
if m is None:
|
||||
raise RuntimeError("Could not analyze line %r" % line)
|
||||
found_entry = self.find_person_entry(person_list, m.groupdict())
|
||||
entry = self.update_person_entry(found_entry, m.groupdict())
|
||||
if found_entry is None:
|
||||
person_list.append(entry)
|
||||
|
||||
def save(self, filename='codemeta.json'):
|
||||
with open('codemeta.json', 'w', encoding='utf8') as fp:
|
||||
json.dump(self.data, fp, indent=2)
|
||||
fp.write('\n')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Update codemeta.json')
|
||||
parser.add_argument('--set-version', dest='newversion')
|
||||
args = parser.parse_args()
|
||||
|
||||
cm = CodeMetaManipulator()
|
||||
cm.load()
|
||||
if args.newversion is not None:
|
||||
cm.data['softwareVersion'] = args.newversion
|
||||
cm.handle_person_list_file('AUTHORS', 'author')
|
||||
cm.handle_person_list_file('CONTRIBUTORS', 'contributor')
|
||||
cm.save()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -16,18 +16,20 @@ Here is an overview of the device/channel options and when they are applied:
|
|||
|
||||
| Property | Applied in |
|
||||
| --- | --- |
|
||||
| `severity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<fairmq/runDevice.h>`)) |
|
||||
| `file-severity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<fairmq/runDevice.h>`)) |
|
||||
| `verbosity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<fairmq/runDevice.h>`)) |
|
||||
| `color` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<fairmq/runDevice.h>`)) |
|
||||
| `log-to-file` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<fairmq/runDevice.h>`)) |
|
||||
| `severity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<runFairMQDevice.h>`)) |
|
||||
| `file-severity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<runFairMQDevice.h>`)) |
|
||||
| `verbosity` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<runFairMQDevice.h>`)) |
|
||||
| `color` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<runFairMQDevice.h>`)) |
|
||||
| `log-to-file` | immidiately (if `fair::mq::DeviceRunner` is used (also the case when using `<runFairMQDevice.h>`)) |
|
||||
| `id` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `io-threads` | 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` |
|
||||
| `init-timeout` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `max-run-time` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `shm-segment-size` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `shm-monitor` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `ofi-size-hint` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `rate` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `session` | at the end of `fair::mq::State::InitializingDevice` |
|
||||
| `chan.*` | at the end of `fair::mq::State::InitializingDevice` (channel addresses can be also applied during `fair::mq::State::Binding`/`fair::mq::State::Connecting`) |
|
||||
|
|
|
@ -6,53 +6,8 @@
|
|||
|
||||
For unit testing it is often not feasible to boot up a full-blown distributed system with dozens of processes.
|
||||
|
||||
In some scenarios it is useful to not even instantiate a `fair::mq::Device` at all. Please see [this example](../test/protocols/_push_pull_multipart.cxx) for single and multi threaded unit test without a device instance. If you store your transport factories and channels on the heap, pls make sure, you destroy the channels before you destroy the related transport factory for proper shutdown. Channels provide all the `Send/Receive` and `New*Message/New*Poller` APIs provided by the device too.
|
||||
In some scenarios it is useful to not even instantiate a `FairMQDevice` at all. Please see [this example](../test/protocols/_push_pull_multipart.cxx) for single and multi threaded unit test without a device instance. If you store your transport factories and channels on the heap, pls make sure, you destroy the channels before you destroy the related transport factory for proper shutdown. Channels provide all the `Send/Receive` and `New*Message/New*Poller` APIs provided by the device too.
|
||||
|
||||
## 4.2 Static Analysis
|
||||
|
||||
With `-DBUILD_TIDY_TOOL=ON` you can build the `fairmq-tidy` tool that implements static checks on your source code. To use it, enable the generation of a [compilation database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) in your project via `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` (generates a file `<builddir>/compile_commands.json`):
|
||||
|
||||
```
|
||||
fairmq-tidy -p <builddir> mysourcefile.cpp
|
||||
```
|
||||
|
||||
If you find any issue (e.g. false positives) with this tool, please tell us by opening an issue on github.
|
||||
|
||||
### 4.2.1 CMake Integration
|
||||
|
||||
When discovering a FairMQ installation in your project, explicitely state, that you want one with the `fairmq-tidy` tool included:
|
||||
|
||||
```
|
||||
find_package(FairMQ COMPONENTS tidy_tool)
|
||||
```
|
||||
|
||||
Now the CMake module [`FairMQTidy.cmake`](../cmake/FairMQTidy.cmake) is available for inclusion:
|
||||
|
||||
```
|
||||
include(FairMQTidy)
|
||||
```
|
||||
|
||||
It provides the CMake function `fairmq_target_tidy()` which attaches appropriate `fairmq-tidy` build rules to each source file contained in the passed library or executable target, e.g. if you have an executable that uses FairMQ:
|
||||
|
||||
```
|
||||
add_executable(myexe mysource1.cpp mysource2.cpp)
|
||||
target_link_libraries(myexe PRIVATE FairMQ::FairMQ)
|
||||
fairmq_target_tidy(TARGET myexe)
|
||||
```
|
||||
|
||||
### 4.2.2 Extra Compiler Arguments
|
||||
|
||||
On most Linux distros you are likely to use GCC to compile your projects, so the resulting `compile_commands.json` contains the command-line tuned for GCC which might be missing options needed to successfully invoke the Clang frontend which is used internally by `fairmq-tidy`. In general, you can pass extra `clang` options via the following options:
|
||||
|
||||
```
|
||||
--extra-arg=<string> - Additional argument to append to the compiler command line
|
||||
--extra-arg-before=<string> - Additional argument to prepend to the compiler command line
|
||||
```
|
||||
|
||||
E.g. if standard headers are not found, you can hint the location like this:
|
||||
|
||||
```
|
||||
fairmq-top -p <builddir> --extra-arg-before=-I$(clang -print-resource-dir)/include mysourcefile.cpp
|
||||
```
|
||||
TODO Multiple devices in one process.
|
||||
|
||||
← [Back](../README.md)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# 1. Device
|
||||
|
||||
The components encapsulating the tasks are called **devices** and derive from the common base class `fair::mq::Device`. FairMQ provides ready to use devices to organize the dataflow between the components (without touching the contents of a message), providing functionality like merging and splitting of the data stream (see subdirectory `devices`).
|
||||
The components encapsulating the tasks are called **devices** and derive from the common base class `FairMQDevice`. FairMQ provides ready to use devices to organize the dataflow between the components (without touching the contents of a message), providing functionality like merging and splitting of the data stream (see subdirectory `devices`).
|
||||
|
||||
## 1.1 Topology
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ Plugin Manager:
|
|||
see man ld.so(8) for details.
|
||||
-P [ --plugin ] arg List of plugin names to load in
|
||||
order,e.g. if the file is called
|
||||
'libfairmq-plugin-example.so', just list
|
||||
'libFairMQPlugin_example.so', just list
|
||||
'example' or 'd:example' here.To load a
|
||||
prelinked plugin, list 'p:example'
|
||||
here.
|
||||
|
@ -54,8 +54,40 @@ A more complete example which may serve as a start including example CMake code
|
|||
|
||||
## 7.3 Provided Plugins
|
||||
|
||||
### 7.3.1 PMIx
|
||||
### 7.3.1 DDS
|
||||
|
||||
The [PMIx](https://pmix.org/) plugin enables launching a FairMQ topology with any PMIx capable launcher, e.g. the [Open Run-Time Environment (ORTE) of OpenMPI](https://www.open-mpi.org/doc/v4.0/man1/mpirun.1.php) or the [Slurm workload manager](https://slurm.schedmd.com/srun.html). This experimental plugin has been last released in v1.4.56 and is removed in v1.5+. For now there are no plans to pick up development of it again.
|
||||
When launching a FairMQ topology via [DDS](http://dds.gsi.de/) the DDS plugin enables FairMQ devices to interact with DDS' custom command and property subsystems - enable the plugin by passing `-P dds` on the command line.
|
||||
|
||||
Via the property subsystem a FairMQ topology may exchange channel connection data (essentially to do service discovery) needed to connect/bind all FairMQ channels appropriately. DDS is highly optimized for this use case. See [examples/dds](examples/dds/README.md) for more details.
|
||||
|
||||
Via the custom command subsystem a FairMQ device can receive a number of commands. FairMQ provides a convenient command line tool `fairmq-dds-command-ui` that allows interactive or scripted control of a running FairMQ topology managed via DDS. If one develops directly against the custom command DDS API, the following table lists all the commands the DDS plugin currently understands:
|
||||
|
||||
| Custom Command | Response | Error | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `check-state` | `<ID>: <STATE> (pid: <PID>)` | n/a | Query current device state, see state machine for possible states |
|
||||
| `dump-config` | `(<ID>: <PKEY> -> <PVALUE>\n)+` | n/a | Query current device config (list property key/value pairs) |
|
||||
| `INIT DEVICE` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `BIND` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `CONNECT` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `INIT TASK` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `RUN` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `STOP` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `RESET TASK` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `RESET DEVICE` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `END` | `<ID>: queued <CMD> transition` | `<ID>: could not queue <CMD> transition` | Initiate state transition |
|
||||
| `subscribe-to-heartbeats` | `heartbeat-subscription: <ID>,OK` | n/a | Subscribe to heartbeats |
|
||||
| on heartbeat subscription | `heartbeat: <ID>,<PID>` | n/a | Heartbeat every 100ms |
|
||||
| `unsubscribe-from-heartbeats` | `heartbeat-unsubscription: <ID>,OK` | n/a | Unsubscribe from heartbeats |
|
||||
| `subscribe-to-state-changes` | `state-changes-subscription: <ID>,OK` | n/a | Subscribe to state changes |
|
||||
| on state changes subscription | `state-change: <ID>,<STATE>` | n/a | State change notification |
|
||||
| `unsubscribe-from-state-changes` | `state-changes-unsubscription: <ID>,OK` | n/a | Unsubscribe from state changes |
|
||||
|
||||
If unknown commands are received the plugin will print a warning.
|
||||
|
||||
### 7.3.2 PMIx
|
||||
|
||||
The [PMIx](https://pmix.org/) plugin enables launching a FairMQ topology with any PMIx capable launcher, e.g. the [Open Run-Time Environment (ORTE) of OpenMPI](https://www.open-mpi.org/doc/v4.0/man1/mpirun.1.php) or the [Slurm workload manager](https://slurm.schedmd.com/srun.html). This plugin is not (yet) very mature and serves as a proof of concept at the moment.
|
||||
|
||||
TODO example usage
|
||||
|
||||
← [Back](../README.md)
|
||||
|
|
34
docs/SDK.md
Normal file
34
docs/SDK.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
← [Back](../README.md)
|
||||
|
||||
# 8. Controller SDK
|
||||
|
||||
The FairMQ Controller Software Development Kit (`-DBUILD_SDK=ON`) contains a (as of today still experimental) set of C++ APIs that provide essential functionality to the implementer of a global controller.
|
||||
|
||||
The FairMQ core library only provides two local controllers - `static` (a fixed sequence of state transitions) and `interactive` (a read-eval-print-loop which reads keyboard commands from standard input). A local controller only knows how steer a single [FairMQ device](Device.md) - in fact, it runs in a thread within the device process.
|
||||
|
||||
A global controller has knowledge about the full topology of connected FairMQ devices. Its responsibility is to facilitate the lifecycle of a distributed FairMQ-based application (*executing a topology*), such as
|
||||
|
||||
* allocating/releasing compute resources from a resource management system,
|
||||
* launching/setting up the run-time environment and the FairMQ devices,
|
||||
* driving the device state machines in lock-step across the full topology,
|
||||
* pushing the device configuration,
|
||||
* monitoring (some aspects of the application's) operation,
|
||||
* and handling/reporting (some) error cases.
|
||||
|
||||
The low-level hook to integrate FairMQ devices with such a global contoller is the [plugin mechanism](Plugins.md) in the FairMQ core library. The FairMQ Controller SDK provides C++ APIs that communicate to the endpoints exposed by such a FairMQ plugin.
|
||||
|
||||
At the moment, the Controller SDK only supports [DDS](https://dds.gsi.de) as resource manager and run-time environment. A second implementation based on [PMIx](https://pmix.org/) (targeting its implementation in [Slurm](https://slurm.schedmd.com/documentation.html) and [OpenRTE](https://www-lb.open-mpi.org/papers/euro-pvmmpi-2005-orte/)) is in development.
|
||||
|
||||
The following section give a short overview on the APIs provided.
|
||||
|
||||
## RMS and run-time environment
|
||||
|
||||
The classes [`fair::mq::sdk::DDSEnvironment`](../fairmq/sdk/DDSEnvironment.h), [`fair::mq::sdk::DDSSession`](../fairmq/sdk/DDSSession.h), and [`fair::mq::sdk::DDSTopology`](../fairmq/sdk/DDSTopology.h) are thin wrappers of most of the synchronous APIs exposed by DDS ([`dds::tools_api`](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1tools__api.html) and [`dds::topology_api`](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1topology__api.html)). E.g. they allow to [start a DDS session](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L26-L28), [allocate resources](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L34) and [launch a topology](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L39) from a C++ program.
|
||||
|
||||
## Driving the global state machine
|
||||
|
||||
The class [`fair::mq::sdk::Topology`](../fairmq/sdk/Topology.h) adds a FairMQ-specific view on an existing DDS session that is executing a topology of FairMQ devices. One can e.g. [initiate a state transition on all devices in the topology simultaneously](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L48-L49). This topology transition completes once a topology-wide barrier is passed (all devices completed the transition). This effectively exposes the device state machine as a topology state machine. The implementation is based on remote procedure calls over the [DDS intercom service](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1intercom__api.html) between the controller and the DDS plugin shipped with FairMQ (`-DBUILD_DDS_PLUGIN=ON`).
|
||||
|
||||
For future versions of the SDK new APIs are planned to inspect and modify the device configurations and also operate only on subsets of a given topology.
|
||||
|
||||
← [Back](../README.md)
|
|
@ -27,34 +27,34 @@ The next table shows the supported address types for each transport implementati
|
|||
|
||||
## 2.1 Message
|
||||
|
||||
Devices transport data between each other in form of `fair::mq::Message`s. These can be filled with arbitrary content. Message can be initialized in three different ways by calling `NewMessage()`:
|
||||
Devices transport data between each other in form of `FairMQMessage`s. These can be filled with arbitrary content. Message can be initialized in three different ways by calling `NewMessage()`:
|
||||
|
||||
```cpp
|
||||
fair::mq::MessagePtr NewMessage() const;
|
||||
FairMQMessagePtr NewMessage() const;
|
||||
```
|
||||
**with no parameters**: Initializes an empty message (typically used for receiving).
|
||||
|
||||
```cpp
|
||||
fair::mq::MessagePtr NewMessage(const size_t size) const;
|
||||
FairMQMessagePtr NewMessage(const size_t size) const;
|
||||
```
|
||||
**given message size**: Initializes message body with a given size. Fill the created contents via buffer pointer.
|
||||
|
||||
```cpp
|
||||
using fairmq_free_fn = void(void* data, void* hint);
|
||||
fair::mq::MessagePtr NewMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) const;
|
||||
FairMQMessagePtr NewMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) const;
|
||||
```
|
||||
**given existing buffer and a size**: Initialize the message from an existing buffer. In case of ZeroMQ this is a zero-copy operation.
|
||||
|
||||
Additionally, FairMQ provides two more message factories for convenience:
|
||||
```cpp
|
||||
template<typename T>
|
||||
fair::mq::MessagePtr NewSimpleMessage(const T& data) const
|
||||
FairMQMessagePtr NewSimpleMessage(const T& data) const
|
||||
```
|
||||
**copy and own**: Copy the `data` argument into the returned message and take ownership (free memory after message is sent). This interface is useful for small, [trivially copyable](http://en.cppreference.com/w/cpp/concept/TriviallyCopyable) data.
|
||||
|
||||
```cpp
|
||||
template<typename T>
|
||||
fair::mq::MessagePtr NewStaticMessage(const T& data) const
|
||||
FairMQMessagePtr NewStaticMessage(const T& data) const
|
||||
```
|
||||
**point to existing memory**: The returned message will point to the `data` argument, but not take ownership (someone else must destruct this variable). Make sure that `data` lives long enough to be successfully sent. This interface is most useful for third party managed, contiguous memory (Be aware of shallow types with internal pointer references! These will not be sent.)
|
||||
|
||||
|
@ -65,19 +65,19 @@ The component of a program, that is reponsible for the allocation or destruction
|
|||
After queuing a message for sending in FairMQ, the transport takes ownership over the message body and will free it with `free()` after it is no longer used. A callback can be passed to the message object, to be called instead of the destruction with `free()` (for initialization via buffer+size).
|
||||
|
||||
```cpp
|
||||
static void fair::mq::NoCleanup(void* /*data*/, void* /*obj*/) {}
|
||||
static void FairMQNoCleanup(void* /*data*/, void* /*obj*/) {}
|
||||
|
||||
template<typename T>
|
||||
static void fair::mq::SimpleMsgCleanup(void* /*data*/, void* obj) { delete static_cast<T*>(obj); }
|
||||
static void FairMQSimpleMsgCleanup(void* /*data*/, void* obj) { delete static_cast<T*>(obj); }
|
||||
```
|
||||
For convenience, two common deleter callbacks are already defined in the `fair::mq::TransportFactory` class to aid the user in controlling ownership of the data.
|
||||
For convenience, two common deleter callbacks are already defined in the `FairMQTransportFactory` class to aid the user in controlling ownership of the data.
|
||||
|
||||
## 2.2 Channel
|
||||
|
||||
A channel represents a communication endpoint in FairMQ. Usage is similar to a traditional Unix network socket. A device usually contains a number of channels that can either listen for incoming connections from channels of other devices or they can connect to other listening channels. Channels are organized by a channel name and a subchannel index.
|
||||
|
||||
```cpp
|
||||
const fair::mq::Channel& GetChannel(const std::string& channelName, const int index = 0) const;
|
||||
const FairMQChannel& GetChannel(const std::string& channelName, const int index = 0) const;
|
||||
```
|
||||
|
||||
All subchannels with a common channel name need to be of the same transport type.
|
||||
|
@ -87,7 +87,7 @@ All subchannels with a common channel name need to be of the same transport type
|
|||
A poller allows to wait on multiple channels either to receive or send a message.
|
||||
|
||||
```cpp
|
||||
fair::mq::PollerPtr NewPoller(const std::vector<const fair::mq::Channel*>& channels)
|
||||
FairMQPollerPtr NewPoller(const std::vector<const FairMQChannel*>& channels)
|
||||
```
|
||||
**list channels**: This poller waits on all supplied channels. Currently, it is limited to channels of the same transport type only.
|
||||
|
||||
|
|
|
@ -1,9 +1,51 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME 1-1 DEVICE sampler sink)
|
||||
add_executable(fairmq-ex-1-1-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-1-1-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-1-1-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-1-1-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(Example11 DEPENDS fairmq-ex-1-1-sampler fairmq-ex-1-1-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-1.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh)
|
||||
|
||||
add_test(NAME Example.1-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh zeromq)
|
||||
set_tests_properties(Example.1-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
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: ")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-1-1-sampler
|
||||
fairmq-ex-1-1-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-1.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-1.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-1-1.sh
|
||||
)
|
||||
|
|
|
@ -30,7 +30,7 @@ struct Sampler : fair::mq::Device
|
|||
// create message object with a pointer to the data buffer, its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
fair::mq::MessagePtr msg(NewMessage(
|
||||
FairMQMessagePtr msg(NewMessage(
|
||||
const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
|||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,24 +8,20 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; rm $chanAddr; exit 0' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-1-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --rate 1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,address=ipc://$chanAddr,rateLogging=0"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://*:5555,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -35,19 +29,13 @@ SINK="fairmq-ex-1-1-sink"
|
|||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --channel-config name=$chan,type=pull,method=connect,address=ipc://$chanAddr,rateLogging=0"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://localhost:5555,rateLogging=0"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
# wait for sampler and sink to finish
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
set +e
|
||||
rm $chanAddr
|
||||
exit 0
|
||||
|
|
|
@ -1,9 +1,64 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME 1-n-1 DEVICE sampler processor sink CONFIG)
|
||||
add_executable(fairmq-ex-1-n-1-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-1-n-1-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-1-n-1-processor processor.cxx)
|
||||
target_link_libraries(fairmq-ex-1-n-1-processor PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-1-n-1-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-1-n-1-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(Example1N1 DEPENDS fairmq-ex-1-n-1-sampler fairmq-ex-1-n-1-processor fairmq-ex-1-n-1-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(EX_CONF_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-n-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-n-1.sh)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-1-n-1.json ${CMAKE_CURRENT_BINARY_DIR}/ex-1-n-1.json)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-n-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh)
|
||||
|
||||
add_test(NAME Example.1-n-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh zeromq)
|
||||
set_tests_properties(Example.1-n-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
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: ")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-1-n-1-sampler
|
||||
fairmq-ex-1-n-1-processor
|
||||
fairmq-ex-1-n-1-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(EX_CONF_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-n-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-n-1.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-1-n-1.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-1-n-1.sh
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-1-n-1.json
|
||||
DESTINATION ${PROJECT_INSTALL_DATADIR}
|
||||
)
|
||||
|
|
|
@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
|
|||
OnData("data1", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received data, processing...";
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
|
|||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
fair::mq::MessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
FairMQMessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
text));
|
||||
|
|
|
@ -28,7 +28,7 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
// Initializing message with NewStaticMessage will avoid copy
|
||||
// but won't delete the data after the sending is completed.
|
||||
fair::mq::MessagePtr msg(NewStaticMessage(fText));
|
||||
FairMQMessagePtr msg(NewStaticMessage(fText));
|
||||
|
||||
LOG(info) << "Sending \"" << fText << "\"";
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
|||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,26 +8,20 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
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"
|
||||
ex2config="@CMAKE_CURRENT_BINARY_DIR@/ex-1-n-1.json"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; 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; exit 0' 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;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-1-n-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 2"
|
||||
SAMPLER+=" --channel-config name=$chan1,type=push,method=bind,address=ipc://$chan1Addr,rateLogging=0"
|
||||
SAMPLER+=" --mq-config $ex2config"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -37,13 +29,10 @@ PROCESSOR1="fairmq-ex-1-n-1-processor"
|
|||
PROCESSOR1+=" --id processor1"
|
||||
PROCESSOR1+=" --transport $transport"
|
||||
PROCESSOR1+=" --verbosity veryhigh"
|
||||
PROCESSOR1+=" --session $session"
|
||||
PROCESSOR1+=" --severity debug"
|
||||
PROCESSOR1+=" --shm-segment-size 100000000"
|
||||
PROCESSOR1+=" --shm-monitor true"
|
||||
PROCESSOR1+=" --session $SESSION"
|
||||
PROCESSOR1+=" --control static --color false"
|
||||
PROCESSOR1+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
|
||||
PROCESSOR1+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
|
||||
PROCESSOR1+=" --mq-config $ex2config"
|
||||
PROCESSOR1+=" --config-key processor"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR1 &
|
||||
PROCESSOR1_PID=$!
|
||||
|
||||
|
@ -51,13 +40,10 @@ PROCESSOR2="fairmq-ex-1-n-1-processor"
|
|||
PROCESSOR2+=" --id processor2"
|
||||
PROCESSOR2+=" --transport $transport"
|
||||
PROCESSOR2+=" --verbosity veryhigh"
|
||||
PROCESSOR2+=" --session $session"
|
||||
PROCESSOR2+=" --severity debug"
|
||||
PROCESSOR2+=" --shm-segment-size 100000000"
|
||||
PROCESSOR2+=" --shm-monitor true"
|
||||
PROCESSOR2+=" --session $SESSION"
|
||||
PROCESSOR2+=" --control static --color false"
|
||||
PROCESSOR2+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr,rateLogging=0"
|
||||
PROCESSOR2+=" name=$chan2,type=push,method=connect,address=ipc://$chan2Addr,rateLogging=0"
|
||||
PROCESSOR2+=" --mq-config $ex2config"
|
||||
PROCESSOR2+=" --config-key processor"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$PROCESSOR2 &
|
||||
PROCESSOR2_PID=$!
|
||||
|
||||
|
@ -65,13 +51,10 @@ SINK="fairmq-ex-1-n-1-sink"
|
|||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 2"
|
||||
SINK+=" --channel-config name=$chan2,type=pull,method=bind,address=ipc://$chan2Addr,rateLogging=0"
|
||||
SINK+=" --mq-config $ex2config"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
|
@ -86,7 +69,3 @@ kill -SIGINT $PROCESSOR2_PID
|
|||
# wait for everything to finish
|
||||
wait $PROCESSOR1_PID
|
||||
wait $PROCESSOR2_PID
|
||||
|
||||
set +e
|
||||
rm $chan1Addr; rm $chan2Addr
|
||||
exit 0
|
||||
|
|
|
@ -1,145 +1,15 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2018-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
set(exe_prefix "fairmq-ex")
|
||||
set(script_prefix "fairmq-start-ex")
|
||||
set(test_script_prefix "test-ex")
|
||||
set(testsuite "Example")
|
||||
set(transports "zeromq" "shmem")
|
||||
|
||||
function(add_example)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 ARG
|
||||
"CONFIG;NO_TRANSPORT;NO_TEST"
|
||||
"NAME"
|
||||
"DEVICE;VARIANT;TRANSPORT;SCRIPT"
|
||||
)
|
||||
|
||||
if(ARG_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unexpected unparsed arguments: ${ARG_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if(ARG_NAME)
|
||||
set(name ${ARG_NAME})
|
||||
else()
|
||||
message(FATAL_ERROR "NAME arg is required")
|
||||
endif()
|
||||
|
||||
if(ENABLE_SANITIZER_LEAK AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22)
|
||||
get_filename_component(lsan_supps "${CMAKE_SOURCE_DIR}/test/leak_sanitizer_suppressions.txt" ABSOLUTE)
|
||||
set(lsan_options "LSAN_OPTIONS=set:suppressions=${lsan_supps}")
|
||||
endif()
|
||||
|
||||
if(ARG_DEVICE)
|
||||
set(exe_targets)
|
||||
foreach(device IN LISTS ARG_DEVICE)
|
||||
set(exe "${exe_prefix}-${name}-${device}")
|
||||
list(APPEND exe_targets ${exe})
|
||||
add_executable(${exe} "${device}.cxx")
|
||||
target_link_libraries(${exe} PRIVATE FairMQ)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ARG_TRANSPORT)
|
||||
set(transports ${ARG_TRANSPORT})
|
||||
endif()
|
||||
|
||||
if(ARG_SCRIPT)
|
||||
set(scripts ${ARG_SCRIPT})
|
||||
else()
|
||||
set(scripts ${ARG_NAME})
|
||||
endif()
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(ARG_CONFIG)
|
||||
set(EX_CONF_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
foreach(script IN LISTS scripts)
|
||||
set(script_file "${script_prefix}-${script}.sh")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${script_file}.in" "${CMAKE_CURRENT_BINARY_DIR}/${script_file}" @ONLY)
|
||||
endforeach()
|
||||
|
||||
if(ARG_CONFIG)
|
||||
set(config "ex-${name}.json")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${config}" "${CMAKE_CURRENT_BINARY_DIR}/${config}")
|
||||
endif()
|
||||
|
||||
# test
|
||||
if(NOT ARG_NO_TEST)
|
||||
set(test_script "${test_script_prefix}-${name}.sh")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${test_script}.in" "${CMAKE_CURRENT_BINARY_DIR}/${test_script}")
|
||||
|
||||
if(ARG_NO_TRANSPORT)
|
||||
set(test "${testsuite}.${name}.${transport}")
|
||||
add_test(NAME ${test} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${test_script} ${transport})
|
||||
set_tests_properties(${test} PROPERTIES TIMEOUT "30")
|
||||
if(lsan_options)
|
||||
set_tests_properties(${test} PROPERTIES ENVIRONMENT_MODIFICATION ${lsan_options})
|
||||
endif()
|
||||
else()
|
||||
foreach(transport IN LISTS transports)
|
||||
if(ARG_VARIANT)
|
||||
foreach(variant IN LISTS ARG_VARIANT)
|
||||
set(test "${testsuite}.${name}.${variant}.${transport}")
|
||||
add_test(NAME ${test} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${test_script} ${transport} ${variant})
|
||||
set_tests_properties(${test} PROPERTIES TIMEOUT "30")
|
||||
if(lsan_options)
|
||||
set_tests_properties(${test} PROPERTIES ENVIRONMENT_MODIFICATION ${lsan_options})
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(test "${testsuite}.${name}.${transport}")
|
||||
add_test(NAME ${test} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${test_script} ${transport})
|
||||
set_tests_properties(${test} PROPERTIES TIMEOUT "30")
|
||||
if(lsan_options)
|
||||
set_tests_properties(${test} PROPERTIES ENVIRONMENT_MODIFICATION ${lsan_options})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# install
|
||||
install(
|
||||
TARGETS ${exe_targets}
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
if(ARG_CONFIG)
|
||||
set(EX_CONF_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR})
|
||||
endif()
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
foreach(script IN LISTS scripts)
|
||||
set(script_file "${script_prefix}-${script}.sh")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${script_file}.in" "${CMAKE_CURRENT_BINARY_DIR}/${script_file}_install" @ONLY)
|
||||
install(
|
||||
PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${script_file}_install"
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME ${script_file}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(ARG_CONFIG)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${config}
|
||||
DESTINATION ${PROJECT_INSTALL_DATADIR}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(1-1)
|
||||
add_subdirectory(1-n-1)
|
||||
add_subdirectory(builtin-devices)
|
||||
add_subdirectory(copypush)
|
||||
add_subdirectory(custom-controller)
|
||||
add_subdirectory(dds)
|
||||
add_subdirectory(multipart)
|
||||
add_subdirectory(multiple-channels)
|
||||
|
|
|
@ -1,11 +1,40 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME builtin-devices
|
||||
VARIANT single_msg multipart
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-builtin-devices.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-builtin-devices.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-builtin-devices.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh)
|
||||
|
||||
add_test(NAME Example.BuiltinDevices.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq)
|
||||
set_tests_properties(Example.BuiltinDevices.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
|
||||
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
# install
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-builtin-devices.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-builtin-devices.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-builtin-devices.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-builtin-devices.sh
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
transport="zeromq"
|
||||
multipart="false"
|
||||
numParts="1"
|
||||
|
@ -12,27 +12,16 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
if [[ $2 =~ ^multipart$ ]]; then
|
||||
multipart="true"
|
||||
numParts=2
|
||||
if [[ $2 =~ ^[a-z]+$ ]]; then
|
||||
multipart=$2
|
||||
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"
|
||||
if [[ $3 =~ ^[0-9]+$ ]]; then
|
||||
numParts=$3
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; 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; exit 0' 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;' TERM
|
||||
|
||||
SAMPLER="fairmq-bsampler"
|
||||
SAMPLER+=" --id bsampler1"
|
||||
|
@ -41,16 +30,14 @@ SAMPLER+=" --transport $transport"
|
|||
SAMPLER+=" --color false"
|
||||
SAMPLER+=" --control static"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --msg-size 100000"
|
||||
SAMPLER+=" --multipart $multipart"
|
||||
SAMPLER+=" --num-parts $numParts"
|
||||
SAMPLER+=" --msg-rate 1"
|
||||
SAMPLER+=" --max-iterations 0"
|
||||
SAMPLER+=" --out-channel $chan1"
|
||||
SAMPLER+=" --channel-config name=$chan1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
|
||||
SAMPLER+=" --out-channel data1"
|
||||
SAMPLER+=" --channel-config name=data1,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555"
|
||||
@FAIRMQ_BIN_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -61,13 +48,11 @@ SPLITTER+=" --transport $transport"
|
|||
SPLITTER+=" --color false"
|
||||
SPLITTER+=" --control static"
|
||||
SPLITTER+=" --verbosity veryhigh"
|
||||
SPLITTER+=" --shm-segment-size 100000000"
|
||||
SPLITTER+=" --shm-monitor true"
|
||||
SPLITTER+=" --multipart $multipart"
|
||||
SPLITTER+=" --in-channel $chan1"
|
||||
SPLITTER+=" --out-channel $chan2"
|
||||
SPLITTER+=" --channel-config name=$chan1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan1Addr"
|
||||
SPLITTER+=" name=$chan2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1,address=ipc://$chan2Addr2"
|
||||
SPLITTER+=" --in-channel data1"
|
||||
SPLITTER+=" --out-channel data2"
|
||||
SPLITTER+=" --channel-config name=data1,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5555"
|
||||
SPLITTER+=" name=data2,type=push,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556,address=tcp://localhost:5557"
|
||||
@FAIRMQ_BIN_DIR@/$SPLITTER &
|
||||
SPLITTER_PID=$!
|
||||
|
||||
|
@ -78,13 +63,11 @@ PROXY1+=" --transport $transport"
|
|||
PROXY1+=" --color false"
|
||||
PROXY1+=" --control static"
|
||||
PROXY1+=" --verbosity veryhigh"
|
||||
PROXY1+=" --shm-segment-size 100000000"
|
||||
PROXY1+=" --shm-monitor true"
|
||||
PROXY1+=" --multipart $multipart"
|
||||
PROXY1+=" --in-channel $chan2"
|
||||
PROXY1+=" --out-channel $chan3"
|
||||
PROXY1+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr1"
|
||||
PROXY1+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1"
|
||||
PROXY1+=" --in-channel data2"
|
||||
PROXY1+=" --out-channel data3"
|
||||
PROXY1+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5556"
|
||||
PROXY1+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558"
|
||||
@FAIRMQ_BIN_DIR@/$PROXY1 &
|
||||
PROXY1_PID=$!
|
||||
|
||||
|
@ -95,13 +78,11 @@ PROXY2+=" --transport $transport"
|
|||
PROXY2+=" --color false"
|
||||
PROXY2+=" --control static"
|
||||
PROXY2+=" --verbosity veryhigh"
|
||||
PROXY2+=" --shm-segment-size 100000000"
|
||||
PROXY2+=" --shm-monitor true"
|
||||
PROXY2+=" --multipart $multipart"
|
||||
PROXY2+=" --in-channel $chan2"
|
||||
PROXY2+=" --out-channel $chan3"
|
||||
PROXY2+=" --channel-config name=$chan2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan2Addr2"
|
||||
PROXY2+=" name=$chan3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr2"
|
||||
PROXY2+=" --in-channel data2"
|
||||
PROXY2+=" --out-channel data3"
|
||||
PROXY2+=" --channel-config name=data2,type=pull,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5557"
|
||||
PROXY2+=" name=data3,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5559"
|
||||
@FAIRMQ_BIN_DIR@/$PROXY2 &
|
||||
PROXY2_PID=$!
|
||||
|
||||
|
@ -112,13 +93,11 @@ MERGER+=" --transport $transport"
|
|||
MERGER+=" --color false"
|
||||
MERGER+=" --control static"
|
||||
MERGER+=" --verbosity veryhigh"
|
||||
MERGER+=" --shm-segment-size 100000000"
|
||||
MERGER+=" --shm-monitor true"
|
||||
MERGER+=" --multipart $multipart"
|
||||
MERGER+=" --in-channel $chan3"
|
||||
MERGER+=" --out-channel $chan4"
|
||||
MERGER+=" --channel-config name=$chan3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan3Addr1,address=ipc://$chan3Addr2"
|
||||
MERGER+=" name=$chan4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
|
||||
MERGER+=" --in-channel data3"
|
||||
MERGER+=" --out-channel data4"
|
||||
MERGER+=" --channel-config name=data3,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5558,address=tcp://localhost:5559"
|
||||
MERGER+=" name=data4,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560"
|
||||
@FAIRMQ_BIN_DIR@/$MERGER &
|
||||
MERGER_PID=$!
|
||||
|
||||
|
@ -129,13 +108,11 @@ MULTIPLIER+=" --transport $transport"
|
|||
MULTIPLIER+=" --color false"
|
||||
MULTIPLIER+=" --control static"
|
||||
MULTIPLIER+=" --verbosity veryhigh"
|
||||
MULTIPLIER+=" --shm-segment-size 100000000"
|
||||
MULTIPLIER+=" --shm-monitor true"
|
||||
MULTIPLIER+=" --multipart $multipart"
|
||||
MULTIPLIER+=" --in-channel $chan4"
|
||||
MULTIPLIER+=" --out-channel $chan5"
|
||||
MULTIPLIER+=" --channel-config name=$chan4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan4Addr"
|
||||
MULTIPLIER+=" name=$chan5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr,address=ipc://$chan5Addr"
|
||||
MULTIPLIER+=" --in-channel data4"
|
||||
MULTIPLIER+=" --out-channel data5"
|
||||
MULTIPLIER+=" --channel-config name=data4,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5560"
|
||||
MULTIPLIER+=" name=data5,type=push,method=connect,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561,address=tcp://localhost:5561"
|
||||
@FAIRMQ_BIN_DIR@/$MULTIPLIER &
|
||||
MULTIPLIER_PID=$!
|
||||
|
||||
|
@ -148,10 +125,9 @@ SINK+=" --control static"
|
|||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --multipart $multipart"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --max-iterations 2"
|
||||
SINK+=" --in-channel $chan5"
|
||||
SINK+=" --channel-config name=$chan5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=ipc://$chan5Addr"
|
||||
SINK+=" --in-channel data5"
|
||||
SINK+=" --channel-config name=data5,type=pull,method=bind,sndBufSize=50,rcvBufSize=50,address=tcp://localhost:5561"
|
||||
@FAIRMQ_BIN_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
|
@ -170,7 +146,3 @@ wait $PROXY1_PID
|
|||
wait $PROXY2_PID
|
||||
wait $MERGER_PID
|
||||
wait $MULTIPLIER_PID
|
||||
|
||||
set +e
|
||||
rm $chan1Addr; rm $chan2Addr1; rm $chan2Addr2; rm $chan3Addr1; rm $chan3Addr2; rm $chan4Addr; rm $chan5Addr
|
||||
exit 0
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME copypush
|
||||
DEVICE sampler sink
|
||||
|
||||
add_executable(fairmq-ex-copypush-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-copypush-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-copypush-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-copypush-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleCopyPush DEPENDS fairmq-ex-copypush-sampler fairmq-ex-copypush-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-copypush.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-copypush.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-copypush.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh)
|
||||
|
||||
add_test(NAME Example.CopyPush.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh zeromq)
|
||||
set_tests_properties(Example.CopyPush.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
|
||||
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: ")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-copypush-sampler
|
||||
fairmq-ex-copypush-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-copypush.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-copypush.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-copypush.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-copypush.sh
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
void InitTask() override
|
||||
{
|
||||
fNumDataChannels = GetNumSubChannels("data");
|
||||
fNumDataChannels = fChannels.at("data").size();
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,10 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fCounter++));
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fCounter++));
|
||||
|
||||
for (int i = 0; i < fNumDataChannels - 1; ++i) {
|
||||
fair::mq::MessagePtr msgCopy(NewMessage());
|
||||
FairMQMessagePtr msgCopy(NewMessage());
|
||||
msgCopy->Copy(*msg);
|
||||
Send(msgCopy, "data", i);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
|||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received message: \"" << *(static_cast<uint64_t*>(msg->GetData())) << "\"";
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,25 +8,19 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
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"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; 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; exit 0' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK1_PID; kill -TERM $SINK2_PID; wait $SAMPLER_PID; wait $SINK1_PID; wait $SINK2_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-copypush-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,rateLogging=0,address=ipc://$chanAddr1,address=ipc://$chanAddr2"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,rateLogging=0,address=tcp://*:5555,address=tcp://*:5556"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -36,13 +28,10 @@ SINK1="fairmq-ex-copypush-sink"
|
|||
SINK1+=" --id sink1"
|
||||
SINK1+=" --transport $transport"
|
||||
SINK1+=" --verbosity veryhigh"
|
||||
SINK1+=" --severity debug"
|
||||
SINK1+=" --shm-segment-size 100000000"
|
||||
SINK1+=" --shm-monitor true"
|
||||
SINK1+=" --session $session"
|
||||
SINK1+=" --session $SESSION"
|
||||
SINK1+=" --control static --color false"
|
||||
SINK1+=" --max-iterations 1"
|
||||
SINK1+=" --channel-config name=$chan,type=pull,method=connect,rateLogging=0,address=ipc://$chanAddr1"
|
||||
SINK1+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5555"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK1 &
|
||||
SINK1_PID=$!
|
||||
|
||||
|
@ -50,13 +39,10 @@ SINK2="fairmq-ex-copypush-sink"
|
|||
SINK2+=" --id sink2"
|
||||
SINK2+=" --transport $transport"
|
||||
SINK2+=" --verbosity veryhigh"
|
||||
SINK2+=" --severity debug"
|
||||
SINK2+=" --shm-segment-size 100000000"
|
||||
SINK2+=" --shm-monitor true"
|
||||
SINK2+=" --session $session"
|
||||
SINK2+=" --session $SESSION"
|
||||
SINK2+=" --control static --color false"
|
||||
SINK2+=" --max-iterations 1"
|
||||
SINK2+=" --channel-config name=$chan,type=pull,method=connect,rateLogging=0,address=ipc://$chanAddr2"
|
||||
SINK2+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5556"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK2 &
|
||||
SINK2_PID=$!
|
||||
|
||||
|
@ -64,7 +50,3 @@ SINK2_PID=$!
|
|||
wait $SAMPLER_PID
|
||||
wait $SINK1_PID
|
||||
wait $SINK2_PID
|
||||
|
||||
set +e
|
||||
rm $chanAddr1; rm $chanAddr2
|
||||
exit 0
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2022-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
set(name "custom-controller")
|
||||
set(exe "${exe_prefix}-${name}")
|
||||
add_executable(${exe} main.cxx)
|
||||
target_link_libraries(${exe} PRIVATE FairMQ)
|
||||
set_target_properties(${exe} PROPERTIES ENABLE_EXPORTS ON)
|
||||
|
||||
set(test "${testsuite}.${name}")
|
||||
add_test(NAME ${test} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${exe})
|
||||
set_tests_properties(${test} PROPERTIES TIMEOUT 30)
|
||||
if(lsan_options)
|
||||
set_tests_properties(${test} PROPERTIES ENVIRONMENT_MODIFICATION ${lsan_options})
|
||||
endif()
|
|
@ -1,97 +0,0 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef FAIR_MQ_EXAMPLE_CUSTOM_CONTROLLER_PLUGIN
|
||||
#define FAIR_MQ_EXAMPLE_CUSTOM_CONTROLLER_PLUGIN
|
||||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <utility> // for std::forward
|
||||
|
||||
namespace example {
|
||||
|
||||
struct MyController : fair::mq::Plugin // NOLINT
|
||||
{
|
||||
template<typename... Args>
|
||||
MyController(Args&&... args)
|
||||
: Plugin(std::forward<Args>(args)...)
|
||||
{
|
||||
TakeDeviceControl();
|
||||
|
||||
SubscribeToDeviceStateChange([this](auto state) {
|
||||
auto shutdown = GetProperty<bool>("please-shut-me-down", false);
|
||||
try {
|
||||
switch (state) {
|
||||
case DeviceState::Idle: {
|
||||
ChangeDeviceState(shutdown ? DeviceStateTransition::End
|
||||
: DeviceStateTransition::InitDevice);
|
||||
break;
|
||||
}
|
||||
case DeviceState::InitializingDevice: {
|
||||
ChangeDeviceState(DeviceStateTransition::CompleteInit);
|
||||
break;
|
||||
}
|
||||
case DeviceState::Initialized: {
|
||||
ChangeDeviceState(DeviceStateTransition::Bind);
|
||||
break;
|
||||
}
|
||||
case DeviceState::Bound: {
|
||||
ChangeDeviceState(DeviceStateTransition::Connect);
|
||||
break;
|
||||
}
|
||||
case DeviceState::DeviceReady: {
|
||||
ChangeDeviceState(shutdown ? DeviceStateTransition::ResetDevice
|
||||
: DeviceStateTransition::InitTask);
|
||||
break;
|
||||
}
|
||||
case DeviceState::Ready: {
|
||||
ChangeDeviceState(shutdown ? DeviceStateTransition::ResetTask
|
||||
: DeviceStateTransition::Run);
|
||||
break;
|
||||
}
|
||||
case DeviceState::Running: {
|
||||
ChangeDeviceState(DeviceStateTransition::Stop);
|
||||
break;
|
||||
}
|
||||
case DeviceState::Exiting: {
|
||||
ReleaseDeviceControl();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (fair::mq::PluginServices::DeviceControlError const&) {
|
||||
// this means we do not have device control
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
~MyController() override { ReleaseDeviceControl(); }
|
||||
};
|
||||
|
||||
// auto MyControllerProgramOptions() -> fair::mq::Plugin::ProgOptions
|
||||
// {
|
||||
// auto plugin_options = boost::program_options::options_description{"MyController Plugin"};
|
||||
// plugin_options.add_options()
|
||||
// ("custom-dummy-option", boost::program_options::value<std::string>(), "Cool custom option.")
|
||||
// ("custom-dummy-option2", boost::program_options::value<std::string>(), "Another one.");
|
||||
// return plugin_options;
|
||||
// }
|
||||
|
||||
} // namespace example
|
||||
|
||||
REGISTER_FAIRMQ_PLUGIN(example::MyController, // Class name
|
||||
mycontroller, // Plugin name (string, lower case chars only)
|
||||
(fair::mq::Plugin::Version{0, 42, 0}), // Version
|
||||
"Mr. Dummy <dummy@test.net>", // Maintainer
|
||||
"https://git.test.net/mycontroller.git", // Homepage
|
||||
// example::MyControllerProgramOptions // Free
|
||||
// function which declares custom
|
||||
// program options for the plugin
|
||||
fair::mq::Plugin::NoProgramOptions)
|
||||
|
||||
#endif /* FAIR_MQ_EXAMPLE_CUSTOM_CONTROLLER_PLUGIN */
|
|
@ -1,46 +0,0 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include "MyController.h"
|
||||
#include "MyDevice.h"
|
||||
|
||||
#include <chrono> // for std::chrono_literals
|
||||
#include <fairlogger/Logger.h>
|
||||
#include <fairmq/DeviceRunner.h>
|
||||
#include <memory> // for std::make_unique
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
using namespace fair::mq;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
DeviceRunner runner(argc, argv);
|
||||
|
||||
runner.AddHook<hooks::LoadPlugins>([](DeviceRunner& r) {
|
||||
r.fPluginManager.LoadPlugin("s:mycontroller");
|
||||
// 's:' stands for static because the plugin is compiled into the executable
|
||||
// 'mycontroller' is the plugin name passed as second arg to REGISTER_FAIRMQ_PLUGIN
|
||||
});
|
||||
|
||||
fair::Logger::SetConsoleSeverity(fair::Severity::debug);
|
||||
|
||||
runner.AddHook<hooks::InstantiateDevice>([](DeviceRunner& r) {
|
||||
r.fConfig.SetProperty<int>("catch-signals", 0);
|
||||
r.fConfig.SetProperty<bool>("please-shut-me-down", false);
|
||||
r.fDevice = std::make_unique<example::MyDevice>(r.fConfig);
|
||||
|
||||
r.fDevice->SubscribeToStateChange("example", [&r](auto state) {
|
||||
if (state == State::Running) {
|
||||
r.fDevice->WaitFor(3s);
|
||||
r.fConfig.SetProperty<bool>("please-shut-me-down", true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return runner.RunWithExceptionHandlers();
|
||||
}
|
|
@ -20,7 +20,7 @@ struct Processor : fair::mq::Device
|
|||
OnData("data1", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received data, processing...";
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct Processor : fair::mq::Device
|
|||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
fair::mq::MessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
FairMQMessagePtr msg2(NewMessage(const_cast<char*>(text->c_str()),
|
||||
text->length(),
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); },
|
||||
text));
|
||||
|
|
|
@ -24,7 +24,7 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage("Data"));
|
||||
FairMQMessagePtr msg(NewSimpleMessage("Data"));
|
||||
|
||||
LOG(info) << "Sending \"Data\"";
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ struct Sink : fair::mq::Device
|
|||
fIterations = fConfig->GetValue<uint64_t>("iterations");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
LOG(info) << "Received: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
||||
|
|
|
@ -1,11 +1,56 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME multipart
|
||||
DEVICE sampler sink
|
||||
add_executable(fairmq-ex-multipart-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-multipart-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-multipart-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-multipart-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleMultipart DEPENDS fairmq-ex-multipart-sampler fairmq-ex-multipart-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multipart.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh)
|
||||
|
||||
add_test(NAME Example.Multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh zeromq)
|
||||
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
|
||||
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")
|
||||
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
add_test(NAME Example.Multipart.ofi COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh ofi)
|
||||
set_tests_properties(Example.Multipart.ofi PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
|
||||
endif()
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-multipart-sampler
|
||||
fairmq-ex-multipart-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multipart.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multipart.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-multipart.sh
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@ A topology of two devices - Sampler and Sink, communicating with PUSH-PULL patte
|
|||
|
||||
The Sampler sends a multipart message to the Sink, consisting of two message parts - header and body.
|
||||
|
||||
Each message part is a regular fair::mq::Message. To combine them into a multi-part message use `fair::mq::Parts`. Add messages to `fair::mq::Parts` with `AddPart` method.
|
||||
Each message part is a regular FairMQMessage. To combine them into a multi-part message use `FairMQParts`. Add messages to `FairMQParts` with `AddPart` method.
|
||||
|
||||
All parts are guaranteed to be delivered together. The Receive call in the sink will recive the entire parts structure.
|
||||
|
||||
|
|
|
@ -35,15 +35,15 @@ struct Sampler : fair::mq::Device
|
|||
}
|
||||
LOG(info) << "Sending header with stopFlag: " << header.stopFlag;
|
||||
|
||||
fair::mq::Parts parts;
|
||||
FairMQParts parts;
|
||||
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
parts.AddPart(NewSimpleMessage(header));
|
||||
parts.AddPart(NewMessage(1000));
|
||||
|
||||
// create more data parts, testing the fair::mq::Parts in-place constructor
|
||||
fair::mq::Parts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
|
||||
// create more data parts, testing the FairMQParts in-place constructor
|
||||
FairMQParts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
|
||||
assert(auxData.Size() == 3);
|
||||
parts.AddPart(std::move(auxData));
|
||||
assert(auxData.Size() == 0);
|
||||
|
|
|
@ -20,14 +20,10 @@ struct Sink : fair::mq::Device
|
|||
OnData("data", &Sink::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::Parts& parts, int)
|
||||
bool HandleData(FairMQParts& parts, int)
|
||||
{
|
||||
LOG(info) << "Received message with " << parts.Size() << " parts";
|
||||
|
||||
if (parts.Size() != 7) {
|
||||
throw std::runtime_error("Number of received parts != 7");
|
||||
}
|
||||
|
||||
example_multipart::Header header;
|
||||
header.stopFlag = (static_cast<example_multipart::Header*>(parts.At(0)->GetData()))->stopFlag;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,25 +8,19 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr=""
|
||||
chanIpcFile="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
chanAddr="ipc://""$chanIpcFile"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID; rm $chanIpcFile; exit 0' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-multipart-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --channel-config name=$chan,type=pair,method=connect,rateLogging=0,address=$chanAddr,linger=1000"
|
||||
SAMPLER+=" --channel-config name=data,type=pair,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555,linger=1000"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -36,17 +28,11 @@ SINK="fairmq-ex-multipart-sink"
|
|||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --channel-config name=$chan,type=pair,method=bind,rateLogging=0,address=$chanAddr"
|
||||
SINK+=" --channel-config name=data,type=pair,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
set +e
|
||||
rm $chanIpcFile
|
||||
exit 0
|
||||
|
|
|
@ -1,12 +1,52 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME multiple-channels
|
||||
DEVICE sampler broadcaster sink
|
||||
TRANSPORT zeromq
|
||||
add_executable(fairmq-ex-multiple-channels-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-channels-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-multiple-channels-broadcaster broadcaster.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-channels-broadcaster PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-multiple-channels-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-channels-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleMultipleChannels DEPENDS fairmq-ex-multiple-channels-sampler fairmq-ex-multiple-channels-broadcaster fairmq-ex-multiple-channels-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-channels.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-channels.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-channels.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh)
|
||||
|
||||
add_test(NAME Example.MultipleChannels.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh zeromq)
|
||||
set_tests_properties(Example.MultipleChannels.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-multiple-channels-sampler
|
||||
fairmq-ex-multiple-channels-broadcaster
|
||||
fairmq-ex-multiple-channels-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-channels.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-channels.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-channels.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-multiple-channels.sh
|
||||
)
|
||||
|
|
|
@ -5,4 +5,4 @@ This example demonstrates how to work with multiple channels and multiplex betwe
|
|||
|
||||
A topology of three devices - **Sampler**, **Sink** and **Broadcaster**. The Sampler sends data to the Sink via the PUSH-PULL pattern. The Broadcaster device sends a message to both Sampler and Sink containing a string "OK" every second. The Broadcaster sends the message via PUB pattern. Both Sampler and Sink, besides doing their PUSH-PULL job, listen via SUB to the Broadcaster.
|
||||
|
||||
The multiplexing between their data channels and the broadcast channels happens with `fair::mq::Poller`.
|
||||
The multiplexing between their data channels and the broadcast channels happens with `FairMQPoller`.
|
||||
|
|
|
@ -22,7 +22,7 @@ struct Broadcaster : fair::mq::Device
|
|||
|
||||
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
|
||||
// Should only be used for small data because of the cost of an additional copy
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage("OK"));
|
||||
FairMQMessagePtr msg(NewSimpleMessage("OK"));
|
||||
|
||||
LOG(info) << "Sending OK";
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
********************************************************************************/
|
||||
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/Poller.h>
|
||||
#include <FairMQPoller.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
|
||||
#include <chrono>
|
||||
|
@ -26,13 +26,13 @@ struct Sampler : fair::mq::Device
|
|||
|
||||
void Run() override
|
||||
{
|
||||
fair::mq::PollerPtr poller(NewPoller("data", "broadcast"));
|
||||
FairMQPollerPtr poller(NewPoller("data", "broadcast"));
|
||||
|
||||
while (!NewStatePending()) {
|
||||
poller->Poll(100);
|
||||
|
||||
if (poller->CheckInput("broadcast", 0)) {
|
||||
fair::mq::MessagePtr msg(NewMessage());
|
||||
FairMQMessagePtr msg(NewMessage());
|
||||
|
||||
if (Receive(msg, "broadcast") > 0) {
|
||||
LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
|
@ -42,7 +42,7 @@ struct Sampler : fair::mq::Device
|
|||
if (poller->CheckOutput("data", 0)) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fText));
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fText));
|
||||
|
||||
if (Send(msg, "data") > 0) {
|
||||
LOG(info) << "Sent \"" << fText << "\"";
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Sink : fair::mq::Device
|
|||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleBroadcast(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
bool HandleBroadcast(FairMQMessagePtr& msg, int /*index*/)
|
||||
{
|
||||
LOG(info) << "Received broadcast: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
fReceivedBroadcast = true;
|
||||
|
@ -35,7 +35,7 @@ struct Sink : fair::mq::Device
|
|||
return CheckIterations();
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
{
|
||||
LOG(info) << "Received message: \"" << std::string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
|
||||
fReceivedData = true;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,26 +8,18 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
dataChan="data"
|
||||
broadcastChan="broadcast"
|
||||
dataChanAddr="/tmp/fmq_$session""_""$dataChan""_""$transport"
|
||||
broadcastChanAddr="/tmp/fmq_$session""_""$broadcastChan""_""$transport"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; 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; exit 0' TERM
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $BROADCASTER_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $BROADCASTER_PID;' TERM
|
||||
|
||||
|
||||
SINK="fairmq-ex-multiple-channels-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --channel-config name=$dataChan,type=pull,method=connect,rateLogging=0,address=ipc://$dataChanAddr"
|
||||
SINK+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,rateLogging=0,address=tcp://localhost:5555"
|
||||
SINK+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
|
@ -37,27 +27,21 @@ sleep 1
|
|||
|
||||
SAMPLER="fairmq-ex-multiple-channels-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --channel-config name=$dataChan,type=push,method=bind,rateLogging=0,address=ipc://$dataChanAddr"
|
||||
SAMPLER+=" name=$broadcastChan,type=sub,method=connect,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,rateLogging=0,address=tcp://*:5555"
|
||||
SAMPLER+=" name=broadcast,type=sub,method=connect,rateLogging=0,address=tcp://localhost:5005"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
BROADCASTER="fairmq-ex-multiple-channels-broadcaster"
|
||||
BROADCASTER+=" --id broadcaster1"
|
||||
BROADCASTER+=" --session $session"
|
||||
BROADCASTER+=" --transport $transport"
|
||||
BROADCASTER+=" --verbosity veryhigh --severity debug"
|
||||
BROADCASTER+=" --shm-segment-size 100000000"
|
||||
BROADCASTER+=" --shm-monitor true"
|
||||
BROADCASTER+=" --verbosity veryhigh"
|
||||
BROADCASTER+=" --control static --color false"
|
||||
BROADCASTER+=" --channel-config name=$broadcastChan,type=pub,method=bind,rateLogging=0,address=ipc://$broadcastChanAddr"
|
||||
BROADCASTER+=" --channel-config name=broadcast,type=pub,method=bind,rateLogging=0,address=tcp://*:5005"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$BROADCASTER &
|
||||
BROADCASTER_PID=$!
|
||||
|
||||
|
@ -69,7 +53,3 @@ kill -SIGINT $BROADCASTER_PID
|
|||
|
||||
# wait for broadcaster to finish
|
||||
wait $BROADCASTER_PID
|
||||
|
||||
set +e
|
||||
rm $dataChanAddr; rm $broadcastChanAddr
|
||||
exit 0
|
||||
|
|
|
@ -1,12 +1,51 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME multiple-transports
|
||||
DEVICE sampler1 sampler2 sink
|
||||
NO_TRANSPORT
|
||||
add_executable(fairmq-ex-multiple-transports-sampler1 sampler1.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-transports-sampler1 PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-multiple-transports-sampler2 sampler2.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-transports-sampler2 PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-multiple-transports-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-multiple-transports-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleMultipleTransports DEPENDS fairmq-ex-multiple-transports-sampler1 fairmq-ex-multiple-transports-sampler2 fairmq-ex-multiple-transports-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
|
||||
add_test(NAME Example.MultipleTransports COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
|
||||
set_tests_properties(Example.MultipleTransports PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-multiple-transports-sampler1
|
||||
fairmq-ex-multiple-transports-sampler2
|
||||
fairmq-ex-multiple-transports-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-multiple-transports.sh
|
||||
)
|
||||
|
|
|
@ -28,7 +28,7 @@ struct Sampler1 : fair::mq::Device
|
|||
bool ConditionalRun() override
|
||||
{
|
||||
// Creates a message using the transport of channel data1
|
||||
fair::mq::MessagePtr msg(NewMessageFor("data1", 0, 1000000));
|
||||
FairMQMessagePtr msg(NewMessageFor("data1", 0, 1000000));
|
||||
|
||||
// in case of error or transfer interruption, return false to go to IDLE state
|
||||
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
|
||||
|
@ -54,7 +54,7 @@ struct Sampler1 : fair::mq::Device
|
|||
uint64_t numAcks = 0;
|
||||
|
||||
while (!NewStatePending()) {
|
||||
fair::mq::MessagePtr ack(NewMessageFor("ack", 0));
|
||||
FairMQMessagePtr ack(NewMessageFor("ack", 0));
|
||||
if (Receive(ack, "ack") < 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct Sampler2 : fair::mq::Device
|
|||
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
fair::mq::MessagePtr msg(NewMessage(1000));
|
||||
FairMQMessagePtr msg(NewMessage(1000));
|
||||
|
||||
// in case of error or transfer interruption, return false to go to IDLE state
|
||||
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
struct Sink : fair::mq::Device
|
||||
|
@ -28,13 +26,13 @@ struct Sink : fair::mq::Device
|
|||
}
|
||||
|
||||
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
|
||||
bool HandleData1(fair::mq::MessagePtr& /*msg*/, int /*index*/)
|
||||
bool HandleData1(FairMQMessagePtr& /*msg*/, int /*index*/)
|
||||
{
|
||||
fNumIterations1++;
|
||||
// Creates a message using the transport of channel ack
|
||||
fair::mq::MessagePtr ack(NewMessageFor("ack", 0));
|
||||
FairMQMessagePtr ack(NewMessageFor("ack", 0));
|
||||
if (Send(ack, "ack") < 0) {
|
||||
throw std::runtime_error("could not send an ack");
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if want to be called again (otherwise go to IDLE state)
|
||||
|
@ -42,7 +40,7 @@ struct Sink : fair::mq::Device
|
|||
}
|
||||
|
||||
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
|
||||
bool HandleData2(fair::mq::MessagePtr& /*msg*/, int /*index*/)
|
||||
bool HandleData2(FairMQMessagePtr& /*msg*/, int /*index*/)
|
||||
{
|
||||
fNumIterations2++;
|
||||
// return true if want to be called again (otherwise go to IDLE state)
|
||||
|
|
|
@ -1,65 +1,47 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
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"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
trap 'set +e; 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; exit 0' 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;' TERM
|
||||
|
||||
SINK="fairmq-ex-multiple-transports-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --verbosity veryhigh --severity debug"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --transport shmem"
|
||||
SINK+=" --channel-config name=$chan1,type=pull,method=connect,address=ipc://$chan1Addr"
|
||||
SINK+=" name=$chan2,type=pull,method=connect,address=ipc://$chan2Addr,transport=zeromq"
|
||||
SINK+=" name=$ackChan,type=pub,method=connect,address=ipc://$ackChanAddr,transport=zeromq"
|
||||
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
|
||||
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=zeromq"
|
||||
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
SAMPLER1="fairmq-ex-multiple-transports-sampler1"
|
||||
SAMPLER1+=" --id sampler1"
|
||||
SAMPLER1+=" --session $session"
|
||||
SAMPLER1+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER1+=" --shm-segment-size 100000000"
|
||||
SAMPLER1+=" --shm-monitor true"
|
||||
SAMPLER1+=" --session $SESSION"
|
||||
SAMPLER1+=" --verbosity veryhigh"
|
||||
SAMPLER1+=" --max-iterations 1"
|
||||
SAMPLER1+=" --control static --color false"
|
||||
SAMPLER1+=" --transport shmem"
|
||||
SAMPLER1+=" --channel-config name=$chan1,type=push,method=bind,address=ipc://$chan1Addr"
|
||||
SAMPLER1+=" name=$ackChan,type=sub,method=bind,address=ipc://$ackChanAddr,transport=zeromq"
|
||||
SAMPLER1+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:5555"
|
||||
SAMPLER1+=" name=ack,type=sub,method=bind,address=tcp://127.0.0.1:5557,transport=zeromq"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER1 &
|
||||
SAMPLER1_PID=$!
|
||||
|
||||
SAMPLER2="fairmq-ex-multiple-transports-sampler2"
|
||||
SAMPLER2+=" --id sampler2"
|
||||
SAMPLER2+=" --session $session"
|
||||
SAMPLER2+=" --verbosity veryhigh --severity debug"
|
||||
SAMPLER2+=" --shm-segment-size 100000000"
|
||||
SAMPLER2+=" --shm-monitor true"
|
||||
SAMPLER2+=" --session $SESSION"
|
||||
SAMPLER2+=" --verbosity veryhigh"
|
||||
SAMPLER2+=" --max-iterations 1"
|
||||
SAMPLER2+=" --control static --color false"
|
||||
SAMPLER2+=" --transport zeromq"
|
||||
SAMPLER2+=" --channel-config name=$chan2,type=push,method=bind,address=ipc://$chan2Addr"
|
||||
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 &
|
||||
SAMPLER2_PID=$!
|
||||
|
||||
wait $SAMPLER1_PID
|
||||
wait $SAMPLER2_PID
|
||||
wait $SINK_PID
|
||||
|
||||
set +e
|
||||
rm $chan1Addr; rm $chan2Addr; rm $ackChanAddr
|
||||
exit 0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2020-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
|
@ -24,7 +24,7 @@ namespace bpo = boost::program_options;
|
|||
|
||||
struct TFBuffer
|
||||
{
|
||||
fair::mq::Parts parts;
|
||||
FairMQParts parts;
|
||||
chrono::steady_clock::time_point start;
|
||||
chrono::steady_clock::time_point end;
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ struct Receiver : fair::mq::Device
|
|||
fMaxTimeframes = GetConfig()->GetValue<int>("max-timeframes");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::Parts& parts, int /* index */)
|
||||
bool HandleData(FairMQParts& parts, int /* index */)
|
||||
{
|
||||
Header& h = *(static_cast<Header*>(parts.At(0)->GetData()));
|
||||
// LOG(info) << "Received sub-time frame #" << h.id << " from Sender" << h.senderIndex;
|
||||
|
@ -54,7 +54,7 @@ struct Receiver : fair::mq::Device
|
|||
fBuffer[h.id].start = chrono::steady_clock::now();
|
||||
}
|
||||
// if the received ID has not previously been discarded, store the data part in the buffer
|
||||
fBuffer[h.id].parts.AddPart(std::move(parts.At(1)));
|
||||
fBuffer[h.id].parts.AddPart(move(parts.At(1)));
|
||||
} else {
|
||||
// if received ID has been previously discarded.
|
||||
LOG(debug) << "Received part from an already discarded timeframe with id " << h.id;
|
||||
|
@ -93,7 +93,7 @@ struct Receiver : fair::mq::Device
|
|||
unordered_map<uint16_t, TFBuffer> fBuffer;
|
||||
unordered_set<uint16_t> fDiscardedSet;
|
||||
|
||||
unsigned int fNumSenders = 0;
|
||||
int fNumSenders = 0;
|
||||
int fBufferTimeoutInMs = 5000;
|
||||
int fMaxTimeframes = 0;
|
||||
int fTimeframeCounter = 0;
|
||||
|
@ -107,7 +107,7 @@ void addCustomOptions(bpo::options_description& options)
|
|||
("max-timeframes", bpo::value<int>()->default_value(0), "Maximum number of timeframes to receive (0 - unlimited)");
|
||||
}
|
||||
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Receiver>();
|
||||
}
|
||||
|
|
|
@ -28,11 +28,11 @@ struct Sender : fair::mq::Device
|
|||
|
||||
void Run() override
|
||||
{
|
||||
fair::mq::Channel& dataInChannel = GetChannel("sync", 0);
|
||||
FairMQChannel& dataInChannel = fChannels.at("sync").at(0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
Header h;
|
||||
fair::mq::MessagePtr id(NewMessage());
|
||||
FairMQMessagePtr id(NewMessage());
|
||||
if (dataInChannel.Receive(id) > 0) {
|
||||
h.id = *(static_cast<uint16_t*>(id->GetData()));
|
||||
h.senderIndex = fIndex;
|
||||
|
@ -40,7 +40,7 @@ struct Sender : fair::mq::Device
|
|||
continue;
|
||||
}
|
||||
|
||||
fair::mq::Parts parts;
|
||||
FairMQParts parts;
|
||||
parts.AddPart(NewSimpleMessage(h));
|
||||
parts.AddPart(NewMessage(fSubtimeframeSize));
|
||||
|
||||
|
@ -66,7 +66,7 @@ void addCustomOptions(bpo::options_description& options)
|
|||
("subtimeframe-size", bpo::value<int>()->default_value(1000), "Subtimeframe size in bytes")
|
||||
("num-receivers", bpo::value<int>()->required(), "Number of EPNs");
|
||||
}
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Sender>();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct Synchronizer : fair::mq::Device
|
|||
{
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
fair::mq::MessagePtr msg(NewSimpleMessage(fTimeframeId));
|
||||
FairMQMessagePtr msg(NewSimpleMessage(fTimeframeId));
|
||||
|
||||
if (Send(msg, "sync") > 0) {
|
||||
if (++fTimeframeId == UINT16_MAX - 1) {
|
||||
|
@ -37,7 +37,7 @@ struct Synchronizer : fair::mq::Device
|
|||
};
|
||||
|
||||
void addCustomOptions(bpo::options_description& /* options */) {}
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /* config */)
|
||||
std::unique_ptr<fair::mq::Device> getDevice(FairMQProgOptions& /* config */)
|
||||
{
|
||||
return std::make_unique<Synchronizer>();
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ struct QCDispatcher : fair::mq::Device
|
|||
});
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int)
|
||||
bool HandleData(FairMQMessagePtr& msg, int)
|
||||
{
|
||||
if (fDoQC.load() == true) {
|
||||
fair::mq::MessagePtr msgCopy(NewMessage());
|
||||
FairMQMessagePtr msgCopy(NewMessage());
|
||||
msgCopy->Copy(*msg);
|
||||
if (Send(msg, "qc") < 0) {
|
||||
return false;
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
|
||||
class QCTask : public fair::mq::Device
|
||||
class QCTask : public FairMQDevice
|
||||
{
|
||||
public:
|
||||
QCTask()
|
||||
{
|
||||
OnData("qc", [](fair::mq::MessagePtr& /*msg*/, int) {
|
||||
OnData("qc", [](FairMQMessagePtr& /*msg*/, int) {
|
||||
LOG(info) << "received data";
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
fair::mq::MessagePtr msg(NewMessage(1000));
|
||||
FairMQMessagePtr msg(NewMessage(1000));
|
||||
|
||||
if (Send(msg, "data1") < 0) {
|
||||
return false;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
struct Sink : fair::mq::Device
|
||||
{
|
||||
Sink() { OnData("data2", &Sink::HandleData); }
|
||||
bool HandleData(fair::mq::MessagePtr& /*msg*/, int /*index*/) { return true; }
|
||||
bool HandleData(FairMQMessagePtr& /*msg*/, int /*index*/) { return true; }
|
||||
};
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
|
|
@ -1,13 +1,59 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME readout
|
||||
DEVICE readout builder processor sender receiver
|
||||
SCRIPT readout readout-processing
|
||||
NO_TEST
|
||||
add_executable(fairmq-ex-readout-readout readout.cxx)
|
||||
target_link_libraries(fairmq-ex-readout-readout PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-readout-builder builder.cxx)
|
||||
target_link_libraries(fairmq-ex-readout-builder PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-readout-processor processor.cxx)
|
||||
target_link_libraries(fairmq-ex-readout-processor PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-readout-sender sender.cxx)
|
||||
target_link_libraries(fairmq-ex-readout-sender PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-readout-receiver receiver.cxx)
|
||||
target_link_libraries(fairmq-ex-readout-receiver PRIVATE FairMQ)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-readout.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout.sh)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-readout-processing.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout-processing.sh)
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-readout-readout
|
||||
fairmq-ex-readout-builder
|
||||
fairmq-ex-readout-processor
|
||||
fairmq-ex-readout-sender
|
||||
fairmq-ex-readout-receiver
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-readout.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout.sh_install)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-readout-processing.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout-processing.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-readout.sh
|
||||
)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-readout-processing.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-readout-processing.sh
|
||||
)
|
||||
|
|
|
@ -7,19 +7,19 @@ This examples shows two possible topologies (out of many) for a node connected t
|
|||
```
|
||||
|------------------------------- Readout Node ---------------------------| |- Processing Node -|
|
||||
| Readout --> Builder --> Sender | --> | Receiver |
|
||||
| [# shared memory segment (unused in this topology) ##################] | zmq | |
|
||||
| [# shared memory segment (unused in this topology) ##################] | ofi | |
|
||||
| [# shmem unmanaged region (readout writes here, others read) ########] | | |
|
||||
|------------------------------------------------------------------------| |-------------------|
|
||||
```
|
||||
|
||||
The devices one the Readout Node communicate via shared memory transport. Readout device writes into shared memory unmanaged region. The data is then forwarded through Builder to Sender process, which sends it out via zeromq transport.
|
||||
The devices one the Readout Node communicate via shared memory transport. Readout device writes into shared memory unmanaged region. The data is then forwarded through Builder to Sender process, which sends it out via OFI transport.
|
||||
|
||||
## Setup with generating new data on the Readout node
|
||||
|
||||
```
|
||||
|------------------------------- Readout Node ---------------------------| |- Processing Node -|
|
||||
| Readout --> Builder --> Processor --> Sender | --> | Receiver |
|
||||
| [# shared memory segment (used between Proccessor and Sender) #######] | zmq | |
|
||||
| [# shared memory segment (used between Proccessor and Sender) #######] | ofi | |
|
||||
| [# shmem unmanaged region (readout writes here, builder & proc read) ] | | |
|
||||
|------------------------------------------------------------------------| |-------------------|
|
||||
```
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
class Builder : public fair::mq::Device
|
||||
class Builder : public FairMQDevice
|
||||
{
|
||||
public:
|
||||
Builder() = default;
|
||||
|
@ -24,7 +24,7 @@ class Builder : public fair::mq::Device
|
|||
OnData("rb", &Builder::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
{
|
||||
if (Send(msg, fOutputChannelName) < 0) {
|
||||
return false;
|
||||
|
|
|
@ -31,10 +31,12 @@ SENDER="fairmq-ex-readout-sender"
|
|||
SENDER+=" --id sender1"
|
||||
SENDER+=" --input-name ps"
|
||||
SENDER+=" --channel-config name=ps,type=pair,method=bind,address=tcp://localhost:7779,transport=shmem"
|
||||
#SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7780,transport=ofi"
|
||||
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7780,transport=zeromq"
|
||||
xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER &
|
||||
|
||||
RECEIVER="fairmq-ex-readout-receiver"
|
||||
RECEIVER+=" --id receiver1"
|
||||
#RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7780,transport=ofi"
|
||||
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7780,transport=zeromq"
|
||||
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &
|
||||
|
|
|
@ -25,10 +25,12 @@ SENDER="fairmq-ex-readout-sender"
|
|||
SENDER+=" --id sender1"
|
||||
SENDER+=" --input-name bs"
|
||||
SENDER+=" --channel-config name=bs,type=pair,method=bind,address=tcp://localhost:7778,transport=shmem"
|
||||
# SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7779,transport=ofi"
|
||||
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7779,transport=zeromq"
|
||||
xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER &
|
||||
|
||||
RECEIVER="fairmq-ex-readout-receiver"
|
||||
RECEIVER+=" --id receiver1"
|
||||
# RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7779,transport=ofi"
|
||||
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7779,transport=zeromq"
|
||||
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &
|
||||
|
|
|
@ -18,9 +18,9 @@ struct Processor : fair::mq::Device
|
|||
OnData("bp", &Processor::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
{
|
||||
fair::mq::MessagePtr msg2(NewMessageFor("ps", 0, msg->GetSize()));
|
||||
FairMQMessagePtr msg2(NewMessageFor("ps", 0, msg->GetSize()));
|
||||
if (Send(msg2, "ps") < 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct Readout : fair::mq::Device
|
|||
fMsgSize = fConfig->GetProperty<int>("msg-size");
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
|
||||
fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
|
||||
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
|
||||
0,
|
||||
10000000,
|
||||
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
|
||||
|
@ -36,7 +36,7 @@ struct Readout : fair::mq::Device
|
|||
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
fair::mq::MessagePtr msg(NewMessageFor("rb", // channel
|
||||
FairMQMessagePtr msg(NewMessageFor("rb", // channel
|
||||
0, // sub-channel
|
||||
fRegion, // region
|
||||
fRegion->GetData(), // ptr within region
|
||||
|
@ -71,7 +71,7 @@ struct Readout : fair::mq::Device
|
|||
int fMsgSize = 10000;
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
fair::mq::UnmanagedRegionPtr fRegion = nullptr;
|
||||
FairMQUnmanagedRegionPtr fRegion = nullptr;
|
||||
std::atomic<uint64_t> fNumUnackedMsgs = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
|
@ -8,15 +8,10 @@
|
|||
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Receiver : Device
|
||||
struct Receiver : fair::mq::Device
|
||||
{
|
||||
void InitTask() override
|
||||
{
|
||||
|
@ -26,14 +21,15 @@ struct Receiver : Device
|
|||
|
||||
void Run() override
|
||||
{
|
||||
Channel& dataInChannel = GetChannel("sr", 0);
|
||||
FairMQChannel& dataInChannel = fChannels.at("sr").at(0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
auto msg(dataInChannel.NewMessage());
|
||||
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
|
||||
dataInChannel.Receive(msg);
|
||||
// void* ptr = msg->GetData();
|
||||
|
||||
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
|
||||
LOG(info) << "Configured max number of iterations reached. Leaving RUNNING state.";
|
||||
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -44,14 +40,13 @@ struct Receiver : Device
|
|||
uint64_t fNumIterations = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void addCustomOptions(bpo::options_description& options)
|
||||
{
|
||||
options.add_options()(
|
||||
"max-iterations",
|
||||
bpo::value<uint64_t>()->default_value(0),
|
||||
"Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
|
||||
options.add_options()
|
||||
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
|
||||
}
|
||||
|
||||
unique_ptr<Device> getDevice(ProgOptions& /*config*/) { return make_unique<Receiver>(); }
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /*config*/)
|
||||
{
|
||||
return std::make_unique<Receiver>();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ struct Sender : fair::mq::Device
|
|||
OnData(fInputChannelName, &Sender::HandleData);
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& msg, int /*index*/)
|
||||
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
|
||||
{
|
||||
if (Send(msg, "sr") < 0) {
|
||||
return false;
|
||||
|
|
|
@ -1,12 +1,51 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME region
|
||||
DEVICE sampler processor sink keep-alive
|
||||
SCRIPT region region-advanced region-advanced-external
|
||||
add_executable(fairmq-ex-region-sampler sampler.cxx)
|
||||
target_link_libraries(fairmq-ex-region-sampler PRIVATE FairMQ)
|
||||
|
||||
add_executable(fairmq-ex-region-sink sink.cxx)
|
||||
target_link_libraries(fairmq-ex-region-sink PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleRegion DEPENDS fairmq-ex-region-sampler fairmq-ex-region-sink)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-region.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh)
|
||||
|
||||
add_test(NAME Example.Region.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh zeromq)
|
||||
set_tests_properties(Example.Region.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
|
||||
|
||||
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")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-region-sampler
|
||||
fairmq-ex-region-sink
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-region.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-region.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-region.sh
|
||||
)
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport=${1:-shmem}
|
||||
msgSize=${2:-1000000}
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
# SAMPLER+=" --sampling-rate 10"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --msg-size $msgSize"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --shmid 1"
|
||||
SAMPLER+=" --shm-monitor false"
|
||||
SAMPLER+=" --rc-segment-size 200000000"
|
||||
SAMPLER+=" --external-region true"
|
||||
SAMPLER+=" --shm-no-cleanup true"
|
||||
SAMPLER+=" --chan-name data1"
|
||||
SAMPLER+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:7777"
|
||||
xterm -geometry 90x60+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
|
||||
|
||||
PROCESSOR1="fairmq-ex-region-processor"
|
||||
PROCESSOR1+=" --id processor1"
|
||||
PROCESSOR1+=" --severity debug"
|
||||
PROCESSOR1+=" --transport $transport"
|
||||
PROCESSOR1+=" --shmid 1"
|
||||
PROCESSOR1+=" --shm-segment-id 1"
|
||||
PROCESSOR1+=" --shm-monitor false"
|
||||
PROCESSOR1+=" --shm-no-cleanup true"
|
||||
PROCESSOR1+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
PROCESSOR1+=" name=data2,type=push,method=bind,address=tcp://127.0.0.1:7778"
|
||||
PROCESSOR1+=" name=data3,type=push,method=bind,address=tcp://127.0.0.1:7779"
|
||||
xterm -geometry 90x40+550+40 -hold -e @EX_BIN_DIR@/$PROCESSOR1 &
|
||||
|
||||
PROCESSOR2="fairmq-ex-region-processor"
|
||||
PROCESSOR2+=" --id processor2"
|
||||
PROCESSOR2+=" --severity debug"
|
||||
PROCESSOR2+=" --transport $transport"
|
||||
PROCESSOR2+=" --shmid 1"
|
||||
PROCESSOR2+=" --shm-segment-id 2"
|
||||
PROCESSOR2+=" --shm-monitor false"
|
||||
PROCESSOR2+=" --shm-no-cleanup true"
|
||||
PROCESSOR2+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
PROCESSOR2+=" name=data2,type=push,method=bind,address=tcp://127.0.0.1:7788"
|
||||
PROCESSOR2+=" name=data3,type=push,method=bind,address=tcp://127.0.0.1:7789"
|
||||
xterm -geometry 90x40+550+600 -hold -e @EX_BIN_DIR@/$PROCESSOR2 &
|
||||
|
||||
SINK1_1="fairmq-ex-region-sink"
|
||||
SINK1_1+=" --id sink1_1"
|
||||
SINK1_1+=" --severity debug"
|
||||
SINK1_1+=" --chan-name data2"
|
||||
SINK1_1+=" --transport $transport"
|
||||
SINK1_1+=" --shmid 1"
|
||||
SINK1_1+=" --shm-segment-id 1"
|
||||
SINK1_1+=" --shm-monitor false"
|
||||
SINK1_1+=" --shm-no-cleanup true"
|
||||
SINK1_1+=" --channel-config name=data2,type=pull,method=connect,address=tcp://127.0.0.1:7778"
|
||||
xterm -geometry 90x20+1100+0 -hold -e @EX_BIN_DIR@/$SINK1_1 &
|
||||
|
||||
SINK1_2="fairmq-ex-region-sink"
|
||||
SINK1_2+=" --id sink1_2"
|
||||
SINK1_2+=" --severity debug"
|
||||
SINK1_2+=" --chan-name data3"
|
||||
SINK1_2+=" --transport $transport"
|
||||
SINK1_2+=" --shmid 1"
|
||||
SINK1_2+=" --shm-segment-id 1"
|
||||
SINK1_2+=" --shm-monitor false"
|
||||
SINK1_2+=" --shm-no-cleanup true"
|
||||
SINK1_2+=" --channel-config name=data3,type=pull,method=connect,address=tcp://127.0.0.1:7779"
|
||||
xterm -geometry 90x20+1100+300 -hold -e @EX_BIN_DIR@/$SINK1_2 &
|
||||
|
||||
SINK2_1="fairmq-ex-region-sink"
|
||||
SINK2_1+=" --id sink2_1"
|
||||
SINK2_1+=" --severity debug"
|
||||
SINK2_1+=" --chan-name data2"
|
||||
SINK2_1+=" --transport $transport"
|
||||
SINK2_1+=" --shmid 1"
|
||||
SINK2_1+=" --shm-segment-id 2"
|
||||
SINK2_1+=" --shm-monitor false"
|
||||
SINK2_1+=" --shm-no-cleanup true"
|
||||
SINK2_1+=" --channel-config name=data2,type=pull,method=connect,address=tcp://127.0.0.1:7788"
|
||||
xterm -geometry 90x20+1100+600 -hold -e @EX_BIN_DIR@/$SINK2_1 &
|
||||
|
||||
SINK2_2="fairmq-ex-region-sink"
|
||||
SINK2_2+=" --id sink2_2"
|
||||
SINK2_2+=" --severity debug"
|
||||
SINK2_2+=" --chan-name data3"
|
||||
SINK2_2+=" --transport $transport"
|
||||
SINK2_2+=" --shmid 1"
|
||||
SINK2_2+=" --shm-segment-id 2"
|
||||
SINK2_2+=" --shm-monitor false"
|
||||
SINK2_2+=" --shm-no-cleanup true"
|
||||
SINK2_2+=" --channel-config name=data3,type=pull,method=connect,address=tcp://127.0.0.1:7789"
|
||||
xterm -geometry 90x20+1100+900 -hold -e @EX_BIN_DIR@/$SINK2_2 &
|
|
@ -1,80 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport=${1:-shmem}
|
||||
msgSize=${2:-1000000}
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
# SAMPLER+=" --sampling-rate 10"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --msg-size $msgSize"
|
||||
SAMPLER+=" --transport $transport"
|
||||
#SAMPLER+=" --rc-segment-size 0"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --chan-name data1"
|
||||
SAMPLER+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:7777"
|
||||
xterm -geometry 90x60+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
|
||||
|
||||
PROCESSOR1="fairmq-ex-region-processor"
|
||||
PROCESSOR1+=" --id processor1"
|
||||
PROCESSOR1+=" --severity debug"
|
||||
PROCESSOR1+=" --transport $transport"
|
||||
PROCESSOR1+=" --shm-segment-id 1"
|
||||
PROCESSOR1+=" --shm-monitor true"
|
||||
PROCESSOR1+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
PROCESSOR1+=" name=data2,type=push,method=bind,address=tcp://127.0.0.1:7778"
|
||||
PROCESSOR1+=" name=data3,type=push,method=bind,address=tcp://127.0.0.1:7779"
|
||||
xterm -geometry 90x40+550+40 -hold -e @EX_BIN_DIR@/$PROCESSOR1 &
|
||||
|
||||
PROCESSOR2="fairmq-ex-region-processor"
|
||||
PROCESSOR2+=" --id processor2"
|
||||
PROCESSOR2+=" --severity debug"
|
||||
PROCESSOR2+=" --transport $transport"
|
||||
PROCESSOR2+=" --shm-segment-id 2"
|
||||
PROCESSOR2+=" --shm-monitor true"
|
||||
PROCESSOR2+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
PROCESSOR2+=" name=data2,type=push,method=bind,address=tcp://127.0.0.1:7788"
|
||||
PROCESSOR2+=" name=data3,type=push,method=bind,address=tcp://127.0.0.1:7789"
|
||||
xterm -geometry 90x40+550+600 -hold -e @EX_BIN_DIR@/$PROCESSOR2 &
|
||||
|
||||
SINK1_1="fairmq-ex-region-sink"
|
||||
SINK1_1+=" --id sink1_1"
|
||||
SINK1_1+=" --severity debug"
|
||||
SINK1_1+=" --chan-name data2"
|
||||
SINK1_1+=" --transport $transport"
|
||||
SINK1_1+=" --shm-segment-id 1"
|
||||
SINK1_1+=" --shm-monitor true"
|
||||
SINK1_1+=" --channel-config name=data2,type=pull,method=connect,address=tcp://127.0.0.1:7778"
|
||||
xterm -geometry 90x20+1100+0 -hold -e @EX_BIN_DIR@/$SINK1_1 &
|
||||
|
||||
SINK1_2="fairmq-ex-region-sink"
|
||||
SINK1_2+=" --id sink1_2"
|
||||
SINK1_2+=" --severity debug"
|
||||
SINK1_2+=" --chan-name data3"
|
||||
SINK1_2+=" --transport $transport"
|
||||
SINK1_2+=" --shm-segment-id 1"
|
||||
SINK1_2+=" --shm-monitor true"
|
||||
SINK1_2+=" --channel-config name=data3,type=pull,method=connect,address=tcp://127.0.0.1:7779"
|
||||
xterm -geometry 90x20+1100+300 -hold -e @EX_BIN_DIR@/$SINK1_2 &
|
||||
|
||||
SINK2_1="fairmq-ex-region-sink"
|
||||
SINK2_1+=" --id sink2_1"
|
||||
SINK2_1+=" --severity debug"
|
||||
SINK2_1+=" --chan-name data2"
|
||||
SINK2_1+=" --transport $transport"
|
||||
SINK2_1+=" --shm-segment-id 2"
|
||||
SINK2_1+=" --shm-monitor true"
|
||||
SINK2_1+=" --channel-config name=data2,type=pull,method=connect,address=tcp://127.0.0.1:7788"
|
||||
xterm -geometry 90x20+1100+600 -hold -e @EX_BIN_DIR@/$SINK2_1 &
|
||||
|
||||
SINK2_2="fairmq-ex-region-sink"
|
||||
SINK2_2+=" --id sink2_2"
|
||||
SINK2_2+=" --severity debug"
|
||||
SINK2_2+=" --chan-name data3"
|
||||
SINK2_2+=" --transport $transport"
|
||||
SINK2_2+=" --shm-segment-id 2"
|
||||
SINK2_2+=" --shm-monitor true"
|
||||
SINK2_2+=" --channel-config name=data3,type=pull,method=connect,address=tcp://127.0.0.1:7789"
|
||||
xterm -geometry 90x20+1100+900 -hold -e @EX_BIN_DIR@/$SINK2_2 &
|
|
@ -2,8 +2,16 @@
|
|||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport=${1:-shmem}
|
||||
msgSize=${2:-1000000}
|
||||
transport="shmem"
|
||||
msgSize="1000000"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
if [[ $2 =~ ^[0-9]+$ ]]; then
|
||||
msgSize=$1
|
||||
fi
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
|
@ -11,10 +19,6 @@ SAMPLER+=" --severity debug"
|
|||
SAMPLER+=" --msg-size $msgSize"
|
||||
# SAMPLER+=" --rate 10"
|
||||
SAMPLER+=" --transport $transport"
|
||||
# SAMPLER+=" --external-region true"
|
||||
# SAMPLER+=" --shm-no-cleaup true"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
# SAMPLER+=" --shmid 1"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777,sndKernelSize=212992"
|
||||
xterm -geometry 120x60+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
|
||||
|
||||
|
@ -22,8 +26,5 @@ SINK="fairmq-ex-region-sink"
|
|||
SINK+=" --id sink1"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --transport $transport"
|
||||
# SINK+=" --shm-no-cleaup true"
|
||||
SINK+=" --shm-monitor true"
|
||||
# SINK+=" --shmid 1"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://127.0.0.1:7777,rcvKernelSize=212992"
|
||||
xterm -geometry 120x60+750+0 -hold -e @EX_BIN_DIR@/$SINK &
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
#include <fairmq/shmem/Common.h>
|
||||
#include <fairmq/shmem/Monitor.h>
|
||||
#include <fairmq/shmem/Segment.h>
|
||||
#include <fairmq/shmem/UnmanagedRegion.h>
|
||||
#include <fairmq/tools/Unique.h>
|
||||
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::program_options;
|
||||
|
||||
namespace {
|
||||
volatile sig_atomic_t gStopping = 0;
|
||||
volatile sig_atomic_t gResetContent = 0;
|
||||
} // namespace
|
||||
|
||||
void signalHandler(int /* signal */) { gStopping = 1; }
|
||||
|
||||
void resetContentHandler(int /* signal */) { gResetContent = 1; }
|
||||
|
||||
struct ShmManager
|
||||
{
|
||||
ShmManager(uint64_t _shmId, const vector<string>& _segments, const vector<string>& _regions, bool zero = true)
|
||||
: shmId(fair::mq::shmem::makeShmIdStr(_shmId))
|
||||
{
|
||||
LOG(info) << "Starting ShmManager for shmId: " << shmId;
|
||||
LOG(info) << "Performing full reset...";
|
||||
FullReset();
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Adding managed segments...";
|
||||
AddSegments(_segments, zero);
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Adding unmanaged regions...";
|
||||
AddRegions(_regions, zero);
|
||||
LOG(info) << "Done.";
|
||||
LOG(info) << "Shared memory is ready for use.";
|
||||
}
|
||||
|
||||
void AddSegments(const vector<string>& _segments, bool zero)
|
||||
{
|
||||
for (const auto& s : _segments) {
|
||||
vector<string> conf;
|
||||
boost::algorithm::split(conf, s, boost::algorithm::is_any_of(","));
|
||||
if (conf.size() != 3) {
|
||||
LOG(error) << "incorrect format for --segments. Expecting pairs of <id>,<size><numaid>.";
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
throw runtime_error("incorrect format for --segments. Expecting pairs of <id>,<size>,<numaid>.");
|
||||
}
|
||||
uint16_t id = stoi(conf.at(0));
|
||||
uint64_t size = stoull(conf.at(1));
|
||||
segmentCfgs.emplace_back(fair::mq::shmem::SegmentConfig{id, size, "rbtree_best_fit"});
|
||||
|
||||
auto ret = segments.emplace(id, fair::mq::shmem::Segment(shmId, id, size, fair::mq::shmem::rbTreeBestFit));
|
||||
fair::mq::shmem::Segment& segment = ret.first->second;
|
||||
LOG(info) << "Created segment " << id << " of size " << segment.GetSize()
|
||||
<< ", starting at " << segment.GetData() << ". Locking...";
|
||||
segment.Lock();
|
||||
LOG(info) << "Done.";
|
||||
if (zero) {
|
||||
LOG(info) << "Zeroing...";
|
||||
segment.Zero();
|
||||
LOG(info) << "Done.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddRegions(const vector<string>& _regions, bool zero)
|
||||
{
|
||||
for (const auto& r : _regions) {
|
||||
vector<string> conf;
|
||||
boost::algorithm::split(conf, r, boost::algorithm::is_any_of(","));
|
||||
if (conf.size() != 3) {
|
||||
LOG(error) << "incorrect format for --regions. Expecting pairs of <id>,<size>,<numaid>.";
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
throw runtime_error("incorrect format for --regions. Expecting pairs of <id>,<size>,<numaid>.");
|
||||
}
|
||||
uint16_t id = stoi(conf.at(0));
|
||||
uint64_t size = stoull(conf.at(1));
|
||||
fair::mq::RegionConfig cfg;
|
||||
cfg.id = id;
|
||||
cfg.rcSegmentSize = 0;
|
||||
cfg.size = size;
|
||||
regionCfgs.push_back(cfg);
|
||||
|
||||
auto ret = regions.emplace(id, make_unique<fair::mq::shmem::UnmanagedRegion>(shmId, cfg));
|
||||
fair::mq::shmem::UnmanagedRegion& region = *(ret.first->second);
|
||||
LOG(info) << "Created unamanged region " << id << " of size " << region.GetSize()
|
||||
<< ", starting at " << region.GetData() << ". Locking...";
|
||||
region.Lock();
|
||||
LOG(info) << "Done.";
|
||||
if (zero) {
|
||||
LOG(info) << "Zeroing...";
|
||||
region.Zero();
|
||||
LOG(info) << "Done.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckPresence()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(localMtx);
|
||||
for (const auto& sc : segmentCfgs) {
|
||||
if (!(fair::mq::shmem::Monitor::SegmentIsPresent(fair::mq::shmem::ShmId{shmId}, sc.id))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const auto& rc : regionCfgs) {
|
||||
if (!(fair::mq::shmem::Monitor::RegionIsPresent(fair::mq::shmem::ShmId{shmId}, rc.id.value()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetContent()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(localMtx);
|
||||
fair::mq::shmem::Monitor::ResetContent(fair::mq::shmem::ShmId{shmId}, segmentCfgs, regionCfgs);
|
||||
}
|
||||
|
||||
void FullReset()
|
||||
{
|
||||
segments.clear();
|
||||
regions.clear();
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
}
|
||||
|
||||
~ShmManager()
|
||||
{
|
||||
// clean all segments, regions and any other shmem objects belonging to this shmId
|
||||
fair::mq::shmem::Monitor::Cleanup(fair::mq::shmem::ShmId{shmId});
|
||||
}
|
||||
|
||||
std::string shmId;
|
||||
std::mutex localMtx;
|
||||
map<uint16_t, fair::mq::shmem::Segment> segments;
|
||||
map<uint16_t, unique_ptr<fair::mq::shmem::UnmanagedRegion>> regions;
|
||||
std::vector<fair::mq::shmem::SegmentConfig> segmentCfgs;
|
||||
std::vector<fair::mq::RegionConfig> regionCfgs;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
fair::Logger::SetConsoleColor(true);
|
||||
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
signal(SIGUSR1, resetContentHandler);
|
||||
|
||||
try {
|
||||
bool nozero = false;
|
||||
bool checkPresence = true;
|
||||
uint64_t shmId = 0;
|
||||
vector<string> segments;
|
||||
vector<string> regions;
|
||||
|
||||
options_description desc("Options");
|
||||
desc.add_options()
|
||||
("shmid", value<uint64_t>(&shmId)->required(), "Shm id")
|
||||
("segments", value<vector<string>>(&segments)->multitoken()->composing(), "Segments, as <id>,<size>,<numaid> <id>,<size>,<numaid> <id>,<size>,<numaid> ... (numaid: -2 disabled, -1 interleave, >=0 node)")
|
||||
("regions", value<vector<string>>(®ions)->multitoken()->composing(), "Regions, as <id>,<size> <id>,<size>,<numaid> <id>,<size>,<numaid> ...")
|
||||
("nozero", value<bool>(&nozero)->default_value(false)->implicit_value(true), "Do not zero segments after initialization")
|
||||
("check-presence", value<bool>(&checkPresence)->default_value(true)->implicit_value(true), "Check periodically if configured segments/regions are still present, and cleanup and leave if they are not")
|
||||
("help,h", "Print help");
|
||||
|
||||
variables_map vm;
|
||||
store(parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
LOG(info) << "ShmManager" << "\n" << desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
notify(vm);
|
||||
|
||||
ShmManager shmManager(shmId, segments, regions, !nozero);
|
||||
|
||||
std::thread resetContentThread([&shmManager]() {
|
||||
while (!gStopping) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
if (gResetContent == 1) {
|
||||
LOG(info) << "Resetting content for shmId " << shmManager.shmId;
|
||||
shmManager.ResetContent();
|
||||
gResetContent = 0;
|
||||
LOG(info) << "Done resetting content for shmId " << shmManager.shmId;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (checkPresence) {
|
||||
while (!gStopping) {
|
||||
if (shmManager.CheckPresence() == false) {
|
||||
LOG(error) << "Failed to find segments, exiting.";
|
||||
gStopping = true;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
}
|
||||
|
||||
resetContentThread.join();
|
||||
|
||||
LOG(info) << "stopping.";
|
||||
} catch (exception& e) {
|
||||
LOG(error) << "Exception reached the top of main: " << e.what() << ", exiting";
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
#include <memory>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Processor : Device
|
||||
{
|
||||
void InitTask() override
|
||||
{
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
GetChannel("data1", 0).Transport()->SubscribeToRegionEvents([](RegionInfo info) {
|
||||
LOG(info) << "Region event: " << info.event << ": "
|
||||
<< (info.managed ? "managed" : "unmanaged") << ", id: " << info.id
|
||||
<< ", ptr: " << info.ptr << ", size: " << info.size
|
||||
<< ", flags: " << info.flags;
|
||||
});
|
||||
}
|
||||
|
||||
void Run() override
|
||||
{
|
||||
Channel& dataIn = GetChannel("data1", 0);
|
||||
Channel& dataOut1 = GetChannel("data2", 0);
|
||||
Channel& dataOut2 = GetChannel("data3", 0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
fair::mq::Parts inParts;
|
||||
dataIn.Receive(inParts);
|
||||
|
||||
fair::mq::Parts outParts1;
|
||||
fair::mq::Parts outParts2;
|
||||
|
||||
for (const auto& inPart : inParts) {
|
||||
outParts1.AddPart(NewMessage());
|
||||
outParts1.fParts.back()->Copy(*inPart);
|
||||
|
||||
outParts2.AddPart(NewMessage());
|
||||
outParts2.fParts.back()->Copy(*inPart);
|
||||
}
|
||||
|
||||
dataOut1.Send(outParts1);
|
||||
dataOut2.Send(outParts2);
|
||||
|
||||
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
|
||||
LOG(info) << "Configured max number of iterations reached. Leaving RUNNING state.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
GetChannel("data1", 0).Transport()->UnsubscribeFromRegionEvents();
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void addCustomOptions(bpo::options_description& options)
|
||||
{
|
||||
options.add_options()("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
|
||||
}
|
||||
|
||||
unique_ptr<Device> getDevice(ProgOptions& /*config*/) { return make_unique<Processor>(); }
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
#include <fairmq/tools/RateLimit.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
@ -20,15 +19,11 @@ struct Sampler : fair::mq::Device
|
|||
{
|
||||
void InitTask() override
|
||||
{
|
||||
fExternalRegion = fConfig->GetProperty<bool>("external-region");
|
||||
fMsgSize = fConfig->GetProperty<int>("msg-size");
|
||||
fLinger = fConfig->GetProperty<uint32_t>("region-linger");
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
fChanName = fConfig->GetProperty<std::string>("chan-name");
|
||||
fSamplingRate = fConfig->GetProperty<float>("sampling-rate");
|
||||
fRCSegmentSize = fConfig->GetProperty<uint64_t>("rc-segment-size");
|
||||
|
||||
GetChannel(fChanName, 0).Transport()->SubscribeToRegionEvents([](fair::mq::RegionInfo info) {
|
||||
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) {
|
||||
LOG(info) << "Region event: " << info.event << ": "
|
||||
<< (info.managed ? "managed" : "unmanaged")
|
||||
<< ", id: " << info.id
|
||||
|
@ -37,111 +32,80 @@ struct Sampler : fair::mq::Device
|
|||
<< ", flags: " << info.flags;
|
||||
});
|
||||
|
||||
fair::mq::RegionConfig regionCfg;
|
||||
regionCfg.linger = fLinger; // delay in ms before region destruction to collect outstanding events
|
||||
// options for testing with an externally-created -region
|
||||
if (fExternalRegion) {
|
||||
regionCfg.id = 1;
|
||||
regionCfg.removeOnDestruction = false;
|
||||
}
|
||||
regionCfg.lock = !fExternalRegion; // mlock region after creation
|
||||
regionCfg.zero = !fExternalRegion; // zero region content after creation
|
||||
regionCfg.rcSegmentSize = fRCSegmentSize; // size of the corresponding reference count segment
|
||||
fRegion = fair::mq::UnmanagedRegionPtr(NewUnmanagedRegionFor(
|
||||
fChanName, // region is created using the transport of this channel...
|
||||
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data", // region is created using the transport of this channel...
|
||||
0, // ... and this sub-channel
|
||||
10000000, // region size
|
||||
[this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fNumUnackedMsgs -= blocks.size();
|
||||
|
||||
if (fMaxIterations > 0) {
|
||||
LOG(info) << "Received " << blocks.size() << " acks";
|
||||
}
|
||||
},
|
||||
regionCfg
|
||||
"", // path, if a region is backed by a file
|
||||
0, // flags that are passed for region creation
|
||||
fair::mq::RegionConfig{true, true} // additional config: { call mlock on the region, zero the region memory }
|
||||
));
|
||||
fRegion->SetLinger(fLinger);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
bool ConditionalRun() override
|
||||
{
|
||||
|
||||
fair::mq::tools::RateLimiter rateLimiter(fSamplingRate);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
fair::mq::Parts parts;
|
||||
// make 64 parts
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
parts.AddPart(NewMessageFor(
|
||||
fChanName, // channel
|
||||
FairMQMessagePtr msg(NewMessageFor("data", // channel
|
||||
0, // sub-channel
|
||||
fRegion, // region
|
||||
fRegion->GetData(), // ptr within region
|
||||
fMsgSize, // offset from ptr
|
||||
nullptr // hint
|
||||
));
|
||||
}
|
||||
|
||||
// static_cast<char*>(fRegion->GetData())[3] = 97;
|
||||
// LOG(info) << "check: " << static_cast<char*>(fRegion->GetData())[3];
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fNumUnackedMsgs += parts.Size();
|
||||
if (Send(parts, fChanName, 0) > 0) {
|
||||
++fNumUnackedMsgs;
|
||||
if (Send(msg, "data", 0) > 0) {
|
||||
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
|
||||
LOG(info) << "Configured maximum number of iterations reached. Stopping sending.";
|
||||
break;
|
||||
}
|
||||
if (fSamplingRate > 0.001) {
|
||||
rateLimiter.maybe_sleep();
|
||||
}
|
||||
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for all acks to arrive
|
||||
while (!NewStatePending()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
fRegion.reset();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
if (fNumUnackedMsgs == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||
}
|
||||
|
||||
if (fNumUnackedMsgs != 0) {
|
||||
LOG(info) << "Done, still not acknowledged: " << fNumUnackedMsgs;
|
||||
} else {
|
||||
LOG(info) << "All acknowledgements received.";
|
||||
}
|
||||
}
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
fRegion.reset();
|
||||
GetChannel(fChanName, 0).Transport()->UnsubscribeFromRegionEvents();
|
||||
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
|
||||
}
|
||||
|
||||
private:
|
||||
int fExternalRegion = false;
|
||||
int fMsgSize = 10000;
|
||||
uint32_t fLinger = 100;
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
uint64_t fRCSegmentSize = 10000000;
|
||||
fair::mq::UnmanagedRegionPtr fRegion = nullptr;
|
||||
FairMQUnmanagedRegionPtr fRegion = nullptr;
|
||||
std::mutex fMtx;
|
||||
uint64_t fNumUnackedMsgs = 0;
|
||||
std::string fChanName;
|
||||
float fSamplingRate = 0.;
|
||||
};
|
||||
|
||||
void addCustomOptions(bpo::options_description& options)
|
||||
{
|
||||
options.add_options()
|
||||
("chan-name", bpo::value<std::string>()->default_value("data"), "name of the output channel")
|
||||
("msg-size", bpo::value<int>()->default_value(1000), "Message size in bytes")
|
||||
("sampling-rate", bpo::value<float>()->default_value(0.), "Sampling rate (Hz).")
|
||||
("region-linger", bpo::value<uint32_t>()->default_value(100), "Linger period for regions")
|
||||
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)")
|
||||
("external-region", bpo::value<bool>()->default_value(false), "Use region created by another process")
|
||||
("rc-segment-size", bpo::value<uint64_t>()->default_value(10000000), "Size of the reference count segment for Unamanged Region");
|
||||
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
|
||||
}
|
||||
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /*config*/)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
|
@ -8,62 +8,60 @@
|
|||
|
||||
#include <fairmq/Device.h>
|
||||
#include <fairmq/runDevice.h>
|
||||
#include <memory>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Sink : Device
|
||||
struct Sink : fair::mq::Device
|
||||
{
|
||||
void InitTask() override
|
||||
{
|
||||
// Get the fMaxIterations value from the command line options (via fConfig)
|
||||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
fChanName = fConfig->GetProperty<std::string>("chan-name");
|
||||
GetChannel(fChanName, 0).Transport()->SubscribeToRegionEvents([](RegionInfo info) {
|
||||
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) {
|
||||
LOG(info) << "Region event: " << info.event << ": "
|
||||
<< (info.managed ? "managed" : "unmanaged") << ", id: " << info.id
|
||||
<< ", ptr: " << info.ptr << ", size: " << info.size
|
||||
<< (info.managed ? "managed" : "unmanaged")
|
||||
<< ", id: " << info.id
|
||||
<< ", ptr: " << info.ptr
|
||||
<< ", size: " << info.size
|
||||
<< ", flags: " << info.flags;
|
||||
});
|
||||
}
|
||||
|
||||
void Run() override
|
||||
{
|
||||
Channel& dataIn = GetChannel(fChanName, 0);
|
||||
FairMQChannel& dataInChannel = fChannels.at("data").at(0);
|
||||
|
||||
while (!NewStatePending()) {
|
||||
fair::mq::Parts parts;
|
||||
dataIn.Receive(parts);
|
||||
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
|
||||
dataInChannel.Receive(msg);
|
||||
|
||||
// void* ptr = msg->GetData();
|
||||
// char* cptr = static_cast<char*>(ptr);
|
||||
// LOG(info) << "check: " << cptr[3];
|
||||
|
||||
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
|
||||
LOG(info) << "Configured max number of iterations reached. Leaving RUNNING state.";
|
||||
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetTask() override
|
||||
{
|
||||
GetChannel(fChanName, 0).Transport()->UnsubscribeFromRegionEvents();
|
||||
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t fMaxIterations = 0;
|
||||
uint64_t fNumIterations = 0;
|
||||
std::string fChanName;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void addCustomOptions(bpo::options_description& options)
|
||||
{
|
||||
options.add_options()
|
||||
("chan-name", bpo::value<std::string>()->default_value("data"), "name of the input channel")
|
||||
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
|
||||
}
|
||||
|
||||
unique_ptr<Device> getDevice(ProgOptions& /*config*/) { return make_unique<Sink>(); }
|
||||
std::unique_ptr<fair::mq::Device> getDevice(fair::mq::ProgOptions& /*config*/)
|
||||
{
|
||||
return std::make_unique<Sink>();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -11,26 +9,22 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
fi
|
||||
|
||||
msgSize="1000000"
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; 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; exit 0' 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' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --session $session"
|
||||
SAMPLER+=" --shm-segment-size 100000000"
|
||||
SAMPLER+=" --shm-monitor true"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --msg-size $msgSize"
|
||||
SAMPLER+=" --region-linger 500"
|
||||
SAMPLER+=" --channel-config name=$chan,type=push,method=bind,address=ipc://$chanAddr"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
|
@ -38,20 +32,14 @@ SINK="fairmq-ex-region-sink"
|
|||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --severity debug"
|
||||
SINK+=" --session $session"
|
||||
SINK+=" --shm-segment-size 100000000"
|
||||
SINK+=" --shm-monitor true"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --channel-config name=$chan,type=pull,method=connect,address=ipc://$chanAddr"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
||||
# wait for sampler and sink to finish
|
||||
wait $SAMPLER_PID
|
||||
wait $SINK_PID
|
||||
|
||||
set +e
|
||||
rm $chanAddr
|
||||
exit 0
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
add_example(NAME req-rep
|
||||
DEVICE client server
|
||||
add_executable(fairmq-ex-req-rep-client client.cxx)
|
||||
target_link_libraries(fairmq-ex-req-rep-client PRIVATE FairMQ)
|
||||
|
||||
|
||||
add_executable(fairmq-ex-req-rep-server server.cxx)
|
||||
target_link_libraries(fairmq-ex-req-rep-server PRIVATE FairMQ)
|
||||
|
||||
add_custom_target(ExampleReqRep DEPENDS fairmq-ex-req-rep-client fairmq-ex-req-rep-server)
|
||||
|
||||
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-req-rep.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-req-rep.sh)
|
||||
|
||||
# test
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-req-rep.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh)
|
||||
|
||||
add_test(NAME Example.ReqRep.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh zeromq)
|
||||
set_tests_properties(Example.ReqRep.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
|
||||
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: ")
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
fairmq-ex-req-rep-client
|
||||
fairmq-ex-req-rep-server
|
||||
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
# configure run script with different executable paths for build and for install directories
|
||||
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
|
||||
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-req-rep.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-req-rep.sh_install)
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-req-rep.sh_install
|
||||
DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
RENAME fairmq-start-ex-req-rep.sh
|
||||
)
|
||||
|
|
|
@ -32,11 +32,11 @@ struct Client : fair::mq::Device
|
|||
// its size,
|
||||
// custom deletion function (called when transfer is done),
|
||||
// and pointer to the object managing the data buffer
|
||||
fair::mq::MessagePtr req(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
FairMQMessagePtr req(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
text->length(), // size
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
|
||||
text)); // object that manages the data
|
||||
fair::mq::MessagePtr rep(NewMessage());
|
||||
FairMQMessagePtr rep(NewMessage());
|
||||
|
||||
LOG(info) << "Sending \"" << fText << "\" to server.";
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ struct Server : fair::mq::Device
|
|||
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
|
||||
}
|
||||
|
||||
bool HandleData(fair::mq::MessagePtr& req, int)
|
||||
bool HandleData(FairMQMessagePtr& req, int)
|
||||
{
|
||||
LOG(info) << "Received request from client: \"" << std::string(static_cast<char*>(req->GetData()), req->GetSize()) << "\"";
|
||||
|
||||
|
@ -34,7 +34,7 @@ struct Server : fair::mq::Device
|
|||
|
||||
LOG(info) << "Sending reply to client.";
|
||||
|
||||
fair::mq::MessagePtr rep(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
FairMQMessagePtr rep(NewMessage(const_cast<char*>(text->c_str()), // data
|
||||
text->length(), // size
|
||||
[](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, // deletion callback
|
||||
text)); // object that manages the data
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
@ -10,23 +8,19 @@ if [[ $1 =~ ^[a-z]+$ ]]; then
|
|||
transport=$1
|
||||
fi
|
||||
|
||||
session="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
chan="data"
|
||||
chanAddr="/tmp/fmq_$session""_""$chan""_""$transport"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'set +e; kill -TERM $CLIENT_PID; kill -TERM $SERVER_PID; wait $CLIENT_PID; wait $SERVER_PID; rm $chanAddr; exit 0' TERM
|
||||
trap 'kill -TERM $CLIENT_PID; kill -TERM $SERVER_PID; wait $CLIENT_PID; wait $SERVER_PID;' TERM
|
||||
|
||||
CLIENT="fairmq-ex-req-rep-client"
|
||||
CLIENT+=" --id client"
|
||||
CLIENT+=" --transport $transport"
|
||||
CLIENT+=" --verbosity veryhigh"
|
||||
CLIENT+=" --session $session"
|
||||
CLIENT+=" --shm-segment-size 100000000"
|
||||
CLIENT+=" --shm-monitor true"
|
||||
CLIENT+=" --session $SESSION"
|
||||
CLIENT+=" --control static --color false"
|
||||
CLIENT+=" --max-iterations 1"
|
||||
CLIENT+=" --channel-config name=$chan,type=req,method=connect,rateLogging=0,address=ipc://$chanAddr"
|
||||
CLIENT+=" --channel-config name=data,type=req,method=connect,rateLogging=0,address=tcp://127.0.0.1:5005"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$CLIENT &
|
||||
CLIENT_PID=$!
|
||||
|
||||
|
@ -34,19 +28,13 @@ SERVER="fairmq-ex-req-rep-server"
|
|||
SERVER+=" --id server"
|
||||
SERVER+=" --transport $transport"
|
||||
SERVER+=" --verbosity veryhigh"
|
||||
SERVER+=" --session $session"
|
||||
SERVER+=" --shm-segment-size 100000000"
|
||||
SERVER+=" --shm-monitor true"
|
||||
SERVER+=" --session $SESSION"
|
||||
SERVER+=" --control static --color false"
|
||||
SERVER+=" --max-iterations 1"
|
||||
SERVER+=" --channel-config name=$chan,type=rep,method=bind,rateLogging=0,address=ipc://$chanAddr"
|
||||
SERVER+=" --channel-config name=data,type=rep,method=bind,rateLogging=0,address=tcp://127.0.0.1:5005"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SERVER &
|
||||
SERVER_PID=$!
|
||||
|
||||
# wait for everything to finish
|
||||
wait $CLIENT_PID
|
||||
wait $SERVER_PID
|
||||
|
||||
set +e
|
||||
rm $chanAddr
|
||||
exit 0
|
||||
|
|
2
extern/googletest
vendored
2
extern/googletest
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7d76a231b0e29caf86e68d1df858308cd53b2a66
|
||||
Subproject commit f5e592d8ee5ffb1d9af5be7f715ce3576b8bf9c4
|
|
@ -1,17 +1,12 @@
|
|||
################################################################################
|
||||
# Copyright (C) 2012-2025 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2012-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
if(BUILD_FAIRMQ)
|
||||
|
||||
if(BUILD_TIDY_TOOL)
|
||||
include(FairMQTidy)
|
||||
endif()
|
||||
|
||||
if(BUILD_FAIRMQ OR BUILD_SDK)
|
||||
###########
|
||||
# Version #
|
||||
###########
|
||||
|
@ -23,6 +18,125 @@ if(BUILD_FAIRMQ)
|
|||
DESTINATION ${PROJECT_INSTALL_INCDIR}
|
||||
)
|
||||
|
||||
#########
|
||||
# Tools #
|
||||
#########
|
||||
set(target Tools)
|
||||
|
||||
set(TOOLS_PUBLIC_HEADER_FILES
|
||||
tools/CppSTL.h
|
||||
tools/InstanceLimit.h
|
||||
tools/Network.h
|
||||
tools/Process.h
|
||||
tools/RateLimit.h
|
||||
tools/Semaphore.h
|
||||
tools/Strings.h
|
||||
tools/Unique.h
|
||||
tools/Version.h
|
||||
Tools.h
|
||||
)
|
||||
|
||||
set(TOOLS_SOURCE_FILES
|
||||
tools/Network.cxx
|
||||
tools/Process.cxx
|
||||
tools/Semaphore.cxx
|
||||
tools/Unique.cxx
|
||||
)
|
||||
|
||||
add_library(${target}
|
||||
${TOOLS_SOURCE_FILES}
|
||||
${TOOLS_PUBLIC_HEADER_FILES}
|
||||
)
|
||||
target_compile_features(${target} PUBLIC cxx_std_17)
|
||||
target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
|
||||
target_include_directories(${target}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
target_link_libraries(${target}
|
||||
PRIVATE
|
||||
FairLogger::FairLogger
|
||||
Threads::Threads
|
||||
Boost::boost
|
||||
)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
OUTPUT_NAME FairMQ${target}
|
||||
)
|
||||
install(
|
||||
TARGETS ${target}
|
||||
EXPORT ${PROJECT_EXPORT_SET}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
)
|
||||
foreach(HEADER ${TOOLS_PUBLIC_HEADER_FILES})
|
||||
get_filename_component(_path ${HEADER} DIRECTORY)
|
||||
file(TO_CMAKE_PATH ${PROJECT_INSTALL_INCDIR}/${_path} _destination)
|
||||
install(FILES ${HEADER}
|
||||
DESTINATION ${_destination}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
#################
|
||||
# State Machine #
|
||||
#################
|
||||
set(target StateMachine)
|
||||
|
||||
set(FSM_PUBLIC_HEADER_FILES
|
||||
StateMachine.h
|
||||
States.h
|
||||
StateQueue.h
|
||||
)
|
||||
|
||||
set(FSM_SOURCE_FILES
|
||||
StateMachine.cxx
|
||||
States.cxx
|
||||
)
|
||||
|
||||
add_library(${target}
|
||||
${FSM_SOURCE_FILES}
|
||||
${FSM_PUBLIC_HEADER_FILES}
|
||||
)
|
||||
target_compile_features(${target} PUBLIC cxx_std_17)
|
||||
target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
|
||||
target_include_directories(${target}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
target_link_libraries(${target}
|
||||
PUBLIC
|
||||
FairLogger::FairLogger
|
||||
|
||||
PRIVATE
|
||||
Boost::boost
|
||||
Tools
|
||||
)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
OUTPUT_NAME FairMQ${target}
|
||||
)
|
||||
install(
|
||||
TARGETS ${target}
|
||||
EXPORT ${PROJECT_EXPORT_SET}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
)
|
||||
foreach(HEADER ${FSM_PUBLIC_HEADER_FILES})
|
||||
get_filename_component(_path ${HEADER} DIRECTORY)
|
||||
file(TO_CMAKE_PATH ${PROJECT_INSTALL_INCDIR}/${_path} _destination)
|
||||
install(FILES ${HEADER}
|
||||
DESTINATION ${_destination}
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(BUILD_FAIRMQ)
|
||||
##########################
|
||||
# libFairMQ header files #
|
||||
##########################
|
||||
|
@ -30,7 +144,6 @@ if(BUILD_FAIRMQ)
|
|||
Channel.h
|
||||
Device.h
|
||||
DeviceRunner.h
|
||||
Error.h
|
||||
EventManager.h
|
||||
FairMQChannel.h
|
||||
FairMQDevice.h
|
||||
|
@ -46,7 +159,6 @@ if(BUILD_FAIRMQ)
|
|||
MemoryResourceTools.h
|
||||
MemoryResources.h
|
||||
Message.h
|
||||
Parts.h
|
||||
Plugin.h
|
||||
PluginManager.h
|
||||
PluginServices.h
|
||||
|
@ -55,41 +167,14 @@ if(BUILD_FAIRMQ)
|
|||
ProgOptionsFwd.h
|
||||
Properties.h
|
||||
PropertyOutput.h
|
||||
Socket.h
|
||||
StateMachine.h
|
||||
States.h
|
||||
StateQueue.h
|
||||
SuboptParser.h
|
||||
Tools.h
|
||||
TransportFactory.h
|
||||
Transports.h
|
||||
TransportEnum.h
|
||||
UnmanagedRegion.h
|
||||
options/FairMQProgOptions.h
|
||||
runDevice.h
|
||||
runFairMQDevice.h
|
||||
shmem/Common.h
|
||||
shmem/Manager.h
|
||||
shmem/Message.h
|
||||
shmem/Monitor.h
|
||||
shmem/Poller.h
|
||||
shmem/Segment.h
|
||||
shmem/Socket.h
|
||||
shmem/TransportFactory.h
|
||||
shmem/UnmanagedRegion.h
|
||||
shmem/UnmanagedRegionImpl.h
|
||||
tools/Compiler.h
|
||||
tools/CppSTL.h
|
||||
tools/Exceptions.h
|
||||
tools/IO.h
|
||||
tools/InstanceLimit.h
|
||||
tools/Network.h
|
||||
tools/Process.h
|
||||
tools/RateLimit.h
|
||||
tools/Semaphore.h
|
||||
tools/Strings.h
|
||||
tools/Unique.h
|
||||
tools/Version.h
|
||||
)
|
||||
|
||||
set(FAIRMQ_PRIVATE_HEADER_FILES
|
||||
|
@ -102,46 +187,66 @@ if(BUILD_FAIRMQ)
|
|||
plugins/Builtin.h
|
||||
plugins/config/Config.h
|
||||
plugins/control/Control.h
|
||||
zeromq/Common.h
|
||||
shmem/Message.h
|
||||
shmem/Poller.h
|
||||
shmem/UnmanagedRegion.h
|
||||
shmem/Socket.h
|
||||
shmem/TransportFactory.h
|
||||
shmem/Common.h
|
||||
shmem/Manager.h
|
||||
shmem/Region.h
|
||||
zeromq/Context.h
|
||||
zeromq/Message.h
|
||||
zeromq/Poller.h
|
||||
zeromq/UnmanagedRegion.h
|
||||
zeromq/Socket.h
|
||||
zeromq/TransportFactory.h
|
||||
zeromq/ZMsg.h
|
||||
)
|
||||
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
|
||||
ofi/Context.h
|
||||
ofi/ControlMessages.h
|
||||
ofi/Message.h
|
||||
ofi/Socket.h
|
||||
ofi/TransportFactory.h
|
||||
)
|
||||
endif()
|
||||
|
||||
##########################
|
||||
# libFairMQ source files #
|
||||
##########################
|
||||
set(FAIRMQ_SOURCE_FILES
|
||||
Channel.cxx
|
||||
Device.cxx
|
||||
DeviceRunner.cxx
|
||||
EventManager.cxx
|
||||
JSONParser.cxx
|
||||
MemoryResources.cxx
|
||||
FairMQChannel.cxx
|
||||
FairMQDevice.cxx
|
||||
FairMQLogger.cxx
|
||||
FairMQMessage.cxx
|
||||
FairMQPoller.cxx
|
||||
FairMQSocket.cxx
|
||||
FairMQTransportFactory.cxx
|
||||
Plugin.cxx
|
||||
PluginManager.cxx
|
||||
PluginServices.cxx
|
||||
ProgOptions.cxx
|
||||
JSONParser.cxx
|
||||
Properties.cxx
|
||||
StateMachine.cxx
|
||||
States.cxx
|
||||
SuboptParser.cxx
|
||||
TransportFactory.cxx
|
||||
plugins/config/Config.cxx
|
||||
plugins/control/Control.cxx
|
||||
shmem/Common.cxx
|
||||
MemoryResources.cxx
|
||||
shmem/Manager.cxx
|
||||
shmem/Monitor.cxx
|
||||
tools/Network.cxx
|
||||
tools/Process.cxx
|
||||
tools/Semaphore.cxx
|
||||
tools/Unique.cxx
|
||||
)
|
||||
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
|
||||
ofi/Context.cxx
|
||||
ofi/Message.cxx
|
||||
ofi/Socket.cxx
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
###################
|
||||
# configure files #
|
||||
|
@ -165,26 +270,14 @@ if(BUILD_FAIRMQ)
|
|||
############################
|
||||
# preprocessor definitions #
|
||||
############################
|
||||
target_compile_definitions(${target} PUBLIC
|
||||
BOOST_ERROR_CODE_HEADER_ONLY
|
||||
BOOST_ASIO_HAS_HAS_STD_CHRONO
|
||||
)
|
||||
target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
|
||||
if(FAIRMQ_DEBUG_MODE)
|
||||
target_compile_definitions(${target} PUBLIC FAIRMQ_DEBUG_MODE)
|
||||
endif()
|
||||
target_compile_definitions(${target} PUBLIC
|
||||
FAIRMQ_HAS_STD_FILESYSTEM=${FAIRMQ_HAS_STD_FILESYSTEM}
|
||||
FAIRMQ_HAS_STD_PMR=${FAIRMQ_HAS_STD_PMR}
|
||||
)
|
||||
if(DEFINED FAIRMQ_CHANNEL_DEFAULT_AUTOBIND)
|
||||
# translate CMake boolean (TRUE, FALSE, 0, 1, OFF, ON) into C++ boolean literal (true, false)
|
||||
if(FAIRMQ_CHANNEL_DEFAULT_AUTOBIND)
|
||||
set(value "true")
|
||||
else()
|
||||
set(value "false")
|
||||
endif()
|
||||
target_compile_definitions(${target} PUBLIC FAIRMQ_CHANNEL_DEFAULT_AUTOBIND=${value})
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
target_compile_definitions(${target} PRIVATE BUILD_OFI_TRANSPORT)
|
||||
endif()
|
||||
target_compile_definitions(${target} PUBLIC FAIRMQ_HAS_STD_FILESYSTEM=${FAIRMQ_HAS_STD_FILESYSTEM})
|
||||
|
||||
|
||||
#######################
|
||||
|
@ -202,6 +295,13 @@ if(BUILD_FAIRMQ)
|
|||
##################
|
||||
# link libraries #
|
||||
##################
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
set(OFI_DEPS
|
||||
asio::asio
|
||||
asiofi::asiofi
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target}
|
||||
INTERFACE # only consumers link against interface dependencies
|
||||
Boost::container
|
||||
|
@ -212,21 +312,21 @@ if(BUILD_FAIRMQ)
|
|||
$<$<PLATFORM_ID:Linux>:rt>
|
||||
Boost::boost
|
||||
Boost::program_options
|
||||
Boost::filesystem # still needed for Boost.DLL
|
||||
Boost::filesystem
|
||||
Boost::regex
|
||||
FairLogger::FairLogger
|
||||
Tools
|
||||
StateMachine
|
||||
|
||||
PRIVATE # only libFairMQ links against private dependencies
|
||||
libzmq
|
||||
PicoSHA2
|
||||
${OFI_DEPS}
|
||||
)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
OUTPUT_NAME ${PROJECT_NAME_LOWER}
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET ${target})
|
||||
endif()
|
||||
|
||||
|
||||
###############
|
||||
|
@ -234,41 +334,23 @@ if(BUILD_FAIRMQ)
|
|||
###############
|
||||
add_executable(fairmq-bsampler devices/runBenchmarkSampler.cxx)
|
||||
target_link_libraries(fairmq-bsampler FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-bsampler)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-merger devices/runMerger.cxx)
|
||||
target_link_libraries(fairmq-merger FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-merger)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-multiplier devices/runMultiplier.cxx)
|
||||
target_link_libraries(fairmq-multiplier FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-multiplier)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-proxy devices/runProxy.cxx)
|
||||
target_link_libraries(fairmq-proxy FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-proxy)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-sink devices/runSink.cxx)
|
||||
target_link_libraries(fairmq-sink FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-sink)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-splitter devices/runSplitter.cxx)
|
||||
target_link_libraries(fairmq-splitter FairMQ)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-splitter)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-shmmonitor shmem/Common.cxx shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
|
||||
add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
|
||||
target_compile_features(fairmq-shmmonitor PUBLIC cxx_std_17)
|
||||
target_compile_definitions(fairmq-shmmonitor PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
|
||||
if(FAIRMQ_DEBUG_MODE)
|
||||
|
@ -288,18 +370,12 @@ if(BUILD_FAIRMQ)
|
|||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
||||
)
|
||||
target_compile_definitions(fairmq-shmmonitor PUBLIC FAIRMQ_HAS_STD_FILESYSTEM=${FAIRMQ_HAS_STD_FILESYSTEM})
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-shmmonitor)
|
||||
endif()
|
||||
|
||||
add_executable(fairmq-uuid-gen tools/runUuidGenerator.cxx)
|
||||
target_link_libraries(fairmq-uuid-gen PUBLIC
|
||||
Boost::program_options
|
||||
FairMQ
|
||||
Tools
|
||||
)
|
||||
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
|
||||
fairmq_target_tidy(TARGET fairmq-uuid-gen)
|
||||
endif()
|
||||
|
||||
|
||||
###########
|
||||
|
@ -332,3 +408,21 @@ if(BUILD_FAIRMQ)
|
|||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(BUILD_SDK_COMMANDS)
|
||||
add_subdirectory(sdk/commands)
|
||||
endif()
|
||||
|
||||
if(BUILD_SDK)
|
||||
add_subdirectory(sdk)
|
||||
endif()
|
||||
|
||||
####################
|
||||
# external plugins #
|
||||
####################
|
||||
if(BUILD_DDS_PLUGIN)
|
||||
add_subdirectory(plugins/DDS)
|
||||
endif()
|
||||
if(BUILD_PMIX_PLUGIN)
|
||||
add_subdirectory(plugins/PMIx)
|
||||
endif()
|
||||
|
|
479
fairmq/Channel.h
479
fairmq/Channel.h
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2021-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
|
@ -9,485 +9,12 @@
|
|||
#ifndef FAIR_MQ_CHANNEL_H
|
||||
#define FAIR_MQ_CHANNEL_H
|
||||
|
||||
#include <fairmq/Message.h>
|
||||
#include <fairmq/Parts.h>
|
||||
#include <fairmq/Properties.h>
|
||||
#include <fairmq/Socket.h>
|
||||
#include <fairmq/TransportFactory.h>
|
||||
#include <fairmq/TransportEnum.h>
|
||||
#include <fairmq/UnmanagedRegion.h>
|
||||
|
||||
#include <cstdint> // int64_t
|
||||
#include <memory> // unique_ptr, shared_ptr
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
#include <vector>
|
||||
#include <FairMQChannel.h>
|
||||
|
||||
namespace fair::mq {
|
||||
|
||||
/**
|
||||
* @class Channel Channel.h <fairmq/Channel.h>
|
||||
* @brief Wrapper class for Socket and related methods
|
||||
*
|
||||
* The class is not thread-safe.
|
||||
*/
|
||||
class Channel
|
||||
{
|
||||
friend class Device;
|
||||
|
||||
public:
|
||||
/// Default constructor
|
||||
Channel();
|
||||
|
||||
/// Constructor
|
||||
/// @param name Channel name
|
||||
Channel(const std::string& name);
|
||||
|
||||
/// Constructor
|
||||
/// @param type Socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
|
||||
/// @param method Socket method (bind/connect)
|
||||
/// @param address Network address to bind/connect to (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
|
||||
Channel(const std::string& type, const std::string& method, const std::string& address);
|
||||
|
||||
/// Constructor
|
||||
/// @param name Channel name
|
||||
/// @param type Socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
|
||||
/// @param factory TransportFactory
|
||||
Channel(const std::string& name, const std::string& type, std::shared_ptr<TransportFactory> factory);
|
||||
|
||||
/// Constructor
|
||||
/// @param name Channel name
|
||||
/// @param type Socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
|
||||
/// @param method Socket method (bind/connect)
|
||||
/// @param address Network address to bind/connect to (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
|
||||
/// @param factory TransportFactory
|
||||
Channel(std::string name, std::string type, std::string method, std::string address, std::shared_ptr<TransportFactory> factory);
|
||||
|
||||
Channel(const std::string& name, int index, const Properties& properties);
|
||||
|
||||
/// Copy Constructor
|
||||
Channel(const Channel&);
|
||||
|
||||
/// Copy Constructor (with new name)
|
||||
Channel(const Channel&, std::string name);
|
||||
|
||||
/// Move constructor
|
||||
Channel(Channel&&) = default;
|
||||
|
||||
/// Assignment operator
|
||||
Channel& operator=(const Channel&);
|
||||
|
||||
/// Move assignment operator
|
||||
Channel& operator=(Channel&&) = default;
|
||||
|
||||
/// Destructor
|
||||
~Channel() = default;
|
||||
// { LOG(warn) << "Destroying channel '" << fName << "'"; }
|
||||
|
||||
struct ChannelConfigurationError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
Socket& GetSocket() const
|
||||
{
|
||||
assert(fSocket); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
|
||||
return *fSocket;
|
||||
}
|
||||
|
||||
bool Bind(const std::string& address)
|
||||
{
|
||||
fMethod = "bind";
|
||||
fAddress = address;
|
||||
return fSocket->Bind(address);
|
||||
}
|
||||
|
||||
bool Connect(const std::string& address)
|
||||
{
|
||||
fMethod = "connect";
|
||||
fAddress = address;
|
||||
return fSocket->Connect(address);
|
||||
}
|
||||
|
||||
/// Get channel name
|
||||
/// @return Returns full channel name (e.g. "data[0]")
|
||||
std::string GetName() const { return fName; }
|
||||
|
||||
/// Get channel prefix
|
||||
/// @return Returns channel prefix (e.g. "data" in "data[0]")
|
||||
std::string GetPrefix() const
|
||||
{
|
||||
std::string prefix = fName;
|
||||
prefix = prefix.erase(fName.rfind('['));
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/// Get channel index
|
||||
/// @return Returns channel index (e.g. 0 in "data[0]")
|
||||
std::string GetIndex() const
|
||||
{
|
||||
std::string indexStr = fName;
|
||||
indexStr.erase(indexStr.rfind(']'));
|
||||
indexStr.erase(0, indexStr.rfind('[') + 1);
|
||||
return indexStr;
|
||||
}
|
||||
|
||||
/// Get socket type
|
||||
/// @return Returns socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
|
||||
std::string GetType() const { return fType; }
|
||||
|
||||
/// Get socket method
|
||||
/// @return Returns socket method (bind/connect)
|
||||
std::string GetMethod() const { return fMethod; }
|
||||
|
||||
/// Get socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
|
||||
/// @return Returns socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
|
||||
std::string GetAddress() const { return fAddress; }
|
||||
|
||||
/// Get channel transport name ("default", "zeromq" or "shmem")
|
||||
/// @return Returns channel transport name (e.g. "default", "zeromq" or "shmem")
|
||||
std::string GetTransportName() const;
|
||||
|
||||
/// Get channel transport type
|
||||
/// @return Returns channel transport type
|
||||
mq::Transport GetTransportType() const;
|
||||
|
||||
/// Get socket send buffer size (in number of messages)
|
||||
/// @return Returns socket send buffer size (in number of messages)
|
||||
int GetSndBufSize() const { return fSndBufSize; }
|
||||
|
||||
/// Get socket receive buffer size (in number of messages)
|
||||
/// @return Returns socket receive buffer size (in number of messages)
|
||||
int GetRcvBufSize() const { return fRcvBufSize; }
|
||||
|
||||
/// Get socket kernel transmit send buffer size (in bytes)
|
||||
/// @return Returns socket kernel transmit send buffer size (in bytes)
|
||||
int GetSndKernelSize() const { return fSndKernelSize; }
|
||||
|
||||
/// Get socket kernel transmit receive buffer size (in bytes)
|
||||
/// @return Returns socket kernel transmit receive buffer size (in bytes)
|
||||
int GetRcvKernelSize() const { return fRcvKernelSize; }
|
||||
|
||||
/// Get socket default send timeout (in ms)
|
||||
/// @return Returns socket default send timeout (in ms)
|
||||
int GetSndTimeout() const { return fSndTimeoutMs; }
|
||||
|
||||
/// Get socket default receive timeout (in ms)
|
||||
/// @return Returns socket default receive timeout (in ms)
|
||||
int GetRcvTimeout() const { return fRcvTimeoutMs; }
|
||||
|
||||
/// Get linger duration (in milliseconds)
|
||||
/// @return Returns linger duration (in milliseconds)
|
||||
int GetLinger() const { return fLinger; }
|
||||
|
||||
/// Get socket rate logging interval (in seconds)
|
||||
/// @return Returns socket rate logging interval (in seconds)
|
||||
int GetRateLogging() const { return fRateLogging; }
|
||||
|
||||
/// Get start of the port range for automatic binding
|
||||
/// @return start of the port range
|
||||
int GetPortRangeMin() const { return fPortRangeMin; }
|
||||
|
||||
/// Get end of the port range for automatic binding
|
||||
/// @return end of the port range
|
||||
int GetPortRangeMax() const { return fPortRangeMax; }
|
||||
|
||||
/// Set automatic binding (pick random port if bind fails)
|
||||
/// @return true/false, true if automatic binding is enabled
|
||||
bool GetAutoBind() const { return fAutoBind; }
|
||||
|
||||
/// @par Thread Safety
|
||||
/// * @e Distinct @e objects: Safe.@n
|
||||
/// * @e Shared @e objects: Unsafe.
|
||||
auto GetNumberOfConnectedPeers() const
|
||||
{
|
||||
return fSocket ? fSocket->GetNumberOfConnectedPeers() : 0;
|
||||
}
|
||||
|
||||
/// Set channel name
|
||||
/// @param name Arbitrary channel name
|
||||
void UpdateName(const std::string& name) { fName = name; Invalidate(); }
|
||||
|
||||
/// Set socket type
|
||||
/// @param type Socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
|
||||
void UpdateType(const std::string& type) { fType = type; Invalidate(); }
|
||||
|
||||
/// Set socket method
|
||||
/// @param method Socket method (bind/connect)
|
||||
void UpdateMethod(const std::string& method) { fMethod = method; Invalidate(); }
|
||||
|
||||
/// Set socket address
|
||||
/// @param Socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
|
||||
void UpdateAddress(const std::string& address) { fAddress = address; Invalidate(); }
|
||||
|
||||
/// Set channel transport
|
||||
/// @param transport transport string ("default", "zeromq" or "shmem")
|
||||
void UpdateTransport(const std::string& transport);
|
||||
|
||||
/// Set socket send buffer size
|
||||
/// @param sndBufSize Socket send buffer size (in number of messages)
|
||||
void UpdateSndBufSize(int sndBufSize) { fSndBufSize = sndBufSize; Invalidate(); }
|
||||
|
||||
/// Set socket receive buffer size
|
||||
/// @param rcvBufSize Socket receive buffer size (in number of messages)
|
||||
void UpdateRcvBufSize(int rcvBufSize) { fRcvBufSize = rcvBufSize; Invalidate(); }
|
||||
|
||||
/// Set socket kernel transmit send buffer size (in bytes)
|
||||
/// @param sndKernelSize Socket send buffer size (in bytes)
|
||||
void UpdateSndKernelSize(int sndKernelSize) { fSndKernelSize = sndKernelSize; Invalidate(); }
|
||||
|
||||
/// Set socket kernel transmit receive buffer size (in bytes)
|
||||
/// @param rcvKernelSize Socket receive buffer size (in bytes)
|
||||
void UpdateRcvKernelSize(int rcvKernelSize) { fRcvKernelSize = rcvKernelSize; Invalidate(); }
|
||||
|
||||
/// Set socket default send timeout (in ms)
|
||||
/// @param sndTimeoutMs Socket default send timeout (in ms)
|
||||
void UpdateSndTimeout(int sndTimeoutMs) { fSndTimeoutMs = sndTimeoutMs; Invalidate(); }
|
||||
|
||||
/// Set socket default receive timeout (in ms)
|
||||
/// @param rcvTimeoutMs Socket default receive timeout (in ms)
|
||||
void UpdateRcvTimeout(int rcvTimeoutMs) { fRcvTimeoutMs = rcvTimeoutMs; Invalidate(); }
|
||||
|
||||
/// Set linger duration (in milliseconds)
|
||||
/// @param duration linger duration (in milliseconds)
|
||||
void UpdateLinger(int duration) { fLinger = duration; Invalidate(); }
|
||||
|
||||
/// Set socket rate logging interval (in seconds)
|
||||
/// @param rateLogging Socket rate logging interval (in seconds)
|
||||
void UpdateRateLogging(int rateLogging) { fRateLogging = rateLogging; Invalidate(); }
|
||||
|
||||
/// Set start of the port range for automatic binding
|
||||
/// @param minPort start of the port range
|
||||
void UpdatePortRangeMin(int minPort) { fPortRangeMin = minPort; Invalidate(); }
|
||||
|
||||
/// Set end of the port range for automatic binding
|
||||
/// @param maxPort end of the port range
|
||||
void UpdatePortRangeMax(int maxPort) { fPortRangeMax = maxPort; Invalidate(); }
|
||||
|
||||
/// Set automatic binding (pick random port if bind fails)
|
||||
/// @param autobind true/false, true to enable automatic binding
|
||||
void UpdateAutoBind(bool autobind) { fAutoBind = autobind; Invalidate(); }
|
||||
|
||||
/// Checks if the configured channel settings are valid (checks the validity parameter, without running full validation (as oposed to ValidateChannel()))
|
||||
/// @return true if channel settings are valid, false otherwise.
|
||||
bool IsValid() const { return fValid; }
|
||||
|
||||
/// Validates channel configuration
|
||||
/// @return true if channel settings are valid, false otherwise.
|
||||
bool Validate();
|
||||
|
||||
void Init();
|
||||
|
||||
bool ConnectEndpoint(const std::string& endpoint);
|
||||
|
||||
bool BindEndpoint(std::string& endpoint);
|
||||
|
||||
/// invalidates the channel (requires validation to be used again).
|
||||
void Invalidate() { fValid = false; }
|
||||
|
||||
/// Send message(s) to the socket queue.
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param sndTimeoutMs send timeout in ms.
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot send).
|
||||
/// If not provided, default timeout will be taken.
|
||||
/// @return Number of bytes that have been queued,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M, typename... Timeout>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, Timeout&&... sndTimeoutMs)
|
||||
{
|
||||
static_assert(sizeof...(sndTimeoutMs) <= 1, "Send called with too many arguments");
|
||||
|
||||
CheckSendCompatibility(m);
|
||||
int t = fSndTimeoutMs;
|
||||
if constexpr (sizeof...(sndTimeoutMs) == 1) {
|
||||
t = {sndTimeoutMs...};
|
||||
}
|
||||
return fSocket->Send(m, t);
|
||||
}
|
||||
|
||||
/// Receive message(s) from the socket queue.
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param rcvTimeoutMs receive timeout in ms.
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot receive).
|
||||
/// If not provided, default timeout will be taken.
|
||||
/// @return Number of bytes that have been received,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M, typename... Timeout>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, Timeout&&... rcvTimeoutMs)
|
||||
{
|
||||
static_assert(sizeof...(rcvTimeoutMs) <= 1, "Receive called with too many arguments");
|
||||
|
||||
CheckReceiveCompatibility(m);
|
||||
int t = fRcvTimeoutMs;
|
||||
if constexpr (sizeof...(rcvTimeoutMs) == 1) {
|
||||
t = {rcvTimeoutMs...};
|
||||
}
|
||||
return fSocket->Receive(m, t);
|
||||
}
|
||||
|
||||
unsigned long GetBytesTx() const { return fSocket->GetBytesTx(); }
|
||||
unsigned long GetBytesRx() const { return fSocket->GetBytesRx(); }
|
||||
unsigned long GetMessagesTx() const { return fSocket->GetMessagesTx(); }
|
||||
unsigned long GetMessagesRx() const { return fSocket->GetMessagesRx(); }
|
||||
|
||||
auto Transport() -> TransportFactory* { return fTransportFactory.get(); };
|
||||
|
||||
template<typename... Args>
|
||||
MessagePtr NewMessage(Args&&... args)
|
||||
{
|
||||
return Transport()->CreateMessage(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MessagePtr NewSimpleMessage(const T& data)
|
||||
{
|
||||
return Transport()->NewSimpleMessage(data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MessagePtr NewStaticMessage(const T& data)
|
||||
{
|
||||
return Transport()->NewStaticMessage(data);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
UnmanagedRegionPtr NewUnmanagedRegion(Args&&... args)
|
||||
{
|
||||
return Transport()->CreateUnmanagedRegion(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static constexpr mq::Transport DefaultTransportType = mq::Transport::DEFAULT;
|
||||
static constexpr const char* DefaultTransportName = "default";
|
||||
static constexpr const char* DefaultName = "";
|
||||
static constexpr const char* DefaultType = "unspecified";
|
||||
static constexpr const char* DefaultMethod = "unspecified";
|
||||
static constexpr const char* DefaultAddress = "unspecified";
|
||||
static constexpr int DefaultSndBufSize = 1000;
|
||||
static constexpr int DefaultRcvBufSize = 1000;
|
||||
static constexpr int DefaultSndKernelSize = 0;
|
||||
static constexpr int DefaultRcvKernelSize = 0;
|
||||
static constexpr int DefaultSndTimeoutMs = -1;
|
||||
static constexpr int DefaultRcvTimeoutMs = -1;
|
||||
static constexpr int DefaultLinger = 500;
|
||||
static constexpr int DefaultRateLogging = 1;
|
||||
static constexpr int DefaultPortRangeMin = 22000;
|
||||
static constexpr int DefaultPortRangeMax = 23000;
|
||||
#ifdef FAIRMQ_CHANNEL_DEFAULT_AUTOBIND
|
||||
static constexpr bool DefaultAutoBind = FAIRMQ_CHANNEL_DEFAULT_AUTOBIND;
|
||||
#else
|
||||
static constexpr bool DefaultAutoBind = true;
|
||||
#endif
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Channel& ch)
|
||||
{
|
||||
return os << "name: " << ch.fName
|
||||
<< ", type: " << ch.fType
|
||||
<< ", method: " << ch.fMethod
|
||||
<< ", address: " << ch.fAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<TransportFactory> fTransportFactory;
|
||||
mq::Transport fTransportType;
|
||||
std::unique_ptr<Socket> fSocket;
|
||||
|
||||
std::string fName;
|
||||
std::string fType;
|
||||
std::string fMethod;
|
||||
std::string fAddress;
|
||||
int fSndBufSize;
|
||||
int fRcvBufSize;
|
||||
int fSndKernelSize;
|
||||
int fRcvKernelSize;
|
||||
int fSndTimeoutMs;
|
||||
int fRcvTimeoutMs;
|
||||
int fLinger;
|
||||
int fRateLogging;
|
||||
int fPortRangeMin;
|
||||
int fPortRangeMax;
|
||||
bool fAutoBind;
|
||||
|
||||
bool fValid;
|
||||
|
||||
bool fMultipart;
|
||||
|
||||
void CheckSendCompatibility(MessagePtr& msg)
|
||||
{
|
||||
if (fTransportType != msg->GetType()) {
|
||||
if (msg->GetSize() > 0) {
|
||||
MessagePtr msgWrapper(NewMessage(
|
||||
msg->GetData(),
|
||||
msg->GetSize(),
|
||||
[](void* /*data*/, void* _msg) { delete static_cast<Message*>(_msg); },
|
||||
msg.get()
|
||||
));
|
||||
msg.release();
|
||||
msg = std::move(msgWrapper);
|
||||
} else {
|
||||
MessagePtr newMsg(NewMessage());
|
||||
msg = std::move(newMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckSendCompatibility(Parts& parts) { CheckSendCompatibility(parts.fParts); }
|
||||
void CheckSendCompatibility(Parts::container & msgVec)
|
||||
{
|
||||
for (auto& msg : msgVec) {
|
||||
if (fTransportType != msg->GetType()) {
|
||||
if (msg->GetSize() > 0) {
|
||||
MessagePtr msgWrapper(NewMessage(
|
||||
msg->GetData(),
|
||||
msg->GetSize(),
|
||||
[](void* /*data*/, void* _msg) { delete static_cast<Message*>(_msg); },
|
||||
msg.get()
|
||||
));
|
||||
msg.release();
|
||||
msg = std::move(msgWrapper);
|
||||
} else {
|
||||
MessagePtr newMsg(NewMessage());
|
||||
msg = std::move(newMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckReceiveCompatibility(MessagePtr& msg)
|
||||
{
|
||||
if (fTransportType != msg->GetType()) {
|
||||
MessagePtr newMsg(NewMessage());
|
||||
msg = std::move(newMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckReceiveCompatibility(Parts& parts) { CheckReceiveCompatibility(parts.fParts); }
|
||||
void CheckReceiveCompatibility(Parts::container& msgVec)
|
||||
{
|
||||
for (auto& msg : msgVec) {
|
||||
if (fTransportType != msg->GetType()) {
|
||||
|
||||
MessagePtr newMsg(NewMessage());
|
||||
msg = std::move(newMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitTransport(std::shared_ptr<TransportFactory> factory)
|
||||
{
|
||||
fTransportFactory = factory;
|
||||
fTransportType = factory->GetType();
|
||||
}
|
||||
};
|
||||
using Channel = FairMQChannel;
|
||||
|
||||
} // namespace fair::mq
|
||||
|
||||
using FairMQChannel [[deprecated("Use fair::mq::Channel")]] = fair::mq::Channel;
|
||||
|
||||
#endif // FAIR_MQ_CHANNEL_H
|
||||
|
|
678
fairmq/Device.h
678
fairmq/Device.h
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2021-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
|
@ -9,683 +9,13 @@
|
|||
#ifndef FAIR_MQ_DEVICE_H
|
||||
#define FAIR_MQ_DEVICE_H
|
||||
|
||||
// FairMQ
|
||||
#include <fairmq/Channel.h>
|
||||
#include <fairmq/Error.h>
|
||||
#include <fairmq/Message.h>
|
||||
#include <fairmq/Parts.h>
|
||||
#include <fairmq/ProgOptions.h>
|
||||
#include <fairmq/StateMachine.h>
|
||||
#include <fairmq/StateQueue.h>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <fairmq/TransportFactory.h>
|
||||
#include <fairmq/TransportEnum.h>
|
||||
#include <fairmq/UnmanagedRegion.h>
|
||||
#include <FairMQDevice.h>
|
||||
|
||||
// logger
|
||||
#include <fairlogger/Logger.h>
|
||||
|
||||
// std
|
||||
#include <algorithm> // find
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory> // unique_ptr
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility> // pair
|
||||
#include <vector>
|
||||
|
||||
namespace fair::mq {
|
||||
|
||||
using ChannelMap = std::unordered_map<std::string, std::vector<Channel>>;
|
||||
|
||||
struct OngoingTransition : std::runtime_error
|
||||
namespace fair::mq
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
using InputMsgCallback = std::function<bool(MessagePtr&, int)>;
|
||||
|
||||
using InputMultipartCallback = std::function<bool(Parts&, int)>;
|
||||
|
||||
class Device
|
||||
{
|
||||
friend class Channel;
|
||||
|
||||
public:
|
||||
Device();
|
||||
Device(ProgOptions& config);
|
||||
Device(tools::Version version);
|
||||
Device(ProgOptions& config, tools::Version version);
|
||||
|
||||
private:
|
||||
Device(ProgOptions* config, tools::Version version);
|
||||
|
||||
public:
|
||||
Device(const Device&) = delete;
|
||||
Device(Device&&) = delete;
|
||||
Device& operator=(const Device&) = delete;
|
||||
Device& operator=(Device&&) = delete;
|
||||
virtual ~Device();
|
||||
|
||||
/// Outputs the socket transfer rates
|
||||
virtual void LogSocketRates();
|
||||
|
||||
template<typename Serializer, typename DataType, typename... Args>
|
||||
[[deprecated]] void Serialize(Message& msg, DataType&& data, Args&&... args) const
|
||||
{
|
||||
Serializer().Serialize(msg, std::forward<DataType>(data), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Deserializer, typename DataType, typename... Args>
|
||||
[[deprecated]] void Deserialize(Message& msg, DataType&& data, Args&&... args) const
|
||||
{
|
||||
Deserializer().Deserialize(msg, std::forward<DataType>(data), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Send `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @return Number of queued bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, const std::string& channel, const int index = 0)
|
||||
{
|
||||
return GetChannel(channel, index).Send(m);
|
||||
}
|
||||
|
||||
/// Receive `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @return Number of received bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, const std::string& channel, const int index = 0)
|
||||
{
|
||||
return GetChannel(channel, index).Receive(m);
|
||||
}
|
||||
|
||||
/// Send `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param sndTimeoutMs send timeout in ms,
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change)),
|
||||
/// 0 will not wait (return immediately if cannot send)
|
||||
/// @return Number of queued bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Send(M& m, const std::string& channel, const int index, int sndTimeoutMs)
|
||||
{
|
||||
return GetChannel(channel, index).Send(m, sndTimeoutMs);
|
||||
}
|
||||
|
||||
/// Receive `m` on `chan` at index `i`
|
||||
/// @param m reference to MessagePtr/Parts/vector<MessagePtr>
|
||||
/// @param chan channel name
|
||||
/// @param i channel index
|
||||
/// @param rcvTimeoutMs receive timeout in ms,
|
||||
/// -1 will wait forever (or until interrupt (e.g. via state change),
|
||||
/// 0 will not wait (return immediately if cannot receive)
|
||||
/// @return Number of received bytes,
|
||||
/// TransferCode::timeout if timed out,
|
||||
/// TransferCode::error if there was an error,
|
||||
/// TransferCode::interrupted if interrupted (e.g. by requested state change)
|
||||
template<typename M>
|
||||
std::enable_if_t<is_transferrable<M>::value, int64_t>
|
||||
Receive(M& m, const std::string& channel, const int index, int rcvTimeoutMs)
|
||||
{
|
||||
return GetChannel(channel, index).Receive(m, rcvTimeoutMs);
|
||||
}
|
||||
|
||||
/// @brief Getter for default transport factory
|
||||
auto Transport() const -> TransportFactory* { return fTransportFactory.get(); }
|
||||
|
||||
// creates message with the default device transport
|
||||
template<typename... Args>
|
||||
MessagePtr NewMessage(Args&&... args)
|
||||
{
|
||||
return Transport()->CreateMessage(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// creates message with the transport of the specified channel
|
||||
template<typename... Args>
|
||||
MessagePtr NewMessageFor(const std::string& channel, int index, Args&&... args)
|
||||
{
|
||||
return GetChannel(channel, index).NewMessage(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// creates a message that will not be cleaned up after transfer, with the default device
|
||||
// transport
|
||||
template<typename T>
|
||||
MessagePtr NewStaticMessage(const T& data)
|
||||
{
|
||||
return Transport()->NewStaticMessage(data);
|
||||
}
|
||||
|
||||
// creates a message that will not be cleaned up after transfer, with the transport of the
|
||||
// specified channel
|
||||
template<typename T>
|
||||
MessagePtr NewStaticMessageFor(const std::string& channel, int index, const T& data)
|
||||
{
|
||||
return GetChannel(channel, index).NewStaticMessage(data);
|
||||
}
|
||||
|
||||
// creates a message with a copy of the provided data, with the default device transport
|
||||
template<typename T>
|
||||
MessagePtr NewSimpleMessage(const T& data)
|
||||
{
|
||||
return Transport()->NewSimpleMessage(data);
|
||||
}
|
||||
|
||||
// creates a message with a copy of the provided data, with the transport of the specified
|
||||
// channel
|
||||
template<typename T>
|
||||
MessagePtr NewSimpleMessageFor(const std::string& channel, int index, const T& data)
|
||||
{
|
||||
return GetChannel(channel, index).NewSimpleMessage(data);
|
||||
}
|
||||
|
||||
// creates unamanaged region with the default device transport
|
||||
template<typename... Args>
|
||||
UnmanagedRegionPtr NewUnmanagedRegion(Args&&... args)
|
||||
{
|
||||
return Transport()->CreateUnmanagedRegion(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// creates unmanaged region with the transport of the specified channel
|
||||
template<typename... Args>
|
||||
UnmanagedRegionPtr NewUnmanagedRegionFor(const std::string& channel, int index, Args&&... args)
|
||||
{
|
||||
return GetChannel(channel, index).NewUnmanagedRegion(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
PollerPtr NewPoller(const Ts&... inputs)
|
||||
{
|
||||
std::vector<std::string> chans{inputs...};
|
||||
|
||||
// if more than one channel provided, check compatibility
|
||||
if (chans.size() > 1) {
|
||||
mq::Transport type = GetChannel(chans.at(0), 0).Transport()->GetType();
|
||||
|
||||
for (unsigned int i = 1; i < chans.size(); ++i) {
|
||||
if (type != GetChannel(chans.at(i), 0).Transport()->GetType()) {
|
||||
LOG(error) << "poller failed: different transports within same poller are not "
|
||||
"yet supported. Going to ERROR state.";
|
||||
throw std::runtime_error("poller failed: different transports within same "
|
||||
"poller are not yet supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetChannel(chans.at(0), 0).Transport()->CreatePoller(GetChannels(), chans);
|
||||
}
|
||||
|
||||
PollerPtr NewPoller(const std::vector<Channel*>& channels)
|
||||
{
|
||||
// if more than one channel provided, check compatibility
|
||||
if (channels.size() > 1) {
|
||||
mq::Transport type = channels.at(0)->Transport()->GetType();
|
||||
|
||||
for (unsigned int i = 1; i < channels.size(); ++i) {
|
||||
if (type != channels.at(i)->Transport()->GetType()) {
|
||||
LOG(error) << "poller failed: different transports within same poller are not "
|
||||
"yet supported. Going to ERROR state.";
|
||||
throw std::runtime_error("poller failed: different transports within same "
|
||||
"poller are not yet supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channels.at(0)->Transport()->CreatePoller(channels);
|
||||
}
|
||||
|
||||
/// Adds a transport to the device if it doesn't exist
|
||||
/// @param transport Transport string ("zeromq"/"shmem")
|
||||
std::shared_ptr<TransportFactory> AddTransport(mq::Transport transport);
|
||||
|
||||
/// Assigns config to the device
|
||||
void SetConfig(ProgOptions& config);
|
||||
/// Get pointer to the config
|
||||
ProgOptions* GetConfig() const { return fConfig; }
|
||||
|
||||
// overload to easily bind member functions
|
||||
template<typename T>
|
||||
void OnData(const std::string& channelName,
|
||||
bool (T::*memberFunction)(MessagePtr& msg, int index))
|
||||
{
|
||||
fDataCallbacks = true;
|
||||
fMsgInputs.insert(
|
||||
std::make_pair(channelName, [this, memberFunction](MessagePtr& msg, int index) {
|
||||
return (static_cast<T*>(this)->*memberFunction)(msg, index);
|
||||
}));
|
||||
|
||||
if (find(fInputChannelKeys.begin(), fInputChannelKeys.end(), channelName)
|
||||
== fInputChannelKeys.end()) {
|
||||
fInputChannelKeys.push_back(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
void OnData(const std::string& channelName, InputMsgCallback callback)
|
||||
{
|
||||
fDataCallbacks = true;
|
||||
fMsgInputs.insert(make_pair(channelName, callback));
|
||||
|
||||
if (find(fInputChannelKeys.begin(), fInputChannelKeys.end(), channelName)
|
||||
== fInputChannelKeys.end()) {
|
||||
fInputChannelKeys.push_back(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
// overload to easily bind member functions
|
||||
template<typename T>
|
||||
void OnData(const std::string& channelName, bool (T::*memberFunction)(Parts& parts, int index))
|
||||
{
|
||||
fDataCallbacks = true;
|
||||
fMultipartInputs.insert(
|
||||
std::make_pair(channelName, [this, memberFunction](Parts& parts, int index) {
|
||||
return (static_cast<T*>(this)->*memberFunction)(parts, index);
|
||||
}));
|
||||
|
||||
if (find(fInputChannelKeys.begin(), fInputChannelKeys.end(), channelName)
|
||||
== fInputChannelKeys.end()) {
|
||||
fInputChannelKeys.push_back(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
void OnData(const std::string& channelName, InputMultipartCallback callback)
|
||||
{
|
||||
fDataCallbacks = true;
|
||||
fMultipartInputs.insert(make_pair(channelName, callback));
|
||||
|
||||
if (find(fInputChannelKeys.begin(), fInputChannelKeys.end(), channelName)
|
||||
== fInputChannelKeys.end()) {
|
||||
fInputChannelKeys.push_back(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
Channel& GetChannel(const std::string& channelName, const int index = 0)
|
||||
try {
|
||||
return GetChannels().at(channelName).at(index);
|
||||
} catch (const std::out_of_range& oor) {
|
||||
LOG(error) << "GetChannel(): '" << channelName << "[" << index << "]' does not exist.";
|
||||
throw;
|
||||
}
|
||||
|
||||
size_t GetNumSubChannels(const std::string& channelName)
|
||||
try {
|
||||
return GetChannels().at(channelName).size();
|
||||
} catch (const std::out_of_range& oor) {
|
||||
LOG(error) << "GetNumSubChannels(): '" << channelName << "' does not exist.";
|
||||
throw;
|
||||
}
|
||||
|
||||
/// @brief Get numbers of connected peers for the given channel
|
||||
/// @param name channel name
|
||||
/// @param index sub-channel
|
||||
unsigned long GetNumberOfConnectedPeers(const std::string& channelName, int index = 0)
|
||||
{
|
||||
return GetChannel(channelName, index).GetNumberOfConnectedPeers();
|
||||
}
|
||||
|
||||
virtual void RegisterChannelEndpoints() {}
|
||||
|
||||
bool RegisterChannelEndpoint(const std::string& channelName,
|
||||
uint16_t minNumSubChannels = 1,
|
||||
uint16_t maxNumSubChannels = 1)
|
||||
{
|
||||
bool ok = fChannelRegistry
|
||||
.insert(std::make_pair(channelName,
|
||||
std::make_pair(minNumSubChannels, maxNumSubChannels)))
|
||||
.second;
|
||||
if (!ok) {
|
||||
LOG(warn) << "Registering channel: name already registered: \"" << channelName << "\"";
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void PrintRegisteredChannels()
|
||||
{
|
||||
if (fChannelRegistry.empty()) {
|
||||
LOGV(info, verylow) << "no channels registered.";
|
||||
} else {
|
||||
for (const auto& c : fChannelRegistry) {
|
||||
LOGV(info, verylow) << c.first << ":" << c.second.first << ":" << c.second.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetId(const std::string& id) { fId = id; }
|
||||
std::string GetId() { return fId; }
|
||||
|
||||
const tools::Version GetVersion() const { return fVersion; }
|
||||
|
||||
void SetNumIoThreads(int numIoThreads) { fConfig->SetProperty("io-threads", numIoThreads); }
|
||||
int GetNumIoThreads() const
|
||||
{
|
||||
return fConfig->GetProperty<int>("io-threads", DefaultIOThreads);
|
||||
}
|
||||
|
||||
void SetNetworkInterface(const std::string& networkInterface)
|
||||
{
|
||||
fConfig->SetProperty("network-interface", networkInterface);
|
||||
}
|
||||
std::string GetNetworkInterface() const
|
||||
{
|
||||
return fConfig->GetProperty<std::string>("network-interface", DefaultNetworkInterface);
|
||||
}
|
||||
|
||||
void SetDefaultTransport(const std::string& name) { fConfig->SetProperty("transport", name); }
|
||||
std::string GetDefaultTransport() const
|
||||
{
|
||||
return fConfig->GetProperty<std::string>("transport", DefaultTransportName);
|
||||
}
|
||||
|
||||
void SetInitTimeoutInS(int initTimeoutInS)
|
||||
{
|
||||
fConfig->SetProperty("init-timeout", initTimeoutInS);
|
||||
}
|
||||
int GetInitTimeoutInS() const
|
||||
{
|
||||
return fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout);
|
||||
}
|
||||
|
||||
/// Sets the default transport for the device
|
||||
/// @param transport Transport string ("zeromq"/"shmem")
|
||||
void SetTransport(const std::string& transport)
|
||||
{
|
||||
fConfig->SetProperty("transport", transport);
|
||||
}
|
||||
/// Gets the default transport name
|
||||
std::string GetTransportName() const
|
||||
{
|
||||
return fConfig->GetProperty<std::string>("transport", DefaultTransportName);
|
||||
}
|
||||
|
||||
void SetRawCmdLineArgs(const std::vector<std::string>& args) { fRawCmdLineArgs = args; }
|
||||
std::vector<std::string> GetRawCmdLineArgs() const { return fRawCmdLineArgs; }
|
||||
|
||||
void RunStateMachine() { fStateMachine.ProcessWork(); };
|
||||
|
||||
/// Wait for the supplied amount of time or for interruption.
|
||||
/// If interrupted, returns false, otherwise true.
|
||||
/// @param duration wait duration
|
||||
template<typename Rep, typename Period>
|
||||
bool WaitFor(std::chrono::duration<Rep, Period> const& duration)
|
||||
{
|
||||
return !fStateMachine.WaitForPendingStateFor(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TransportFactory> fTransportFactory; ///< Default transport factory
|
||||
std::unordered_map<mq::Transport, std::shared_ptr<TransportFactory>>
|
||||
fTransports; ///< Container for transports
|
||||
|
||||
public:
|
||||
[[deprecated("Use GetChannels() instead.")]]
|
||||
std::unordered_map<std::string, std::vector<Channel>> fChannels; ///< Device channels
|
||||
std::unordered_map<std::string, std::vector<Channel>>& GetChannels()
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
return fChannels;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
std::unordered_map<std::string, std::vector<Channel>> const& GetChannels() const
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
return fChannels;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
std::unique_ptr<ProgOptions> fInternalConfig; ///< Internal program options configuration
|
||||
ProgOptions* fConfig; ///< Pointer to config (internal or external)
|
||||
|
||||
void AddChannel(const std::string& name, Channel&& channel)
|
||||
{
|
||||
fConfig->AddChannel(name, channel);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string fId; ///< Device ID
|
||||
|
||||
/// Additional user initialization (can be overloaded in child classes). Prefer to use
|
||||
/// InitTask().
|
||||
virtual void Init() {}
|
||||
|
||||
virtual void Bind() {}
|
||||
|
||||
virtual void Connect() {}
|
||||
|
||||
/// Task initialization (can be overloaded in child classes)
|
||||
virtual void InitTask() {}
|
||||
|
||||
/// Runs the device (to be overloaded in child classes)
|
||||
virtual void Run() {}
|
||||
|
||||
/// Called in the RUNNING state once before executing the Run()/ConditionalRun() method
|
||||
virtual void PreRun() {}
|
||||
|
||||
/// Called during RUNNING state repeatedly until it returns false or device state changes
|
||||
virtual bool ConditionalRun() { return false; }
|
||||
|
||||
/// Called in the RUNNING state once after executing the Run()/ConditionalRun() method
|
||||
virtual void PostRun() {}
|
||||
|
||||
/// Resets the user task (to be overloaded in child classes)
|
||||
virtual void ResetTask() {}
|
||||
|
||||
/// Resets the device (can be overloaded in child classes)
|
||||
virtual void Reset() {}
|
||||
|
||||
public:
|
||||
/// @brief Request a device state transition
|
||||
/// @param transition state transition
|
||||
/// @return whether the transition was successfully scheduled
|
||||
///
|
||||
/// The state transition may not happen immediately, but when the current state evaluates the
|
||||
/// pending transition event and terminates. In other words, the device states are scheduled
|
||||
/// cooperatively.
|
||||
[[nodiscard]] bool ChangeState(const Transition transition)
|
||||
{
|
||||
return fStateMachine.ChangeState(transition);
|
||||
}
|
||||
/// @brief Request a device state transition
|
||||
/// @param transition state transition
|
||||
/// @return whether the transition was successfully scheduled
|
||||
///
|
||||
/// The state transition may not happen immediately, but when the current state evaluates the
|
||||
/// pending transition event and terminates. In other words, the device states are scheduled
|
||||
/// cooperatively.
|
||||
[[nodiscard]] bool ChangeState(const std::string& transition)
|
||||
{
|
||||
return fStateMachine.ChangeState(GetTransition(transition));
|
||||
}
|
||||
/// @brief Request a device state transition
|
||||
/// @param transition state transition
|
||||
/// @throws when the transition could not have been scheduled
|
||||
///
|
||||
/// Throwing version of Device::ChangeState().
|
||||
void ChangeStateOrThrow(Transition transition)
|
||||
{
|
||||
if(!ChangeState(transition)) {
|
||||
auto const err = MakeErrorCode(ErrorCode::DeviceChangeStateFailed);
|
||||
throw std::system_error(err.value(),
|
||||
err.category(),
|
||||
tools::ToString("Invalid transition: ", transition));
|
||||
}
|
||||
}
|
||||
/// @brief Request a device state transition
|
||||
/// @param transition state transition
|
||||
/// @throws when the transition could not have been scheduled
|
||||
///
|
||||
/// Throwing version of Device::ChangeState().
|
||||
void ChangeStateOrThrow(std::string const& transition)
|
||||
{
|
||||
ChangeStateOrThrow(GetTransition(transition));
|
||||
}
|
||||
|
||||
/// @brief waits for the next state (any) to occur
|
||||
State WaitForNextState() { return fStateQueue.WaitForNext(); }
|
||||
/// @brief waits for the specified state to occur
|
||||
/// @param state state to wait for
|
||||
void WaitForState(State state) { fStateQueue.WaitForState(state); }
|
||||
/// @brief waits for the specified state to occur
|
||||
/// @param state state to wait for
|
||||
void WaitForState(const std::string& state) { WaitForState(GetState(state)); }
|
||||
|
||||
/// @brief Subscribe with a callback to state changes
|
||||
/// @param key id to identify your subscription
|
||||
/// @param callback callback (called with the new state as the parameter)
|
||||
///
|
||||
/// The callback is called at the beginning of a new state.
|
||||
/// The callback is called from the thread the state is running in.
|
||||
void SubscribeToStateChange(const std::string& key, std::function<void(const State)> callback)
|
||||
{
|
||||
fStateMachine.SubscribeToStateChange(key, callback);
|
||||
}
|
||||
/// @brief Unsubscribe from state changes
|
||||
/// @param key id (that was used when subscribing)
|
||||
void UnsubscribeFromStateChange(const std::string& key)
|
||||
{
|
||||
fStateMachine.UnsubscribeFromStateChange(key);
|
||||
}
|
||||
|
||||
/// @brief Subscribe with a callback to incoming state transitions
|
||||
/// @param key id to identify your subscription
|
||||
/// @param callback callback (called with the incoming transition as the parameter)
|
||||
/// The callback is called when new transition is initiated.
|
||||
/// The callback is called from the thread that initiates the transition (via ChangeState).
|
||||
void SubscribeToNewTransition(const std::string& key,
|
||||
std::function<void(const Transition)> callback)
|
||||
{
|
||||
fStateMachine.SubscribeToNewTransition(key, callback);
|
||||
}
|
||||
/// @brief Unsubscribe from state transitions
|
||||
/// @param key id (that was used when subscribing)
|
||||
void UnsubscribeFromNewTransition(const std::string& key)
|
||||
{
|
||||
fStateMachine.UnsubscribeFromNewTransition(key);
|
||||
}
|
||||
|
||||
/// @brief Returns true if a new state has been requested, signaling the current handler to
|
||||
/// stop.
|
||||
bool NewStatePending() const { return fStateMachine.NewStatePending(); }
|
||||
|
||||
/// @brief Returns the current state
|
||||
State GetCurrentState() const { return fStateMachine.GetCurrentState(); }
|
||||
/// @brief Returns the name of the current state as a string
|
||||
std::string GetCurrentStateName() const { return fStateMachine.GetCurrentStateName(); }
|
||||
|
||||
/// @brief Returns name of the given state as a string
|
||||
/// @param state state
|
||||
[[deprecated("Use fair::mq::GetStateName from <fairmq/States.h> directly")]]
|
||||
static std::string GetStateName(State state) { return fair::mq::GetStateName(state); }
|
||||
/// @brief Returns name of the given transition as a string
|
||||
/// @param transition transition
|
||||
[[deprecated("Use fair::mq::GetTransitionName from <fairmq/States.h> directly")]]
|
||||
static std::string GetTransitionName(Transition transition)
|
||||
{
|
||||
return fair::mq::GetTransitionName(transition);
|
||||
}
|
||||
|
||||
static constexpr const char* DefaultId = "";
|
||||
static constexpr int DefaultIOThreads = 1;
|
||||
static constexpr const char* DefaultTransportName = "zeromq";
|
||||
static constexpr mq::Transport DefaultTransportType = mq::Transport::ZMQ;
|
||||
static constexpr const char* DefaultNetworkInterface = "default";
|
||||
static constexpr int DefaultInitTimeout = 120;
|
||||
static constexpr float DefaultRate = 0.;
|
||||
static constexpr const char* DefaultSession = "default";
|
||||
|
||||
private:
|
||||
mq::Transport fDefaultTransportType; ///< Default transport for the device
|
||||
StateMachine fStateMachine;
|
||||
|
||||
/// Handles the initialization
|
||||
void InitWrapper();
|
||||
/// Initializes binding channels
|
||||
void BindWrapper();
|
||||
/// Initializes connecting channels
|
||||
void ConnectWrapper();
|
||||
/// Handles the InitTask() method
|
||||
void InitTaskWrapper();
|
||||
/// Handles the Run() method
|
||||
void RunWrapper();
|
||||
/// Handles the ResetTask() method
|
||||
void ResetTaskWrapper();
|
||||
/// Handles the Reset() method
|
||||
void ResetWrapper();
|
||||
|
||||
/// Notifies transports to cease any blocking activity
|
||||
void InterruptTransports();
|
||||
|
||||
/// Notifies transports to resume any blocking activity
|
||||
void ResumeTransports();
|
||||
|
||||
/// Shuts down the transports and the device
|
||||
void Exit() {}
|
||||
|
||||
/// Attach (bind/connect) channels in the list
|
||||
void AttachChannels(std::vector<Channel*>& chans);
|
||||
bool AttachChannel(Channel& ch);
|
||||
|
||||
void HandleSingleChannelInput();
|
||||
void HandleMultipleChannelInput();
|
||||
void HandleMultipleTransportInput();
|
||||
void PollForTransport(const TransportFactory* factory,
|
||||
const std::vector<std::string>& channelKeys);
|
||||
|
||||
bool HandleMsgInput(const std::string& chName, const InputMsgCallback& callback, int i);
|
||||
bool HandleMultipartInput(const std::string& chName,
|
||||
const InputMultipartCallback& callback,
|
||||
int i);
|
||||
|
||||
std::vector<Channel*> fUninitializedBindingChannels;
|
||||
std::vector<Channel*> fUninitializedConnectingChannels;
|
||||
|
||||
bool fDataCallbacks;
|
||||
std::unordered_map<std::string, InputMsgCallback> fMsgInputs;
|
||||
std::unordered_map<std::string, InputMultipartCallback> fMultipartInputs;
|
||||
std::unordered_map<mq::Transport, std::vector<std::string>> fMultitransportInputs;
|
||||
std::unordered_map<std::string, std::pair<uint16_t, uint16_t>> fChannelRegistry;
|
||||
std::vector<std::string> fInputChannelKeys;
|
||||
std::mutex fMultitransportMutex;
|
||||
std::atomic<bool> fMultitransportProceed;
|
||||
|
||||
const tools::Version fVersion;
|
||||
float fRate; ///< Rate limiting for ConditionalRun
|
||||
int fInitializationTimeoutInS;
|
||||
std::vector<std::string> fRawCmdLineArgs;
|
||||
|
||||
StateQueue fStateQueue;
|
||||
|
||||
std::mutex fTransportMtx; ///< guards access to transports container
|
||||
};
|
||||
using Device = ::FairMQDevice;
|
||||
|
||||
} // namespace fair::mq
|
||||
|
||||
using FairMQChannelMap [[deprecated("Use fair::mq::ChannelMap")]] = fair::mq::ChannelMap;
|
||||
using InputMsgCallback [[deprecated("Use fair::mq::InputMsgCallback")]] = fair::mq::InputMsgCallback;
|
||||
using InputMultipartCallback [[deprecated("Use fair::mq::InputMultipartCallback")]] = fair::mq::InputMultipartCallback;
|
||||
using FairMQDevice [[deprecated("Use fair::mq::Device")]] = fair::mq::Device;
|
||||
|
||||
#endif /* FAIR_MQ_DEVICE_H */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user