Compare commits

..

6 Commits

Author SHA1 Message Date
Alexey Rybalchenko
92632a022c Support region callbacks when no channel is specified 2019-03-08 11:06:30 +01:00
Alexey Rybalchenko
bd5105d609 Remove hint parameter from builder 2019-03-06 16:35:02 +01:00
Alexey Rybalchenko
080dd0a9df Remove wrong readme file 2019-03-06 16:35:02 +01:00
Alexey Rybalchenko
a9dfe39bf7 Add a hack to set the expected msg size via cmd option 2019-03-06 16:35:02 +01:00
Alexey Rybalchenko
e1b1e5e21b Temporary remove the OFI control band 2019-03-06 16:35:02 +01:00
Alexey Rybalchenko
763c21ffdd Remove azmq on send, make connect/bind blocking 2019-03-06 16:35:02 +01:00
231 changed files with 4919 additions and 8821 deletions

View File

@@ -1,3 +0,0 @@
---
Checks: '*,-google-*,-fuchsia-*,-cert-*,-llvm-header-guard,-readability-named-parameter,-misc-non-private-member-variables-in-classes,-*-magic-numbers,-llvm-include-order,-hicpp-no-array-decay,-performance-unnecessary-value-param,-cppcoreguidelines-pro-bounds-array-to-pointer-decay'
HeaderFilterRegex: '/(fairmq/|FairMQ)'

View File

@@ -7,12 +7,13 @@
################################################################################
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
cmake_policy(VERSION 3.10...3.14)
# Project ######################################################################
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(FairMQLib)
set_fairmq_cmake_policies()
get_git_version()
project(FairMQ VERSION ${PROJECT_VERSION} LANGUAGES CXX)
@@ -39,7 +40,6 @@ cmake_dependent_option(BUILD_OFI_TRANSPORT "Build experimental OFI transport." O
cmake_dependent_option(BUILD_DDS_PLUGIN "Build DDS plugin." OFF "BUILD_FAIRMQ" OFF)
cmake_dependent_option(BUILD_PMIX_PLUGIN "Build PMIx plugin." OFF "BUILD_FAIRMQ" OFF)
cmake_dependent_option(BUILD_EXAMPLES "Build FairMQ examples." ON "BUILD_FAIRMQ" OFF)
option(BUILD_SDK "Build the FairMQ controller SDK." OFF)
option(BUILD_DOCS "Build FairMQ documentation." OFF)
option(FAST_BUILD "Fast production build. Not recommended for development." OFF)
################################################################################
@@ -61,11 +61,14 @@ endif()
if(BUILD_OFI_TRANSPORT)
find_package2(PRIVATE asiofi REQUIRED
VERSION 0.3.1
VERSION 0.2.0
)
find_package2(PRIVATE OFI REQUIRED
ADD_REQUIREMENTS_OF asiofi
VERSION ${asiofi_OFI_VERSION}
COMPONENTS ${asiofi_OFI_COMPONENTS}
)
find_package2(PRIVATE AZMQ REQUIRED)
set(PROJECT_AZMQ_VERSION 1.0.2)
endif()
if(BUILD_NANOMSG_TRANSPORT)
@@ -74,38 +77,9 @@ if(BUILD_NANOMSG_TRANSPORT)
)
endif()
if(BUILD_SDK)
set(required_dds_version 2.5.22)
else()
set(required_dds_version 2.4)
endif()
if(BUILD_DDS_PLUGIN OR BUILD_SDK)
find_package2(PRIVATE DDS REQUIRED
VERSION ${required_dds_version}
)
set(DDS_Boost_COMPONENTS system log log_setup)
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.2.0
)
if(NOT DEFINED Boost_NO_BOOST_CMAKE AND CMAKE_VERSION VERSION_LESS 3.15)
# Since Boost 1.70 a CMake package is shipped by default. Unfortunately, it has a number
# of problems that are only fixed in Boost 1.71 or CMake 3.15. By default we skip the
# BoostConfig lookup. This can be overridden on the command line via -DBoost_NO_BOOST_CMAKE=OFF
set(Boost_NO_BOOST_CMAKE ON)
endif()
if(BUILD_FAIRMQ)
find_package2(PUBLIC Boost REQUIRED
VERSION 1.64
VERSION 1.64 ${asiofi_Boost_VERSION}
COMPONENTS
container
@@ -113,20 +87,24 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
filesystem
date_time
regex
ADD_REQUIREMENTS_OF
asiofi
DDS
FairLogger
${asiofi_Boost_COMPONENTS}
)
find_package2(PUBLIC FairLogger REQUIRED
VERSION 1.2.0
)
endif()
if(BUILD_FAIRMQ)
find_package2(PRIVATE ZeroMQ REQUIRED
VERSION 4.1.5
)
endif()
if(BUILD_DDS_PLUGIN)
find_package2(PRIVATE DDS VERSION 2.2 REQUIRED)
endif()
if(BUILD_PMIX_PLUGIN)
find_package2(PRIVATE PMIx VERSION 2.1.4 REQUIRED)
endif()
if(BUILD_TESTING)
find_package2(PRIVATE GTest REQUIRED
VERSION 1.7.0
@@ -144,7 +122,12 @@ endif()
# Targets ######################################################################
if(BUILD_FAIRMQ OR BUILD_SDK)
if(BUILD_FAIRMQ)
configure_file(${PROJECT_NAME_LOWER}/Version.h.in
${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}/Version.h
@ONLY
)
add_subdirectory(fairmq)
endif()
@@ -193,18 +176,29 @@ endif()
if(BUILD_DOCS)
list(APPEND PROJECT_PACKAGE_COMPONENTS docs)
endif()
if(BUILD_SDK)
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk)
endif()
################################################################################
# Installation #################################################################
if(BUILD_FAIRMQ)
install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}/Version.h
DESTINATION ${PROJECT_INSTALL_INCDIR}
)
install(FILES cmake/FindZeroMQ.cmake
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
)
endif()
if(BUILD_DDS_PLUGIN)
install(FILES cmake/FindDDS.cmake
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
)
endif()
if(BUILD_OFI_TRANSPORT)
install(FILES cmake/FindAZMQ.cmake
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
)
endif()
if(BUILD_DOCS)
install(DIRECTORY ${CMAKE_BINARY_DIR}/doxygen/html
DESTINATION ${PROJECT_INSTALL_DATADIR}/docs
@@ -247,11 +241,7 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
foreach(dep IN LISTS PROJECT_PACKAGE_DEPENDENCIES)
if(${dep}_VERSION)
if(${dep} STREQUAL Boost)
if(Boost_VERSION_MAJOR)
set(version_str "${BGreen}${${dep}_VERSION_MAJOR}.${${dep}_VERSION_MINOR}${CR}")
else()
set(version_str "${BGreen}${${dep}_MAJOR_VERSION}.${${dep}_MINOR_VERSION}${CR}")
endif()
set(version_str "${BGreen}${${dep}_MAJOR_VERSION}.${${dep}_MINOR_VERSION}${CR}")
else()
set(version_str "${BGreen}${${dep}_VERSION}${CR}")
endif()
@@ -268,11 +258,7 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
pad("${version_str}${version_req_str}" 25 " " version_padded COLOR 1)
endif()
if(${dep} STREQUAL FairLogger)
if(FairLogger_PREFIX)
set(prefix ${FairLogger_PREFIX})
else()
set(prefix ${FairLogger_ROOT})
endif()
set(prefix ${FairLogger_ROOT})
elseif(${dep} STREQUAL GTest)
get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE)
elseif(${dep} STREQUAL msgpack)
@@ -285,15 +271,6 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
elseif(${dep} STREQUAL nanomsg)
get_target_property(nn_include nanomsg INTERFACE_INCLUDE_DIRECTORIES)
get_filename_component(prefix ${nn_include}/.. ABSOLUTE)
elseif(${dep} STREQUAL DDS)
set(prefix "${DDS_INSTALL_PREFIX}")
elseif(${dep} STREQUAL Boost)
if(TARGET Boost::headers)
get_target_property(boost_include Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
else()
get_target_property(boost_include Boost::boost INTERFACE_INCLUDE_DIRECTORIES)
endif()
get_filename_component(prefix ${boost_include}/.. ABSOLUTE)
elseif(${dep} STREQUAL Doxygen)
get_target_property(doxygen_bin Doxygen::doxygen INTERFACE_LOCATION)
get_filename_component(prefix ${doxygen_bin} DIRECTORY)
@@ -357,33 +334,5 @@ else()
set(docs_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_DOCS=ON${CR})")
endif()
message(STATUS " ${BWhite}docs${CR} ${docs_summary}")
if(BUILD_SDK)
set(sdk_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})")
else()
set(sdk_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})")
endif()
message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}")
message(STATUS " ")
if(RUN_STATIC_ANALYSIS)
list(LENGTH PROJECT_STATIC_ANALYSERS size)
unset(analyser_list)
set(count 0)
foreach(analyser IN LISTS PROJECT_STATIC_ANALYSERS)
if(${analyser}_FOUND)
set(${analyser}_status "${analyser} ${BGreen}YES${CR}")
else()
set(${analyser}_status "${analyser} ${BRed}NO${CR}")
endif()
math(EXPR count "${count} + 1")
string(APPEND analyser_list "${${analyser}_status}")
if(count LESS size)
string(APPEND analyser_list "${BWhite},${CR} ")
endif()
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}OFF${CR} (default, enable with ${BMagenta}-DRUN_STATIC_ANALYSIS=ON${CR})")
endif()
message(STATUS " ${Cyan}RUN STATIC ANALYSIS ${static_ana_summary}")
message(STATUS " ")
################################################################################

View File

@@ -4,9 +4,9 @@ Upstream-Contact: Mohammad Al-Turany <m.al-turany@gsi.de>
Source: https://github.com/FairRootGroup/FairMQ
Files: *
Copyright: 2012-2019, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright: 2012-2019, [see AUTHORS file]
Copyright: 2012-2019, [see CONTRIBUTORS file]
Copyright: 2012-2018, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright: 2012-2018, [see AUTHORS file]
Copyright: 2012-2018, [see CONTRIBUTORS file]
Comment: The copyright of individual contributors is documented in the
Git history.
License: LGPL-3.0-only

View File

@@ -29,7 +29,6 @@ Set(configure_options "${configure_options};-DCMAKE_PREFIX_PATH=$ENV{SIMPATH}")
Set(configure_options "${configure_options};-DBUILD_NANOMSG_TRANSPORT=ON")
# Set(configure_options "${configure_options};-DBUILD_OFI_TRANSPORT=ON")
Set(configure_options "${configure_options};-DBUILD_DDS_PLUGIN=ON")
Set(configure_options "${configure_options};-DBUILD_SDK=ON")
Set(configure_options "${configure_options};-DFAST_BUILD=ON")
Set(configure_options "${configure_options};-DCOTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES=-j$ENV{number_of_processors}")
@@ -60,9 +59,17 @@ Ctest_Build(BUILD "${CTEST_BINARY_DIRECTORY}")
Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
# PARALLEL_LEVEL $ENV{number_of_processors}
PARALLEL_LEVEL $ENV{number_of_processors}
PARALLEL_LEVEL 1
RETURN_VALUE _ctest_test_ret_val
)
If("$ENV{do_codecov_upload}")
ForEach(i RANGE 4)
# Gather statistics to catch time sensitive branches
Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
PARALLEL_LEVEL $ENV{number_of_processors}
)
EndForEach()
EndIf()
If(GCOV_COMMAND)
Ctest_Coverage(BUILD "${CTEST_BINARY_DIRECTORY}" LABELS coverage)

View File

@@ -38,7 +38,7 @@ a simulation, reconstruction and analysis framework.
* PUBLIC: [**Boost**](https://www.boost.org/), [**FairLogger**](https://github.com/FairRootGroup/FairLogger)
* BUILD: [CMake](https://cmake.org/), [GTest](https://github.com/google/googletest), [Doxygen](http://www.doxygen.org/)
* PRIVATE: [ZeroMQ](http://zeromq.org/), [Msgpack](https://msgpack.org/index.html), [nanomsg](http://nanomsg.org/),
[asiofi](https://github.com/FairRootGroup/asiofi), [DDS](http://dds.gsi.de), [PMIx](https://pmix.org/)
[asiofi](https://github.com/FairRootGroup/asiofi), [DDS](http://dds.gsi.de), [PMIx](https://pmix.org/), [AZMQ](https://github.com/zeromq/azmq), [asiofi](https://github.com/FairRootGroup/asiofi)
Supported platforms: Linux and MacOS.
@@ -51,7 +51,7 @@ cmake -DCMAKE_INSTALL_PREFIX=./fairmq_install ../fairmq
cmake --build . --target install
```
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`, `MSGPACK`, `NANOMSG`, `OFI`, `PMIX`, `ASIOFI` or `DDS` (`*_ROOT` variables can also be environment variables).
If dependencies are not installed in standard system directories, you can hint the installation location via `-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...`. `{DEPENDENCY}` can be `GTEST`, `BOOST`, `FAIRLOGGER`, `ZEROMQ`, `MSGPACK`, `NANOMSG`, `OFI`, `PMIX`, `ASIOFI`, `AZMQ` or `DDS` (`*_ROOT` variables can also be environment variables).
## Usage
@@ -126,11 +126,9 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
| `${FairMQ_LIBDIR}` | the installation lib directory |
| `${FairMQ_DATADIR}` | the installation data directory (`../share/fairmq`) |
| `${FairMQ_CMAKEMODDIR}` | the installation directory of shipped CMake find modules |
| `${FairMQ_CXX_STANDARD_REQUIRED}` | the value of `CMAKE_CXX_STANDARD_REQUIRED` at build-time |
| `${FairMQ_CXX_STANDARD}` | the value of `CMAKE_CXX_STANDARD` at build-time |
| `${FairMQ_CXX_EXTENSIONS}` | the values of `CMAKE_CXX_EXTENSIONS` at build-time |
| `${FairMQ_BUILD_TYPE}` | the value of `CMAKE_BUILD_TYPE` at build-time |
| `${FairMQ_CXX_FLAGS}` | the values of `CMAKE_CXX_FLAGS` and `CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}` at build-time |
| `${FairMQ_CXX_STANDARD_REQUIRED}` | the value of `CMAKE_CXX_STANDARD_REQUIRED` at built-time |
| `${FairMQ_CXX_STANDARD}` | the value of `CMAKE_CXX_STANDARD` at built-time |
| `${FairMQ_CXX_EXTENSIONS}` | the values of `CMAKE_CXX_EXTENSIONS` at built-time |
## Documentation
@@ -159,10 +157,3 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
4. [File output](docs/Logging.md#54-file-output)
5. [Custom sinks](docs/Logging.md#55-custom-sinks)
6. [Examples](docs/Examples.md#6-examples)
7. [Plugins](docs/Plugins.md#7-plugins)
1. [Usage](docs/Plugins.md#71-usage)
2. [Development](docs/Plugins.md#72-development)
3. [Provided Plugins](docs/Plugins.md#73-provided-plugins)
1. [DDS](docs/Plugins.md#731-dds)
2. [PMIx](docs/Plugins.md#732-pmix)

View File

@@ -13,20 +13,17 @@ set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
set(@PROJECT_NAME@_GIT_VERSION @PROJECT_GIT_VERSION@)
set(@PROJECT_NAME@_GIT_DATE @PROJECT_GIT_DATE@)
set(@PROJECT_NAME@_PREFIX @PACKAGE_CMAKE_INSTALL_PREFIX@)
set(@PROJECT_NAME@_BINDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_BINDIR@)
set(@PROJECT_NAME@_INCDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@)
set(@PROJECT_NAME@_LIBDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_LIBDIR@)
set(@PROJECT_NAME@_DATADIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_DATADIR@)
set(@PROJECT_NAME@_CMAKEMODDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_CMAKEMODDIR@)
set_and_check(@PROJECT_NAME@_PREFIX @PACKAGE_CMAKE_INSTALL_PREFIX@)
set_and_check(@PROJECT_NAME@_BINDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_BINDIR@)
set_and_check(@PROJECT_NAME@_INCDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@)
set_and_check(@PROJECT_NAME@_LIBDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_LIBDIR@)
set_and_check(@PROJECT_NAME@_DATADIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_DATADIR@)
set_and_check(@PROJECT_NAME@_CMAKEMODDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_CMAKEMODDIR@)
set(@PROJECT_NAME@_CXX_STANDARD_REQUIRED @CMAKE_CXX_STANDARD_REQUIRED@)
set(@PROJECT_NAME@_CXX_STANDARD @CMAKE_CXX_STANDARD@)
set(@PROJECT_NAME@_CXX_EXTENSIONS @CMAKE_CXX_EXTENSIONS@)
set(@PROJECT_NAME@_VERSION_HOTFIX @PROJECT_VERSION_HOTFIX@)
set(@PROJECT_NAME@_BUILD_TYPE @CMAKE_BUILD_TYPE@)
set(@PROJECT_NAME@_BUILD_TYPE_UPPER @PROJECT_BUILD_TYPE_UPPER@)
set(@PROJECT_NAME@_CXX_FLAGS @PROJECT_CXX_FLAGS@)
### Import cmake modules
set(CMAKE_MODULE_PATH ${@PROJECT_NAME@_CMAKEMODDIR} ${CMAKE_MODULE_PATH})

View File

@@ -29,6 +29,26 @@ if(NOT WIN32 AND NOT DISABLE_COLOR)
set(BWhite "${Esc}[1;37m")
endif()
# set_fairmq_cmake_policies()
#
# Sets CMake policies.
macro(set_fairmq_cmake_policies)
# Find more details to each policy with cmake --help-policy CMPXXXX
foreach(policy
CMP0025 # Compiler id for Apple Clang is now AppleClang.
CMP0028 # Double colon in target name means ALIAS or IMPORTED target.
CMP0042 # MACOSX_RPATH is enabled by default.
CMP0048 # The ``project()`` command manages VERSION variables.
CMP0054 # Only interpret ``if()`` arguments as variables or keywords when unquoted.
CMP0074 # ``find_package()`` uses ``<PackageName>_ROOT`` variables.
)
if(POLICY ${policy})
cmake_policy(SET ${policy} NEW)
endif()
endforeach()
endmacro()
find_package(Git)
# get_git_version([DEFAULT_VERSION version] [DEFAULT_DATE date] [OUTVAR_PREFIX prefix])
#
@@ -166,34 +186,6 @@ macro(set_fairmq_defaults)
else()
set(PROJECT_VERSION_HOTFIX ${PROJECT_VERSION_TWEAK})
endif()
if(NOT DEFINED RUN_STATIC_ANALYSIS)
set(RUN_STATIC_ANALYSIS OFF)
endif()
unset(PROJECT_STATIC_ANALYSERS)
if(RUN_STATIC_ANALYSIS)
set(analyser "clang-tidy")
find_program(${analyser}_FOUND "${analyser}")
if(${analyser}_FOUND)
set(CMAKE_CXX_CLANG_TIDY "${${analyser}_FOUND}")
endif()
list(APPEND PROJECT_STATIC_ANALYSERS "${analyser}")
set(analyser "iwyu")
find_program(${analyser}_FOUND "${analyser}")
if(${analyser}_FOUND)
set(CMAKE_CXX_IWYU "${${analyser}_FOUND}")
endif()
list(APPEND PROJECT_STATIC_ANALYSERS "${analyser}")
set(analyser "cpplint")
find_program(${analyser}_FOUND "${analyser}")
if(${analyser}_FOUND)
set(CMAKE_CXX_CPPLINT "${${analyser}_FOUND}")
endif()
list(APPEND PROJECT_STATIC_ANALYSERS "${analyser}")
endif()
endmacro()
function(join VALUES GLUE OUTPUT)
@@ -288,8 +280,6 @@ macro(install_cmake_package)
)
generate_package_dependencies() # fills ${PACKAGE_DEPENDENCIES}
generate_package_components() # fills ${PACKAGE_COMPONENTS}
string(TOUPPER ${CMAKE_BUILD_TYPE} PROJECT_BUILD_TYPE_UPPER)
set(PROJECT_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${PROJECT_BUILD_TYPE_UPPER}})
configure_package_config_file(
${CMAKE_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
@@ -303,97 +293,49 @@ macro(install_cmake_package)
)
endmacro()
#
# find_package2(PRIVATE|PUBLIC|INTERFACE <pkgname>
# [VERSION <version>]
# [COMPONENTS <list of components>]
# [ADD_REQUIREMENTS_OF <list of dep_pgkname>]
# [any other option the native find_package supports]...)
#
# Wrapper around CMake's native find_package command to add some features and bookkeeping.
#
# The qualifier (PRIVATE|PUBLIC|INTERFACE) to the package to populate
# the variables PROJECT_[INTERFACE]_<pkgname>_([VERSION]|[COMPONENTS]|PACKAGE_DEPENDENCIES)
# accordingly. This bookkeeping information is used to print our dependency found summary
# table and to generate a part of our CMake package.
#
# When a dependending package is listed with ADD_REQUIREMENTS_OF the variables
# <dep_pkgname>_<pkgname>_VERSION|COMPONENTS are looked up to and added to the native
# VERSION (selected highest version) and COMPONENTS (deduplicated) args.
#
# COMPONENTS and VERSION args are then just passed to the native find_package.
#
macro(find_package2 qualifier pkgname)
cmake_parse_arguments(ARGS "" "VERSION" "COMPONENTS;ADD_REQUIREMENTS_OF" ${ARGN})
cmake_parse_arguments(ARGS "" "" "VERSION;COMPONENTS" ${ARGN})
string(TOUPPER ${pkgname} pkgname_upper)
set(__old_cpp__ ${CMAKE_PREFIX_PATH})
set(old_CPP ${CMAKE_PREFIX_PATH})
set(CMAKE_PREFIX_PATH ${${pkgname_upper}_ROOT} $ENV{${pkgname_upper}_ROOT} ${CMAKE_PREFIX_PATH})
# build lists of required versions and components
unset(__required_versions__)
unset(__components__)
if(ARGS_VERSION)
list(APPEND __required_versions__ ${ARGS_VERSION})
endif()
if(ARGS_COMPONENTS)
list(APPEND __components__ ${ARGS_COMPONENTS})
endif()
if(ARGS_ADD_REQUIREMENTS_OF)
foreach(dep_pkgname IN LISTS ARGS_ADD_REQUIREMENTS_OF)
if(${dep_pkgname}_${pkgname}_VERSION)
list(APPEND __required_versions__ ${${dep_pkgname}_${pkgname}_VERSION})
endif()
if(${dep_pkgname}_${pkgname}_COMPONENTS)
list(APPEND __components__ ${${dep_pkgname}_${pkgname}_COMPONENTS})
endif()
endforeach()
endif()
# select highest required version
unset(__version__)
if(__required_versions__)
list(GET __required_versions__ 0 __version__)
foreach(v IN LISTS __required_versions__)
if(ARGS_VERSION)
list(GET ARGS_VERSION 0 __version__)
list(LENGTH ARGS_VERSION __length__)
foreach(v IN LISTS ARGS_VERSION)
if(${v} VERSION_GREATER ${__version__})
set(__version__ ${v})
endif()
endforeach()
endif()
# deduplicate required component list
if(__components__)
list(REMOVE_DUPLICATES __components__)
endif()
# call native find_package
if(__components__)
find_package(${pkgname} ${__version__} QUIET COMPONENTS ${__components__} ${ARGS_UNPARSED_ARGUMENTS})
if(ARGS_COMPONENTS)
list(REMOVE_DUPLICATES ARGS_COMPONENTS)
find_package(${pkgname} ${__version__} QUIET COMPONENTS ${ARGS_COMPONENTS} ${ARGS_UNPARSED_ARGUMENTS})
else()
find_package(${pkgname} ${__version__} QUIET ${ARGS_UNPARSED_ARGUMENTS})
endif()
set(CMAKE_PREFIX_PATH ${old_CPP})
unset(old_CPP)
if(${pkgname}_FOUND)
if(${qualifier} STREQUAL PRIVATE)
set(PROJECT_${pkgname}_VERSION ${__version__})
set(PROJECT_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
elseif(${qualifier} STREQUAL PUBLIC)
set(PROJECT_${pkgname}_VERSION ${__version__})
set(PROJECT_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
elseif(${qualifier} STREQUAL INTERFACE)
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
endif()
endif()
unset(__version__)
unset(__components__)
unset(__required_versions__)
set(CMAKE_PREFIX_PATH ${__old_cpp__})
unset(__old_cpp__)
endmacro()

57
cmake/FindAZMQ.cmake Normal file
View File

@@ -0,0 +1,57 @@
################################################################################
# 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" #
################################################################################
#
# ###########################
# # Locate the AZMQ library #
# ###########################
#
#
# Usage:
#
# find_package(AZMQ [version] [QUIET] [REQUIRED])
#
#
# Defines the following variables:
#
# AZMQ_FOUND - Found the ZeroMQ library
# AZMQ_INCLUDE_DIR (CMake cache) - Include directory
#
#
# Accepts the following variables as hints for installation directories:
#
# AZMQ_ROOT (CMake var, ENV var)
#
#
# If the above variables are not defined, or if ZeroMQ could not be found there,
# it will look for it in the system directories. Custom ZeroMQ installations
# will always have priority over system ones.
#
if(NOT AZMQ_ROOT)
set(AZMQ_ROOT $ENV{AZMQ_ROOT})
endif()
find_path(AZMQ_INCLUDE_DIR
NAMES azmq/socket.hpp
HINTS ${AZMQ_ROOT} $ENV{AZMQ_ROOT}
PATH_SUFFIXES include
DOC "AZMQ include directory"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(AZMQ
REQUIRED_VARS AZMQ_INCLUDE_DIR
)
if(AZMQ_FOUND AND NOT TARGET AZMQ::AZMQ)
add_library(AZMQ::AZMQ INTERFACE IMPORTED)
set_target_properties(AZMQ::AZMQ PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${AZMQ_INCLUDE_DIR}
INTERFACE_LINK_LIBRARIES "libzmq;Boost::boost;Boost::container;Boost::system"
)
endif()

88
cmake/FindDDS.cmake Normal file
View File

@@ -0,0 +1,88 @@
################################################################################
# Copyright (C) 2014-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" #
################################################################################
find_path(DDS_INCLUDE_DIR
NAMES dds_intercom.h
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES include
)
find_path(DDS_LIBRARY_DIR
NAMES libdds_intercom_lib.dylib libdds_intercom_lib.so
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES lib
)
find_library(DDS_INTERCOM_LIBRARY_SHARED
NAMES libdds_intercom_lib.dylib libdds_intercom_lib.so
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES lib
DOC "Path to libdds_intercom_lib.dylib libdds_intercom_lib.so."
)
find_library(DDS_PROTOCOL_LIBRARY_SHARED
NAMES libdds_protocol_lib.dylib libdds_protocol_lib.so
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES lib
DOC "Path to libdds_protocol_lib.dylib libdds_protocol_lib.so."
)
find_library(DDS_USER_DEFAULTS_LIBRARY_SHARED
NAMES libdds-user-defaults.dylib libdds-user-defaults.so
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES lib
DOC "Path to libdds-user-defaults.dylib libdds-user-defaults.so."
)
find_file(DDS_VERSION_FILE
NAMES version
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
PATH_SUFFIXES etc
)
if(DDS_VERSION_FILE AND NOT DDS_VERSION)
file(READ ${DDS_VERSION_FILE} DDS_VERSION)
string(STRIP "${DDS_VERSION}" DDS_VERSION)
set(DDS_VERSION ${DDS_VERSION} CACHE string "DDS version.")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DDS
REQUIRED_VARS
DDS_INCLUDE_DIR
DDS_LIBRARY_DIR
DDS_INTERCOM_LIBRARY_SHARED
DDS_PROTOCOL_LIBRARY_SHARED
DDS_USER_DEFAULTS_LIBRARY_SHARED
VERSION_VAR DDS_VERSION
)
if(NOT TARGET DDS::dds_intercom_lib AND DDS_FOUND)
add_library(DDS::dds_intercom_lib SHARED IMPORTED)
set_target_properties(DDS::dds_intercom_lib PROPERTIES
IMPORTED_LOCATION ${DDS_INTERCOM_LIBRARY_SHARED}
INTERFACE_INCLUDE_DIRECTORIES ${DDS_INCLUDE_DIR}
)
endif()
if(NOT TARGET DDS::dds_protocol_lib AND DDS_FOUND)
add_library(DDS::dds_protocol_lib SHARED IMPORTED)
set_target_properties(DDS::dds_protocol_lib PROPERTIES
IMPORTED_LOCATION ${DDS_PROTOCOL_LIBRARY_SHARED}
INTERFACE_INCLUDE_DIRECTORIES ${DDS_INCLUDE_DIR}
)
endif()
if(NOT TARGET DDS::dds-user-defaults AND DDS_FOUND)
add_library(DDS::dds-user-defaults SHARED IMPORTED)
set_target_properties(DDS::dds-user-defaults PROPERTIES
IMPORTED_LOCATION ${DDS_USER_DEFAULTS_LIBRARY_SHARED}
INTERFACE_INCLUDE_DIRECTORIES ${DDS_INCLUDE_DIR}
)
endif()

View File

@@ -4,37 +4,7 @@
## 3.1 Device Configuration
Device Configuration is stored in configuration object - `fair::mq::ProgOptions`. It is accessible by the device, plugins or from DeviceRunner/main:
Plugins <---read/write---> ProgOptions <---read/write---> Device
Whenever a configuration property is set, it is set in ProgOptions. Device/Channels/User code read this value and apply it as necessary at different stages:
- apply it immidiately
- apply it in device/channels during InitializingDevice/Binding/Connecting states
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 `<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`) |
## 3.2 Configuration options
Devices receive configuration primarily via provided command line options (that can be extended per device).
## 3.2 Communication Channels Configuration
@@ -62,14 +32,6 @@ This parser reads channel configuration from a JSON file. Example:
"address": "tcp://*:5555",
"sndBufSize": 1000,
"rcvBufSize": 1000,
"sndKernelSize" : 0,
"rcvKernelSize" : 0,
"transport": "shmem",
"linger": "500",
"portRangeMin": "22000",
"portRangeMax": "23000",
"autoBind": false,
"numSockets": 0,
"rateLogging": 1
}
]
@@ -86,7 +48,9 @@ This parser reads channel configuration from a JSON file. Example:
"type": "pull",
"method": "connect",
"address": "tcp://localhost:5555",
"transport": "shmem"
"sndBufSize": 1000,
"rcvBufSize": 1000,
"rateLogging": 1
}
]
}

View File

@@ -24,7 +24,7 @@ FairMQ devices communicate via the communication patterns offered by ZeroMQ (or
Each FairMQ device has an internal state machine:
![FairMQ state machine](images/device_states.svg "FairMQ state machine")
![FairMQ state machine](images/device_states.png?raw=true "FairMQ state machine")
The state machine can be querried and controlled via `GetCurrentStateName()` and `ChangeState("<state name>")` methods. Only legal state transitions are allowed (see image above). Illegal transitions will fail with an error.
@@ -48,6 +48,6 @@ Without the interactive mode, for example for a run in background, two other con
## 1.4 Multiple devices in the same process
Technically one can create two or more devices within the same process without any conflicts. However the configuration (fair::mq::ProgOptions) currently assumes the supplied configuration values are for one device/process.
Technically one can create two or more devices within the same process without any conflicts. However the configuration (FairMQProgOptions) currently assumes the supplied configuration values are for one device/process.
← [Back](../README.md)

View File

@@ -1,93 +0,0 @@
← [Back](../README.md)
# 7. Plugins
FairMQ devices can be integrated with external configuration and control systems through its plugin system. FairMQ plugins are special dynamic libraries that can be loaded at runtime. Plugins have access to the Plugin API which includes the capability to control/monitor the device [state machine](Device.md#13-state-machine) and change/monitor configuration properties.
A simple plugin may add the feature to read configuration from a certain desired file format once at the start of a device. A more complex plugin may create a long-running thread that integrates a network client to an external API of a central experiment control system.
Because plugins are loaded dynamically, they can be developed in separate repositories/projects and also have their own set of runtime dependency that are not needed to be known at compile-time of the FairMQ device.
## 7.1 Usage
To load a plugin pass the `-P <name>[,<name>]` (or long `--plugin`) command line option. Multiple plugins can be loaded at the same time. The load order is as specified at the command line. This determines the order in which the plugins are instantiated (ctor call order) and in which order they are notified, should they subscribe to any notifications.
When passing `-h/--help` on the command line one can find more detailed information:
```
Plugin Manager:
-S [ --plugin-search-path ] arg List of plugin search paths.
* Override default search path, e.g.
-S /home/user/lib /lib
* Append(>) or prepend(<) to default
search path, e.g.
-S >/lib </home/user/lib
* If you mix the overriding and
appending/prepending syntaxes, the
overriding paths act as default search
path, e.g.
-S /usr/lib >/lib </home/user/lib
/usr/local/lib results in
/home/user/lib,/usr/local/lib,/usr/lib/
,/lib
If nothing is found, the default
dynamic library lookup is performed,
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
'libFairMQPlugin_example.so', just list
'example' or 'd:example' here.To load a
prelinked plugin, list 'p:example'
here.
```
## 7.2 Development
To develop a custom FairMQ plugin, one simply needs to inherit from the `fair::mq::Plugin` base class (`#include <fairmq/Plugin.h>`) and call the `REGISTER_FAIRMQ_PLUGIN` macro. It is possible to introduce new command line option together with a plugin.
The Plugin API includes:
* `Take/Steal/ReleaseDeviceControl()`/`GetCurrent/ChangeDeviceState()`/`SubscribeTo/UnsubscribeFromDeviceStateChange()` APIs enable controlling the device state machine. Only one plugin is authorized to control at the same time. Which one is determined by which plugin calls `TakeDeviceControl()` first.
* `Set/GetProperty()`/`GetPropertyKeys()`/`SubscribeTo/UnsubscribeFromPropertyChange()` APIs enable configuration of device properties.
See [`<fairmq/Plugin.h>`](/fairmq/Plugin.h) for the full API.
A more complete example which may serve as a start including example CMake code can be found here: [FairRootGroup/FairMQPlugin_example](https://github.com/FairRootGroup/FairMQPlugin_example).
## 7.3 Provided Plugins
### 7.3.1 DDS
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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 170 KiB

View File

@@ -26,8 +26,8 @@ Sampler::Sampler()
void Sampler::InitTask()
{
// Get the fText and fMaxIterations values from the command line options (via fConfig)
fText = fConfig->GetProperty<string>("text");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fText = fConfig->GetValue<string>("text");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler::ConditionalRun()

View File

@@ -30,7 +30,7 @@ Sink::Sink()
void Sink::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)

View File

@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_1_1::Sampler();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_1_1::Sink();
}

View File

@@ -32,8 +32,8 @@ Sampler::Sampler()
void Sampler::InitTask()
{
// Get the fText and fMaxIterations values from the command line options (via fConfig)
fText = fConfig->GetProperty<string>("text");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fText = fConfig->GetValue<string>("text");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler::ConditionalRun()

View File

@@ -30,7 +30,7 @@ Sink::Sink()
void Sink::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
// handler is called whenever a message arrives on "data2", with a reference to the message and a sub-channel index (here 0)

View File

@@ -15,7 +15,7 @@ void addCustomOptions(bpo::options_description& /*options*/)
{
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_1_n_1::Processor();
}

View File

@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_1_n_1::Sampler();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_1_n_1::Sink();
}

View File

@@ -33,11 +33,12 @@ Sampler::Sampler()
void Sampler::InitTask()
{
fNumDataChannels = fChannels.at("data").size();
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler::ConditionalRun()
{
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
// Should only be used for small data because of the cost of an additional copy
FairMQMessagePtr msg(NewSimpleMessage(fCounter++));

View File

@@ -27,7 +27,7 @@ Sink::Sink()
void Sink::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sink::HandleData(FairMQMessagePtr& msg, int /*index*/)

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_copypush::Sampler();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_copypush::Sink();
}

View File

@@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2014-2019 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, #
@@ -28,13 +28,12 @@ target_link_libraries(fairmq-ex-dds-sink PRIVATE ExampleDDSLib)
add_custom_target(ExampleDDS DEPENDS fairmq-ex-dds-sampler fairmq-ex-dds-processor fairmq-ex-dds-sink)
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/fairmq/plugins/DDS)
set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(DDS_PLUGIN_LIB_DIR ${CMAKE_BINARY_DIR}/fairmq/plugins/DDS)
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology-infinite.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-hosts.cfg ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-hosts.cfg COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-dds-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-dds-env.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh @ONLY)
# test
@@ -51,12 +50,10 @@ install(
)
# configure run script with different executable paths for build and for install directories
set(BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
set(DATA_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR})
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
set(DDS_PLUGIN_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR})
set(FAIRMQ_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR}/fairmq)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology-infinite.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-dds-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-dds-env.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml_install
@@ -64,25 +61,7 @@ install(
RENAME ex-dds-topology.xml
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-dds-topology-infinite.xml
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-hosts.cfg
DESTINATION ${PROJECT_INSTALL_DATADIR}
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-dds-env.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-ex-dds-env.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-dds.sh
)

View File

@@ -40,9 +40,9 @@ The configuration of the channel connection addresses is done by the DDS plugin
**If you chose step 2b earlier**, then modify the provided `ex-dds-topology.xml` in the top that the following lines read as following:
```xml
<declrequirement name="SamplerWorker" type="wnname" value=".*"/>
<declrequirement name="ProcessorWorker" type="wnname" value=".*"/>
<declrequirement name="SinkWorker" type="wnname" value=".*"/>
<declrequirement id="SamplerWorker" type="wnname" value=".*"/>
<declrequirement id="ProcessorWorker" type="wnname" value=".*"/>
<declrequirement id="SinkWorker" type="wnname" value=".*"/>
```
Note that the attributes `value` contain a different value.

View File

@@ -26,14 +26,10 @@ Sampler::Sampler()
{
}
void Sampler::InitTask()
{
fIterations = fConfig->GetValue<uint64_t>("iterations");
fCounter = 0;
}
bool Sampler::ConditionalRun()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
// NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
// Should only be used for small data because of the cost of an additional copy
FairMQMessagePtr msg(NewSimpleMessage("Data"));
@@ -42,18 +38,11 @@ bool Sampler::ConditionalRun()
// 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).
if (Send(msg, "data1") < 0) {
if (Send(msg, "data1") < 0)
{
return false;
}
if (fIterations > 0) {
++fCounter;
if (fCounter >= fIterations) {
LOG(info) << "Sent " << fCounter << " messages. Finished.";
return false;
}
}
return true;
}

View File

@@ -25,14 +25,9 @@ class Sampler : public FairMQDevice
public:
Sampler();
virtual ~Sampler();
void InitTask() override;
protected:
bool ConditionalRun() override;
private:
uint64_t fIterations;
uint64_t fCounter;
virtual bool ConditionalRun();
};
} // namespace example_dds

View File

@@ -25,24 +25,11 @@ Sink::Sink()
OnData("data2", &Sink::HandleData);
}
void Sink::InitTask()
{
fIterations = fConfig->GetValue<uint64_t>("iterations");
fCounter = 0;
}
// handler is called whenever a message arrives on "data2", with a reference to the message and a sub-channel index (here 0)
bool Sink::HandleData(FairMQMessagePtr& msg, int /*index*/)
{
LOG(info) << "Received: \"" << string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
if (fIterations > 0) {
++fCounter;
if (fCounter >= fIterations) {
LOG(info) << "Received " << fCounter << " messages. Finished.";
return false;
}
}
// return true if want to be called again (otherwise go to IDLE state)
return true;
}

View File

@@ -25,14 +25,9 @@ class Sink : public FairMQDevice
public:
Sink();
virtual ~Sink();
void InitTask() override;
protected:
bool HandleData(FairMQMessagePtr&, int);
private:
uint64_t fIterations;
uint64_t fCounter;
};
} // namespace example_dds

View File

@@ -1,3 +1,7 @@
sampler, 127.0.0.1, , /tmp/fairmq-ex-dds, 1
processor, 127.0.0.1, , /tmp/fairmq-ex-dds, 10
sink, 127.0.0.1, , /tmp/fairmq-ex-dds, 1
@bash_begin@
# source setup.sh
@bash_end@
sampler, username@localhost, , /path/to/dds-work/, 1
processor, username@localhost, , /path/to/dds-work/, 10
sink, username@localhost, , /path/to/dds-work/, 1

View File

@@ -1,52 +0,0 @@
<topology name="ExampleDDS">
<property name="data1" />
<property name="data2" />
<declrequirement name="SamplerWorker" type="wnname" value="sampler"/>
<declrequirement name="ProcessorWorker" type="wnname" value="processor"/>
<declrequirement name="SinkWorker" type="wnname" value="sink"/>
<decltask name="Sampler">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sampler --id sampler --color false --channel-config name=data1,type=push,method=bind --rate 100 -P dds</exe>
<requirements>
<name>SamplerWorker</name>
</requirements>
<properties>
<name access="write">data1</name>
</properties>
</decltask>
<decltask name="Processor">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-processor --id processor_%taskIndex% --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<requirements>
<id>ProcessorWorker</id>
</requirements>
<properties>
<name access="read">data1</name>
<name access="read">data2</name>
</properties>
</decltask>
<decltask name="Sink">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sink --id sink --color false --channel-config name=data2,type=pull,method=bind -P dds</exe>
<requirements>
<name>SinkWorker</name>
</requirements>
<properties>
<name access="write">data2</name>
</properties>
</decltask>
<main name="main">
<task>Sampler</task>
<task>Sink</task>
<group name="ProcessorGroup" n="10">
<task>Processor</task>
</group>
</main>
</topology>

View File

@@ -1,50 +1,47 @@
<topology name="ExampleDDS">
<topology id="ExampleDDS">
<property name="data1" />
<property name="data2" />
<property id="data1" />
<property id="data2" />
<declrequirement name="SamplerWorker" type="wnname" value="sampler"/>
<declrequirement name="ProcessorWorker" type="wnname" value="processor"/>
<declrequirement name="SinkWorker" type="wnname" value="sink"/>
<declrequirement id="SamplerWorker" type="wnname" value="sampler"/>
<declrequirement id="ProcessorWorker" type="wnname" value="processor"/>
<declrequirement id="SinkWorker" type="wnname" value="sink"/>
<decltask name="Sampler">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sampler --id sampler --color false --channel-config name=data1,type=push,method=bind -P dds --iterations 10</exe>
<decltask id="Sampler">
<exe reachable="true">@EX_BIN_DIR@/fairmq-ex-dds-sampler --id sampler --color false --channel-config name=data1,type=push,method=bind -S "&lt;@DDS_PLUGIN_LIB_DIR@/" -P dds</exe>
<requirements>
<name>SamplerWorker</name>
<id>SamplerWorker</id>
</requirements>
<properties>
<name access="write">data1</name>
<id access="write">data1</id>
</properties>
</decltask>
<decltask name="Processor">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-processor --id processor_%taskIndex% --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<decltask id="Processor">
<exe reachable="true">@EX_BIN_DIR@/fairmq-ex-dds-processor --id processor_%taskIndex% --config-key processor --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -S "&lt;@DDS_PLUGIN_LIB_DIR@/" -P dds</exe>
<requirements>
<id>ProcessorWorker</id>
</requirements>
<properties>
<name access="read">data1</name>
<name access="read">data2</name>
<id access="read">data1</id>
<id access="read">data2</id>
</properties>
</decltask>
<decltask name="Sink">
<env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sink --id sink --color false --channel-config name=data2,type=pull,method=bind -P dds --iterations 10</exe>
<decltask id="Sink">
<exe reachable="true">@EX_BIN_DIR@/fairmq-ex-dds-sink --id sink --color false --channel-config name=data2,type=pull,method=bind -S "&lt;@DDS_PLUGIN_LIB_DIR@/" -P dds</exe>
<requirements>
<name>SinkWorker</name>
<id>SinkWorker</id>
</requirements>
<properties>
<name access="write">data2</name>
<id access="write">data2</id>
</properties>
</decltask>
<main name="main">
<main id="main">
<task>Sampler</task>
<task>Sink</task>
<group name="ProcessorGroup" n="10">
<group id="ProcessorGroup" n="10">
<task>Processor</task>
</group>
</main>

View File

@@ -1,11 +0,0 @@
#!/bin/bash
################################################################################
# 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" #
################################################################################
export PATH=@BIN_DIR@:$PATH

View File

@@ -1,85 +0,0 @@
#!/bin/bash
################################################################################
# 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" #
################################################################################
# fairmq-start-ex-dds.sh [localhost] -> submit agents with localhost plugin
# fairmq-start-ex-dds.sh ssh -> submit agents with ssh plugin
set -e
cleanup() {
dds-session stop $1
echo "CLEANUP PERFORMED"
}
source @DDS_INSTALL_PREFIX@/DDS_env.sh
export PATH=@BIN_DIR@:$PATH
plugin=${1:-localhost}
exec 5>&1
output=$(dds-session start | tee >(cat - >&5))
export DDS_SESSION_ID=$(echo ${output} | grep "DDS session ID: " | cut -d' ' -f4)
echo "SESSION ID: ${DDS_SESSION_ID}"
trap "cleanup ${DDS_SESSION_ID}" EXIT
requiredNofAgents=12
if [[ "$plugin" == "ssh" ]]; then
dds-submit -r ${plugin} -c @DATA_DIR@/ex-dds-hosts.cfg
else
dds-submit -r ${plugin} -n ${requiredNofAgents}
fi
echo "...waiting for ${requiredNofAgents} idle agents..."
dds-info --wait-for-idle-agents ${requiredNofAgents}
topologyFile=@DATA_DIR@/ex-dds-topology.xml
echo "TOPOLOGY FILE: ${topologyFile}"
# TODO Uncomment once DDS 2.6 is released
# echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${topologyFile})"
# TODO Uncomment once DDS 2.6 is released
# dds-info --active-topology
dds-topology --disable-validation --activate ${topologyFile}
# dds-info --active-topology
# dds-info --wait-for-executing-agents ${requiredNofAgents}
sleep 1
echo "------------------------"
echo "...waiting for Topology to finish..."
# TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely
fairmq-dds-command-ui -w "IDLE" -n ${requiredNofAgents}
fairmq-dds-command-ui -c i -w "INITIALIZING DEVICE" -n ${requiredNofAgents}
fairmq-dds-command-ui -c k -w "INITIALIZED" -n ${requiredNofAgents}
fairmq-dds-command-ui -c b -w "BOUND" -n ${requiredNofAgents}
fairmq-dds-command-ui -c x -w "DEVICE READY" -n ${requiredNofAgents}
fairmq-dds-command-ui -c j -w "READY" -n ${requiredNofAgents}
fairmq-dds-command-ui -c r
sampler_and_sink="main/(Sampler|Sink)"
fairmq-dds-command-ui -p $sampler_and_sink -w "RUNNING->READY" -n 2
echo "...$sampler_and_sink are READY, sending shutdown..."
fairmq-dds-command-ui -c s -w "RUNNING->READY" -n ${requiredNofAgents}
fairmq-dds-command-ui -c t -w "DEVICE READY" -n ${requiredNofAgents}
fairmq-dds-command-ui -c d -w "IDLE" -n ${requiredNofAgents}
fairmq-dds-command-ui -c q
echo "...waiting for ${requiredNofAgents} idle agents..."
dds-info --wait-for-idle-agents ${requiredNofAgents}
echo "------------------------"
# TODO Uncomment once DDS 2.6 is released
# dds-info --active-topology
dds-topology --stop
# dds-info --active-topology
dds-agent-cmd getlog -a
logDir="${wrkDir}/logs"
for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done
echo "AGENT LOG FILES IN: ${logDir}"
# Cleanup function is called by EXIT trap

View File

@@ -15,7 +15,7 @@ void addCustomOptions(bpo::options_description& /*options*/)
{
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_dds::Processor();
}

View File

@@ -11,15 +11,11 @@
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
void addCustomOptions(bpo::options_description& /*options*/)
{
options.add_options()(
"iterations,i",
bpo::value<uint64_t>()->default_value(1000),
"Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_dds::Sampler();
}

View File

@@ -11,15 +11,11 @@
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
void addCustomOptions(bpo::options_description& /*options*/)
{
options.add_options()(
"iterations,i",
bpo::value<uint64_t>()->default_value(1000),
"Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_dds::Sink();
}

View File

@@ -32,20 +32,15 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multipart.sh.in ${CMA
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh)
add_test(NAME Example.Multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh zeromq)
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts")
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 2 parts")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.Multipart.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh nanomsg)
set_tests_properties(Example.Multipart.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts")
set_tests_properties(Example.Multipart.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 2 parts")
endif()
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 5 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 5 parts")
endif()
set_tests_properties(Example.Multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 2 parts")
# install

View File

@@ -31,7 +31,7 @@ Sampler::Sampler()
void Sampler::InitTask()
{
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler::ConditionalRun()
@@ -53,13 +53,6 @@ bool Sampler::ConditionalRun()
parts.AddPart(NewSimpleMessage(header));
parts.AddPart(NewMessage(1000));
// create more data parts, testing the FairMQParts in-place constructor
FairMQParts auxData{ NewMessage(500), NewMessage(600), NewMessage(700) };
assert(auxData.Size() == 3);
parts.AddPart(std::move(auxData));
assert(auxData.Size() == 0);
assert(parts.Size() == 5);
LOG(info) << "Sending body of size: " << parts.At(1)->GetSize();
Send(parts, "data");
@@ -81,4 +74,4 @@ Sampler::~Sampler()
{
}
} // namespace example_multipart
} // namespace example_multipart

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(5), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multipart::Sampler();
}

View File

@@ -15,7 +15,7 @@ void addCustomOptions(bpo::options_description& /*options*/)
{
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multipart::Sink();
}

View File

@@ -20,7 +20,7 @@ SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION"
SAMPLER+=" --max-iterations 1"
SAMPLER+=" --control static --color false"
SAMPLER+=" --channel-config name=data,type=pair,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555"
SAMPLER+=" --channel-config name=data,type=push,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$!
@@ -30,7 +30,7 @@ SINK+=" --transport $transport"
SINK+=" --verbosity veryhigh"
SINK+=" --session $SESSION"
SINK+=" --control static --color false"
SINK+=" --channel-config name=data,type=pair,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
SINK+=" --channel-config name=data,type=pull,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$!

View File

@@ -33,8 +33,8 @@ Sampler::Sampler()
void Sampler::InitTask()
{
fText = fConfig->GetProperty<string>("text");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fText = fConfig->GetValue<string>("text");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
void Sampler::Run()

View File

@@ -31,7 +31,7 @@ Sink::Sink()
void Sink::InitTask()
{
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sink::HandleBroadcast(FairMQMessagePtr& msg, int /*index*/)

View File

@@ -15,7 +15,7 @@ void addCustomOptions(bpo::options_description& /*options*/)
{
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_channels::Broadcaster();
}

View File

@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_channels::Sampler();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_channels::Sink();
}

View File

@@ -22,7 +22,7 @@ Sampler1::Sampler1()
void Sampler1::InitTask()
{
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
void Sampler1::PreRun()

View File

@@ -21,7 +21,7 @@ Sampler2::Sampler2()
void Sampler2::InitTask()
{
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler2::ConditionalRun()

View File

@@ -31,7 +31,7 @@ Sink::Sink()
void Sink::InitTask()
{
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sampler1();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sampler2();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sink();
}

View File

@@ -5,42 +5,36 @@
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEREGIONBUILDER_H
#define FAIRMQEXAMPLEREGIONBUILDER_H
#include <atomic>
#include "FairMQDevice.h"
#include <string>
namespace example_readout
namespace example_region
{
class Builder : public FairMQDevice
{
public:
Builder()
: fOutputChannelName()
{}
void Init() override
{
fOutputChannelName = fConfig->GetProperty<std::string>("output-name");
OnData("rb", &Builder::HandleData);
Builder() {
OnData("data1", &Builder::HandleData);
}
virtual ~Builder() {}
protected:
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
{
if (Send(msg, fOutputChannelName) < 0) {
if (Send(msg, "data2") < 0) {
return false;
}
return true;
}
private:
std::string fOutputChannelName;
};
} // namespace example_readout
} // namespace example_region
#endif /* FAIRMQEXAMPLEREGIONBUILDER_H */

View File

@@ -6,35 +6,38 @@
# copied verbatim in the file "LICENSE" #
################################################################################
add_executable(fairmq-ex-readout-readout runReadout.cxx)
target_link_libraries(fairmq-ex-readout-readout PRIVATE FairMQ)
add_library(ExampleReadoutLib STATIC
"Sampler.cxx"
"Sampler.h"
"Builder.h"
"Sink.cxx"
"Sink.h"
)
target_link_libraries(ExampleReadoutLib PUBLIC FairMQ)
add_executable(fairmq-ex-readout-sampler runSampler.cxx)
target_link_libraries(fairmq-ex-readout-sampler PRIVATE ExampleReadoutLib)
add_executable(fairmq-ex-readout-builder runBuilder.cxx)
target_link_libraries(fairmq-ex-readout-builder PRIVATE FairMQ)
target_link_libraries(fairmq-ex-readout-builder PRIVATE ExampleReadoutLib)
add_executable(fairmq-ex-readout-processor runProcessor.cxx)
target_link_libraries(fairmq-ex-readout-processor PRIVATE FairMQ)
add_executable(fairmq-ex-readout-sink runSink.cxx)
target_link_libraries(fairmq-ex-readout-sink PRIVATE ExampleReadoutLib)
add_executable(fairmq-ex-readout-sender runSender.cxx)
target_link_libraries(fairmq-ex-readout-sender PRIVATE FairMQ)
add_executable(fairmq-ex-readout-receiver runReceiver.cxx)
target_link_libraries(fairmq-ex-readout-receiver PRIVATE FairMQ)
add_custom_target(ExampleReadout DEPENDS fairmq-ex-readout-sampler fairmq-ex-readout-builder fairmq-ex-readout-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-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-sampler
fairmq-ex-readout-builder
fairmq-ex-readout-processor
fairmq-ex-readout-sender
fairmq-ex-readout-receiver
fairmq-ex-readout-sink
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
@@ -44,16 +47,9 @@ install(
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
)

View File

@@ -1,27 +0,0 @@
# Readout example
This examples shows two possible topologies (out of many) for a node connected to a detector readout (followed by a processing node).
## Setup without new data generation
```
|------------------------------- Readout Node ---------------------------| |- Processing Node -|
| Readout --> Builder --> Sender | --> | Receiver |
| [# 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 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) #######] | ofi | |
| [# shmem unmanaged region (readout writes here, builder & proc read) ] | | |
|------------------------------------------------------------------------| |-------------------|
```
In this topology one more device is added - Processor. It examines the arriving data and creates new data in shared memory. This data is not part of the unmanaged region, but lives in the general shared memory segment (unused in the previous setup). This new data is then forwarded to Sender and the Readout device is notified that the corresponding data piece in the unmanaged region is no longer used.

View File

@@ -1,91 +0,0 @@
/********************************************************************************
* 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" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEREADOUTREADOUT_H
#define FAIRMQEXAMPLEREADOUTREADOUT_H
#include <atomic>
#include <thread>
#include <chrono>
#include "FairMQDevice.h"
namespace example_readout
{
class Readout : public FairMQDevice
{
public:
Readout()
: fMsgSize(10000)
, fMaxIterations(0)
, fNumIterations(0)
, fRegion(nullptr)
, fNumUnackedMsgs(0)
{}
protected:
void InitTask() override
{
fMsgSize = fConfig->GetProperty<int>("msg-size");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
0,
10000000,
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport
--fNumUnackedMsgs;
if (fMaxIterations > 0) {
LOG(debug) << "Received ack";
}
}
));
}
bool ConditionalRun() override
{
FairMQMessagePtr msg(NewMessageFor("rb", // channel
0, // sub-channel
fRegion, // region
fRegion->GetData(), // ptr within region
fMsgSize, // offset from ptr
nullptr // hint
));
if (Send(msg, "rb", 0) > 0) {
++fNumUnackedMsgs;
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false;
}
}
return true;
}
void ResetTask() override
{
// if not all messages acknowledged, wait for a bit. But only once, since receiver could be already dead.
if (fNumUnackedMsgs != 0) {
LOG(debug) << "waiting for all acknowledgements... (" << fNumUnackedMsgs << ")";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
LOG(debug) << "done, still unacked: " << fNumUnackedMsgs;
}
fRegion.reset();
}
private:
int fMsgSize;
uint64_t fMaxIterations;
uint64_t fNumIterations;
FairMQUnmanagedRegionPtr fRegion;
std::atomic<uint64_t> fNumUnackedMsgs;
};
} // namespace example_readout
#endif /* FAIRMQEXAMPLEREADOUTREADOUT_H */

View File

@@ -1,54 +0,0 @@
/********************************************************************************
* 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" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEREGIONRECEIVER_H
#define FAIRMQEXAMPLEREGIONRECEIVER_H
#include "FairMQDevice.h"
namespace example_readout
{
class Receiver : public FairMQDevice
{
public:
Receiver()
: fMaxIterations(0)
, fNumIterations(0)
{}
protected:
void InitTask() override
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
}
void Run() override
{
FairMQChannel& dataInChannel = fChannels.at("sr").at(0);
while (!NewStatePending()) {
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
dataInChannel.Receive(msg);
// void* ptr = msg->GetData();
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
break;
}
}
}
private:
uint64_t fMaxIterations;
uint64_t fNumIterations;
};
} // namespace example_readout
#endif /* FAIRMQEXAMPLEREGIONRECEIVER_H */

View File

@@ -0,0 +1,86 @@
/********************************************************************************
* 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" *
********************************************************************************/
/**
* Sampler.cpp
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#include "Sampler.h"
#include <thread>
using namespace std;
namespace example_region
{
Sampler::Sampler()
: fMsgSize(10000)
, fMaxIterations(0)
, fNumIterations(0)
, fRegion(nullptr)
, fNumUnackedMsgs(0)
{
}
void Sampler::InitTask()
{
fMsgSize = fConfig->GetValue<int>("msg-size");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegion(10000000,
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport
--fNumUnackedMsgs;
if (fMaxIterations > 0)
{
LOG(debug) << "Received ack";
}
}));
}
bool Sampler::ConditionalRun()
{
FairMQMessagePtr msg(NewMessage(fRegion, // region
fRegion->GetData(), // ptr within region
fMsgSize, // offset from ptr
nullptr // hint
));
if (Send(msg, "data1", 0) > 0)
{
++fNumUnackedMsgs;
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false;
}
}
return true;
}
void Sampler::ResetTask()
{
// if not all messages acknowledged, wait for a bit. But only once, since receiver could be already dead.
if (fNumUnackedMsgs != 0)
{
LOG(debug) << "waiting for all acknowledgements... (" << fNumUnackedMsgs << ")";
this_thread::sleep_for(chrono::milliseconds(500));
LOG(debug) << "done, still unacked: " << fNumUnackedMsgs;
}
fRegion.reset();
}
Sampler::~Sampler()
{
}
} // namespace example_region

View File

@@ -0,0 +1,46 @@
/********************************************************************************
* 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" *
********************************************************************************/
/**
* Sampler.h
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#ifndef FAIRMQEXAMPLEREGIONSAMPLER_H
#define FAIRMQEXAMPLEREGIONSAMPLER_H
#include <atomic>
#include "FairMQDevice.h"
namespace example_region
{
class Sampler : public FairMQDevice
{
public:
Sampler();
virtual ~Sampler();
protected:
virtual void InitTask();
virtual bool ConditionalRun();
virtual void ResetTask();
private:
int fMsgSize;
uint64_t fMaxIterations;
uint64_t fNumIterations;
FairMQUnmanagedRegionPtr fRegion;
std::atomic<uint64_t> fNumUnackedMsgs;
};
} // namespace example_region
#endif /* FAIRMQEXAMPLEREGIONSAMPLER_H */

View File

@@ -1,46 +0,0 @@
/********************************************************************************
* 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" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEREGIONSENDER_H
#define FAIRMQEXAMPLEREGIONSENDER_H
#include "FairMQDevice.h"
#include <string>
namespace example_readout
{
class Sender : public FairMQDevice
{
public:
Sender()
: fInputChannelName()
{}
void Init() override
{
fInputChannelName = fConfig->GetProperty<std::string>("input-name");
OnData(fInputChannelName, &Sender::HandleData);
}
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
{
if (Send(msg, "sr") < 0) {
return false;
}
return true;
}
private:
std::string fInputChannelName;
};
} // namespace example_readout
#endif /* FAIRMQEXAMPLEREGIONSENDER_H */

56
examples/readout/Sink.cxx Normal file
View File

@@ -0,0 +1,56 @@
/********************************************************************************
* 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" *
********************************************************************************/
/**
* Sink.cxx
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#include "Sink.h"
using namespace std;
namespace example_region
{
Sink::Sink()
: fMaxIterations(0)
, fNumIterations(0)
{
}
void Sink::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
void Sink::Run()
{
FairMQChannel& dataInChannel = fChannels.at("data").at(0);
while (!NewStatePending())
{
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
dataInChannel.Receive(msg);
// void* ptr = msg->GetData();
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
break;
}
}
}
Sink::~Sink()
{
}
} // namespace example_region

View File

@@ -5,33 +5,38 @@
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEREGIONPROCESSOR_H
#define FAIRMQEXAMPLEREGIONPROCESSOR_H
/**
* Sink.h
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#ifndef FAIRMQEXAMPLEREGIONSINK_H
#define FAIRMQEXAMPLEREGIONSINK_H
#include <string>
#include "FairMQDevice.h"
namespace example_readout
namespace example_region
{
class Processor : public FairMQDevice
class Sink : public FairMQDevice
{
public:
Processor() {
OnData("bp", &Processor::HandleData);
}
Sink();
virtual ~Sink();
protected:
bool HandleData(FairMQMessagePtr& msg, int /*index*/)
{
FairMQMessagePtr msg2(NewMessageFor("ps", 0, msg->GetSize()));
if (Send(msg2, "ps") < 0) {
return false;
}
virtual void Run();
virtual void InitTask();
return true;
}
private:
uint64_t fMaxIterations;
uint64_t fNumIterations;
};
} // namespace example_readout
} // namespace example_region
#endif /* FAIRMQEXAMPLEREGIONPROCESSOR_H */
#endif /* FAIRMQEXAMPLEREGIONSINK_H */

View File

@@ -1,40 +0,0 @@
#!/bin/bash
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
msgSize="1000000"
if [[ $1 =~ ^[0-9]+$ ]]; then
msgSize=$1
fi
READOUT="fairmq-ex-readout-readout"
READOUT+=" --id readout1"
READOUT+=" --msg-size $msgSize"
READOUT+=" --channel-config name=rb,type=pair,method=bind,address=tcp://localhost:7777,transport=shmem"
xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$READOUT &
BUILDER="fairmq-ex-readout-builder"
BUILDER+=" --id builder1"
BUILDER+=" --output-name bp"
BUILDER+=" --channel-config name=rb,type=pair,method=connect,address=tcp://localhost:7777,transport=shmem"
BUILDER+=" name=bp,type=pair,method=connect,address=tcp://localhost:7778,transport=shmem"
xterm -geometry 80x23+500+0 -hold -e @EX_BIN_DIR@/$BUILDER &
PROCESSOR="fairmq-ex-readout-processor"
PROCESSOR+=" --id processor1"
PROCESSOR+=" --channel-config name=bp,type=pair,method=bind,address=tcp://localhost:7778,transport=shmem"
PROCESSOR+=" name=ps,type=pair,method=connect,address=tcp://localhost:7779,transport=shmem"
xterm -geometry 80x23+750+500 -hold -e @EX_BIN_DIR@/$PROCESSOR &
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"
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"
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &

View File

@@ -2,33 +2,31 @@
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
msgSize="1000000"
msgSize="2000000"
if [[ $1 =~ ^[0-9]+$ ]]; then
msgSize=$1
fi
READOUT="fairmq-ex-readout-readout"
READOUT+=" --id readout1"
READOUT+=" --msg-size $msgSize"
READOUT+=" --channel-config name=rb,type=pair,method=bind,address=tcp://localhost:7777,transport=shmem"
xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$READOUT &
SAMPLER="fairmq-ex-readout-sampler"
SAMPLER+=" --id sampler1"
SAMPLER+=" --severity debug"
SAMPLER+=" --transport shmem"
SAMPLER+=" --msg-size $msgSize"
# SAMPLER+=" --rate 10"
SAMPLER+=" --channel-config name=data1,type=pair,method=bind,address=tcp://127.0.0.1:7777,transport=shmem"
xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
BUILDER="fairmq-ex-readout-builder"
BUILDER+=" --id builder1"
BUILDER+=" --output-name bs"
BUILDER+=" --channel-config name=rb,type=pair,method=connect,address=tcp://localhost:7777,transport=shmem"
BUILDER+=" name=bs,type=pair,method=connect,address=tcp://localhost:7778,transport=shmem"
BUILDER+=" --severity debug"
BUILDER+=" --channel-config name=data1,type=pair,method=connect,address=tcp://127.0.0.1:7777,transport=shmem"
BUILDER+=" name=data2,type=pair,method=connect,address=tcp://127.0.0.1:7778,transport=ofi"
xterm -geometry 80x23+500+0 -hold -e @EX_BIN_DIR@/$BUILDER &
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"
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"
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &
SINK="fairmq-ex-readout-sink"
SINK+=" --id sink1"
SINK+=" --severity debug"
SINK+=" --ofi-size-hint $msgSize"
SINK+=" --channel-config name=data,type=pair,method=bind,address=tcp://127.0.0.1:7778,transport=ofi"
xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SINK &

View File

@@ -11,13 +11,10 @@
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("output-name", bpo::value<std::string>()->default_value("bs"), "Output channel name");
}
void addCustomOptions(bpo::options_description& /* options */)
{}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_readout::Builder();
return new example_region::Builder();
}

View File

@@ -1,20 +0,0 @@
/********************************************************************************
* 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" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "Processor.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& /* options */)
{}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
{
return new example_readout::Processor();
}

View File

@@ -7,7 +7,7 @@
********************************************************************************/
#include "runFairMQDevice.h"
#include "Readout.h"
#include "Sampler.h"
namespace bpo = boost::program_options;
@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_readout::Readout();
return new example_region::Sampler();
}

View File

@@ -1,23 +0,0 @@
/********************************************************************************
* 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" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "Sender.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("input-name", bpo::value<std::string>()->default_value("bs"), "Input channel name");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
{
return new example_readout::Sender();
}

View File

@@ -7,7 +7,7 @@
********************************************************************************/
#include "runFairMQDevice.h"
#include "Receiver.h"
#include "Sink.h"
namespace bpo = boost::program_options;
@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_readout::Receiver();
return new example_region::Sink();
}

View File

@@ -32,15 +32,16 @@ Sampler::Sampler()
void Sampler::InitTask()
{
fMsgSize = fConfig->GetProperty<int>("msg-size");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMsgSize = fConfig->GetValue<int>("msg-size");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data",
0,
10000000,
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport
--fNumUnackedMsgs;
if (fMaxIterations > 0) {
if (fMaxIterations > 0)
{
LOG(debug) << "Received ack";
}
}
@@ -57,14 +58,12 @@ bool Sampler::ConditionalRun()
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));
if (Send(msg, "data", 0) > 0) {
if (Send(msg, "data", 0) > 0)
{
++fNumUnackedMsgs;
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false;
}
@@ -76,7 +75,8 @@ bool Sampler::ConditionalRun()
void Sampler::ResetTask()
{
// if not all messages acknowledged, wait for a bit. But only once, since receiver could be already dead.
if (fNumUnackedMsgs != 0) {
if (fNumUnackedMsgs != 0)
{
LOG(debug) << "waiting for all acknowledgements... (" << fNumUnackedMsgs << ")";
this_thread::sleep_for(chrono::milliseconds(500));
LOG(debug) << "done, still unacked: " << fNumUnackedMsgs;

View File

@@ -28,22 +28,21 @@ Sink::Sink()
void Sink::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
void Sink::Run()
{
FairMQChannel& dataInChannel = fChannels.at("data").at(0);
while (!NewStatePending()) {
while (!NewStatePending())
{
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) {
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
break;
}

View File

@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_region::Sampler();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_region::Sink();
}

View File

@@ -31,8 +31,8 @@ Client::Client()
void Client::InitTask()
{
fText = fConfig->GetProperty<string>("text");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fText = fConfig->GetValue<string>("text");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Client::ConditionalRun()

View File

@@ -29,7 +29,7 @@ Server::Server()
void Server::InitTask()
{
// Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Server::HandleData(FairMQMessagePtr& req, int /*index*/)

View File

@@ -18,7 +18,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_req_rep::Client();
}

View File

@@ -17,7 +17,7 @@ void addCustomOptions(bpo::options_description& options)
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/)
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_req_rep::Server();
}

View File

@@ -16,450 +16,328 @@ if(BUILD_PMIX_PLUGIN)
add_subdirectory(plugins/PMIx)
endif()
if(BUILD_FAIRMQ OR BUILD_SDK)
###########
# Version #
###########
configure_file(Version.h.in
${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}/Version.h
@ONLY
)
install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}/Version.h
DESTINATION ${PROJECT_INSTALL_INCDIR}
)
#########
# Tools #
#########
set(target Tools)
##########################
# libFairMQ header files #
##########################
set(FAIRMQ_PUBLIC_HEADER_FILES
DeviceRunner.h
EventManager.h
FairMQChannel.h
FairMQDevice.h
FairMQLogger.h
FairMQMessage.h
FairMQParts.h
FairMQPoller.h
FairMQUnmanagedRegion.h
FairMQSocket.h
StateMachine.h
FairMQTransportFactory.h
MemoryResources.h
MemoryResourceTools.h
Tools.h
Transports.h
options/FairMQProgOptions.h
options/FairProgOptions.h
Plugin.h
PluginManager.h
PluginServices.h
runFairMQDevice.h
tools/CppSTL.h
tools/Network.h
tools/Process.h
tools/RateLimit.h
tools/Strings.h
tools/Unique.h
tools/Version.h
)
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(FAIRMQ_PRIVATE_HEADER_FILES
devices/FairMQBenchmarkSampler.h
devices/FairMQMerger.h
devices/FairMQMultiplier.h
devices/FairMQProxy.h
devices/FairMQSink.h
devices/FairMQSplitter.h
options/FairMQParser.h
options/FairMQSuboptParser.h
options/FairProgOptionsHelper.h
plugins/Builtin.h
plugins/Control.h
shmem/FairMQMessageSHM.h
shmem/FairMQPollerSHM.h
shmem/FairMQUnmanagedRegionSHM.h
shmem/FairMQSocketSHM.h
shmem/FairMQTransportFactorySHM.h
shmem/Common.h
shmem/Manager.h
shmem/Region.h
zeromq/FairMQMessageZMQ.h
zeromq/FairMQPollerZMQ.h
zeromq/FairMQUnmanagedRegionZMQ.h
zeromq/FairMQSocketZMQ.h
zeromq/FairMQTransportFactoryZMQ.h
)
set(TOOLS_SOURCE_FILES
tools/Network.cxx
tools/Process.cxx
tools/Semaphore.cxx
tools/Unique.cxx
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
nanomsg/FairMQMessageNN.h
nanomsg/FairMQPollerNN.h
nanomsg/FairMQUnmanagedRegionNN.h
nanomsg/FairMQSocketNN.h
nanomsg/FairMQTransportFactoryNN.h
)
add_library(${target}
${TOOLS_SOURCE_FILES}
${TOOLS_PUBLIC_HEADER_FILES}
)
target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
target_include_directories(${target}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(${target}
PRIVATE
FairLogger::FairLogger
PUBLIC
Boost::boost
)
set_target_properties(${target} PROPERTIES
VERSION ${PROJECT_GIT_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_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
target_include_directories(${target}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(${target}
PUBLIC
FairLogger::FairLogger
PRIVATE
Boost::boost
Tools
)
set_target_properties(${target} PROPERTIES
VERSION ${PROJECT_GIT_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 #
##########################
set(FAIRMQ_PUBLIC_HEADER_FILES
DeviceRunner.h
EventManager.h
FairMQChannel.h
FairMQDevice.h
FairMQLogger.h
FairMQMessage.h
FairMQParts.h
FairMQPoller.h
FairMQUnmanagedRegion.h
FairMQSocket.h
FairMQTransportFactory.h
MemoryResources.h
MemoryResourceTools.h
Transports.h
options/FairMQProgOptions.h
JSONParser.h
ProgOptionsFwd.h
ProgOptions.h
Properties.h
PropertyOutput.h
SuboptParser.h
Plugin.h
PluginManager.h
PluginServices.h
runFairMQDevice.h
if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
ofi/Context.h
ofi/Message.h
ofi/Poller.h
ofi/Socket.h
ofi/TransportFactory.h
)
endif()
set(FAIRMQ_PRIVATE_HEADER_FILES
devices/FairMQBenchmarkSampler.h
devices/FairMQMerger.h
devices/FairMQMultiplier.h
devices/FairMQProxy.h
devices/FairMQSink.h
devices/FairMQSplitter.h
plugins/Builtin.h
plugins/config/Config.h
plugins/Control.h
shmem/FairMQMessageSHM.h
shmem/FairMQPollerSHM.h
shmem/FairMQUnmanagedRegionSHM.h
shmem/FairMQSocketSHM.h
shmem/FairMQTransportFactorySHM.h
shmem/Common.h
shmem/Manager.h
shmem/Region.h
zeromq/FairMQMessageZMQ.h
zeromq/FairMQPollerZMQ.h
zeromq/FairMQUnmanagedRegionZMQ.h
zeromq/FairMQSocketZMQ.h
zeromq/FairMQTransportFactoryZMQ.h
##########################
# libFairMQ source files #
##########################
set(FAIRMQ_SOURCE_FILES
DeviceRunner.cxx
FairMQChannel.cxx
FairMQDevice.cxx
FairMQLogger.cxx
FairMQMessage.cxx
FairMQPoller.cxx
FairMQSocket.cxx
StateMachine.cxx
FairMQTransportFactory.cxx
devices/FairMQBenchmarkSampler.cxx
devices/FairMQMerger.cxx
devices/FairMQMultiplier.cxx
devices/FairMQProxy.cxx
devices/FairMQSplitter.cxx
options/FairMQParser.cxx
options/FairMQProgOptions.cxx
options/FairMQSuboptParser.cxx
Plugin.cxx
PluginManager.cxx
PluginServices.cxx
plugins/Control.cxx
shmem/FairMQMessageSHM.cxx
shmem/FairMQPollerSHM.cxx
shmem/FairMQUnmanagedRegionSHM.cxx
shmem/FairMQSocketSHM.cxx
shmem/FairMQTransportFactorySHM.cxx
shmem/Manager.cxx
shmem/Region.cxx
tools/Network.cxx
tools/Process.cxx
tools/Unique.cxx
zeromq/FairMQMessageZMQ.cxx
zeromq/FairMQPollerZMQ.cxx
zeromq/FairMQUnmanagedRegionZMQ.cxx
zeromq/FairMQSocketZMQ.cxx
zeromq/FairMQTransportFactoryZMQ.cxx
MemoryResources.cxx
)
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
nanomsg/FairMQMessageNN.cxx
nanomsg/FairMQPollerNN.cxx
nanomsg/FairMQUnmanagedRegionNN.cxx
nanomsg/FairMQSocketNN.cxx
nanomsg/FairMQTransportFactoryNN.cxx
)
endif()
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
nanomsg/FairMQMessageNN.h
nanomsg/FairMQPollerNN.h
nanomsg/FairMQUnmanagedRegionNN.h
nanomsg/FairMQSocketNN.h
nanomsg/FairMQTransportFactoryNN.h
)
endif()
if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
ofi/Context.h
ofi/Message.h
ofi/Poller.h
ofi/Socket.h
ofi/TransportFactory.h
)
endif()
##########################
# libFairMQ source files #
##########################
set(FAIRMQ_SOURCE_FILES
DeviceRunner.cxx
FairMQChannel.cxx
FairMQDevice.cxx
FairMQLogger.cxx
FairMQMessage.cxx
FairMQPoller.cxx
FairMQSocket.cxx
FairMQTransportFactory.cxx
devices/FairMQBenchmarkSampler.cxx
devices/FairMQMerger.cxx
devices/FairMQMultiplier.cxx
devices/FairMQProxy.cxx
devices/FairMQSplitter.cxx
Plugin.cxx
PluginManager.cxx
PluginServices.cxx
ProgOptions.cxx
JSONParser.cxx
Properties.cxx
SuboptParser.cxx
plugins/config/Config.cxx
plugins/Control.cxx
shmem/FairMQMessageSHM.cxx
shmem/FairMQPollerSHM.cxx
shmem/FairMQUnmanagedRegionSHM.cxx
shmem/FairMQSocketSHM.cxx
shmem/FairMQTransportFactorySHM.cxx
shmem/Manager.cxx
shmem/Region.cxx
zeromq/FairMQMessageZMQ.cxx
zeromq/FairMQPollerZMQ.cxx
zeromq/FairMQUnmanagedRegionZMQ.cxx
zeromq/FairMQSocketZMQ.cxx
zeromq/FairMQTransportFactoryZMQ.cxx
MemoryResources.cxx
if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
ofi/Context.cxx
ofi/Message.cxx
ofi/Poller.cxx
ofi/Socket.cxx
ofi/TransportFactory.cxx
)
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
nanomsg/FairMQMessageNN.cxx
nanomsg/FairMQPollerNN.cxx
nanomsg/FairMQUnmanagedRegionNN.cxx
nanomsg/FairMQSocketNN.cxx
nanomsg/FairMQTransportFactoryNN.cxx
)
endif()
if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
ofi/Context.cxx
ofi/Message.cxx
ofi/Poller.cxx
ofi/Socket.cxx
ofi/TransportFactory.cxx
)
endif()
endif()
###################
# configure files #
###################
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run/startMQBenchmark.sh.in ${CMAKE_CURRENT_BINARY_DIR}/startMQBenchmark.sh)
#################################
# define libFairMQ build target #
#################################
if(FAST_BUILD)
set(_target FairMQ_)
else()
set(_target FairMQ)
endif()
add_library(${_target}
${FAIRMQ_SOURCE_FILES}
${FAIRMQ_PUBLIC_HEADER_FILES} # for IDE integration
${FAIRMQ_PRIVATE_HEADER_FILES} # for IDE integration
)
set_target_properties(${_target} PROPERTIES LABELS coverage)
if(FAST_BUILD)
set_target_properties(${_target} PROPERTIES OUTPUT_NAME FairMQ)
endif()
###################
# configure files #
###################
set(FAIRMQ_BIN_DIR ${CMAKE_BINARY_DIR}/fairmq)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run/startMQBenchmark.sh.in ${CMAKE_CURRENT_BINARY_DIR}/startMQBenchmark.sh)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/options/startConfigExample.sh.in ${CMAKE_CURRENT_BINARY_DIR}/startConfigExample.sh)
############################
# preprocessor definitions #
############################
target_compile_definitions(${_target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
if(BUILD_NANOMSG_TRANSPORT)
target_compile_definitions(${_target} PRIVATE BUILD_NANOMSG_TRANSPORT)
endif()
if(BUILD_OFI_TRANSPORT)
target_compile_definitions(${_target} PRIVATE BUILD_OFI_TRANSPORT)
endif()
#################################
# define libFairMQ build target #
#################################
if(FAST_BUILD)
set(_target FairMQ_)
else()
set(_target FairMQ)
endif()
add_library(${_target}
${FAIRMQ_SOURCE_FILES}
${FAIRMQ_PUBLIC_HEADER_FILES} # for IDE integration
${FAIRMQ_PRIVATE_HEADER_FILES} # for IDE integration
)
set_target_properties(${_target} PROPERTIES LABELS coverage)
if(FAST_BUILD)
set_target_properties(${_target} PROPERTIES OUTPUT_NAME FairMQ)
endif()
#######################
# include directories #
#######################
target_include_directories(${_target}
PUBLIC # consumers inherit public include directories
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
$<INSTALL_INTERFACE:include/fairmq>
$<INSTALL_INTERFACE:include>
)
############################
# preprocessor definitions #
############################
target_compile_definitions(${_target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
if(BUILD_NANOMSG_TRANSPORT)
target_compile_definitions(${_target} PRIVATE BUILD_NANOMSG_TRANSPORT)
endif()
if(BUILD_OFI_TRANSPORT)
target_compile_definitions(${_target} PRIVATE BUILD_OFI_TRANSPORT)
endif()
##################
# link libraries #
##################
if(BUILD_NANOMSG_TRANSPORT)
set(NANOMSG_DEPS nanomsg msgpackc-cxx)
endif()
if(BUILD_OFI_TRANSPORT)
set(OFI_DEPS
asiofi::asiofi
Boost::container
)
endif()
set(optional_deps ${NANOMSG_DEPS} ${OFI_DEPS})
if(optional_deps)
list(REMOVE_DUPLICATES optional_deps)
endif()
target_link_libraries(${_target}
INTERFACE # only consumers link against interface dependencies
#######################
# include directories #
#######################
target_include_directories(${_target}
PUBLIC # consumers inherit public include directories
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
$<INSTALL_INTERFACE:include/fairmq>
$<INSTALL_INTERFACE:include>
)
##################
# link libraries #
##################
if(BUILD_NANOMSG_TRANSPORT)
set(NANOMSG_DEPS nanomsg msgpackc-cxx)
endif()
if(BUILD_OFI_TRANSPORT)
set(OFI_DEPS
asiofi::asiofi
Boost::container
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
Threads::Threads
dl
$<$<PLATFORM_ID:Linux>:rt>
Boost::boost
Boost::program_options
Boost::filesystem
Boost::regex
FairLogger::FairLogger
Tools
StateMachine
PRIVATE # only libFairMQ links against private dependencies
libzmq
${NANOMSG_DEPS}
${OFI_DEPS}
AZMQ::AZMQ
)
endif()
set(optional_deps ${NANOMSG_DEPS} ${OFI_DEPS})
if(optional_deps)
list(REMOVE_DUPLICATES optional_deps)
endif()
target_link_libraries(${_target}
INTERFACE # only consumers link against interface dependencies
Boost::container
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
Threads::Threads
dl
$<$<PLATFORM_ID:Linux>:rt>
Boost::boost
Boost::program_options
Boost::filesystem
Boost::regex
FairLogger::FairLogger
PRIVATE # only libFairMQ links against private dependencies
libzmq
${NANOMSG_DEPS}
${OFI_DEPS}
)
set_target_properties(${_target} PROPERTIES
VERSION ${PROJECT_GIT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
)
##############
# fast build #
##############
if(FAST_BUILD)
set_target_properties(${_target} PROPERTIES
VERSION ${PROJECT_GIT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
COTIRE_UNITY_TARGET_NAME "FairMQ"
# COTIRE_ENABLE_PRECOMPILED_HEADER FALSE
EXCLUDE_FROM_ALL TRUE
)
##############
# fast build #
##############
if(FAST_BUILD)
set_target_properties(${_target} PROPERTIES
COTIRE_UNITY_TARGET_NAME "FairMQ"
# COTIRE_ENABLE_PRECOMPILED_HEADER FALSE
EXCLUDE_FROM_ALL TRUE
)
cotire(${_target})
set_target_properties(FairMQ PROPERTIES EXCLUDE_FROM_ALL FALSE)
set_target_properties(FairMQ PROPERTIES LABELS coverage)
endif()
###############
# executables #
###############
add_executable(fairmq-bsampler run/runBenchmarkSampler.cxx)
target_link_libraries(fairmq-bsampler FairMQ)
add_executable(fairmq-merger run/runMerger.cxx)
target_link_libraries(fairmq-merger FairMQ)
add_executable(fairmq-multiplier run/runMultiplier.cxx)
target_link_libraries(fairmq-multiplier FairMQ)
add_executable(fairmq-proxy run/runProxy.cxx)
target_link_libraries(fairmq-proxy FairMQ)
add_executable(fairmq-sink run/runSink.cxx)
target_link_libraries(fairmq-sink FairMQ)
add_executable(fairmq-splitter run/runSplitter.cxx)
target_link_libraries(fairmq-splitter FairMQ)
add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
target_compile_definitions(fairmq-shmmonitor PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries(fairmq-shmmonitor PUBLIC
Threads::Threads
$<$<PLATFORM_ID:Linux>:rt>
Boost::boost
Boost::date_time
Boost::program_options
)
target_include_directories(fairmq-shmmonitor PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
)
add_executable(fairmq-uuid-gen run/runUuidGenerator.cxx)
target_link_libraries(fairmq-uuid-gen FairMQ)
###########
# install #
###########
install(
TARGETS
FairMQ
fairmq-bsampler
fairmq-merger
fairmq-multiplier
fairmq-proxy
fairmq-sink
fairmq-splitter
fairmq-shmmonitor
fairmq-uuid-gen
EXPORT ${PROJECT_EXPORT_SET}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${PROJECT_INSTALL_LIBDIR}
)
# preserve relative path and prepend fairmq
foreach(HEADER ${FAIRMQ_PUBLIC_HEADER_FILES})
get_filename_component(_path ${HEADER} DIRECTORY)
file(TO_CMAKE_PATH ${PROJECT_INSTALL_INCDIR}/${_path} _destination)
install(FILES ${HEADER}
DESTINATION ${_destination}
)
endforeach()
cotire(${_target})
set_target_properties(FairMQ PROPERTIES EXCLUDE_FROM_ALL FALSE)
set_target_properties(FairMQ PROPERTIES LABELS coverage)
endif()
if(BUILD_SDK)
add_subdirectory(sdk)
endif()
###############
# executables #
###############
add_executable(fairmq-bsampler run/runBenchmarkSampler.cxx)
target_link_libraries(fairmq-bsampler FairMQ)
add_executable(fairmq-merger run/runMerger.cxx)
target_link_libraries(fairmq-merger FairMQ)
add_executable(fairmq-multiplier run/runMultiplier.cxx)
target_link_libraries(fairmq-multiplier FairMQ)
add_executable(fairmq-proxy run/runProxy.cxx)
target_link_libraries(fairmq-proxy FairMQ)
add_executable(fairmq-sink run/runSink.cxx)
target_link_libraries(fairmq-sink FairMQ)
add_executable(fairmq-splitter run/runSplitter.cxx)
target_link_libraries(fairmq-splitter FairMQ)
add_executable(runConfigExample options/runConfigEx.cxx)
target_link_libraries(runConfigExample FairMQ)
add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
target_link_libraries(fairmq-shmmonitor PUBLIC
Threads::Threads
$<$<PLATFORM_ID:Linux>:rt>
Boost::boost
Boost::date_time
Boost::program_options
)
target_include_directories(fairmq-shmmonitor PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
)
add_executable(fairmq-uuid-gen run/runUuidGenerator.cxx)
target_link_libraries(fairmq-uuid-gen FairMQ)
###########
# install #
###########
install(
TARGETS
FairMQ
fairmq-bsampler
fairmq-merger
fairmq-multiplier
fairmq-proxy
fairmq-sink
fairmq-splitter
fairmq-shmmonitor
fairmq-uuid-gen
EXPORT ${PROJECT_EXPORT_SET}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${PROJECT_INSTALL_LIBDIR}
)
# preserve relative path and prepend fairmq
foreach(HEADER ${FAIRMQ_PUBLIC_HEADER_FILES})
get_filename_component(_path ${HEADER} DIRECTORY)
file(TO_CMAKE_PATH ${PROJECT_INSTALL_INCDIR}/${_path} _destination)
install(FILES ${HEADER}
DESTINATION ${_destination}
)
endforeach()

View File

@@ -12,10 +12,9 @@
#include <fairmq/Tools.h>
#include <fairmq/Version.h>
using namespace std;
using namespace fair::mq;
DeviceRunner::DeviceRunner(int argc, char*const* argv, bool printLogo)
DeviceRunner::DeviceRunner(int argc, char* const argv[], bool printLogo)
: fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))
, fConfig()
, fDevice(nullptr)
@@ -24,82 +23,8 @@ DeviceRunner::DeviceRunner(int argc, char*const* argv, bool printLogo)
, fEvents()
{}
bool DeviceRunner::HandleGeneralOptions(const fair::mq::ProgOptions& config, bool printLogo)
{
if (config.Count("help")) {
config.PrintHelp();
return false;
}
if (config.Count("print-options")) {
config.PrintOptionsRaw();
return false;
}
if (config.Count("print-channels") || config.Count("version")) {
fair::Logger::SetConsoleSeverity("nolog");
} else {
string severity = config.GetProperty<string>("severity");
string logFile = config.GetProperty<string>("log-to-file");
string logFileSeverity = config.GetProperty<string>("file-severity");
bool color = config.GetProperty<bool>("color");
string verbosity = config.GetProperty<string>("verbosity");
fair::Logger::SetVerbosity(verbosity);
if (logFile != "") {
fair::Logger::InitFileSink(logFileSeverity, logFile);
fair::Logger::SetConsoleSeverity("nolog");
} else {
fair::Logger::SetConsoleColor(color);
fair::Logger::SetConsoleSeverity(severity);
}
if (printLogo) {
LOG(info) << endl
<< " ______ _ _______ _________ " << endl
<< " / ____/___ _(_)_______ |/ /_ __ \\ version " << FAIRMQ_GIT_VERSION << endl
<< " / /_ / __ `/ / ___/__ /|_/ /_ / / / build " << FAIRMQ_BUILD_TYPE << endl
<< " / __/ / /_/ / / / _ / / / / /_/ / " << FAIRMQ_REPO_URL << endl
<< " /_/ \\__,_/_/_/ /_/ /_/ \\___\\_\\ " << FAIRMQ_LICENSE << " © " << FAIRMQ_COPYRIGHT << endl;
}
config.PrintOptions();
}
return true;
}
void DeviceRunner::SubscribeForConfigChange()
{
fConfig.Subscribe<bool>("device-runner", [](const std::string& key, const bool val) {
if (key == "color") {
fair::Logger::SetConsoleColor(val);
}
});
fConfig.Subscribe<string>("device-runner", [&](const std::string& key, const std::string val) {
if (key == "severity") {
fair::Logger::SetConsoleSeverity(val);
} else if (key == "file-severity") {
fair::Logger::SetFileSeverity(val);
} else if (key == "verbosity") {
fair::Logger::SetVerbosity(val);
} else if (key == "log-to-file") {
string fileSeverity = fConfig.GetProperty<string>("file-severity");
fair::Logger::InitFileSink(fileSeverity, val);
}
});
}
void DeviceRunner::UnsubscribeFromConfigChange()
{
fConfig.Unsubscribe<bool>("device-runner");
fConfig.Unsubscribe<string>("device-runner");
}
auto DeviceRunner::Run() -> int
{
fPluginManager.LoadPlugin("s:config");
////// CALL HOOK ///////
fEvents.Emit<hooks::LoadPlugins>(*this);
////////////////////////
@@ -111,25 +36,28 @@ auto DeviceRunner::Run() -> int
fEvents.Emit<hooks::SetCustomCmdLineOptions>(*this);
////////////////////////
fPluginManager.ForEachPluginProgOptions([&](boost::program_options::options_description options) {
fConfig.AddToCmdLineOptions(options);
});
fPluginManager.ForEachPluginProgOptions(
[&](boost::program_options::options_description options) {
fConfig.AddToCmdLineOptions(options);
});
fConfig.AddToCmdLineOptions(fPluginManager.ProgramOptions());
////// CALL HOOK ///////
fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);
////////////////////////
fConfig.ParseAll(fRawCmdLineArgs, true);
if (!HandleGeneralOptions(fConfig)) {
if (fConfig.ParseAll(fRawCmdLineArgs, true)) {
return 0;
}
fConfig.Notify();
// handle configuration updates (for general options)
SubscribeForConfigChange();
if (fPrintLogo) {
LOG(info) << std::endl
<< " ______ _ _______ _________ " << std::endl
<< " / ____/___ _(_)_______ |/ /_ __ \\ version " << FAIRMQ_GIT_VERSION << std::endl
<< " / /_ / __ `/ / ___/__ /|_/ /_ / / / build " << FAIRMQ_BUILD_TYPE << std::endl
<< " / __/ / /_/ / / / _ / / / / /_/ / " << FAIRMQ_REPO_URL << std::endl
<< " /_/ \\__,_/_/_/ /_/ /_/ \\___\\_\\ " << FAIRMQ_LICENSE << " © " << FAIRMQ_COPYRIGHT << std::endl;
}
////// CALL HOOK ///////
fEvents.Emit<hooks::InstantiateDevice>(*this);
@@ -152,8 +80,7 @@ auto DeviceRunner::Run() -> int
// Handle --version
if (fConfig.Count("version")) {
cout << "FairMQ version: " << FAIRMQ_GIT_VERSION << endl;
cout << "User device version: " << fDevice->GetVersion() << endl;
std::cout << "User device version: " << fDevice->GetVersion() << std::endl;
fDevice->ChangeState(fair::mq::Transition::End);
return 0;
}
@@ -175,9 +102,6 @@ auto DeviceRunner::Run() -> int
// Wait for control plugin to release device control
fPluginManager.WaitForPluginsToReleaseDeviceControl();
// stop handling configuration updates (for general options)
UnsubscribeFromConfigChange();
return 0;
}
@@ -185,7 +109,7 @@ auto DeviceRunner::RunWithExceptionHandlers() -> int
{
try {
return Run();
} catch (exception& e) {
} catch (std::exception& e) {
LOG(error) << "Uncaught exception reached the top of DeviceRunner: " << e.what();
return 1;
} catch (...) {

View File

@@ -11,9 +11,9 @@
#include <fairmq/EventManager.h>
#include <fairmq/PluginManager.h>
#include <fairmq/ProgOptions.h>
#include <FairMQDevice.h>
#include <FairMQLogger.h>
#include <options/FairMQProgOptions.h>
#include <functional>
#include <memory>
@@ -51,16 +51,11 @@ namespace mq {
class DeviceRunner
{
public:
DeviceRunner(int argc, char*const* argv, bool printLogo = true);
DeviceRunner(int argc, char* const argv[], bool printLogo = true);
auto Run() -> int;
auto RunWithExceptionHandlers() -> int;
static bool HandleGeneralOptions(const fair::mq::ProgOptions& config, bool printLogo = true);
void SubscribeForConfigChange();
void UnsubscribeFromConfigChange();
template<typename H>
auto AddHook(std::function<void(DeviceRunner&)> hook) -> void
{
@@ -73,7 +68,7 @@ class DeviceRunner
}
std::vector<std::string> fRawCmdLineArgs;
fair::mq::ProgOptions fConfig;
FairMQProgOptions fConfig;
std::unique_ptr<FairMQDevice> fDevice;
PluginManager fPluginManager;
const bool fPrintLogo;

View File

@@ -5,113 +5,64 @@
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
/**
* FairMQChannel.cxx
*
* @since 2015-06-02
* @author A. Rybalchenko
*/
#include "FairMQChannel.h"
#include <fairmq/Tools.h>
#include <boost/algorithm/string.hpp> // join/split
#include <regex>
#include <set>
#include <random>
using namespace std;
using namespace fair::mq;
template<typename T>
T GetPropertyOrDefault(const fair::mq::Properties& m, const string& k, const T& ifNotFound) noexcept
{
if (m.count(k)) {
return boost::any_cast<T>(m.at(k));
}
return ifNotFound;
}
constexpr fair::mq::Transport FairMQChannel::DefaultTransportType;
constexpr const char* FairMQChannel::DefaultTransportName;
constexpr const char* FairMQChannel::DefaultName;
constexpr const char* FairMQChannel::DefaultType;
constexpr const char* FairMQChannel::DefaultMethod;
constexpr const char* FairMQChannel::DefaultAddress;
constexpr int FairMQChannel::DefaultSndBufSize;
constexpr int FairMQChannel::DefaultRcvBufSize;
constexpr int FairMQChannel::DefaultSndKernelSize;
constexpr int FairMQChannel::DefaultRcvKernelSize;
constexpr int FairMQChannel::DefaultLinger;
constexpr int FairMQChannel::DefaultRateLogging;
constexpr int FairMQChannel::DefaultPortRangeMin;
constexpr int FairMQChannel::DefaultPortRangeMax;
constexpr bool FairMQChannel::DefaultAutoBind;
mutex FairMQChannel::fChannelMutex;
FairMQChannel::FairMQChannel()
: FairMQChannel(DefaultName, DefaultType, DefaultMethod, DefaultAddress, nullptr)
{}
FairMQChannel::FairMQChannel(const string& name)
: FairMQChannel(name, DefaultType, DefaultMethod, DefaultAddress, nullptr)
: FairMQChannel("", "unspecified", "unspecified", "unspecified", nullptr)
{}
FairMQChannel::FairMQChannel(const string& type, const string& method, const string& address)
: FairMQChannel(DefaultName, type, method, address, nullptr)
: FairMQChannel("", type, method, address, nullptr)
{}
FairMQChannel::FairMQChannel(const string& name, const string& type, shared_ptr<FairMQTransportFactory> factory)
: FairMQChannel(name, type, DefaultMethod, DefaultAddress, factory)
: FairMQChannel(name, type, "unspecified", "unspecified", factory)
{}
FairMQChannel::FairMQChannel(const string& name, const string& type, const string& method, const string& address, shared_ptr<FairMQTransportFactory> factory)
: fTransportFactory(factory)
, fTransportType(factory ? factory->GetType() : DefaultTransportType)
, fTransportType(factory ? factory->GetType() : fair::mq::Transport::DEFAULT)
, fSocket(factory ? factory->CreateSocket(type, name) : nullptr)
, fName(name)
, fType(type)
, fMethod(method)
, fAddress(address)
, fSndBufSize(DefaultSndBufSize)
, fRcvBufSize(DefaultRcvBufSize)
, fSndKernelSize(DefaultSndKernelSize)
, fRcvKernelSize(DefaultRcvKernelSize)
, fLinger(DefaultLinger)
, fRateLogging(DefaultRateLogging)
, fPortRangeMin(DefaultPortRangeMin)
, fPortRangeMax(DefaultPortRangeMax)
, fAutoBind(DefaultAutoBind)
, fSndBufSize(1000)
, fRcvBufSize(1000)
, fSndKernelSize(0)
, fRcvKernelSize(0)
, fLinger(500)
, fRateLogging(1)
, fPortRangeMin(22000)
, fPortRangeMax(23000)
, fAutoBind(true)
, fName(name)
, fIsValid(false)
, fMultipart(false)
, fModified(true)
, fReset(false)
, fMtx()
{}
FairMQChannel::FairMQChannel(const string& name, int index, const fair::mq::Properties& properties)
: FairMQChannel(tools::ToString(name, "[", index, "]"), "unspecified", "unspecified", "unspecified", nullptr)
{
string prefix(tools::ToString("chans.", name, ".", index, "."));
fType = GetPropertyOrDefault(properties, string(prefix + "type"), fType);
fMethod = GetPropertyOrDefault(properties, string(prefix + "method"), fMethod);
fAddress = GetPropertyOrDefault(properties, string(prefix + "address"), fAddress);
fTransportType = TransportTypes.at(GetPropertyOrDefault(properties, string(prefix + "transport"), TransportNames.at(fTransportType)));
fSndBufSize = GetPropertyOrDefault(properties, string(prefix + "sndBufSize"), fSndBufSize);
fRcvBufSize = GetPropertyOrDefault(properties, string(prefix + "rcvBufSize"), fRcvBufSize);
fSndKernelSize = GetPropertyOrDefault(properties, string(prefix + "sndKernelSize"), fSndKernelSize);
fRcvKernelSize = GetPropertyOrDefault(properties, string(prefix + "rcvKernelSize"), fRcvKernelSize);
fLinger = GetPropertyOrDefault(properties, string(prefix + "linger"), fLinger);
fRateLogging = GetPropertyOrDefault(properties, string(prefix + "rateLogging"), fRateLogging);
fPortRangeMin = GetPropertyOrDefault(properties, string(prefix + "portRangeMin"), fPortRangeMin);
fPortRangeMax = GetPropertyOrDefault(properties, string(prefix + "portRangeMax"), fPortRangeMax);
fAutoBind = GetPropertyOrDefault(properties, string(prefix + "autoBind"), fAutoBind);
}
FairMQChannel::FairMQChannel(const FairMQChannel& chan)
: FairMQChannel(chan, chan.fName)
{}
FairMQChannel::FairMQChannel(const FairMQChannel& chan, const string& newName)
: fTransportFactory(nullptr)
, fTransportType(chan.fTransportType)
, fSocket(nullptr)
, fName(newName)
, fType(chan.fType)
, fMethod(chan.fMethod)
, fAddress(chan.fAddress)
@@ -124,6 +75,7 @@ FairMQChannel::FairMQChannel(const FairMQChannel& chan, const string& newName)
, fPortRangeMin(chan.fPortRangeMin)
, fPortRangeMax(chan.fPortRangeMax)
, fAutoBind(chan.fAutoBind)
, fName(chan.fName)
, fIsValid(false)
, fMultipart(chan.fMultipart)
, fModified(chan.fModified)
@@ -135,7 +87,6 @@ FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
fTransportFactory = nullptr;
fTransportType = chan.fTransportType;
fSocket = nullptr;
fName = chan.fName;
fType = chan.fType;
fMethod = chan.fMethod;
fAddress = chan.fAddress;
@@ -148,6 +99,7 @@ FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
fPortRangeMin = chan.fPortRangeMin;
fPortRangeMax = chan.fPortRangeMax;
fAutoBind = chan.fAutoBind;
fName = chan.fName;
fIsValid = false;
fMultipart = chan.fMultipart;
fModified = chan.fModified;
@@ -164,13 +116,13 @@ FairMQSocket & FairMQChannel::GetSocket() const
string FairMQChannel::GetName() const
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fName;
}
string FairMQChannel::GetPrefix() const
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
string prefix = fName;
prefix = prefix.erase(fName.rfind('['));
return prefix;
@@ -178,7 +130,7 @@ string FairMQChannel::GetPrefix() const
string FairMQChannel::GetIndex() const
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
string indexStr = fName;
indexStr.erase(indexStr.rfind(']'));
indexStr.erase(0, indexStr.rfind('[') + 1);
@@ -187,306 +139,296 @@ string FairMQChannel::GetIndex() const
string FairMQChannel::GetType() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fType;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetType: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
string FairMQChannel::GetMethod() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fMethod;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetMethod: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
string FairMQChannel::GetAddress() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fAddress;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetAddress: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
string FairMQChannel::GetTransportName() const
try {
lock_guard<mutex> lock(fMtx);
return TransportNames.at(fTransportType);
lock_guard<mutex> lock(fChannelMutex);
return fair::mq::TransportNames.at(fTransportType);
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetTransportName: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
Transport FairMQChannel::GetTransportType() const
try {
lock_guard<mutex> lock(fMtx);
return fTransportType;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetTransportType: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetSndBufSize() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fSndBufSize;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetSndBufSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetRcvBufSize() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fRcvBufSize;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetRcvBufSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetSndKernelSize() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fSndKernelSize;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetSndKernelSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetRcvKernelSize() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fRcvKernelSize;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetRcvKernelSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetLinger() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fLinger;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetLinger: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetRateLogging() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fRateLogging;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetRateLogging: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetPortRangeMin() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fPortRangeMin;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetPortRangeMin: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
int FairMQChannel::GetPortRangeMax() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fPortRangeMax;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetPortRangeMax: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
bool FairMQChannel::GetAutoBind() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fAutoBind;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::GetAutoBind: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateType(const string& type)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fType = type;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateType: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateMethod(const string& method)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fMethod = method;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateMethod: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateAddress(const string& address)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fAddress = address;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateAddress: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateTransport(const string& transport)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fTransportType = TransportTypes.at(transport);
fTransportType = fair::mq::TransportTypes.at(transport);
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateTransport: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateSndBufSize(const int sndBufSize)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fSndBufSize = sndBufSize;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateSndBufSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateRcvBufSize(const int rcvBufSize)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fRcvBufSize = rcvBufSize;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateRcvBufSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateSndKernelSize(const int sndKernelSize)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fSndKernelSize = sndKernelSize;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateSndKernelSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateRcvKernelSize(const int rcvKernelSize)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fRcvKernelSize = rcvKernelSize;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateRcvKernelSize: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateLinger(const int duration)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fLinger = duration;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateLinger: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateRateLogging(const int rateLogging)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fRateLogging = rateLogging;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateRateLogging: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdatePortRangeMin(const int minPort)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fPortRangeMin = minPort;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdatePortRangeMin: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdatePortRangeMax(const int maxPort)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fPortRangeMax = maxPort;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdatePortRangeMax: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateAutoBind(const bool autobind)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fAutoBind = autobind;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateAutoBind: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
auto FairMQChannel::SetModified(const bool modified) -> void
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fModified = modified;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::SetModified: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
void FairMQChannel::UpdateName(const string& name)
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
fName = name;
fModified = true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::UpdateName: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
bool FairMQChannel::IsValid() const
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fIsValid;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::IsValid: " << e.what();
throw ChannelConfigurationError(tools::ToString("failed to acquire lock: ", e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString("failed to acquire lock: ", e.what()));
}
bool FairMQChannel::Validate()
try {
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
stringstream ss;
ss << "Validating channel '" << fName << "'... ";
@@ -496,22 +438,13 @@ try {
return true;
}
// validate channel name
smatch m;
if (regex_search(fName, m, regex("[^a-zA-Z0-9\\-_\\[\\]#]"))) {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "channel name contains illegal character: '" << m.str(0) << "', allowed characters are: a-z, A-Z, 0-9, -, _, [, ], #";
return false;
}
// validate socket type
const set<string> socketTypes{ "sub", "pub", "pull", "push", "req", "rep", "xsub", "xpub", "dealer", "router", "pair" };
if (socketTypes.find(fType) == socketTypes.end()) {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "Invalid channel type: '" << fType << "'";
throw ChannelConfigurationError(tools::ToString("Invalid channel type: '", fType, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("Invalid channel type: '", fType, "'"));
}
// validate socket address
@@ -534,7 +467,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "Invalid endpoint connection method: '" << fMethod << "' for " << endpoint;
throw ChannelConfigurationError(tools::ToString("Invalid endpoint connection method: '", fMethod, "' for ", endpoint));
throw ChannelConfigurationError(fair::mq::tools::ToString("Invalid endpoint connection method: '", fMethod, "' for ", endpoint));
}
address = endpoint;
}
@@ -590,7 +523,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "invalid channel send buffer size (cannot be negative): '" << fSndBufSize << "'";
throw ChannelConfigurationError(tools::ToString("invalid channel send buffer size (cannot be negative): '", fSndBufSize, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("invalid channel send buffer size (cannot be negative): '", fSndBufSize, "'"));
}
// validate socket buffer size for receiving
@@ -598,7 +531,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "invalid channel receive buffer size (cannot be negative): '" << fRcvBufSize << "'";
throw ChannelConfigurationError(tools::ToString("invalid channel receive buffer size (cannot be negative): '", fRcvBufSize, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("invalid channel receive buffer size (cannot be negative): '", fRcvBufSize, "'"));
}
// validate socket kernel transmit size for sending
@@ -606,7 +539,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "invalid channel send kernel transmit size (cannot be negative): '" << fSndKernelSize << "'";
throw ChannelConfigurationError(tools::ToString("invalid channel send kernel transmit size (cannot be negative): '", fSndKernelSize, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("invalid channel send kernel transmit size (cannot be negative): '", fSndKernelSize, "'"));
}
// validate socket kernel transmit size for receiving
@@ -614,7 +547,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "invalid channel receive kernel transmit size (cannot be negative): '" << fRcvKernelSize << "'";
throw ChannelConfigurationError(tools::ToString("invalid channel receive kernel transmit size (cannot be negative): '", fRcvKernelSize, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("invalid channel receive kernel transmit size (cannot be negative): '", fRcvKernelSize, "'"));
}
// validate socket rate logging interval
@@ -622,7 +555,7 @@ try {
ss << "INVALID";
LOG(debug) << ss.str();
LOG(error) << "invalid socket rate logging interval (cannot be negative): '" << fRateLogging << "'";
throw ChannelConfigurationError(tools::ToString("invalid socket rate logging interval (cannot be negative): '", fRateLogging, "'"));
throw ChannelConfigurationError(fair::mq::tools::ToString("invalid socket rate logging interval (cannot be negative): '", fRateLogging, "'"));
}
fIsValid = true;
@@ -631,12 +564,12 @@ try {
return true;
} catch (exception& e) {
LOG(error) << "Exception caught in FairMQChannel::ValidateChannel: " << e.what();
throw ChannelConfigurationError(tools::ToString(e.what()));
throw ChannelConfigurationError(fair::mq::tools::ToString(e.what()));
}
void FairMQChannel::Init()
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fSocket = fTransportFactory->CreateSocket(fType, fName);
@@ -658,14 +591,14 @@ void FairMQChannel::Init()
bool FairMQChannel::ConnectEndpoint(const string& endpoint)
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
return fSocket->Connect(endpoint);
}
bool FairMQChannel::BindEndpoint(string& endpoint)
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
// try to bind to the configured port. If it fails, try random one (if AutoBind is on).
if (fSocket->Bind(endpoint)) {
@@ -690,7 +623,7 @@ bool FairMQChannel::BindEndpoint(string& endpoint)
}
size_t pos = endpoint.rfind(':');
endpoint = endpoint.substr(0, pos + 1) + tools::ToString(static_cast<int>(randomPort(generator)));
endpoint = endpoint.substr(0, pos + 1) + fair::mq::tools::ToString(static_cast<int>(randomPort(generator)));
} while (!fSocket->Bind(endpoint));
return true;
@@ -703,7 +636,7 @@ bool FairMQChannel::BindEndpoint(string& endpoint)
void FairMQChannel::ResetChannel()
{
lock_guard<mutex> lock(fMtx);
lock_guard<mutex> lock(fChannelMutex);
fIsValid = false;
// TODO: implement channel resetting
}

View File

@@ -9,16 +9,6 @@
#ifndef FAIRMQCHANNEL_H_
#define FAIRMQCHANNEL_H_
#include <FairMQTransportFactory.h>
#include <FairMQSocket.h>
#include <fairmq/Transports.h>
#include <FairMQLogger.h>
#include <FairMQParts.h>
#include <fairmq/Properties.h>
#include <FairMQMessage.h>
#include <boost/any.hpp>
#include <string>
#include <memory> // unique_ptr, shared_ptr
#include <vector>
@@ -27,6 +17,13 @@
#include <stdexcept>
#include <utility> // std::move
#include <FairMQTransportFactory.h>
#include <FairMQSocket.h>
#include <fairmq/Transports.h>
#include <FairMQLogger.h>
#include <FairMQParts.h>
#include <FairMQMessage.h>
class FairMQChannel
{
friend class FairMQDevice;
@@ -35,10 +32,6 @@ class FairMQChannel
/// Default constructor
FairMQChannel();
/// Constructor
/// @param name Channel name
FairMQChannel(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)
@@ -59,28 +52,14 @@ class FairMQChannel
/// @param factory TransportFactory
FairMQChannel(const std::string& name, const std::string& type, const std::string& method, const std::string& address, std::shared_ptr<FairMQTransportFactory> factory);
FairMQChannel(const std::string& name, int index, const fair::mq::Properties& properties);
/// Copy Constructor
FairMQChannel(const FairMQChannel&);
/// Copy Constructor (with new name)
FairMQChannel(const FairMQChannel&, const std::string& name);
/// Move constructor
FairMQChannel(FairMQChannel&&) = default;
/// Assignment operator
FairMQChannel& operator=(const FairMQChannel&);
/// Move assignment operator
FairMQChannel& operator=(FairMQChannel&&) = default;
/// Destructor
virtual ~FairMQChannel()
{
// LOG(debug) << "Destroying channel " << fName;
}
/// Default destructor
virtual ~FairMQChannel() {}
struct ChannelConfigurationError : std::runtime_error { using std::runtime_error::runtime_error; };
@@ -102,17 +81,17 @@ class FairMQChannel
/// Get channel name
/// @return Returns full channel name (e.g. "data[0]")
std::string GetChannelName() const __attribute__((deprecated("Use GetName()"))) { return GetName(); }
std::string GetName() const ;
std::string GetChannelName() const { return GetName(); } // TODO: deprecate this in favor of following
std::string GetName() const;
/// Get channel prefix
/// @return Returns channel prefix (e.g. "data" in "data[0]")
std::string GetChannelPrefix() const __attribute__((deprecated("Use GetPrefix()"))) { return GetPrefix(); }
std::string GetChannelPrefix() const { return GetPrefix(); } // TODO: deprecate this in favor of following
std::string GetPrefix() const;
/// Get channel index
/// @return Returns channel index (e.g. 0 in "data[0]")
std::string GetChannelIndex() const __attribute__((deprecated("Use GetIndex()"))) { return GetIndex(); }
std::string GetChannelIndex() const { return GetIndex(); } // TODO: deprecate this in favor of following
std::string GetIndex() const;
/// Get socket type
@@ -127,14 +106,10 @@ class FairMQChannel
/// @return Returns socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
std::string GetAddress() const;
/// Get channel transport name ("default", "zeromq", "nanomsg" or "shmem")
/// @return Returns channel transport name (e.g. "default", "zeromq", "nanomsg" or "shmem")
/// Get channel transport ("default", "zeromq", "nanomsg" or "shmem")
/// @return Returns channel transport (e.g. "default", "zeromq", "nanomsg" or "shmem")
std::string GetTransportName() const;
/// Get channel transport type
/// @return Returns channel transport type
fair::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;
@@ -225,7 +200,7 @@ class FairMQChannel
/// Set channel name
/// @param name Arbitrary channel name
void UpdateChannelName(const std::string& name) __attribute__((deprecated("Use UpdateName()"))) { UpdateName(name); }
void UpdateChannelName(const std::string& name) { UpdateName(name); } // TODO: deprecate this in favor of following
void UpdateName(const std::string& name);
/// Checks if the configured channel settings are valid (checks the validity parameter, without running full validation (as oposed to ValidateChannel()))
@@ -234,7 +209,10 @@ class FairMQChannel
/// Validates channel configuration
/// @return true if channel settings are valid, false otherwise.
bool ValidateChannel() __attribute__((deprecated("Use Validate()"))) { return Validate(); }
bool ValidateChannel() // TODO: deprecate this
{
return Validate();
}
/// Validates channel configuration
/// @return true if channel settings are valid, false otherwise.
@@ -269,6 +247,17 @@ class FairMQChannel
return fSocket->Receive(msg, rcvTimeoutInMs);
}
int SendAsync(FairMQMessagePtr& msg) __attribute__((deprecated("For non-blocking Send, use timeout version with timeout of 0: Send(msg, timeout);")))
{
CheckSendCompatibility(msg);
return fSocket->Send(msg, 0);
}
int ReceiveAsync(FairMQMessagePtr& msg) __attribute__((deprecated("For non-blocking Receive, use timeout version with timeout of 0: Receive(msg, timeout);")))
{
CheckReceiveCompatibility(msg);
return fSocket->Receive(msg, 0);
}
/// Send a vector of messages
/// @param msgVec message vector reference
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
@@ -289,6 +278,17 @@ class FairMQChannel
return fSocket->Receive(msgVec, rcvTimeoutInMs);
}
int64_t SendAsync(std::vector<FairMQMessagePtr>& msgVec) __attribute__((deprecated("For non-blocking Send, use timeout version with timeout of 0: Send(msgVec, timeout);")))
{
CheckSendCompatibility(msgVec);
return fSocket->Send(msgVec, 0);
}
int64_t ReceiveAsync(std::vector<FairMQMessagePtr>& msgVec) __attribute__((deprecated("For non-blocking Receive, use timeout version with timeout of 0: Receive(msgVec, timeout);")))
{
CheckReceiveCompatibility(msgVec);
return fSocket->Receive(msgVec, 0);
}
/// Send FairMQParts
/// @param parts FairMQParts reference
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
@@ -307,6 +307,16 @@ class FairMQChannel
return Receive(parts.fParts, rcvTimeoutInMs);
}
int64_t SendAsync(FairMQParts& parts) __attribute__((deprecated("For non-blocking Send, use timeout version with timeout of 0: Send(parts, timeout);")))
{
return Send(parts.fParts, 0);
}
int64_t ReceiveAsync(FairMQParts& parts) __attribute__((deprecated("For non-blocking Receive, use timeout version with timeout of 0: Receive(parts, timeout);")))
{
return Receive(parts.fParts, 0);
}
unsigned long GetBytesTx() const { return fSocket->GetBytesTx(); }
unsigned long GetBytesRx() const { return fSocket->GetBytesRx(); }
unsigned long GetMessagesTx() const { return fSocket->GetMessagesTx(); }
@@ -335,33 +345,11 @@ class FairMQChannel
return Transport()->NewStaticMessage(data);
}
FairMQUnmanagedRegionPtr NewUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0)
{
return Transport()->CreateUnmanagedRegion(size, callback, path, flags);
}
static constexpr fair::mq::Transport DefaultTransportType = fair::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 DefaultLinger = 500;
static constexpr int DefaultRateLogging = 1;
static constexpr int DefaultPortRangeMin = 22000;
static constexpr int DefaultPortRangeMax = 23000;
static constexpr bool DefaultAutoBind = true;
private:
std::shared_ptr<FairMQTransportFactory> fTransportFactory;
fair::mq::Transport fTransportType;
std::unique_ptr<FairMQSocket> fSocket;
std::string fName;
std::string fType;
std::string fMethod;
std::string fAddress;
@@ -375,17 +363,23 @@ class FairMQChannel
int fPortRangeMax;
bool fAutoBind;
bool fIsValid;
std::string fName;
std::atomic<bool> fIsValid;
// use static mutex to make the class easily copyable
// implication: same mutex is used for all instances of the class
// this does not hurt much, because mutex is used only during initialization with very low contention
// possible TODO: improve this
static std::mutex fChannelMutex;
bool fMultipart;
bool fModified;
bool fReset;
mutable std::mutex fMtx;
void CheckSendCompatibility(FairMQMessagePtr& msg)
{
if (fTransportType != msg->GetType()) {
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
FairMQMessagePtr msgWrapper(NewMessage(
msg->GetData(),
msg->GetSize(),
@@ -401,7 +395,7 @@ class FairMQChannel
{
for (auto& msg : msgVec) {
if (fTransportType != msg->GetType()) {
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
FairMQMessagePtr msgWrapper(NewMessage(
msg->GetData(),
msg->GetSize(),
@@ -417,6 +411,7 @@ class FairMQChannel
void CheckReceiveCompatibility(FairMQMessagePtr& msg)
{
if (fTransportType != msg->GetType()) {
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
FairMQMessagePtr newMsg(NewMessage());
msg = move(newMsg);
}
@@ -426,7 +421,7 @@ class FairMQChannel
{
for (auto& msg : msgVec) {
if (fTransportType != msg->GetType()) {
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
FairMQMessagePtr newMsg(NewMessage());
msg = move(newMsg);
}
@@ -438,7 +433,6 @@ class FairMQChannel
fTransportFactory = factory;
fTransportType = factory->GetType();
}
auto SetModified(const bool modified) -> void;
};

View File

@@ -26,91 +26,63 @@
#include <algorithm> // std::max
using namespace std;
using namespace fair::mq;
static map<Transition, State> backwardsCompatibilityWaitForEndOfStateHelper =
static map<fair::mq::Transition, fair::mq::State> backwardsCompatibilityWaitForEndOfStateHelper =
{
{ Transition::InitDevice, State::InitializingDevice },
{ Transition::CompleteInit, State::Initialized },
{ Transition::Bind, State::Bound },
{ Transition::Connect, State::DeviceReady },
{ Transition::InitTask, State::Ready },
{ Transition::Run, State::Ready },
{ Transition::Stop, State::Ready },
{ Transition::ResetTask, State::DeviceReady },
{ Transition::ResetDevice, State::Idle }
{ fair::mq::Transition::InitDevice, fair::mq::State::InitializingDevice },
{ fair::mq::Transition::CompleteInit, fair::mq::State::Initialized },
{ fair::mq::Transition::Bind, fair::mq::State::Bound },
{ fair::mq::Transition::Connect, fair::mq::State::DeviceReady },
{ fair::mq::Transition::InitTask, fair::mq::State::Ready },
{ fair::mq::Transition::Run, fair::mq::State::Ready },
{ fair::mq::Transition::Stop, fair::mq::State::Ready },
{ fair::mq::Transition::ResetTask, fair::mq::State::DeviceReady },
{ fair::mq::Transition::ResetDevice, fair::mq::State::Idle }
};
static map<int, Transition> backwardsCompatibilityChangeStateHelper =
static map<int, fair::mq::Transition> backwardsCompatibilityChangeStateHelper =
{
{ FairMQDevice::Event::INIT_DEVICE, Transition::InitDevice },
{ FairMQDevice::Event::internal_DEVICE_READY, Transition::Auto },
{ FairMQDevice::Event::INIT_TASK, Transition::InitTask },
{ FairMQDevice::Event::internal_READY, Transition::Auto },
{ FairMQDevice::Event::RUN, Transition::Run },
{ FairMQDevice::Event::STOP, Transition::Stop },
{ FairMQDevice::Event::RESET_TASK, Transition::ResetTask },
{ FairMQDevice::Event::RESET_DEVICE, Transition::ResetDevice },
{ FairMQDevice::Event::internal_IDLE, Transition::Auto },
{ FairMQDevice::Event::END, Transition::End },
{ FairMQDevice::Event::ERROR_FOUND, Transition::ErrorFound }
};
constexpr const char* FairMQDevice::DefaultId;
constexpr int FairMQDevice::DefaultIOThreads;
constexpr const char* FairMQDevice::DefaultTransportName;
constexpr fair::mq::Transport FairMQDevice::DefaultTransportType;
constexpr const char* FairMQDevice::DefaultNetworkInterface;
constexpr int FairMQDevice::DefaultInitTimeout;
constexpr uint64_t FairMQDevice::DefaultMaxRunTime;
constexpr float FairMQDevice::DefaultRate;
constexpr const char* FairMQDevice::DefaultSession;
struct StateSubscription
{
fair::mq::StateMachine& fStateMachine;
fair::mq::StateQueue& fStateQueue;
string fId;
explicit StateSubscription(const string& id, fair::mq::StateMachine& stateMachine, fair::mq::StateQueue& stateQueue)
: fStateMachine(stateMachine)
, fStateQueue(stateQueue)
, fId(id)
{
fStateMachine.SubscribeToStateChange(fId, [&](fair::mq::State state) {
fStateQueue.Push(state);
});
}
~StateSubscription() {
fStateMachine.UnsubscribeFromStateChange(fId);
}
{ FairMQDevice::Event::INIT_DEVICE, fair::mq::Transition::InitDevice },
{ FairMQDevice::Event::internal_DEVICE_READY, fair::mq::Transition::Auto },
{ FairMQDevice::Event::INIT_TASK, fair::mq::Transition::InitTask },
{ FairMQDevice::Event::internal_READY, fair::mq::Transition::Auto },
{ FairMQDevice::Event::RUN, fair::mq::Transition::Run },
{ FairMQDevice::Event::STOP, fair::mq::Transition::Stop },
{ FairMQDevice::Event::RESET_TASK, fair::mq::Transition::ResetTask },
{ FairMQDevice::Event::RESET_DEVICE, fair::mq::Transition::ResetDevice },
{ FairMQDevice::Event::internal_IDLE, fair::mq::Transition::Auto },
{ FairMQDevice::Event::END, fair::mq::Transition::End },
{ FairMQDevice::Event::ERROR_FOUND, fair::mq::Transition::ErrorFound }
};
FairMQDevice::FairMQDevice()
: FairMQDevice(nullptr, {0, 0, 0})
{}
{
}
FairMQDevice::FairMQDevice(ProgOptions& config)
FairMQDevice::FairMQDevice(FairMQProgOptions& config)
: FairMQDevice(&config, {0, 0, 0})
{}
{
}
FairMQDevice::FairMQDevice(const tools::Version version)
FairMQDevice::FairMQDevice(const fair::mq::tools::Version version)
: FairMQDevice(nullptr, version)
{}
{
}
FairMQDevice::FairMQDevice(ProgOptions& config, const tools::Version version)
FairMQDevice::FairMQDevice(FairMQProgOptions& config, const fair::mq::tools::Version version)
: FairMQDevice(&config, version)
{}
{
}
FairMQDevice::FairMQDevice(ProgOptions* config, const tools::Version version)
FairMQDevice::FairMQDevice(FairMQProgOptions* config, const fair::mq::tools::Version version)
: fTransportFactory(nullptr)
, fTransports()
, fChannels()
, fInternalConfig(config ? nullptr : tools::make_unique<ProgOptions>())
, fInternalConfig(config ? nullptr : fair::mq::tools::make_unique<FairMQProgOptions>())
, fConfig(config ? config : fInternalConfig.get())
, fId(DefaultId)
, fDefaultTransportType(DefaultTransportType)
, fId()
, fDefaultTransportType(fair::mq::Transport::ZMQ)
, fStateMachine()
, fUninitializedBindingChannels()
, fUninitializedConnectingChannels()
@@ -123,18 +95,15 @@ FairMQDevice::FairMQDevice(ProgOptions* config, const tools::Version version)
, fMultitransportMutex()
, fMultitransportProceed(false)
, fVersion(version)
, fRate(DefaultRate)
, fMaxRunRuntimeInS(DefaultMaxRunTime)
, fInitializationTimeoutInS(DefaultInitTimeout)
, fRate(0.)
, fMaxRunRuntimeInS(0)
, fRawCmdLineArgs()
, fTransitionMtx()
, fTransitioning(false)
{
SubscribeToNewTransition("device", [&](Transition transition) {
SubscribeToNewTransition("device", [&](fair::mq::Transition transition) {
LOG(trace) << "device notified on new transition: " << transition;
switch (transition) {
case Transition::Stop:
case fair::mq::Transition::Stop:
UnblockTransports();
break;
default:
@@ -145,7 +114,11 @@ FairMQDevice::FairMQDevice(ProgOptions* config, const tools::Version version)
fStateMachine.HandleStates([&](fair::mq::State state) {
LOG(trace) << "device notified on new state: " << state;
fStateQueue.Push(state);
{
lock_guard<mutex> lock(fStatesMtx);
fStates.push(state);
}
fStatesCV.notify_one();
switch (state) {
case fair::mq::State::InitializingDevice:
@@ -181,71 +154,27 @@ FairMQDevice::FairMQDevice(ProgOptions* config, const tools::Version version)
fStateMachine.Start();
}
void FairMQDevice::TransitionTo(const fair::mq::State s)
fair::mq::State FairMQDevice::WaitForNextState()
{
{
lock_guard<mutex> lock(fTransitionMtx);
if (fTransitioning) {
LOG(debug) << "Attempting a transition with TransitionTo() while another one is already in progress";
throw OngoingTransition("Attempting a transition with TransitionTo() while another one is already in progress");
}
fTransitioning = true;
unique_lock<mutex> lock(fStatesMtx);
while (fStates.empty()) {
fStatesCV.wait_for(lock, chrono::milliseconds(50));
}
using fair::mq::State;
auto result = fStates.front();
StateQueue sq;
StateSubscription ss(tools::ToString(fId, ".TransitionTo"), fStateMachine, sq);
State currentState = GetCurrentState();
while (s != currentState) {
switch (currentState) {
case State::Idle:
if (s == State::Exiting) { ChangeState(Transition::End); }
else { ChangeState(Transition::InitDevice); }
break;
case State::InitializingDevice:
ChangeState(Transition::CompleteInit);
break;
case State::Initialized:
if (s == State::Exiting || s == State::Idle) { ChangeState(Transition::ResetDevice); }
else { ChangeState(Transition::Bind); }
break;
case State::Bound:
if (s == State::DeviceReady || s == State::Ready || s == State::Running) { ChangeState(Transition::Connect); }
else { ChangeState(Transition::ResetDevice); }
break;
case State::DeviceReady:
if (s == State::Running || s == State::Ready) { ChangeState(Transition::InitTask); }
else { ChangeState(Transition::ResetDevice); }
break;
case State::Ready:
if (s == State::Running) { ChangeState(Transition::Run); }
else { ChangeState(Transition::ResetTask); }
break;
case State::Running:
ChangeState(Transition::Stop);
break;
case State::Binding:
case State::Connecting:
case State::InitializingTask:
case State::ResettingDevice:
case State::ResettingTask:
LOG(debug) << "TransitionTo ignoring state: " << currentState << " (expected, automatic transition).";
break;
default:
LOG(debug) << "TransitionTo ignoring state: " << currentState;
break;
}
currentState = sq.WaitForNext();
if (result == fair::mq::State::Error) {
throw DeviceStateError("Device transitioned to error state.");
}
{
lock_guard<mutex> lock(fTransitionMtx);
fTransitioning = false;
}
fStates.pop();
return result;
}
void FairMQDevice::WaitForState(fair::mq::State state)
{
while (WaitForNextState() != state) {}
}
bool FairMQDevice::ChangeState(const int transition)
@@ -253,79 +182,83 @@ bool FairMQDevice::ChangeState(const int transition)
return ChangeState(backwardsCompatibilityChangeStateHelper.at(transition));
}
void FairMQDevice::WaitForEndOfState(Transition transition)
void FairMQDevice::WaitForEndOfState(fair::mq::Transition transition)
{
WaitForState(backwardsCompatibilityWaitForEndOfStateHelper.at(transition));
}
void FairMQDevice::InitWrapper()
{
// run initialization once CompleteInit transition is requested
fStateMachine.WaitForPendingState();
fId = fConfig->GetProperty<string>("id", DefaultId);
fId = fConfig->GetValue<string>("id");
Init();
fRate = fConfig->GetProperty<float>("rate", DefaultRate);
fMaxRunRuntimeInS = fConfig->GetProperty<uint64_t>("max-run-time", DefaultMaxRunTime);
fInitializationTimeoutInS = fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout);
fRate = fConfig->GetValue<float>("rate");
fMaxRunRuntimeInS = fConfig->GetValue<uint64_t>("max-run-time");
try {
fDefaultTransportType = fair::mq::TransportTypes.at(fConfig->GetProperty<string>("transport", DefaultTransportName));
fDefaultTransportType = fair::mq::TransportTypes.at(fConfig->GetValue<string>("transport"));
} catch (const exception& e) {
LOG(error) << "exception: " << e.what();
LOG(error) << "invalid transport type provided: " << fConfig->GetProperty<string>("transport", "not provided");
LOG(error) << "invalid transport type provided: " << fConfig->GetValue<string>("transport");
throw;
}
unordered_map<string, int> infos = fConfig->GetChannelInfo();
for (const auto& info : infos) {
for (int i = 0; i < info.second; ++i) {
fChannels[info.first].emplace_back(info.first, i, fConfig->GetPropertiesStartingWith(tools::ToString("chans.", info.first, ".", i, ".")));
for (auto& c : fConfig->GetFairMQMap()) {
if (fChannels.find(c.first) == fChannels.end()) {
LOG(debug) << "Inserting new device channel from config: " << c.first;
fChannels.insert(c);
} else {
LOG(debug) << "Updating existing device channel from config: " << c.first;
fChannels[c.first] = c.second;
}
}
LOG(debug) << "Setting '" << fair::mq::TransportNames.at(fDefaultTransportType) << "' as default transport for the device";
fTransportFactory = AddTransport(fDefaultTransportType);
string networkInterface = fConfig->GetProperty<string>("network-interface", DefaultNetworkInterface);
string networkInterface = fConfig->GetValue<string>("network-interface");
// Fill the uninitialized channel containers
for (auto& channel : fChannels) {
for (auto& mi : fChannels) {
int subChannelIndex = 0;
for (auto& subChannel : channel.second) {
// set channel transport
LOG(debug) << "Initializing transport for channel " << subChannel.fName << ": " << fair::mq::TransportNames.at(subChannel.fTransportType);
subChannel.InitTransport(AddTransport(subChannel.fTransportType));
for (auto& vi : mi.second) {
// set channel name: name + vector index
vi.fName = fair::mq::tools::ToString(mi.first, "[", subChannelIndex, "]");
if (subChannel.fMethod == "bind") {
// set channel transport
LOG(debug) << "Initializing transport for channel " << vi.fName << ": " << fair::mq::TransportNames.at(vi.fTransportType);
vi.InitTransport(AddTransport(vi.fTransportType));
if (vi.fMethod == "bind") {
// if binding address is not specified, try getting it from the configured network interface
if (subChannel.fAddress == "unspecified" || subChannel.fAddress == "") {
if (vi.fAddress == "unspecified" || vi.fAddress == "") {
// if the configured network interface is default, get its name from the default route
if (networkInterface == "default") {
networkInterface = tools::getDefaultRouteNetworkInterface();
networkInterface = fair::mq::tools::getDefaultRouteNetworkInterface();
}
subChannel.fAddress = "tcp://" + tools::getInterfaceIP(networkInterface) + ":1";
vi.fAddress = "tcp://" + fair::mq::tools::getInterfaceIP(networkInterface) + ":1";
}
// fill the uninitialized list
fUninitializedBindingChannels.push_back(&subChannel);
} else if (subChannel.fMethod == "connect") {
fUninitializedBindingChannels.push_back(&vi);
} else if (vi.fMethod == "connect") {
// fill the uninitialized list
fUninitializedConnectingChannels.push_back(&subChannel);
} else if (subChannel.fAddress.find_first_of("@+>") != string::npos) {
fUninitializedConnectingChannels.push_back(&vi);
} else if (vi.fAddress.find_first_of("@+>") != string::npos) {
// fill the uninitialized list
fUninitializedConnectingChannels.push_back(&subChannel);
fUninitializedConnectingChannels.push_back(&vi);
} else {
LOG(error) << "Cannot update configuration. Socket method (bind/connect) for channel '" << subChannel.fName << "' not specified.";
throw runtime_error(tools::ToString("Cannot update configuration. Socket method (bind/connect) for channel ", subChannel.fName, " not specified."));
LOG(error) << "Cannot update configuration. Socket method (bind/connect) for channel '" << vi.fName << "' not specified.";
throw runtime_error(fair::mq::tools::ToString("Cannot update configuration. Socket method (bind/connect) for channel ", vi.fName, " not specified."));
}
subChannelIndex++;
}
}
// ChangeState(Transition::Auto);
// ChangeState(fair::mq::Transition::Auto);
}
void FairMQDevice::BindWrapper()
@@ -336,20 +269,22 @@ void FairMQDevice::BindWrapper()
if (!fUninitializedBindingChannels.empty()) {
LOG(error) << fUninitializedBindingChannels.size() << " of the binding channels could not initialize. Initial configuration incomplete.";
throw runtime_error(tools::ToString(fUninitializedBindingChannels.size(), " of the binding channels could not initialize. Initial configuration incomplete."));
throw runtime_error(fair::mq::tools::ToString(fUninitializedBindingChannels.size(), " of the binding channels could not initialize. Initial configuration incomplete."));
}
Bind();
ChangeState(Transition::Auto);
ChangeState(fair::mq::Transition::Auto);
}
void FairMQDevice::ConnectWrapper()
{
int initializationTimeoutInS = fConfig->GetValue<int>("initialization-timeout");
// go over the list of channels until all are initialized (and removed from the uninitialized list)
int numAttempts = 1;
auto sleepTimeInMS = 50;
auto maxAttempts = fInitializationTimeoutInS * 1000 / sleepTimeInMS;
auto maxAttempts = initializationTimeoutInS * 1000 / sleepTimeInMS;
// first attempt
AttachChannels(fUninitializedConnectingChannels);
// if not all channels could be connected, update their address values from config and retry
@@ -357,16 +292,16 @@ void FairMQDevice::ConnectWrapper()
this_thread::sleep_for(chrono::milliseconds(sleepTimeInMS));
for (auto& chan : fUninitializedConnectingChannels) {
string key{"chans." + chan->GetPrefix() + "." + chan->GetIndex() + ".address"};
string newAddress = fConfig->GetProperty<string>(key);
string key{"chans." + chan->GetChannelPrefix() + "." + chan->GetChannelIndex() + ".address"};
string newAddress = fConfig->GetValue<string>(key);
if (newAddress != chan->GetAddress()) {
chan->UpdateAddress(newAddress);
}
}
if (numAttempts++ > maxAttempts) {
LOG(error) << "could not connect all channels after " << fInitializationTimeoutInS << " attempts";
throw runtime_error(tools::ToString("could not connect all channels after ", fInitializationTimeoutInS, " attempts"));
LOG(error) << "could not connect all channels after " << initializationTimeoutInS << " attempts";
throw runtime_error(fair::mq::tools::ToString("could not connect all channels after ", initializationTimeoutInS, " attempts"));
}
AttachChannels(fUninitializedConnectingChannels);
@@ -378,7 +313,7 @@ void FairMQDevice::ConnectWrapper()
Connect();
ChangeState(Transition::Auto);
ChangeState(fair::mq::Transition::Auto);
}
void FairMQDevice::AttachChannels(vector<FairMQChannel*>& chans)
@@ -386,7 +321,7 @@ void FairMQDevice::AttachChannels(vector<FairMQChannel*>& chans)
auto itr = chans.begin();
while (itr != chans.end()) {
if ((*itr)->Validate()) {
if ((*itr)->ValidateChannel()) {
(*itr)->Init();
if (AttachChannel(**itr)) {
(*itr)->SetModified(false);
@@ -431,7 +366,7 @@ bool FairMQDevice::AttachChannel(FairMQChannel& chan)
string hostPart = addressString.substr(0, pos);
if (!(bind && hostPart == "*")) {
string portPart = addressString.substr(pos + 1);
string resolvedHost = tools::getIpFromHostname(hostPart);
string resolvedHost = fair::mq::tools::getIpFromHostname(hostPart);
if (resolvedHost == "") {
return false;
}
@@ -469,7 +404,7 @@ bool FairMQDevice::AttachChannel(FairMQChannel& chan)
chan.UpdateAddress(newAddress);
// update address in the config, it could have been modified during binding
fConfig->SetProperty({"chans." + chan.GetPrefix() + "." + chan.GetIndex() + ".address"}, newAddress);
fConfig->SetValue({"chans." + chan.GetPrefix() + "." + chan.GetIndex() + ".address"}, newAddress);
}
return true;
@@ -479,7 +414,7 @@ void FairMQDevice::InitTaskWrapper()
{
InitTask();
ChangeState(Transition::Auto);
ChangeState(fair::mq::Transition::Auto);
}
bool FairMQDevice::SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs)
@@ -498,7 +433,7 @@ void FairMQDevice::SortChannel(const string& name, const bool reindex)
for (auto vi = fChannels.at(name).begin(); vi != fChannels.at(name).end(); ++vi)
{
// set channel name: name + vector index
vi->fName = tools::ToString(name, "[", vi - fChannels.at(name).begin(), "]");
vi->fName = fair::mq::tools::ToString(name, "[", vi - fChannels.at(name).begin(), "]");
}
}
}
@@ -532,7 +467,7 @@ void FairMQDevice::RunWrapper()
HandleMultipleChannelInput();
}
} else {
tools::RateLimiter rateLimiter(fRate);
fair::mq::tools::RateLimiter rateLimiter(fRate);
while (!NewStatePending() && ConditionalRun()) {
if (fRate > 0.001) {
@@ -546,7 +481,7 @@ void FairMQDevice::RunWrapper()
// if Run() exited and the state is still RUNNING, transition to READY.
if (!NewStatePending()) {
UnblockTransports();
ChangeState(Transition::Stop);
ChangeState(fair::mq::Transition::Stop);
}
PostRun();
@@ -554,10 +489,10 @@ void FairMQDevice::RunWrapper()
} catch (const out_of_range& oor) {
LOG(error) << "out of range: " << oor.what();
LOG(error) << "incorrect/incomplete channel configuration?";
ChangeState(Transition::ErrorFound);
ChangeState(fair::mq::Transition::ErrorFound);
throw;
} catch (...) {
ChangeState(Transition::ErrorFound);
ChangeState(fair::mq::Transition::ErrorFound);
throw;
}
@@ -729,7 +664,7 @@ void FairMQDevice::PollForTransport(const FairMQTransportFactory* factory, const
catch (exception& e)
{
LOG(error) << "FairMQDevice::PollForTransport() failed: " << e.what() << ", going to ERROR state.";
throw runtime_error(tools::ToString("FairMQDevice::PollForTransport() failed: ", e.what(), ", going to ERROR state."));
throw runtime_error(fair::mq::tools::ToString("FairMQDevice::PollForTransport() failed: ", e.what(), ", going to ERROR state."));
}
}
@@ -780,7 +715,7 @@ shared_ptr<FairMQTransportFactory> FairMQDevice::AddTransport(fair::mq::Transpor
}
}
void FairMQDevice::SetConfig(ProgOptions& config)
void FairMQDevice::SetConfig(FairMQProgOptions& config)
{
fInternalConfig.reset();
fConfig = &config;
@@ -788,7 +723,7 @@ void FairMQDevice::SetConfig(ProgOptions& config)
void FairMQDevice::LogSocketRates()
{
vector<FairMQChannel*> filteredChannels;
vector<FairMQSocket*> filteredSockets;
vector<string> filteredChannelNames;
vector<int> logIntervals;
vector<int> intervalCounters;
@@ -796,40 +731,40 @@ void FairMQDevice::LogSocketRates()
size_t chanNameLen = 0;
// iterate over the channels map
for (auto& channel : fChannels) {
for (const auto& mi : fChannels) {
// iterate over the channels vector
for (auto& subChannel : channel.second) {
if (subChannel.fRateLogging > 0) {
filteredChannels.push_back(&subChannel);
logIntervals.push_back(subChannel.fRateLogging);
for (auto vi = (mi.second).begin(); vi != (mi.second).end(); ++vi) {
if (vi->fRateLogging > 0) {
filteredSockets.push_back(vi->fSocket.get());
logIntervals.push_back(vi->fRateLogging);
intervalCounters.push_back(0);
filteredChannelNames.push_back(subChannel.GetName());
filteredChannelNames.push_back(fair::mq::tools::ToString(mi.first, "[", vi - (mi.second).begin(), "]"));
chanNameLen = max(chanNameLen, filteredChannelNames.back().length());
}
}
}
vector<unsigned long> bytesIn(filteredChannels.size());
vector<unsigned long> msgIn(filteredChannels.size());
vector<unsigned long> bytesOut(filteredChannels.size());
vector<unsigned long> msgOut(filteredChannels.size());
vector<unsigned long> bytesIn(filteredSockets.size());
vector<unsigned long> msgIn(filteredSockets.size());
vector<unsigned long> bytesOut(filteredSockets.size());
vector<unsigned long> msgOut(filteredSockets.size());
vector<unsigned long> bytesInNew(filteredChannels.size());
vector<unsigned long> msgInNew(filteredChannels.size());
vector<unsigned long> bytesOutNew(filteredChannels.size());
vector<unsigned long> msgOutNew(filteredChannels.size());
vector<unsigned long> bytesInNew(filteredSockets.size());
vector<unsigned long> msgInNew(filteredSockets.size());
vector<unsigned long> bytesOutNew(filteredSockets.size());
vector<unsigned long> msgOutNew(filteredSockets.size());
vector<double> mbPerSecIn(filteredChannels.size());
vector<double> msgPerSecIn(filteredChannels.size());
vector<double> mbPerSecOut(filteredChannels.size());
vector<double> msgPerSecOut(filteredChannels.size());
vector<double> mbPerSecIn(filteredSockets.size());
vector<double> msgPerSecIn(filteredSockets.size());
vector<double> mbPerSecOut(filteredSockets.size());
vector<double> msgPerSecOut(filteredSockets.size());
int i = 0;
for (const auto& channel : filteredChannels) {
bytesIn.at(i) = channel->GetBytesRx();
bytesOut.at(i) = channel->GetBytesTx();
msgIn.at(i) = channel->GetMessagesRx();
msgOut.at(i) = channel->GetMessagesTx();
for (const auto& vi : filteredSockets) {
bytesIn.at(i) = vi->GetBytesRx();
bytesOut.at(i) = vi->GetBytesTx();
msgIn.at(i) = vi->GetMessagesRx();
msgOut.at(i) = vi->GetMessagesTx();
++i;
}
@@ -846,17 +781,17 @@ void FairMQDevice::LogSocketRates()
i = 0;
for (const auto& channel : filteredChannels) {
for (const auto& vi : filteredSockets) {
intervalCounters.at(i)++;
if (intervalCounters.at(i) == logIntervals.at(i)) {
intervalCounters.at(i) = 0;
if (msSinceLastLog > 0) {
bytesInNew.at(i) = channel->GetBytesRx();
msgInNew.at(i) = channel->GetMessagesRx();
bytesOutNew.at(i) = channel->GetBytesTx();
msgOutNew.at(i) = channel->GetMessagesTx();
bytesInNew.at(i) = vi->GetBytesRx();
msgInNew.at(i) = vi->GetMessagesRx();
bytesOutNew.at(i) = vi->GetBytesTx();
msgOutNew.at(i) = vi->GetMessagesTx();
mbPerSecIn.at(i) = (static_cast<double>(bytesInNew.at(i) - bytesIn.at(i)) / (1000. * 1000.)) / static_cast<double>(msSinceLastLog) * 1000.;
msgPerSecIn.at(i) = static_cast<double>(msgInNew.at(i) - msgIn.at(i)) / static_cast<double>(msSinceLastLog) * 1000.;
@@ -879,15 +814,15 @@ void FairMQDevice::LogSocketRates()
t0 = t1;
if (fMaxRunRuntimeInS > 0 && ++secondsElapsed >= fMaxRunRuntimeInS) {
ChangeState(Transition::Stop);
ChangeState(fair::mq::Transition::Stop);
}
}
}
void FairMQDevice::UnblockTransports()
{
for (auto& transport : fTransports) {
transport.second->Interrupt();
for (auto& t : fTransports) {
t.second->Interrupt();
}
}
@@ -895,21 +830,27 @@ void FairMQDevice::ResetTaskWrapper()
{
ResetTask();
ChangeState(Transition::Auto);
ChangeState(fair::mq::Transition::Auto);
}
void FairMQDevice::ResetWrapper()
{
for (auto& transport : fTransports) {
transport.second->Reset();
for (auto& t : fTransports) {
t.second->Reset();
}
// iterate over the channels map
for (auto& mi : fChannels) {
// iterate over the channels vector
for (auto& vi : mi.second) {
// vi.fReset = true;
vi.fSocket.reset(); // destroy FairMQSocket
}
}
Reset();
fChannels.clear();
fTransports.clear();
fTransportFactory.reset();
ChangeState(Transition::Auto);
ChangeState(fair::mq::Transition::Auto);
}
FairMQDevice::~FairMQDevice()

View File

@@ -12,7 +12,6 @@
#include <StateMachine.h>
#include <FairMQTransportFactory.h>
#include <fairmq/Transports.h>
#include <fairmq/StateQueue.h>
#include <FairMQSocket.h>
#include <FairMQChannel.h>
@@ -20,7 +19,7 @@
#include <FairMQParts.h>
#include <FairMQUnmanagedRegion.h>
#include <FairMQLogger.h>
#include <fairmq/ProgOptions.h>
#include <options/FairMQProgOptions.h>
#include <vector>
#include <memory> // unique_ptr
@@ -45,14 +44,6 @@ using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChann
using InputMsgCallback = std::function<bool(FairMQMessagePtr&, int)>;
using InputMultipartCallback = std::function<bool(FairMQParts&, int)>;
namespace fair
{
namespace mq
{
struct OngoingTransition : std::runtime_error { using std::runtime_error::runtime_error; };
}
}
class FairMQDevice
{
friend class FairMQChannel;
@@ -92,17 +83,17 @@ class FairMQDevice
/// Default constructor
FairMQDevice();
/// Constructor with external fair::mq::ProgOptions
FairMQDevice(fair::mq::ProgOptions& config);
/// Constructor with external FairMQProgOptions
FairMQDevice(FairMQProgOptions& config);
/// Constructor that sets the version
FairMQDevice(const fair::mq::tools::Version version);
/// Constructor that sets the version and external fair::mq::ProgOptions
FairMQDevice(fair::mq::ProgOptions& config, const fair::mq::tools::Version version);
/// Constructor that sets the version and external FairMQProgOptions
FairMQDevice(FairMQProgOptions& config, const fair::mq::tools::Version version);
private:
FairMQDevice(fair::mq::ProgOptions* config, const fair::mq::tools::Version version);
FairMQDevice(FairMQProgOptions* config, const fair::mq::tools::Version version);
public:
/// Copy constructor (disabled)
@@ -200,58 +191,50 @@ class FairMQDevice
return fTransportFactory.get();
}
// creates message with the default device transport
template<typename... Args>
FairMQMessagePtr NewMessage(Args&&... args)
{
return Transport()->CreateMessage(std::forward<Args>(args)...);
}
// creates message with the transport of the specified channel
template<typename... Args>
FairMQMessagePtr 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>
FairMQMessagePtr 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>
FairMQMessagePtr 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>
FairMQMessagePtr 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>
FairMQMessagePtr NewSimpleMessageFor(const std::string& channel, int index, const T& data)
{
return GetChannel(channel, index).NewSimpleMessage(data);
}
// creates unamanaged region with the default device transport
FairMQUnmanagedRegionPtr NewUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr)
{
return Transport()->CreateUnmanagedRegion(size, callback);
}
// creates unmanaged region with the transport of the specified channel
FairMQUnmanagedRegionPtr NewUnmanagedRegionFor(const std::string& channel, int index, const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0)
FairMQUnmanagedRegionPtr NewUnmanagedRegionFor(const std::string& channel, int index, const size_t size, FairMQRegionCallback callback = nullptr)
{
return GetChannel(channel, index).NewUnmanagedRegion(size, callback, path, flags);
return GetChannel(channel, index).Transport()->CreateUnmanagedRegion(size, callback);
}
template<typename ...Ts>
@@ -305,9 +288,9 @@ class FairMQDevice
std::shared_ptr<FairMQTransportFactory> AddTransport(const fair::mq::Transport transport);
/// Assigns config to the device
void SetConfig(fair::mq::ProgOptions& config);
void SetConfig(FairMQProgOptions& config);
/// Get pointer to the config
fair::mq::ProgOptions* GetConfig() const
FairMQProgOptions* GetConfig() const
{
return fConfig;
}
@@ -375,9 +358,8 @@ class FairMQDevice
try {
return fChannels.at(channelName).at(index);
} catch (const std::out_of_range& oor) {
LOG(error) << "requested channel has not been configured? check channel names/configuration.";
LOG(error) << "channel: " << channelName << ", index: " << index;
LOG(error) << "out of range: " << oor.what();
LOG(error) << "requested channel has not been configured? check channel names/configuration.";
throw;
}
@@ -408,23 +390,23 @@ class FairMQDevice
const fair::mq::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 SetNumIoThreads(int numIoThreads) { fConfig->SetValue<int>("io-threads", numIoThreads);}
int GetNumIoThreads() const { return fConfig->GetValue<int>("io-threads"); }
void SetNetworkInterface(const std::string& networkInterface) { fConfig->SetProperty("network-interface", networkInterface); }
std::string GetNetworkInterface() const { return fConfig->GetProperty<std::string>("network-interface", DefaultNetworkInterface); }
void SetNetworkInterface(const std::string& networkInterface) { fConfig->SetValue<std::string>("network-interface", networkInterface); }
std::string GetNetworkInterface() const { return fConfig->GetValue<std::string>("network-interface"); }
void SetDefaultTransport(const std::string& name) { fConfig->SetProperty("transport", name); }
std::string GetDefaultTransport() const { return fConfig->GetProperty<std::string>("transport", DefaultTransportName); }
void SetDefaultTransport(const std::string& name) { fConfig->SetValue<std::string>("transport", name); }
std::string GetDefaultTransport() const { return fConfig->GetValue<std::string>("transport"); }
void SetInitTimeoutInS(int initTimeoutInS) { fConfig->SetProperty("init-timeout", initTimeoutInS); }
int GetInitTimeoutInS() const { return fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout); }
void SetInitializationTimeoutInS(int initializationTimeoutInS) { fConfig->SetValue<int>("initialization-timeout", initializationTimeoutInS); }
int GetInitializationTimeoutInS() const { return fConfig->GetValue<int>("initialization-timeout"); }
/// Sets the default transport for the device
/// @param transport Transport string ("zeromq"/"nanomsg"/"shmem")
void SetTransport(const std::string& transport) { fConfig->SetProperty("transport", transport); }
void SetTransport(const std::string& transport) { fConfig->SetValue<std::string>("transport", transport); }
/// Gets the default transport name
std::string GetTransportName() const { return fConfig->GetProperty<std::string>("transport", DefaultTransportName); }
std::string GetTransportName() const { return fConfig->GetValue<std::string>("transport"); }
void SetRawCmdLineArgs(const std::vector<std::string>& args) { fRawCmdLineArgs = args; }
std::vector<std::string> GetRawCmdLineArgs() const { return fRawCmdLineArgs; }
@@ -437,10 +419,10 @@ class FairMQDevice
/// 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>
template<class Rep, class Period>
bool WaitFor(std::chrono::duration<Rep, Period> const& duration)
{
return !fStateMachine.WaitForPendingStateFor(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
return fStateMachine.WaitForPendingStateFor(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
}
protected:
@@ -449,12 +431,12 @@ class FairMQDevice
public:
std::unordered_map<std::string, std::vector<FairMQChannel>> fChannels; ///< Device channels
std::unique_ptr<fair::mq::ProgOptions> fInternalConfig; ///< Internal program options configuration
fair::mq::ProgOptions* fConfig; ///< Pointer to config (internal or external)
std::unique_ptr<FairMQProgOptions> fInternalConfig; ///< Internal program options configuration
FairMQProgOptions* fConfig; ///< Pointer to config (internal or external)
void AddChannel(const std::string& name, FairMQChannel&& channel)
void AddChannel(const std::string& channelName, const FairMQChannel& channel)
{
fConfig->AddChannel(name, channel);
fConfig->AddChannel(channelName, channel);
}
protected:
@@ -492,18 +474,16 @@ class FairMQDevice
public:
bool ChangeState(const fair::mq::Transition transition) { return fStateMachine.ChangeState(transition); }
bool ChangeState(const std::string& transition) { return fStateMachine.ChangeState(fair::mq::GetTransition(transition)); }
bool ChangeState(const std::string& transition) { return fStateMachine.ChangeState(fair::mq::StateMachine::GetTransition(transition)); }
bool ChangeState(const int transition) __attribute__((deprecated("Use ChangeState(const fair::mq::Transition transition).")));
void WaitForEndOfState(const fair::mq::Transition transition) __attribute__((deprecated("Use WaitForState(fair::mq::State expectedState).")));
void WaitForEndOfState(const std::string& transition) __attribute__((deprecated("Use WaitForState(fair::mq::State expectedState)."))) { WaitForState(transition); }
fair::mq::State WaitForNextState() { return fStateQueue.WaitForNext(); }
void WaitForState(fair::mq::State state) { fStateQueue.WaitForState(state); }
void WaitForState(const std::string& state) { WaitForState(fair::mq::GetState(state)); }
void TransitionTo(const fair::mq::State state);
fair::mq::State WaitForNextState();
void WaitForState(fair::mq::State state);
void WaitForState(const std::string& state) { fair::mq::StateMachine::GetState(state); }
void SubscribeToStateChange(const std::string& key, std::function<void(const fair::mq::State)> callback) { fStateMachine.SubscribeToStateChange(key, callback); }
void UnsubscribeFromStateChange(const std::string& key) { fStateMachine.UnsubscribeFromStateChange(key); }
@@ -520,18 +500,10 @@ class FairMQDevice
fair::mq::State GetCurrentState() const { return fStateMachine.GetCurrentState(); }
std::string GetCurrentStateName() const { return fStateMachine.GetCurrentStateName(); }
static std::string GetStateName(const fair::mq::State state) { return fair::mq::GetStateName(state); }
static std::string GetTransitionName(const fair::mq::Transition transition) { return fair::mq::GetTransitionName(transition); }
static std::string GetStateName(const fair::mq::State state) { return fair::mq::StateMachine::GetStateName(state); }
static std::string GetTransitionName(const fair::mq::Transition transition) { return fair::mq::StateMachine::GetTransitionName(transition); }
static constexpr const char* DefaultId = "";
static constexpr int DefaultIOThreads = 1;
static constexpr const char* DefaultTransportName = "zeromq";
static constexpr fair::mq::Transport DefaultTransportType = fair::mq::Transport::ZMQ;
static constexpr const char* DefaultNetworkInterface = "default";
static constexpr int DefaultInitTimeout = 120;
static constexpr uint64_t DefaultMaxRunTime = 0;
static constexpr float DefaultRate = 0.;
static constexpr const char* DefaultSession = "default";
struct DeviceStateError : std::runtime_error { using std::runtime_error::runtime_error; };
private:
fair::mq::Transport fDefaultTransportType; ///< Default transport for the device
@@ -585,13 +557,11 @@ class FairMQDevice
const fair::mq::tools::Version fVersion;
float fRate; ///< Rate limiting for ConditionalRun
uint64_t fMaxRunRuntimeInS; ///< Maximum runtime for the Running state handler, after which state will change to Ready (in seconds, 0 for no limit).
int fInitializationTimeoutInS;
std::vector<std::string> fRawCmdLineArgs;
fair::mq::StateQueue fStateQueue;
std::mutex fTransitionMtx;
bool fTransitioning;
std::queue<fair::mq::State> fStates;
std::mutex fStatesMtx;
std::condition_variable fStatesCV;
};
#endif /* FAIRMQDEVICE_H_ */

View File

@@ -31,9 +31,6 @@ class FairMQParts
FairMQParts(FairMQParts&& p) = default;
/// Assignment operator
FairMQParts& operator=(const FairMQParts&) = delete;
/// Constructor from argument pack of std::unique_ptr<FairMQMessage> rvalues
template <typename... Ts>
FairMQParts(Ts&&... messages) : fParts() {AddPart(std::forward<Ts>(messages)...);}
/// Default destructor
~FairMQParts() {};
@@ -44,6 +41,14 @@ class FairMQParts
fParts.push_back(std::unique_ptr<FairMQMessage>(msg));
}
/// Adds part (std::unique_ptr<FairMQMessage>&) to the container (move)
/// @param msg unique pointer to FairMQMessage
/// lvalue ref (move not required when passing argument)
// inline void AddPart(std::unique_ptr<FairMQMessage>& msg)
// {
// fParts.push_back(std::move(msg));
// }
/// Adds part (std::unique_ptr<FairMQMessage>&) to the container (move)
/// @param msg unique pointer to FairMQMessage
/// rvalue ref (move required when passing argument)
@@ -52,23 +57,6 @@ class FairMQParts
fParts.push_back(std::move(msg));
}
/// Add variable list of parts to the container (move)
template <typename... Ts>
void AddPart(std::unique_ptr<FairMQMessage>&& first, Ts&&... remaining)
{
AddPart(std::move(first));
AddPart(std::forward<Ts>(remaining)...);
}
/// Add content of another object by move
void AddPart(FairMQParts&& other)
{
container parts = std::move(other.fParts);
for (auto& part : parts) {
fParts.push_back(std::move(part));
}
}
/// Get reference to part in the container at index (without bounds check)
/// @param index container index
FairMQMessage& operator[](const int index) { return *(fParts[index]); }

View File

@@ -27,7 +27,7 @@ FairMQTransportFactory::FairMQTransportFactory(const std::string& id)
{
}
auto FairMQTransportFactory::CreateTransportFactory(const std::string& type, const std::string& id, const fair::mq::ProgOptions* config) -> std::shared_ptr<FairMQTransportFactory>
auto FairMQTransportFactory::CreateTransportFactory(const std::string& type, const std::string& id, const FairMQProgOptions* config) -> std::shared_ptr<FairMQTransportFactory>
{
using namespace std;

View File

@@ -12,7 +12,6 @@
#include <FairMQLogger.h>
#include <FairMQMessage.h>
#include <FairMQPoller.h>
#include <fairmq/ProgOptionsFwd.h>
#include <FairMQSocket.h>
#include <FairMQUnmanagedRegion.h>
#include <fairmq/MemoryResources.h>
@@ -24,6 +23,7 @@
#include <unordered_map>
class FairMQChannel;
class FairMQProgOptions;
class FairMQTransportFactory
{
@@ -72,7 +72,7 @@ class FairMQTransportFactory
/// Create a poller for specific channels (all subchannels)
virtual FairMQPollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const = 0;
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) const = 0;
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr) const = 0;
/// Get transport type
virtual fair::mq::Transport GetType() const = 0;
@@ -83,7 +83,7 @@ class FairMQTransportFactory
virtual ~FairMQTransportFactory() {};
static auto CreateTransportFactory(const std::string& type, const std::string& id = "", const fair::mq::ProgOptions* config = nullptr) -> std::shared_ptr<FairMQTransportFactory>;
static auto CreateTransportFactory(const std::string& type, const std::string& id = "", const FairMQProgOptions* config = nullptr) -> std::shared_ptr<FairMQTransportFactory>;
static void FairMQNoCleanup(void* /*data*/, void* /*obj*/)
{

View File

@@ -1,187 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-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" *
********************************************************************************/
/*
* File: JSONParser.cxx
* Author: winckler
*
* Created on May 14, 2015, 5:01 PM
*/
#include <fairmq/PropertyOutput.h>
#include "JSONParser.h"
#include "FairMQLogger.h"
#include <fairmq/Tools.h>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/any.hpp>
#include <ios>
using namespace std;
using namespace fair::mq;
using namespace fair::mq::tools;
using namespace boost::property_tree;
namespace fair
{
namespace mq
{
fair::mq::Properties PtreeParser(const ptree& pt, const string& id)
{
if (id == "") {
throw ParserError("no device ID provided. Provide with `--id` cmd option");
}
// json_parser::write_json(cout, pt);
return helper::DeviceParser(pt.get_child("fairMQOptions"), id);
}
fair::mq::Properties JSONParser(const string& filename, const string& deviceId)
{
ptree pt;
LOG(debug) << "Parsing JSON from " << filename << " ...";
read_json(filename, pt);
return PtreeParser(pt, deviceId);
}
namespace helper
{
fair::mq::Properties DeviceParser(const ptree& fairMQOptions, const string& deviceId)
{
fair::mq::Properties properties;
for (const auto& node : fairMQOptions) {
if (node.first == "devices") {
for (const auto& device : node.second) {
// check if key is provided, otherwise use id
string deviceIdKey = device.second.get<string>("key", device.second.get<string>("id", ""));
// if not correct device id, do not fill MQMap
if (deviceId != deviceIdKey) {
continue;
}
LOG(trace) << "Found following channels for device ID '" << deviceId << "' :";
ChannelParser(device.second, properties);
}
}
}
return properties;
}
void ChannelParser(const ptree& tree, fair::mq::Properties& properties)
{
for (const auto& node : tree) {
if (node.first == "channels") {
for (const auto& cn : node.second) {
fair::mq::Properties commonProperties;
commonProperties.emplace("type", cn.second.get<string>("type", FairMQChannel::DefaultType));
commonProperties.emplace("method", cn.second.get<string>("method", FairMQChannel::DefaultMethod));
commonProperties.emplace("address", cn.second.get<string>("address", FairMQChannel::DefaultAddress));
commonProperties.emplace("transport", cn.second.get<string>("transport", FairMQChannel::DefaultTransportName));
commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", FairMQChannel::DefaultSndBufSize));
commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", FairMQChannel::DefaultRcvBufSize));
commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", FairMQChannel::DefaultSndKernelSize));
commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", FairMQChannel::DefaultRcvKernelSize));
commonProperties.emplace("linger", cn.second.get<int>("linger", FairMQChannel::DefaultLinger));
commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", FairMQChannel::DefaultRateLogging));
commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", FairMQChannel::DefaultPortRangeMin));
commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", FairMQChannel::DefaultPortRangeMax));
commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", FairMQChannel::DefaultAutoBind));
string name = cn.second.get<string>("name");
int numSockets = cn.second.get<int>("numSockets", 0);
if (numSockets > 0) {
LOG(trace) << name << ":";
LOG(trace) << "\tnumSockets of " << numSockets << " specified, applying common settings to each:";
for (auto& p : commonProperties) {
LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;
}
for (int i = 0; i < numSockets; ++i) {
for (const auto& p : commonProperties) {
properties.emplace(ToString("chans.", name, ".", i, ".", p.first), p.second);
}
}
} else {
SubChannelParser(cn.second.get_child(""), properties, name, commonProperties);
}
}
}
}
}
void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties, const string& channelName, const fair::mq::Properties& commonProperties)
{
// for each socket in channel
int i = 0;
for (const auto& node : channelTree) {
if (node.first == "sockets") {
for (const auto& sn : node.second) {
// a sub-channel inherits relevant properties from the common channel ...
fair::mq::Properties newProperties(commonProperties);
// ... and adds/overwrites its own properties
newProperties["type"] = sn.second.get<string>("type", boost::any_cast<string>(commonProperties.at("type")));
newProperties["method"] = sn.second.get<string>("method", boost::any_cast<string>(commonProperties.at("method")));
newProperties["address"] = sn.second.get<string>("address", boost::any_cast<string>(commonProperties.at("address")));
newProperties["transport"] = sn.second.get<string>("transport", boost::any_cast<string>(commonProperties.at("transport")));
newProperties["sndBufSize"] = sn.second.get<int>("sndBufSize", boost::any_cast<int>(commonProperties.at("sndBufSize")));
newProperties["rcvBufSize"] = sn.second.get<int>("rcvBufSize", boost::any_cast<int>(commonProperties.at("rcvBufSize")));
newProperties["sndKernelSize"] = sn.second.get<int>("sndKernelSize", boost::any_cast<int>(commonProperties.at("sndKernelSize")));
newProperties["rcvKernelSize"] = sn.second.get<int>("rcvKernelSize", boost::any_cast<int>(commonProperties.at("rcvKernelSize")));
newProperties["linger"] = sn.second.get<int>("linger", boost::any_cast<int>(commonProperties.at("linger")));
newProperties["rateLogging"] = sn.second.get<int>("rateLogging", boost::any_cast<int>(commonProperties.at("rateLogging")));
newProperties["portRangeMin"] = sn.second.get<int>("portRangeMin", boost::any_cast<int>(commonProperties.at("portRangeMin")));
newProperties["portRangeMax"] = sn.second.get<int>("portRangeMax", boost::any_cast<int>(commonProperties.at("portRangeMax")));
newProperties["autoBind"] = sn.second.get<bool>("autoBind", boost::any_cast<bool>(commonProperties.at("autoBind")));
LOG(trace) << "" << channelName << "[" << i << "]:";
for (auto& p : newProperties) {
LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;
}
for (const auto& p : newProperties) {
properties.emplace(ToString("chans.", channelName, ".", i, ".", p.first), p.second);
}
++i;
}
}
}
if (i > 0) {
LOG(trace) << "Found " << i << " socket(s) in channel.";
} else {
// if no sockets are specified, apply common channel properties
LOG(trace) << "" << channelName << ":";
LOG(trace) << "\tNo sockets specified,";
LOG(trace) << "\tapplying common settings to the channel:";
fair::mq::Properties newProperties(commonProperties);
for (auto& p : newProperties) {
LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;
}
for (const auto& p : newProperties) {
properties.emplace(ToString("chans.", channelName, ".0.", p.first), p.second);
}
}
}
} // helper namespace
} // namespace mq
} // namespace fair

View File

@@ -1,51 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-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" *
********************************************************************************/
/*
* File: FairMQParser.h
* Author: winckler
*
* Created on May 14, 2015, 5:01 PM
*/
#ifndef FAIR_MQ_JSONPARSER_H
#define FAIR_MQ_JSONPARSER_H
#include <string>
#include <vector>
#include <unordered_map>
#include <exception>
#include <boost/property_tree/ptree_fwd.hpp>
#include "FairMQChannel.h"
#include <fairmq/Properties.h>
namespace fair
{
namespace mq
{
struct ParserError : std::runtime_error { using std::runtime_error::runtime_error; };
fair::mq::Properties PtreeParser(const boost::property_tree::ptree& pt, const std::string& deviceId);
fair::mq::Properties JSONParser(const std::string& filename, const std::string& deviceId);
namespace helper
{
fair::mq::Properties DeviceParser(const boost::property_tree::ptree& tree, const std::string& deviceId);
void ChannelParser(const boost::property_tree::ptree& tree, fair::mq::Properties& properties);
void SubChannelParser(const boost::property_tree::ptree& tree, fair::mq::Properties& properties, const std::string& channelName, const fair::mq::Properties& commonProperties);
} // helper namespace
} // namespace mq
} // namespace fair
#endif /* FAIR_MQ_JSONPARSER_H */

View File

@@ -79,37 +79,19 @@ class Plugin
auto StealDeviceControl() -> void { fPluginServices->StealDeviceControl(fkName); };
auto ReleaseDeviceControl() -> void { fPluginServices->ReleaseDeviceControl(fkName); };
auto ChangeDeviceState(const DeviceStateTransition next) -> bool { return fPluginServices->ChangeDeviceState(fkName, next); }
void TransitionDeviceStateTo(const DeviceState state) { return fPluginServices->TransitionDeviceStateTo(fkName, state); }
auto SubscribeToDeviceStateChange(std::function<void(DeviceState)> callback) -> void { fPluginServices->SubscribeToDeviceStateChange(fkName, callback); }
auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices->UnsubscribeFromDeviceStateChange(fkName); }
// device config API
// see <fairmq/PluginServices.h> for docs
auto PropertyExists(const std::string& key) -> int { return fPluginServices->PropertyExists(key); }
template<typename T>
T GetProperty(const std::string& key) const { return fPluginServices->GetProperty<T>(key); }
template<typename T>
T GetProperty(const std::string& key, const T& ifNotFound) const { return fPluginServices->GetProperty(key, ifNotFound); }
std::string GetPropertyAsString(const std::string& key) const { return fPluginServices->GetPropertyAsString(key); }
std::string GetPropertyAsString(const std::string& key, const std::string& ifNotFound) const { return fPluginServices->GetPropertyAsString(key, ifNotFound); }
fair::mq::Properties GetProperties(const std::string& q) const { return fPluginServices->GetProperties(q); }
fair::mq::Properties GetPropertiesStartingWith(const std::string& q) const { return fPluginServices->GetPropertiesStartingWith(q); };
std::map<std::string, std::string> GetPropertiesAsString(const std::string& q) const { return fPluginServices->GetPropertiesAsString(q); }
std::map<std::string, std::string> GetPropertiesAsStringStartingWith(const std::string& q) const { return fPluginServices->GetPropertiesAsStringStartingWith(q); };
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fPluginServices->GetChannelInfo(); }
auto GetPropertyKeys() const -> std::vector<std::string> { return fPluginServices->GetPropertyKeys(); }
template<typename T>
auto SetProperty(const std::string& key, T val) -> void { fPluginServices->SetProperty(key, val); }
void SetProperties(const fair::mq::Properties& props) { fPluginServices->SetProperties(props); }
template<typename T>
bool UpdateProperty(const std::string& key, T val) { return fPluginServices->UpdateProperty(key, val); }
bool UpdateProperties(const fair::mq::Properties& input) { return fPluginServices->UpdateProperties(input); }
void DeleteProperty(const std::string& key) { fPluginServices->DeleteProperty(key); }
auto GetProperty(const std::string& key) const -> T { return fPluginServices->GetProperty<T>(key); }
auto GetPropertyAsString(const std::string& key) const -> std::string { return fPluginServices->GetPropertyAsString(key); }
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fPluginServices->GetChannelInfo(); }
auto GetPropertyKeys() const -> std::vector<std::string> { return fPluginServices->GetPropertyKeys(); }
template<typename T>
auto SubscribeToPropertyChange(std::function<void(const std::string& key, T newValue)> callback) -> void { fPluginServices->SubscribeToPropertyChange<T>(fkName, callback); }
template<typename T>

View File

@@ -49,11 +49,13 @@ fair::mq::PluginManager::PluginManager(const vector<string> args)
// Parse command line options
auto options = ProgramOptions();
auto vm = po::variables_map{};
try {
try
{
auto parsed = po::command_line_parser(args).options(options).allow_unregistered().run();
po::store(parsed, vm);
po::notify(vm);
} catch (const po::error& e) {
} catch (const po::error& e)
{
throw ProgramOptionsParseError{ToString("Error occured while parsing the 'Plugin Manager' program options: ", e.what())};
}
@@ -61,8 +63,10 @@ fair::mq::PluginManager::PluginManager(const vector<string> args)
auto append = vector<fs::path>{};
auto prepend = vector<fs::path>{};
auto searchPaths = vector<fs::path>{};
if (vm.count("plugin-search-path")) {
for (const auto& path : vm["plugin-search-path"].as<vector<string>>()) {
if (vm.count("plugin-search-path"))
{
for (const auto& path : vm["plugin-search-path"].as<vector<string>>())
{
if (path.substr(0, 1) == "<") { prepend.emplace_back(path.substr(1)); }
else if (path.substr(0, 1) == ">") { append.emplace_back(path.substr(1)); }
else { searchPaths.emplace_back(path); }
@@ -122,16 +126,23 @@ auto fair::mq::PluginManager::ProgramOptions() -> po::options_description
auto fair::mq::PluginManager::LoadPlugin(const string& pluginName) -> void
{
if (pluginName.substr(0,2) == "p:") {
if (pluginName.substr(0,2) == "p:")
{
// Mechanism A: prelinked dynamic
LoadPluginPrelinkedDynamic(pluginName.substr(2));
} else if (pluginName.substr(0,2) == "d:") {
}
else if (pluginName.substr(0,2) == "d:")
{
// Mechanism B: dynamic
LoadPluginDynamic(pluginName.substr(2));
} else if (pluginName.substr(0,2) == "s:") {
}
else if (pluginName.substr(0,2) == "s:")
{
// Mechanism C: static (builtin)
LoadPluginStatic(pluginName.substr(2));
} else {
}
else
{
// Mechanism B: dynamic (default)
LoadPluginDynamic(pluginName);
}
@@ -140,11 +151,15 @@ auto fair::mq::PluginManager::LoadPlugin(const string& pluginName) -> void
auto fair::mq::PluginManager::LoadPluginPrelinkedDynamic(const string& pluginName) -> void
{
// Load symbol
if (fPluginFactories.find(pluginName) == fPluginFactories.end()) {
try {
if (fPluginFactories.find(pluginName) == fPluginFactories.end())
{
try
{
LoadSymbols(pluginName, dll::program_location());
fPluginOrder.push_back(pluginName);
} catch (boost::system::system_error& e) {
}
catch (boost::system::system_error& e)
{
throw PluginLoadError(ToString("An error occurred while loading prelinked dynamic plugin ", pluginName, ": ", e.what()));
}
}
@@ -153,11 +168,13 @@ auto fair::mq::PluginManager::LoadPluginPrelinkedDynamic(const string& pluginNam
auto fair::mq::PluginManager::LoadPluginDynamic(const string& pluginName) -> void
{
// Search plugin and load, if found
if (fPluginFactories.find(pluginName) == fPluginFactories.end()) {
if (fPluginFactories.find(pluginName) == fPluginFactories.end())
{
auto success = false;
for (const auto& searchPath : SearchPaths()) {
try {
LoadSymbols(pluginName, searchPath / ToString(LibPrefix(), pluginName),
LoadSymbols(pluginName,
searchPath / ToString(LibPrefix(), pluginName),
dll::load_mode::append_decorations | dll::load_mode::rtld_global);
fPluginOrder.push_back(pluginName);
success = true;
@@ -196,11 +213,15 @@ auto fair::mq::PluginManager::LoadPluginDynamic(const string& pluginName) -> voi
auto fair::mq::PluginManager::LoadPluginStatic(const string& pluginName) -> void
{
// Load symbol
if (fPluginFactories.find(pluginName) == fPluginFactories.end()) {
try {
if (fPluginFactories.find(pluginName) == fPluginFactories.end())
{
try
{
LoadSymbols(pluginName, dll::program_location());
fPluginOrder.push_back(pluginName);
} catch (boost::system::system_error& e) {
}
catch (boost::system::system_error& e)
{
throw PluginLoadError(ToString("An error occurred while loading static plugin ", pluginName, ": ", e.what()));
}
}
@@ -208,17 +229,22 @@ auto fair::mq::PluginManager::LoadPluginStatic(const string& pluginName) -> void
auto fair::mq::PluginManager::InstantiatePlugin(const string& pluginName) -> void
{
if (fPlugins.find(pluginName) == fPlugins.end()) {
if (fPlugins.find(pluginName) == fPlugins.end())
{
fPlugins[pluginName] = fPluginFactories[pluginName](*fPluginServices);
}
}
auto fair::mq::PluginManager::InstantiatePlugins() -> void
{
for(const auto& pluginName : fPluginOrder) {
try {
for(const auto& pluginName : fPluginOrder)
{
try
{
InstantiatePlugin(pluginName);
} catch (std::exception& e) {
}
catch (std::exception& e)
{
throw PluginInstantiationError(ToString("An error occurred while instantiating plugin ", pluginName, ": ", e.what()));
}
}

View File

@@ -11,47 +11,134 @@
using namespace fair::mq;
using namespace std;
auto PluginServices::ChangeDeviceState(const string& controller, const DeviceStateTransition next) -> bool
const std::unordered_map<std::string, PluginServices::DeviceState> PluginServices::fkDeviceStateStrMap = {
{"OK", DeviceState::Ok},
{"ERROR", DeviceState::Error},
{"IDLE", DeviceState::Idle},
{"INITIALIZING DEVICE", DeviceState::InitializingDevice},
{"INITIALIZED", DeviceState::Initialized},
{"BINDING", DeviceState::Binding},
{"BOUND", DeviceState::Bound},
{"CONNECTING", DeviceState::Connecting},
{"DEVICE READY", DeviceState::DeviceReady},
{"INITIALIZING TASK", DeviceState::InitializingTask},
{"READY", DeviceState::Ready},
{"RUNNING", DeviceState::Running},
{"RESETTING TASK", DeviceState::ResettingTask},
{"RESETTING DEVICE", DeviceState::ResettingDevice},
{"EXITING", DeviceState::Exiting}
};
const std::unordered_map<PluginServices::DeviceState, std::string, tools::HashEnum<PluginServices::DeviceState>> PluginServices::fkStrDeviceStateMap = {
{DeviceState::Ok, "OK"},
{DeviceState::Error, "ERROR"},
{DeviceState::Idle, "IDLE"},
{DeviceState::InitializingDevice, "INITIALIZING DEVICE"},
{DeviceState::Initialized, "INITIALIZED"},
{DeviceState::Binding, "BINDING"},
{DeviceState::Bound, "BOUND"},
{DeviceState::Connecting, "CONNECTING"},
{DeviceState::DeviceReady, "DEVICE READY"},
{DeviceState::InitializingTask, "INITIALIZING TASK"},
{DeviceState::Ready, "READY"},
{DeviceState::Running, "RUNNING"},
{DeviceState::ResettingTask, "RESETTING TASK"},
{DeviceState::ResettingDevice, "RESETTING DEVICE"},
{DeviceState::Exiting, "EXITING"}
};
const std::unordered_map<std::string, PluginServices::DeviceStateTransition> PluginServices::fkDeviceStateTransitionStrMap = {
{"AUTO", DeviceStateTransition::Auto},
{"INIT DEVICE", DeviceStateTransition::InitDevice},
{"COMPLETE INIT", DeviceStateTransition::CompleteInit},
{"BIND", DeviceStateTransition::Bind},
{"CONNECT", DeviceStateTransition::Connect},
{"INIT TASK", DeviceStateTransition::InitTask},
{"RUN", DeviceStateTransition::Run},
{"STOP", DeviceStateTransition::Stop},
{"RESET TASK", DeviceStateTransition::ResetTask},
{"RESET DEVICE", DeviceStateTransition::ResetDevice},
{"END", DeviceStateTransition::End},
{"ERROR FOUND", DeviceStateTransition::ErrorFound},
};
const std::unordered_map<PluginServices::DeviceStateTransition, std::string, tools::HashEnum<PluginServices::DeviceStateTransition>> PluginServices::fkStrDeviceStateTransitionMap = {
{DeviceStateTransition::Auto, "Auto"},
{DeviceStateTransition::InitDevice, "INIT DEVICE"},
{DeviceStateTransition::CompleteInit, "COMPLETE INIT"},
{DeviceStateTransition::Bind, "BIND"},
{DeviceStateTransition::Connect, "CONNECT"},
{DeviceStateTransition::InitTask, "INIT TASK"},
{DeviceStateTransition::Run, "RUN"},
{DeviceStateTransition::Stop, "STOP"},
{DeviceStateTransition::ResetTask, "RESET TASK"},
{DeviceStateTransition::ResetDevice, "RESET DEVICE"},
{DeviceStateTransition::End, "END"},
{DeviceStateTransition::ErrorFound, "ERROR FOUND"},
};
const std::unordered_map<fair::mq::State, PluginServices::DeviceState, fair::mq::tools::HashEnum<fair::mq::State>> PluginServices::fkDeviceStateMap = {
{fair::mq::State::Ok, DeviceState::Ok},
{fair::mq::State::Error, DeviceState::Error},
{fair::mq::State::Idle, DeviceState::Idle},
{fair::mq::State::InitializingDevice, DeviceState::InitializingDevice},
{fair::mq::State::Initialized, DeviceState::Initialized},
{fair::mq::State::Binding, DeviceState::Binding},
{fair::mq::State::Bound, DeviceState::Bound},
{fair::mq::State::Connecting, DeviceState::Connecting},
{fair::mq::State::DeviceReady, DeviceState::DeviceReady},
{fair::mq::State::InitializingTask, DeviceState::InitializingTask},
{fair::mq::State::Ready, DeviceState::Ready},
{fair::mq::State::Running, DeviceState::Running},
{fair::mq::State::ResettingTask, DeviceState::ResettingTask},
{fair::mq::State::ResettingDevice, DeviceState::ResettingDevice},
{fair::mq::State::Exiting, DeviceState::Exiting}
};
const std::unordered_map<PluginServices::DeviceStateTransition, fair::mq::Transition, tools::HashEnum<PluginServices::DeviceStateTransition>> PluginServices::fkDeviceStateTransitionMap = {
{DeviceStateTransition::Auto, fair::mq::Transition::Auto},
{DeviceStateTransition::InitDevice, fair::mq::Transition::InitDevice},
{DeviceStateTransition::CompleteInit, fair::mq::Transition::CompleteInit},
{DeviceStateTransition::Bind, fair::mq::Transition::Bind},
{DeviceStateTransition::Connect, fair::mq::Transition::Connect},
{DeviceStateTransition::InitTask, fair::mq::Transition::InitTask},
{DeviceStateTransition::Run, fair::mq::Transition::Run},
{DeviceStateTransition::Stop, fair::mq::Transition::Stop},
{DeviceStateTransition::ResetTask, fair::mq::Transition::ResetTask},
{DeviceStateTransition::ResetDevice, fair::mq::Transition::ResetDevice},
{DeviceStateTransition::End, fair::mq::Transition::End},
{DeviceStateTransition::ErrorFound, fair::mq::Transition::ErrorFound}
};
auto PluginServices::ChangeDeviceState(const std::string& controller, const DeviceStateTransition next) -> bool
{
lock_guard<mutex> lock{fDeviceControllerMutex};
if (!fDeviceController) fDeviceController = controller;
bool result = false;
if (fDeviceController == controller) {
return fDevice.ChangeState(next);
result = fDevice.ChangeState(fkDeviceStateTransitionMap.at(next));
} else {
throw DeviceControlError{tools::ToString(
"Plugin '", controller, "' is not allowed to change device states. ",
"Currently, plugin '", *fDeviceController, "' has taken control."
)};
}
return result;
}
void PluginServices::TransitionDeviceStateTo(const std::string& controller, DeviceState state)
auto PluginServices::TakeDeviceControl(const std::string& controller) -> void
{
lock_guard<mutex> lock{fDeviceControllerMutex};
if (!fDeviceController) fDeviceController = controller;
if (fDeviceController == controller) {
fDevice.TransitionTo(state);
} else {
throw DeviceControlError{tools::ToString(
"Plugin '", controller, "' is not allowed to change device states. ",
"Currently, plugin '", *fDeviceController, "' has taken control."
)};
}
}
auto PluginServices::TakeDeviceControl(const string& controller) -> void
{
lock_guard<mutex> lock{fDeviceControllerMutex};
if (!fDeviceController) {
if (!fDeviceController)
{
fDeviceController = controller;
} else if (fDeviceController == controller) {
}
else if (fDeviceController == controller)
{
// nothing to do
} else {
}
else
{
throw DeviceControlError{tools::ToString(
"Plugin '", controller, "' is not allowed to take over control. ",
"Currently, plugin '", *fDeviceController, "' has taken control."
@@ -59,21 +146,24 @@ auto PluginServices::TakeDeviceControl(const string& controller) -> void
}
}
auto PluginServices::StealDeviceControl(const string& controller) -> void
auto PluginServices::StealDeviceControl(const std::string& controller) -> void
{
lock_guard<mutex> lock{fDeviceControllerMutex};
fDeviceController = controller;
}
auto PluginServices::ReleaseDeviceControl(const string& controller) -> void
auto PluginServices::ReleaseDeviceControl(const std::string& controller) -> void
{
{
lock_guard<mutex> lock{fDeviceControllerMutex};
if (fDeviceController == controller) {
if (fDeviceController == controller)
{
fDeviceController = boost::none;
} else {
}
else
{
throw DeviceControlError{tools::ToString("Plugin '", controller, "' cannot release control because it has not taken over control.")};
}
}
@@ -81,7 +171,7 @@ auto PluginServices::ReleaseDeviceControl(const string& controller) -> void
fReleaseDeviceControlCondition.notify_one();
}
auto PluginServices::GetDeviceController() const -> boost::optional<string>
auto PluginServices::GetDeviceController() const -> boost::optional<std::string>
{
lock_guard<mutex> lock{fDeviceControllerMutex};
@@ -92,7 +182,8 @@ auto PluginServices::WaitForReleaseDeviceControl() -> void
{
unique_lock<mutex> lock{fDeviceControllerMutex};
while (fDeviceController) {
while (fDeviceController)
{
fReleaseDeviceControlCondition.wait(lock);
}
}

View File

@@ -10,10 +10,8 @@
#define FAIR_MQ_PLUGINSERVICES_H
#include <fairmq/Tools.h>
#include <fairmq/States.h>
#include <FairMQDevice.h>
#include <fairmq/ProgOptions.h>
#include <fairmq/Properties.h>
#include <options/FairMQProgOptions.h>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
@@ -22,7 +20,6 @@
#include <string>
#include <unordered_map>
#include <mutex>
#include <map>
#include <condition_variable>
#include <stdexcept>
@@ -42,7 +39,7 @@ class PluginServices
{
public:
PluginServices() = delete;
PluginServices(ProgOptions& config, FairMQDevice& device)
PluginServices(FairMQProgOptions& config, FairMQDevice& device)
: fConfig(config)
, fDevice(device)
, fDeviceController()
@@ -59,8 +56,41 @@ class PluginServices
PluginServices(const PluginServices&) = delete;
PluginServices operator=(const PluginServices&) = delete;
using DeviceState = fair::mq::State;
using DeviceStateTransition = fair::mq::Transition;
/// See https://github.com/FairRootGroup/FairRoot/blob/dev/fairmq/docs/Device.md#13-state-machine
enum class DeviceState : int
{
Ok,
Error,
Idle,
InitializingDevice,
Initialized,
Binding,
Bound,
Connecting,
DeviceReady,
InitializingTask,
Ready,
Running,
ResettingTask,
ResettingDevice,
Exiting
};
enum class DeviceStateTransition : int // transition event between DeviceStates
{
Auto,
InitDevice,
CompleteInit,
Bind,
Connect,
InitTask,
Run,
Stop,
ResetTask,
ResetDevice,
End,
ErrorFound
};
// Control API
@@ -68,26 +98,29 @@ class PluginServices
/// @param state to convert
/// @return DeviceState enum entry
/// @throw std::out_of_range if a string cannot be resolved to a DeviceState
static auto ToDeviceState(const std::string& state) -> DeviceState { return GetState(state); }
static auto ToDeviceState(const std::string& state) -> DeviceState { return fkDeviceStateStrMap.at(state); }
/// @brief Convert string to DeviceStateTransition
/// @param transition to convert
/// @return DeviceStateTransition enum entry
/// @throw std::out_of_range if a string cannot be resolved to a DeviceStateTransition
static auto ToDeviceStateTransition(const std::string& transition) -> DeviceStateTransition { return GetTransition(transition); }
static auto ToDeviceStateTransition(const std::string& transition) -> DeviceStateTransition { return fkDeviceStateTransitionStrMap.at(transition); }
/// @brief Convert DeviceState to string
/// @param state to convert
/// @return string representation of DeviceState enum entry
static auto ToStr(DeviceState state) -> std::string { return GetStateName(state); }
static auto ToStr(DeviceState state) -> std::string { return fkStrDeviceStateMap.at(state); }
/// @brief Convert DeviceStateTransition to string
/// @param transition to convert
/// @return string representation of DeviceStateTransition enum entry
static auto ToStr(DeviceStateTransition transition) -> std::string { return GetTransitionName(transition); }
static auto ToStr(DeviceStateTransition transition) -> std::string { return fkStrDeviceStateTransitionMap.at(transition); }
friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); }
friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); }
/// @return current device state
auto GetCurrentDeviceState() const -> DeviceState { return fDevice.GetCurrentState(); }
auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<fair::mq::State>(fDevice.GetCurrentState())); }
/// @brief Become device controller
/// @param controller id
@@ -125,8 +158,6 @@ class PluginServices
/// If the device control role has not been taken yet, calling this function will take over control implicitely.
auto ChangeDeviceState(const std::string& controller, const DeviceStateTransition next) -> bool;
void TransitionDeviceStateTo(const std::string& controller, DeviceState state);
/// @brief Subscribe with a callback to device state changes
/// @param subscriber id
/// @param callback
@@ -136,7 +167,7 @@ class PluginServices
auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function<void(DeviceState /*newState*/)> callback) -> void
{
fDevice.SubscribeToStateChange(subscriber, [&,callback](fair::mq::State newState){
callback(newState);
callback(fkDeviceStateMap.at(newState));
});
}
@@ -145,91 +176,62 @@ class PluginServices
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice.UnsubscribeFromStateChange(subscriber); }
// Config API
struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
/// @brief Checks a property with the given key exist in the configuration
/// @param key
/// @return true if it exists, false otherwise
auto PropertyExists(const std::string& key) const -> bool { return fConfig.Count(key) > 0; }
/// @brief Set config property
/// @param key
/// @param val
/// @throws fair::mq::PluginServices::InvalidStateError if method is called in unsupported device states
///
/// Setting a config property will store the value in the FairMQ internal config store and notify any subscribers about the update.
/// It is property dependent, if the call to this method will have an immediate, delayed or any effect at all.
template<typename T>
auto SetProperty(const std::string& key, T val) -> void { fConfig.SetProperty(key, val); }
/// @brief Set multiple config properties
/// @param props fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any
void SetProperties(const fair::mq::Properties& props) { fConfig.SetProperties(props); }
/// @brief Updates an existing config property (or fails if it doesn't exist)
auto SetProperty(const std::string& key, T val) -> void
{
auto currentState = GetCurrentDeviceState();
if ( (currentState == DeviceState::InitializingDevice)
|| (currentState == DeviceState::Initialized)
|| (currentState == DeviceState::Binding)
|| (currentState == DeviceState::Bound)
|| (currentState == DeviceState::Connecting)
|| (currentState == DeviceState::Idle && key == "channel-config")) {
fConfig.SetValue(key, val);
} else {
throw InvalidStateError{
tools::ToString("PluginServices::SetProperty is not supported in device state ", currentState, ". ",
"Supported state is ", DeviceState::InitializingDevice, ".")};
}
}
struct InvalidStateError : std::runtime_error { using std::runtime_error::runtime_error; };
/// @brief Read config property
/// @param key
/// @param val
/// @return config property value
///
/// TODO Currently, if a non-existing key is requested and a default constructed object is returned.
/// This behaviour will be changed in the future to throw an exception in that case to provide a proper sentinel.
template<typename T>
bool UpdateProperty(const std::string& key, T val) { return fConfig.UpdateProperty(key, val); }
/// @brief Updates multiple existing config properties (or fails of any of then do not exist, leaving property store unchanged)
/// @param props (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
bool UpdateProperties(const fair::mq::Properties& input) { return fConfig.UpdateProperties(input); }
auto GetProperty(const std::string& key) const -> T {
if (PropertyExists(key)) {
return fConfig.GetValue<T>(key);
}
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
}
/// @brief Deletes a property with the given key from the config store
/// @brief Read config property as string
/// @param key
void DeleteProperty(const std::string& key) { fConfig.DeleteProperty(key); }
/// @brief Read config property, throw if no property with this key exists
/// @param key
/// @return config property
template<typename T>
auto GetProperty(const std::string& key) const -> T { return fConfig.GetProperty<T>(key); }
/// @brief Read config property, return provided value if no property with this key exists
/// @param key
/// @param ifNotFound value to return if key is not found
/// @return config property
template<typename T>
T GetProperty(const std::string& key, const T& ifNotFound) const { return fConfig.GetProperty(key, ifNotFound); }
/// @brief Read config property as string, throw if no property with this key exists
/// @param key
/// @return config property converted to string
/// @return config property value converted to string
///
/// Supports conversion to string for a fixed set of types,
/// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`
/// the provided type must then be convertible to string via operator<<
auto GetPropertyAsString(const std::string& key) const -> std::string { return fConfig.GetPropertyAsString(key); }
/// If a type is not supported, the user can provide support by overloading the ostream operator for this type
auto GetPropertyAsString(const std::string& key) const -> std::string {
if (PropertyExists(key)) {
return fConfig.GetStringValue(key);
}
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
}
/// @brief Read config property, return provided value if no property with this key exists
/// @param key
/// @param ifNotFound value to return if key is not found
/// @return config property converted to string
///
/// Supports conversion to string for a fixed set of types,
/// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`
/// the provided type must then be convertible to string via operator<<
auto GetPropertyAsString(const std::string& key, const std::string& ifNotFound) const -> std::string { return fConfig.GetPropertyAsString(key, ifNotFound); }
/// @brief Read several config properties whose keys match the provided regular expression
/// @param q regex string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
fair::mq::Properties GetProperties(const std::string& q) const { return fConfig.GetProperties(q); }
/// @brief Read several config properties whose keys start with the provided string
/// @param q string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
///
/// Typically more performant than GetProperties with regex
fair::mq::Properties GetPropertiesStartingWith(const std::string& q) const { return fConfig.GetPropertiesStartingWith(q); }
/// @brief Read several config properties as string whose keys match the provided regular expression
/// @param q regex string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
std::map<std::string, std::string> GetPropertiesAsString(const std::string& q) const { return fConfig.GetPropertiesAsString(q); }
/// @brief Read several config properties as string whose keys start with the provided string
/// @param q string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
///
/// Typically more performant than GetPropertiesAsString with regex
std::map<std::string, std::string> GetPropertiesAsStringStartingWith(const std::string& q) const { return fConfig.GetPropertiesAsStringStartingWith(q); }
/// @brief Retrieve current channel information
/// @return a map of <channel name, number of subchannels>
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig.GetChannelInfo(); }
/// @brief Discover the list of property keys
@@ -266,17 +268,20 @@ class PluginServices
/// @param subscriber
auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig.UnsubscribeAsString(subscriber); }
/// @brief Increases console logging severity, or sets it to lowest if it is already highest
auto CycleLogConsoleSeverityUp() -> void { Logger::CycleConsoleSeverityUp(); }
/// @brief Decreases console logging severity, or sets it to highest if it is already lowest
auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); }
/// @brief Increases logging verbosity, or sets it to lowest if it is already highest
auto CycleLogVerbosityUp() -> void { Logger::CycleVerbosityUp(); }
/// @brief Decreases logging verbosity, or sets it to highest if it is already lowest
auto CycleLogVerbosityDown() -> void { Logger::CycleVerbosityDown(); }
static const std::unordered_map<std::string, DeviceState> fkDeviceStateStrMap;
static const std::unordered_map<DeviceState, std::string, tools::HashEnum<DeviceState>> fkStrDeviceStateMap;
static const std::unordered_map<std::string, DeviceStateTransition> fkDeviceStateTransitionStrMap;
static const std::unordered_map<DeviceStateTransition, std::string, tools::HashEnum<DeviceStateTransition>> fkStrDeviceStateTransitionMap;
static const std::unordered_map<fair::mq::State, DeviceState, tools::HashEnum<fair::mq::State>> fkDeviceStateMap;
static const std::unordered_map<DeviceStateTransition, fair::mq::Transition, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
private:
fair::mq::ProgOptions& fConfig;
FairMQProgOptions& fConfig;
FairMQDevice& fDevice;
boost::optional<std::string> fDeviceController;
mutable std::mutex fDeviceControllerMutex;

View File

@@ -1,446 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-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" *
********************************************************************************/
/*
* File: ProgOptions.cxx
* Author: winckler
*
* Created on March 11, 2015, 10:20 PM
*/
#include "FairMQLogger.h"
#include <fairmq/ProgOptions.h>
#include "tools/Unique.h"
#include <boost/any.hpp>
#include <boost/regex.hpp>
#include <algorithm>
#include <exception>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <utility> // pair
using namespace std;
using namespace fair::mq;
namespace po = boost::program_options;
struct ValInfo
{
string value;
string type;
string origin;
};
namespace fair
{
namespace mq
{
ValInfo ConvertVarValToValInfo(const po::variable_value& v)
{
string origin;
if (v.defaulted()) {
origin = "[default]";
} else if (v.empty()) {
origin = "[empty]";
} else {
origin = "[provided]";
}
try {
pair<string, string> info = PropertyHelper::GetPropertyInfo(v.value());
return {info.first, info.second, origin};
} catch (out_of_range& oor) {
return {string("[unidentified_type]"), string("[unidentified_type]"), origin};
}
};
string ConvertVarValToString(const po::variable_value& v)
{
return ConvertVarValToValInfo(v).value;
}
ProgOptions::ProgOptions()
: fVarMap()
, fAllOptions("FairMQ Command Line Options")
, fUnregisteredOptions()
, fEvents()
, fMtx()
{
fAllOptions.add_options()
("help,h", "Print help")
("version,v", "Print version")
("severity", po::value<string>()->default_value("debug"), "Log severity level (console): trace, debug, info, state, warn, error, fatal, nolog")
("file-severity", po::value<string>()->default_value("debug"), "Log severity level (file): trace, debug, info, state, warn, error, fatal, nolog")
("verbosity", po::value<string>()->default_value("medium"), "Log verbosity level: veryhigh, high, medium, low")
("color", po::value<bool >()->default_value(true), "Log color (true/false)")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file.")
("print-options", po::value<bool >()->implicit_value(true), "Print options in machine-readable format (<option>:<computed-value>:<type>:<description>)");
ParseDefaults();
}
void ProgOptions::ParseDefaults()
{
vector<string> emptyArgs = {"dummy"};
vector<const char*> argv(emptyArgs.size());
transform(emptyArgs.begin(), emptyArgs.end(), argv.begin(), [](const string& str) {
return str.c_str();
});
po::store(po::parse_command_line(argv.size(), const_cast<char**>(argv.data()), fAllOptions), fVarMap);
}
void ProgOptions::ParseAll(const vector<string>& cmdArgs, bool allowUnregistered)
{
vector<const char*> argv(cmdArgs.size());
transform(cmdArgs.begin(), cmdArgs.end(), argv.begin(), [](const string& str) {
return str.c_str();
});
ParseAll(argv.size(), const_cast<char**>(argv.data()), allowUnregistered);
}
void ProgOptions::ParseAll(const int argc, char const* const* argv, bool allowUnregistered)
{
lock_guard<mutex> lock(fMtx);
// clear the container because it was filled with default values and subsequent calls to store() do not overwrite the existing values
fVarMap.clear();
if (allowUnregistered) {
po::command_line_parser parser(argc, argv);
parser.options(fAllOptions).allow_unregistered();
po::parsed_options parsed = parser.run();
fUnregisteredOptions = po::collect_unrecognized(parsed.options, po::include_positional);
po::store(parsed, fVarMap);
} else {
po::store(po::parse_command_line(argc, argv, fAllOptions), fVarMap);
}
}
void ProgOptions::Notify()
{
lock_guard<mutex> lock(fMtx);
po::notify(fVarMap);
}
void ProgOptions::AddToCmdLineOptions(const po::options_description optDesc, bool /* visible */)
{
lock_guard<mutex> lock(fMtx);
fAllOptions.add(optDesc);
}
po::options_description& ProgOptions::GetCmdLineOptions()
{
return fAllOptions;
}
int ProgOptions::Count(const string& key) const
{
lock_guard<mutex> lock(fMtx);
return fVarMap.count(key);
}
unordered_map<string, int> ProgOptions::GetChannelInfo() const
{
lock_guard<mutex> lock(fMtx);
return GetChannelInfoImpl();
}
unordered_map<string, int> ProgOptions::GetChannelInfoImpl() const
{
unordered_map<string, int> info;
boost::regex re("chans\\..*\\.type");
for (const auto& m : fVarMap) {
if (boost::regex_match(m.first, re)) {
string chan = m.first.substr(6);
string::size_type n = chan.find(".");
string chanName = chan.substr(0, n);
if (info.find(chanName) == info.end()) {
info.emplace(chanName, 1);
} else {
info[chanName] = info[chanName] + 1;
}
}
}
return info;
}
vector<string> ProgOptions::GetPropertyKeys() const
{
lock_guard<mutex> lock(fMtx);
vector<string> keys;
for (const auto& it : fVarMap) {
keys.push_back(it.first.c_str());
}
return keys;
}
string ProgOptions::GetPropertyAsString(const string& key) const
{
lock_guard<mutex> lock(fMtx);
if (fVarMap.count(key)) {
return ConvertVarValToString(fVarMap.at(key));
} else {
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
}
}
string ProgOptions::GetStringValue(const string& key) const
{
lock_guard<mutex> lock(fMtx);
if (fVarMap.count(key)) {
return ConvertVarValToString(fVarMap.at(key));
} else {
LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";
return string();
}
}
string ProgOptions::GetPropertyAsString(const string& key, const string& ifNotFound) const
{
lock_guard<mutex> lock(fMtx);
if (fVarMap.count(key)) {
return ConvertVarValToString(fVarMap.at(key));
}
return ifNotFound;
}
Properties ProgOptions::GetProperties(const string& q) const
{
boost::regex re(q);
Properties properties;
lock_guard<mutex> lock(fMtx);
for (const auto& m : fVarMap) {
if (boost::regex_match(m.first, re)) {
properties.emplace(m.first, m.second.value());
}
}
if (properties.size() == 0) {
LOG(warn) << "could not find anything with \"" << q << "\"";
}
return properties;
}
Properties ProgOptions::GetPropertiesStartingWith(const string& q) const
{
Properties properties;
lock_guard<mutex> lock(fMtx);
for (const auto& m : fVarMap) {
if (m.first.compare(0, q.length(), q) == 0) {
properties.emplace(m.first, m.second.value());
}
}
return properties;
}
map<string, string> ProgOptions::GetPropertiesAsString(const string& q) const
{
boost::regex re(q);
map<string, string> properties;
lock_guard<mutex> lock(fMtx);
for (const auto& m : fVarMap) {
if (boost::regex_match(m.first, re)) {
properties.emplace(m.first, PropertyHelper::ConvertPropertyToString(m.second.value()));
}
}
if (properties.size() == 0) {
LOG(warn) << "could not find anything with \"" << q << "\"";
}
return properties;
}
map<string, string> ProgOptions::GetPropertiesAsStringStartingWith(const string& q) const
{
map<string, string> properties;
lock_guard<mutex> lock(fMtx);
for (const auto& m : fVarMap) {
if (m.first.compare(0, q.length(), q) == 0) {
properties.emplace(m.first, PropertyHelper::ConvertPropertyToString(m.second.value()));
}
}
return properties;
}
void ProgOptions::SetProperties(const Properties& input)
{
unique_lock<mutex> lock(fMtx);
map<string, boost::program_options::variable_value>& vm = fVarMap;
for (const auto& m : input) {
vm[m.first].value() = m.second;
}
lock.unlock();
for (const auto& m : input) {
PropertyHelper::fEventEmitters.at(m.second.type())(fEvents, m.first, m.second);
fEvents.Emit<PropertyChangeAsString, string>(m.first, PropertyHelper::ConvertPropertyToString(m.second));
}
}
bool ProgOptions::UpdateProperties(const Properties& input)
{
unique_lock<mutex> lock(fMtx);
for (const auto& m : input) {
if (fVarMap.count(m.first) == 0) {
LOG(debug) << "UpdateProperties failed, no property found with key '" << m.first << "'";
return false;
}
}
map<string, boost::program_options::variable_value>& vm = fVarMap;
for (const auto& m : input) {
vm[m.first].value() = m.second;
}
lock.unlock();
for (const auto& m : input) {
PropertyHelper::fEventEmitters.at(m.second.type())(fEvents, m.first, m.second);
fEvents.Emit<PropertyChangeAsString, string>(m.first, PropertyHelper::ConvertPropertyToString(m.second));
}
return true;
}
void ProgOptions::DeleteProperty(const string& key)
{
lock_guard<mutex> lock(fMtx);
map<string, boost::program_options::variable_value>& vm = fVarMap;
vm.erase(key);
}
void ProgOptions::AddChannel(const string& name, const FairMQChannel& channel)
{
lock_guard<mutex> lock(fMtx);
unordered_map<string, int> existingChannels = GetChannelInfoImpl();
int index = 0;
if (existingChannels.count(name) > 0) {
index = existingChannels.at(name);
}
string prefix = fair::mq::tools::ToString("chans.", name, ".", index, ".");
SetVarMapValue<string>(string(prefix + "type"), channel.GetType());
SetVarMapValue<string>(string(prefix + "method"), channel.GetMethod());
SetVarMapValue<string>(string(prefix + "address"), channel.GetAddress());
SetVarMapValue<string>(string(prefix + "transport"), channel.GetTransportName());
SetVarMapValue<int>(string(prefix + "sndBufSize"), channel.GetSndBufSize());
SetVarMapValue<int>(string(prefix + "rcvBufSize"), channel.GetRcvBufSize());
SetVarMapValue<int>(string(prefix + "sndKernelSize"), channel.GetSndKernelSize());
SetVarMapValue<int>(string(prefix + "rcvKernelSize"), channel.GetRcvKernelSize());
SetVarMapValue<int>(string(prefix + "linger"), channel.GetLinger());
SetVarMapValue<int>(string(prefix + "rateLogging"), channel.GetRateLogging());
SetVarMapValue<int>(string(prefix + "portRangeMin"), channel.GetPortRangeMin());
SetVarMapValue<int>(string(prefix + "portRangeMax"), channel.GetPortRangeMax());
SetVarMapValue<bool>(string(prefix + "autoBind"), channel.GetAutoBind());
}
void ProgOptions::PrintHelp() const
{
cout << fAllOptions << endl;
}
void ProgOptions::PrintOptions() const
{
map<string, ValInfo> mapinfo;
int maxLenKey = 0;
int maxLenValue = 0;
int maxLenType = 0;
int maxLenDefault = 0;
for (const auto& m : fVarMap) {
maxLenKey = max(maxLenKey, static_cast<int>(m.first.length()));
ValInfo valinfo = ConvertVarValToValInfo(m.second);
mapinfo[m.first] = valinfo;
maxLenValue = max(maxLenValue, static_cast<int>(valinfo.value.length()));
maxLenType = max(maxLenType, static_cast<int>(valinfo.type.length()));
maxLenDefault = max(maxLenDefault, static_cast<int>(valinfo.origin.length()));
}
if (maxLenValue > 100) {
maxLenValue = 100;
}
for (const auto& o : fUnregisteredOptions) {
LOG(debug) << "detected unregistered option: " << o;
}
stringstream ss;
ss << "Configuration: \n";
for (const auto& p : mapinfo) {
string type("<" + p.second.type + ">");
ss << setfill(' ') << left
<< setw(maxLenKey) << p.first << " = "
<< setw(maxLenValue) << p.second.value << " "
<< setw(maxLenType + 2) << type << " "
<< setw(maxLenDefault) << p.second.origin
<< "\n";
}
LOG(debug) << ss.str();
}
void ProgOptions::PrintOptionsRaw() const
{
const vector<boost::shared_ptr<po::option_description>>& options = fAllOptions.options();
for (const auto& o : options) {
ValInfo value;
if (fVarMap.count(o->canonical_display_name())) {
value = ConvertVarValToValInfo(fVarMap[o->canonical_display_name()]);
}
string description = o->description();
replace(description.begin(), description.end(), '\n', ' ');
cout << o->long_name() << ":" << value.value << ":" << (value.type == "" ? "<unknown>" : value.type) << ":" << description << endl;
}
}
} // namespace mq
} // namespace fair

View File

@@ -1,276 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-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" *
********************************************************************************/
#ifndef FAIR_MQ_PROGOPTIONS_H
#define FAIR_MQ_PROGOPTIONS_H
#include "FairMQChannel.h"
#include "FairMQLogger.h"
#include <fairmq/EventManager.h>
#include <fairmq/ProgOptionsFwd.h>
#include <fairmq/Properties.h>
#include <fairmq/Tools.h>
#include <boost/program_options.hpp>
#include <functional>
#include <map>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include <stdexcept>
namespace fair
{
namespace mq
{
struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
class ProgOptions
{
public:
ProgOptions();
virtual ~ProgOptions() {}
void ParseAll(const std::vector<std::string>& cmdArgs, bool allowUnregistered);
void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = true);
void Notify();
void AddToCmdLineOptions(const boost::program_options::options_description optDesc, bool visible = true);
boost::program_options::options_description& GetCmdLineOptions();
/// @brief Checks a property with the given key exist in the configuration
/// @param key
/// @return 1 if it exists, 0 otherwise
int Count(const std::string& key) const;
/// @brief Retrieve current channel information
/// @return a map of <channel name, number of subchannels>
std::unordered_map<std::string, int> GetChannelInfo() const;
/// @brief Discover the list of property keys
/// @return list of property keys
std::vector<std::string> GetPropertyKeys() const;
/// @brief Read config property, throw if no property with this key exists
/// @param key
/// @return config property
template<typename T>
T GetProperty(const std::string& key) const
{
std::lock_guard<std::mutex> lock(fMtx);
if (fVarMap.count(key)) {
return fVarMap[key].as<T>();
} else {
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
}
}
/// @brief Read config property, return provided value if no property with this key exists
/// @param key
/// @param ifNotFound value to return if key is not found
/// @return config property
template<typename T>
T GetProperty(const std::string& key, const T& ifNotFound) const
{
std::lock_guard<std::mutex> lock(fMtx);
if (fVarMap.count(key)) {
return fVarMap[key].as<T>();
}
return ifNotFound;
}
/// @brief Read config property as string, throw if no property with this key exists
/// @param key
/// @return config property converted to string
///
/// Supports conversion to string for a fixed set of types,
/// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`
/// the provided type must then be convertible to string via operator<<
std::string GetPropertyAsString(const std::string& key) const;
/// @brief Read config property, return provided value if no property with this key exists
/// @param key
/// @param ifNotFound value to return if key is not found
/// @return config property converted to string
///
/// Supports conversion to string for a fixed set of types,
/// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`
/// the provided type must then be convertible to string via operator<<
std::string GetPropertyAsString(const std::string& key, const std::string& ifNotFound) const;
/// @brief Read several config properties whose keys match the provided regular expression
/// @param q regex string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
fair::mq::Properties GetProperties(const std::string& q) const;
/// @brief Read several config properties whose keys start with the provided string
/// @param q string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
///
/// Typically more performant than GetProperties with regex
fair::mq::Properties GetPropertiesStartingWith(const std::string& q) const;
/// @brief Read several config properties as string whose keys match the provided regular expression
/// @param q regex string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
std::map<std::string, std::string> GetPropertiesAsString(const std::string& q) const;
/// @brief Read several config properties as string whose keys start with the provided string
/// @param q string to match for
/// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
///
/// Typically more performant than GetPropertiesAsString with regex
std::map<std::string, std::string> GetPropertiesAsStringStartingWith(const std::string& q) const;
/// @brief Set config property
/// @param key
/// @param val
template<typename T>
void SetProperty(const std::string& key, T val)
{
std::unique_lock<std::mutex> lock(fMtx);
SetVarMapValue<typename std::decay<T>::type>(key, val);
lock.unlock();
fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);
fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetPropertyAsString(key));
}
/// @brief Updates an existing config property (or fails if it doesn't exist)
/// @param key
/// @param val
template<typename T>
bool UpdateProperty(const std::string& key, T val)
{
std::unique_lock<std::mutex> lock(fMtx);
if (fVarMap.count(key)) {
SetVarMapValue<typename std::decay<T>::type>(key, val);
lock.unlock();
fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);
fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetPropertyAsString(key));
return true;
} else {
LOG(debug) << "UpdateProperty failed, no property found with key '" << key << "'";
return false;
}
}
/// @brief Set multiple config properties
/// @param props fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any
void SetProperties(const fair::mq::Properties& input);
/// @brief Updates multiple existing config properties (or fails of any of then do not exist, leaving property store unchanged)
/// @param props (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)
bool UpdateProperties(const fair::mq::Properties& input);
/// @brief Deletes a property with the given key from the config store
/// @param key
void DeleteProperty(const std::string& key);
/// @brief Takes the provided channel and creates properties based on it
/// @param name channel name
/// @param channel FairMQChannel reference
void AddChannel(const std::string& name, const FairMQChannel& channel);
/// @brief Subscribe to property updates of type T
/// @param subscriber
/// @param callback function
///
/// Subscribe to property changes with a callback to monitor property changes in an event based fashion.
template<typename T>
void Subscribe(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, T)> func) const
{
std::lock_guard<std::mutex> lock(fMtx);
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
"In template member ProgOptions::Subscribe<T>(key,Lambda) the types const char* or char* for the calback signatures are not supported.");
fEvents.Subscribe<fair::mq::PropertyChange, T>(subscriber, func);
}
/// @brief Unsubscribe from property updates of type T
/// @param subscriber
template<typename T>
void Unsubscribe(const std::string& subscriber) const
{
std::lock_guard<std::mutex> lock(fMtx);
fEvents.Unsubscribe<fair::mq::PropertyChange, T>(subscriber);
}
/// @brief Subscribe to property updates, with values converted to string
/// @param subscriber
/// @param callback function
///
/// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string.
void SubscribeAsString(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, std::string)> func) const
{
std::lock_guard<std::mutex> lock(fMtx);
fEvents.Subscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber, func);
}
/// @brief Unsubscribe from property updates that convert to string
/// @param subscriber
void UnsubscribeAsString(const std::string& subscriber) const
{
std::lock_guard<std::mutex> lock(fMtx);
fEvents.Unsubscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber);
}
/// @brief prints full options description
void PrintHelp() const;
/// @brief prints properties stored in the property container
void PrintOptions() const;
/// @brief prints full options description in a compact machine-readable format
void PrintOptionsRaw() const;
/// @brief returns the property container
const boost::program_options::variables_map& GetVarMap() const { return fVarMap; }
/// @brief Read config property, return default-constructed object if key doesn't exist
/// @param key
/// @return config property
template<typename T>
T GetValue(const std::string& key) const /* TODO: deprecate this */
{
std::lock_guard<std::mutex> lock(fMtx);
if (fVarMap.count(key)) {
return fVarMap[key].as<T>();
} else {
LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";
return T();
}
}
template<typename T>
int SetValue(const std::string& key, T val) /* TODO: deprecate this */ { SetProperty(key, val); return 0; }
/// @brief Read config property as string, return default-constructed object if key doesn't exist
/// @param key
/// @return config property
std::string GetStringValue(const std::string& key) const; /* TODO: deprecate this */
private:
void ParseDefaults();
std::unordered_map<std::string, int> GetChannelInfoImpl() const;
template<typename T>
void SetVarMapValue(const std::string& key, const T& val)
{
std::map<std::string, boost::program_options::variable_value>& vm = fVarMap;
vm[key].value() = boost::any(val);
}
boost::program_options::variables_map fVarMap; ///< options container
boost::program_options::options_description fAllOptions; ///< all options descriptions
std::vector<std::string> fUnregisteredOptions; ///< container with unregistered options
mutable fair::mq::EventManager fEvents;
mutable std::mutex fMtx;
};
} // namespace mq
} // namespace fair
#endif /* FAIR_MQ_PROGOPTIONS_H */

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