mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-15 17:41:45 +00:00
Compare commits
96 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cf9a2944c2 | ||
|
94297f9833 | ||
|
957233cf95 | ||
|
5397cef9d1 | ||
|
f6c1f5dc0f | ||
|
c4145e9ef1 | ||
|
4123ebc9d4 | ||
|
88f897536e | ||
|
e3c55a0ff8 | ||
|
60f27b94b2 | ||
|
adfa0e2c95 | ||
|
c2bea85b90 | ||
|
2c6b2e7f04 | ||
|
6f7ffeef13 | ||
|
2eddde0e5f | ||
|
4aae1ad8d4 | ||
|
b89c309768 | ||
|
c02fbed331 | ||
|
76aeb2c7e6 | ||
|
db5f3d794c | ||
|
b814e40c87 | ||
|
5d37ab2f01 | ||
|
5303e916fb | ||
|
7d5e76dece | ||
|
2498837b8e | ||
|
6545daeda7 | ||
|
e95096eb37 | ||
|
1bb558a457 | ||
|
1c78b8ef0a | ||
|
017c5cdc3f | ||
|
d4daa9c262 | ||
|
9564b13c19 | ||
|
56cdb3812d | ||
|
2a002a2984 | ||
|
a7429ed79b | ||
|
09ef175736 | ||
|
a55db74848 | ||
|
8b3e3bbe28 | ||
|
e71c9c1121 | ||
|
fc0adba26b | ||
|
24dff2fd76 | ||
|
70ffc0d8c6 | ||
|
ff701006fd | ||
|
c8bd19b7a1 | ||
|
aee2ba7b9b | ||
|
9184d5bdae | ||
|
5e6f3a5430 | ||
|
d0fe175cab | ||
|
6f22ccf4c1 | ||
|
b2034c20cf | ||
|
ab6fd35a86 | ||
|
4a8e46c65c | ||
|
90e00730b1 | ||
|
924c8ac5f6 | ||
|
1e0159b775 | ||
|
ef3eb5f83e | ||
|
ee8afd7d2b | ||
|
a53ef79552 | ||
|
c064da91df | ||
|
f5e3212cbf | ||
|
c1d61007a1 | ||
|
93fb407af6 | ||
|
8e7e23e2d0 | ||
|
f0ec5fa2be | ||
|
aaaadf0a0b | ||
|
daec266341 | ||
|
38a149d50c | ||
|
cfebfb3407 | ||
|
e403d18cb9 | ||
|
9bab3f9f4c | ||
|
ee3a84ce7a | ||
|
f05118f4eb | ||
|
21419adb40 | ||
|
1554c1c273 | ||
|
59b04a1a64 | ||
|
653e82cab4 | ||
|
96e2076300 | ||
|
2894af803b | ||
|
8b88e67360 | ||
|
ca694e4054 | ||
|
3f96181ffd | ||
|
72f5cdef58 | ||
|
811e716731 | ||
|
5ab21946f8 | ||
|
30367eb76d | ||
|
89d71ce14c | ||
|
e54db27242 | ||
|
cc4a8b8f7f | ||
|
e4c349888d | ||
|
436f79bee5 | ||
|
2a6e4de72c | ||
|
e295978b3e | ||
|
e4d73f1a9a | ||
|
d93dc2f7f7 | ||
|
7a4fd96b27 | ||
|
155618af57 |
33
.clang-format
Normal file
33
.clang-format
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Mozilla
|
||||
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: true
|
||||
FixNamespaceComments: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
IncludeBlocks: Regroup
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
SortIncludes: true
|
||||
SpacesBeforeTrailingComments: 3
|
||||
Standard: Cpp11
|
||||
UseTab: Never
|
||||
...
|
2
.codecov.yml
Normal file
2
.codecov.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
comment:
|
||||
layout: "diff, files"
|
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Describe environment
|
||||
2. Describe compile options used
|
||||
3. Give commands you invoked
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Logs / Screenshots**
|
||||
If applicable, add logs or screenshots to help explain your problem.
|
||||
|
||||
**System information (please complete the following information):**
|
||||
- OS: [e.g. MacOS 10.13, Fedora 28, Ubuntu 14.04]
|
||||
- Compiler: [e.g. GCC 8.1, Clang 3.5]
|
||||
- Environment: [e.g. FairSoft version, alfadist revision]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
See [github markdown cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) on how to format inline codes examples and logs.
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
7
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
7
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Question / Support
|
||||
about: Any FairMQ related matter you are interested in
|
||||
|
||||
---
|
||||
|
||||
|
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
Describe your proposal.
|
||||
|
||||
Mention any issue this PR is resolves or is related to.
|
||||
|
||||
---
|
||||
|
||||
Checklist:
|
||||
|
||||
* [ ] Rebased against `dev` branch
|
||||
* [ ] My name is in the resp. CONTRIBUTORS/AUTHORS file
|
||||
* [ ] Followed [the seven rules of great commit messages](https://chris.beams.io/posts/git-commit/#seven-rules)
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
build
|
||||
|
||||
.DS_Store
|
||||
|
||||
.vscode
|
||||
|
@@ -34,22 +34,31 @@ 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_EXAMPLES "Build FairMQ examples." ON "BUILD_FAIRMQ" OFF)
|
||||
option(BUILD_DOCS "Build FairMQ documentation." OFF)
|
||||
option(FAST_BUILD "Fast production build. Not recommended for development." OFF)
|
||||
################################################################################
|
||||
|
||||
|
||||
# Dependencies #################################################################
|
||||
if(FAST_BUILD)
|
||||
include(cotire)
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
if(BUILD_FAIRMQ)
|
||||
find_package2(PUBLIC Boost VERSION 1.64 REQUIRED
|
||||
COMPONENTS program_options thread system filesystem regex date_time signals
|
||||
)
|
||||
find_package2(PUBLIC FairLogger VERSION 1.0.6 REQUIRED)
|
||||
find_package2(PUBLIC FairLogger VERSION 1.2.0 REQUIRED)
|
||||
find_package2(PRIVATE ZeroMQ VERSION 4.1.5 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
find_package2(PRIVATE nanomsg VERSION 1.0.0 REQUIRED)
|
||||
find_package2(PRIVATE msgpack VERSION 2.1.5 REQUIRED)
|
||||
set(msgpack_ROOT ${PACKAGE_PREFIX_DIR})
|
||||
find_package2(PRIVATE nanomsg REQUIRED)
|
||||
set(PROJECT_nanomsg_VERSION 1.1.3) # Once upstream releases 1.1.5, we should bump again and use version check
|
||||
find_package2(PRIVATE msgpack VERSION 3.1.0 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
@@ -94,6 +103,7 @@ if(BUILD_DOCS)
|
||||
set(DOXYGEN_PROJECT_NUMBER ${PROJECT_GIT_VERSION})
|
||||
set(DOXYGEN_PROJECT_BRIEF "C++ Message Passing Framework")
|
||||
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE README.md)
|
||||
set(DOXYGEN_HTML_FOOTER docs/footer.html)
|
||||
doxygen_add_docs(doxygen README.md fairmq)
|
||||
add_custom_target(docs ALL DEPENDS doxygen)
|
||||
endif()
|
||||
@@ -140,11 +150,6 @@ if(BUILD_DDS_PLUGIN)
|
||||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
)
|
||||
endif()
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
install(FILES cmake/Findnanomsg.cmake
|
||||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
)
|
||||
endif()
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
install(FILES cmake/FindOFI.cmake
|
||||
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
|
||||
@@ -161,6 +166,29 @@ install_cmake_package()
|
||||
|
||||
|
||||
# Summary ######################################################################
|
||||
if(CMAKE_CXX_FLAGS)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}GLOBAL CXX FLAGS${CR} ${BGreen}${CMAKE_CXX_FLAGS}${CR}")
|
||||
endif()
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}BUILD TYPE CXX FLAGS${CR}")
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" selected_type)
|
||||
foreach(type IN LISTS CMAKE_CONFIGURATION_TYPES)
|
||||
string(TOUPPER "${type}" type_upper)
|
||||
if(type_upper STREQUAL selected_type)
|
||||
pad("${type}" 18 " " type_padded)
|
||||
message(STATUS "${BGreen}* ${type_padded}${CMAKE_CXX_FLAGS_${type_upper}}${CR}")
|
||||
else()
|
||||
pad("${type}" 18 " " type_padded)
|
||||
message(STATUS " ${BWhite}${type_padded}${CR}${CMAKE_CXX_FLAGS_${type_upper}}")
|
||||
endif()
|
||||
unset(type_padded)
|
||||
unset(type_upper)
|
||||
endforeach()
|
||||
message(STATUS " ")
|
||||
message(STATUS " (Change the build type with ${BMagenta}-DCMAKE_BUILD_TYPE=...${CR})")
|
||||
endif()
|
||||
if(PROJECT_PACKAGE_DEPENDENCIES)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}")
|
||||
@@ -188,9 +216,13 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
|
||||
elseif(${dep} STREQUAL GTest)
|
||||
get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE)
|
||||
elseif(${dep} STREQUAL msgpack)
|
||||
set(prefix ${msgpack_ROOT})
|
||||
get_target_property(msgpack_include msgpackc-cxx INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_filename_component(prefix ${msgpack_include}/.. ABSOLUTE)
|
||||
elseif(${dep} STREQUAL OFI)
|
||||
get_filename_component(prefix ${${dep}_INCLUDE_DIRS}/.. ABSOLUTE)
|
||||
elseif(${dep} STREQUAL nanomsg)
|
||||
get_target_property(nn_include nanomsg INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_filename_component(prefix ${nn_include}/.. ABSOLUTE)
|
||||
elseif(${dep} STREQUAL Doxygen)
|
||||
get_target_property(doxygen_bin Doxygen::doxygen INTERFACE_LOCATION)
|
||||
get_filename_component(prefix ${doxygen_bin} DIRECTORY)
|
||||
|
@@ -2,6 +2,7 @@ Aphecetche, Laurent
|
||||
Binet, Sebastien
|
||||
Eulisse, Giulio
|
||||
Karabowicz, Radoslaw
|
||||
Kretz, Matthias <kretz@kde.org>
|
||||
Krzewicki, Mikolaj
|
||||
Neskovic, Gvozden
|
||||
Richter, Matthias
|
||||
|
41
COPYRIGHT
Normal file
41
COPYRIGHT
Normal file
@@ -0,0 +1,41 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: FairMQ
|
||||
Upstream-Contact: Mohammad Al-Turany <m.al-turany@gsi.de>
|
||||
Source: https://github.com/FairRootGroup/FairMQ
|
||||
|
||||
Files: *
|
||||
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
|
||||
|
||||
Files: cmake/cotire.cmake
|
||||
Copyright: 2012-2018 Sascha Kratky
|
||||
License: COTIRE
|
||||
|
||||
License: LGPL-3.0-only
|
||||
[see LICENSE file]
|
||||
|
||||
License: COTIRE
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
40
Dart.sh
40
Dart.sh
@@ -41,13 +41,15 @@ if [ "$#" -lt "2" ]; then
|
||||
fi
|
||||
|
||||
# test if a valid ctest model is defined
|
||||
if [ "$1" == "Experimental" -o "$1" == "Nightly" -o "$1" == "Continuous" -o "$1" == "Profile" -o "$1" == "alfa_ci" ]; then
|
||||
echo ""
|
||||
else
|
||||
echo "-- Error -- This ctest model is not supported."
|
||||
echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile."
|
||||
exit 1
|
||||
fi
|
||||
case "$1" in
|
||||
Experimental|Nightly|Continuous|Profile|alfa_ci|codecov)
|
||||
;;
|
||||
*)
|
||||
echo "-- Error -- This ctest model is not supported."
|
||||
echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# test if the input file exists and execute it
|
||||
if [ -e "$2" ];then
|
||||
@@ -61,6 +63,9 @@ fi
|
||||
# set the ctest model to command line parameter
|
||||
if [ "$1" == "alfa_ci" ]; then
|
||||
export ctest_model=Experimental
|
||||
elif [ "$1" == "codecov" ]; then
|
||||
export ctest_model=Profile
|
||||
export do_codecov_upload=1
|
||||
else
|
||||
export ctest_model=$1
|
||||
fi
|
||||
@@ -83,13 +88,20 @@ else
|
||||
COMPILER=$CXX$($CXX -dumpversion)
|
||||
fi
|
||||
|
||||
if [ "$1" == "alfa_ci" ]; then
|
||||
export LABEL1=alfa_ci-$COMPILER-FairMQ_$GIT_BRANCH
|
||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||
else
|
||||
export LABEL1=${LINUX_FLAVOUR}-$chip-$COMPILER-FairMQ_$GIT_BRANCH
|
||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||
fi
|
||||
case "$1" in
|
||||
alfa_ci)
|
||||
export LABEL1=alfa_ci-$COMPILER-FairMQ_$GIT_BRANCH
|
||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||
;;
|
||||
codecov)
|
||||
export LABEL1=codecov-$COMPILER-FairMQ_$GIT_BRANCH
|
||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||
;;
|
||||
*)
|
||||
export LABEL1=${LINUX_FLAVOUR}-$chip-$COMPILER-FairMQ_$GIT_BRANCH
|
||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||
;;
|
||||
esac
|
||||
|
||||
# get the number of processors
|
||||
# and information about the host
|
||||
|
@@ -28,24 +28,24 @@ Set(configure_options "${configure_options};-DDISABLE_COLOR=ON")
|
||||
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_DDS_PLUGIN=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}")
|
||||
|
||||
Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS})
|
||||
If(EXTRA_FLAGS)
|
||||
Set(configure_options "${configure_options};${EXTRA_FLAGS}")
|
||||
EndIf()
|
||||
|
||||
If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile)
|
||||
|
||||
If($ENV{ctest_model} MATCHES Profile)
|
||||
Find_Program(GCOV_COMMAND gcov)
|
||||
If(GCOV_COMMAND)
|
||||
Message("Found GCOV: ${GCOV_COMMAND}")
|
||||
Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND})
|
||||
EndIf(GCOV_COMMAND)
|
||||
EndIf()
|
||||
|
||||
Set(ENV{ctest_model} Nightly)
|
||||
|
||||
CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
|
||||
|
||||
If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile)
|
||||
Ctest_Empty_Binary_Directory(${CTEST_BINARY_DIRECTORY})
|
||||
EndIf()
|
||||
|
||||
Ctest_Start($ENV{ctest_model})
|
||||
@@ -60,9 +60,26 @@ Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
|
||||
PARALLEL_LEVEL $ENV{number_of_processors}
|
||||
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}")
|
||||
Ctest_Coverage(BUILD "${CTEST_BINARY_DIRECTORY}" LABELS coverage)
|
||||
EndIf()
|
||||
|
||||
If("$ENV{do_codecov_upload}")
|
||||
Execute_Process(COMMAND curl https://codecov.io/bash -o codecov_uploader.sh
|
||||
WORKING_DIRECTORY ${CTEST_BINARY_DIRECTORY}
|
||||
TIMEOUT 60)
|
||||
Execute_Process(COMMAND bash ./codecov_uploader.sh -X gcov
|
||||
WORKING_DIRECTORY ${CTEST_BINARY_DIRECTORY}
|
||||
TIMEOUT 60)
|
||||
EndIf()
|
||||
|
||||
Ctest_Submit()
|
||||
|
44
Jenkinsfile
vendored
44
Jenkinsfile
vendored
@@ -4,24 +4,31 @@ def specToLabel(Map spec) {
|
||||
return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}"
|
||||
}
|
||||
|
||||
def buildMatrix(List specs, Closure callback) {
|
||||
def jobMatrix(String prefix, List specs, Closure callback) {
|
||||
def nodes = [:]
|
||||
for (spec in specs) {
|
||||
def label = specToLabel(spec)
|
||||
nodes[label] = {
|
||||
nodes["${prefix}/${label}"] = {
|
||||
node(label) {
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Building ...', status: 'PENDING')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
|
||||
try {
|
||||
deleteDir()
|
||||
checkout scm
|
||||
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||
echo "export PATH=$SIMPATH/bin:$PATH" >> Dart.cfg
|
||||
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
||||
'''
|
||||
|
||||
callback.call(spec, label)
|
||||
|
||||
deleteDir()
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Success', status: 'SUCCESS')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS')
|
||||
} catch (e) {
|
||||
deleteDir()
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Error', status: 'ERROR')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR')
|
||||
throw e
|
||||
}
|
||||
}
|
||||
@@ -33,22 +40,25 @@ def buildMatrix(List specs, Closure callback) {
|
||||
pipeline{
|
||||
agent none
|
||||
stages {
|
||||
stage("Run Build/Test Matrix") {
|
||||
stage("Run CI Matrix") {
|
||||
steps{
|
||||
script {
|
||||
parallel(buildMatrix([
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'apr18'],
|
||||
[os: 'MacOS10.11', arch: 'x86_64', compiler: 'AppleLLVM8.0.0', fairsoft: 'apr18'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'apr18'],
|
||||
def build_jobs = jobMatrix('alfa-ci/build', [
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'may18'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'may18'],
|
||||
]) { spec, label ->
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||
echo "export PATH=$SIMPATH/bin:$PATH" >> Dart.cfg
|
||||
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
||||
'''
|
||||
sh './Dart.sh alfa_ci Dart.cfg'
|
||||
})
|
||||
}
|
||||
|
||||
def profile_jobs = jobMatrix('alfa-ci/codecov', [
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'may18'],
|
||||
]) { spec, label ->
|
||||
withCredentials([string(credentialsId: 'fairmq_codecov_token', variable: 'CODECOV_TOKEN')]) {
|
||||
sh './Dart.sh codecov Dart.cfg'
|
||||
}
|
||||
}
|
||||
|
||||
parallel(build_jobs + profile_jobs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,9 +35,9 @@ pipeline{
|
||||
steps{
|
||||
script {
|
||||
parallel(buildMatrix([
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'apr18'],
|
||||
[os: 'MacOS10.11', arch: 'x86_64', compiler: 'AppleLLVM8.0.0', fairsoft: 'apr18'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'apr18'],
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'may18'],
|
||||
[os: 'MacOS10.11', arch: 'x86_64', compiler: 'AppleLLVM8.0.0', fairsoft: 'may18'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'may18'],
|
||||
]) { spec, label ->
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
|
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
62
README.md
62
README.md
@@ -1,12 +1,16 @@
|
||||
<!-- {#mainpage} -->
|
||||
# FairMQ
|
||||
# FairMQ [](COPYRIGHT) [](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [](https://codecov.io/gh/FairRootGroup/FairMQ/branch/master) [](https://www.codacy.com/app/dennisklein/FairMQ?utm_source=github.com&utm_medium=referral&utm_content=FairRootGroup/FairMQ&utm_campaign=Badge_Grade)
|
||||
|
||||
C++ Message passing framework
|
||||
C++ Message Queuing Library and Framework
|
||||
|
||||
| Branch | Build Status |
|
||||
| :---: | :--- |
|
||||
| `master` |  |
|
||||
| `dev` |  |
|
||||
| Release | Version | Docs |
|
||||
| :---: | :--- | :--- |
|
||||
| `stable` | [](https://github.com/FairRootGroup/FairMQ/releases/latest) | [API](https://fairrootgroup.github.io/FairMQ/latest), [Book](https://github.com/FairRootGroup/FairMQ/blob/master/README.md#documentation) |
|
||||
| `testing` | [](https://github.com/FairRootGroup/FairMQ/tags) | [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation) |
|
||||
|
||||
Find all FairMQ releases [here](https://github.com/FairRootGroup/FairMQ/releases).
|
||||
|
||||
## Introduction
|
||||
|
||||
FairMQ is designed to help implementing large-scale data processing workflows needed in next-generation Particle Physics experiments. FairMQ is written in C++ and aims to
|
||||
* provide **an asynchronous message passing abstraction** of different data transport technologies,
|
||||
@@ -23,7 +27,7 @@ In addition to this core functionality FairMQ provides a framework for creating
|
||||
are communicating through message passing. FairMQ does not only allow the user to use different transport but also to mix them; i.e: A Device can communicate using different transport on different channels at the same time. Device execution is modelled as a simple state machine that
|
||||
shapes the integration points for the user task. Devices also incorporate a plugin system for runtime configuration and control.
|
||||
Next to the provided devices and plugins (e.g. [DDS](https://github.com/FairRootGroup/DDS))
|
||||
the user can extened FairMQ by developing his own plugins to integrate his devices with external
|
||||
the user can extend FairMQ by developing his own plugins to integrate his devices with external
|
||||
configuration and control services.
|
||||
|
||||
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
|
||||
@@ -31,29 +35,13 @@ a simulation, reconstruction and analysis framework.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [**Boost**](https://www.boost.org/) (PUBLIC)
|
||||
* [**FairLogger**](https://github.com/FairRootGroup/FairLogger) (PUBLIC)
|
||||
* [CMake](https://cmake.org/) (BUILD)
|
||||
* [GTest](https://github.com/google/googletest) (BUILD, optional, `tests`)
|
||||
* [Doxygen](http://www.doxygen.org/) (BUILD, optional, `docs`)
|
||||
* [ZeroMQ](http://zeromq.org/) (PRIVATE)
|
||||
* [Msgpack](https://msgpack.org/index.html) (PRIVATE, optional, `nanomsg_transport`)
|
||||
* [nanomsg](http://nanomsg.org/) (PRIVATE, optional, `nanomsg_transport`)
|
||||
* [OFI](https://ofiwg.github.io/libfabric/) (PRIVATE, optional, `ofi_transport`)
|
||||
* [Protobuf](https://developers.google.com/protocol-buffers/) (PRIVATE, optional, `ofi_transport`)
|
||||
* [DDS](http://dds.gsi.de) (PRIVATE, optional, `dds_plugin`)
|
||||
* 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/),
|
||||
[OFI](https://ofiwg.github.io/libfabric/), [Protobuf](https://developers.google.com/protocol-buffers/), [DDS](http://dds.gsi.de)
|
||||
|
||||
Supported platforms: Linux and MacOS.
|
||||
|
||||
## Releases
|
||||
|
||||
| Stable release | Date | API Docs |
|
||||
| --- | --- | --- |
|
||||
| [**1.2.1**](https://github.com/FairRootGroup/FairMQ/releases/tag/v1.2.1) | May 2018 | [link](https://fairrootgroup.github.io/FairMQ/v1.2.1/index.html) |
|
||||
| [**1.2.0**](https://github.com/FairRootGroup/FairMQ/releases/tag/v1.2.0) | May 2018 | [link](https://fairrootgroup.github.io/FairMQ/v1.2.0/index.html) |
|
||||
|
||||
Find all FairMQ stable and development releases [here](https://github.com/FairRootGroup/FairMQ/releases).
|
||||
|
||||
## Installation from Source
|
||||
|
||||
```bash
|
||||
@@ -80,14 +68,16 @@ set(CMAKE_PREFIX_PATH /path/to/FairMQ_install_prefix ${CMAKE_PREFIX_PATH})
|
||||
find_package(FairMQ)
|
||||
```
|
||||
|
||||
`find_package(FairMQ)` will define an imported target `FairMQ::FairMQ` (An alias `FairRoot::FairMQ` is also defined (if you use CMake 3.11+) for backwards compatibility, but it is deprecated).
|
||||
`find_package(FairMQ)` will define an imported target `FairMQ::FairMQ`.
|
||||
|
||||
In order to succesfully compile and link against the `FairMQ::FairMQ` target, you need to discover its public package dependencies, too.
|
||||
|
||||
```cmake
|
||||
find_package(FairMQ)
|
||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_BOOST_COMPONENTS})
|
||||
if(FairMQ_FOUND)
|
||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS})
|
||||
endif()
|
||||
```
|
||||
|
||||
Of course, feel free to customize the above commands to your needs.
|
||||
@@ -96,8 +86,10 @@ Optionally, you can require certain FairMQ package components and a minimum vers
|
||||
|
||||
```cmake
|
||||
find_package(FairMQ 1.1.0 COMPONENTS nanomsg_transport dds_plugin)
|
||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_BOOST_COMPONENTS})
|
||||
if(FairMQ_FOUND)
|
||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS})
|
||||
endif()
|
||||
```
|
||||
|
||||
When building FairMQ, CMake will print a summary table of all available package components.
|
||||
@@ -164,9 +156,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)
|
||||
|
||||
## License
|
||||
|
||||
GNU Lesser General Public Licence (LGPL) version 3, see [LICENSE](LICENSE).
|
||||
|
||||
Copyright (C) 2013-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
|
||||
|
@@ -23,6 +23,7 @@ set_and_check(@PROJECT_NAME@_CMAKEMODDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT
|
||||
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@)
|
||||
|
||||
### Import cmake modules
|
||||
set(CMAKE_MODULE_PATH ${@PROJECT_NAME@_CMAKEMODDIR} ${CMAKE_MODULE_PATH})
|
||||
@@ -32,9 +33,4 @@ set(CMAKE_MODULE_PATH ${@PROJECT_NAME@_CMAKEMODDIR} ${CMAKE_MODULE_PATH})
|
||||
### Import targets
|
||||
include(@PACKAGE_CMAKE_INSTALL_PREFIX@/@PACKAGE_INSTALL_DESTINATION@/@PROJECT_EXPORT_SET@.cmake)
|
||||
|
||||
### Alias target for backwards compat (DEPRECATED)
|
||||
if((NOT TARGET FairRoot::@PROJECT_NAME@) AND (CMAKE_VERSION VERSION_GREATER 3.10.99))
|
||||
add_library(FairRoot::@PROJECT_NAME@ ALIAS @PROJECT_NAME@::@PROJECT_NAME@)
|
||||
endif()
|
||||
|
||||
@PACKAGE_COMPONENTS@
|
||||
|
@@ -112,7 +112,6 @@ macro(set_fairmq_defaults)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
endif()
|
||||
|
||||
|
||||
# Handle C++ standard level
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
@@ -124,8 +123,14 @@ macro(set_fairmq_defaults)
|
||||
endif()
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON CACHE BOOL "Whether to build shared libraries or static archives")
|
||||
endif()
|
||||
|
||||
# Set -fPIC as default for all library types
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if(NOT CMAKE_POSITION_INDEPENDENT_CODE)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# Generate compile_commands.json file (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
@@ -158,9 +163,29 @@ macro(set_fairmq_defaults)
|
||||
# Define export set, only one for now
|
||||
set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets)
|
||||
|
||||
# Override CMake defaults
|
||||
set(CMAKE_CXX_FLAGS_NIGHTLY "-O2 -g -Wshadow -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs -Wshadow -Wall -Wextra -Wunused-variable")
|
||||
# Configure build types
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo" "Nightly" "Profile" "AdressSan" "ThreadSan")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wshadow -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -Wshadow -Wall -Wextra -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_NIGHTLY "-O2 -g -Wshadow -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -Wshadow -Wall -Wextra -fno-inline -ftest-coverage -fprofile-arcs")
|
||||
set(CMAKE_CXX_FLAGS_ADRESSSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS_THREADSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=thread")
|
||||
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
||||
endif()
|
||||
|
||||
if(NOT PROJECT_VERSION_TWEAK)
|
||||
set(PROJECT_VERSION_HOTFIX 0)
|
||||
else()
|
||||
set(PROJECT_VERSION_HOTFIX ${PROJECT_VERSION_TWEAK})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(join VALUES GLUE OUTPUT)
|
||||
@@ -237,7 +262,7 @@ endfunction()
|
||||
macro(install_cmake_package)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(PACKAGE_INSTALL_DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_GIT_VERSION}
|
||||
)
|
||||
if(BUILD_FAIRMQ)
|
||||
install(EXPORT ${PROJECT_EXPORT_SET}
|
||||
@@ -280,20 +305,22 @@ macro(find_package2 qualifier pkgname)
|
||||
set(CMAKE_PREFIX_PATH ${old_CPP})
|
||||
unset(old_CPP)
|
||||
|
||||
if(${qualifier} STREQUAL PRIVATE)
|
||||
set(PROJECT_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
elseif(${qualifier} STREQUAL PUBLIC)
|
||||
set(PROJECT_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
set(PROJECT_INTERFACE_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
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 ${ARGS_VERSION})
|
||||
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
if(${pkgname}_FOUND)
|
||||
if(${qualifier} STREQUAL PRIVATE)
|
||||
set(PROJECT_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
elseif(${qualifier} STREQUAL PUBLIC)
|
||||
set(PROJECT_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
set(PROJECT_INTERFACE_${pkgname}_VERSION ${ARGS_VERSION})
|
||||
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 ${ARGS_VERSION})
|
||||
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
@@ -89,7 +89,7 @@ endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ZeroMQ
|
||||
REQUIRED_VARS ZeroMQ_LIBRARY_SHARED ZeroMQ_INCLUDE_DIR ZeroMQ_LIBRARY_STATIC
|
||||
REQUIRED_VARS ZeroMQ_LIBRARY_SHARED ZeroMQ_INCLUDE_DIR
|
||||
VERSION_VAR ZeroMQ_VERSION
|
||||
)
|
||||
|
||||
|
@@ -1,34 +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" #
|
||||
################################################################################
|
||||
|
||||
find_path(nanomsg_INCLUDE_DIR
|
||||
NAMES nanomsg/nn.h
|
||||
HINTS ${NANOMSG_ROOT} $ENV{NANOMSG_ROOT}
|
||||
PATH_SUFFIXES include
|
||||
DOC "Path to nanomsg include header files."
|
||||
)
|
||||
|
||||
find_library(nanomsg_LIBRARY_SHARED
|
||||
NAMES libnanomsg.dylib libnanomsg.so
|
||||
HINTS ${NANOMSG_ROOT} $ENV{NANOMSG_ROOT}
|
||||
PATH_SUFFIXES lib
|
||||
DOC "Path to libnanomsg.dylib libnanomsg.so."
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(nanomsg
|
||||
REQUIRED_VARS nanomsg_LIBRARY_SHARED nanomsg_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if(NOT TARGET nanomsg AND nanomsg_FOUND)
|
||||
add_library(nanomsg SHARED IMPORTED)
|
||||
set_target_properties(nanomsg PROPERTIES
|
||||
IMPORTED_LOCATION ${nanomsg_LIBRARY_SHARED}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${nanomsg_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
@@ -51,7 +51,7 @@ function(add_testsuite suitename)
|
||||
cmake_parse_arguments(testsuite
|
||||
""
|
||||
"TIMEOUT;RUN_SERIAL"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES;DEFINITIONS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
@@ -69,6 +69,9 @@ function(add_testsuite suitename)
|
||||
if(testsuite_INCLUDES)
|
||||
target_include_directories(${target} PUBLIC ${testsuite_INCLUDES})
|
||||
endif()
|
||||
if(testsuite_DEFINITIONS)
|
||||
target_compile_definitions("${target}" PUBLIC ${testsuite_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
add_test(NAME "${suitename}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${target})
|
||||
if(testsuite_TIMEOUT)
|
||||
@@ -86,7 +89,7 @@ function(add_testhelper helpername)
|
||||
cmake_parse_arguments(testhelper
|
||||
""
|
||||
""
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES;DEFINITIONS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
@@ -102,6 +105,9 @@ function(add_testhelper helpername)
|
||||
if(testhelper_INCLUDES)
|
||||
target_include_directories(${target} PUBLIC ${testhelper_INCLUDES})
|
||||
endif()
|
||||
if(testhelper_DEFINITIONS)
|
||||
target_compile_definitions(${target} PUBLIC ${testhelper_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
list(APPEND ALL_TEST_TARGETS ${target})
|
||||
set(ALL_TEST_TARGETS ${ALL_TEST_TARGETS} PARENT_SCOPE)
|
||||
@@ -111,7 +117,7 @@ function(add_testlib libname)
|
||||
cmake_parse_arguments(testlib
|
||||
"HIDDEN"
|
||||
"VERSION"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES"
|
||||
"SOURCES;LINKS;DEPENDS;INCLUDES;DEFINITIONS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
@@ -133,6 +139,9 @@ function(add_testlib libname)
|
||||
if(testlib_VERSION)
|
||||
set_target_properties(${target} PROPERTIES VERSION ${testlib_VERSION})
|
||||
endif()
|
||||
if(testlib_DEFINITIONS)
|
||||
target_compile_definitions(${target} PUBLIC ${testlib_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
list(APPEND ALL_TEST_TARGETS ${target})
|
||||
set(ALL_TEST_TARGETS ${ALL_TEST_TARGETS} PARENT_SCOPE)
|
||||
|
4190
cmake/cotire.cmake
Normal file
4190
cmake/cotire.cmake
Normal file
File diff suppressed because it is too large
Load Diff
1
docs/footer.html
Normal file
1
docs/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
<p style="margin: 0 12px 10px 12px;"><a href="https://help.github.com/articles/github-privacy-statement/">privacy</a></p>
|
@@ -31,8 +31,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-1-1.sh.in ${CMAKE_CUR
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh)
|
||||
|
||||
add_test(NAME Example-1-1 COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh)
|
||||
set_tests_properties(Example-1-1 PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
add_test(NAME Example-1-1-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh zeromq)
|
||||
set_tests_properties(Example-1-1-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-1-1-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh nanomsg)
|
||||
set_tests_properties(Example-1-1-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
endif()
|
||||
|
||||
add_test(NAME Example-1-1-shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh shmem)
|
||||
set_tests_properties(Example-1-1-shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -1,16 +1,10 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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" *
|
||||
********************************************************************************/
|
||||
/**
|
||||
* Sampler.cpp
|
||||
*
|
||||
* @since 2014-10-10
|
||||
* @author A. Rybalchenko
|
||||
*/
|
||||
|
||||
#include <thread> // this_thread::sleep_for
|
||||
#include <chrono>
|
||||
@@ -64,8 +58,6 @@ bool Sampler::ConditionalRun()
|
||||
return false;
|
||||
}
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
SAMPLER="fairmq-ex-1-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --rate 1"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://*:5555,rateLogging=0"
|
||||
xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
|
||||
|
||||
|
@@ -1,10 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-1-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --rate 1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
@@ -14,6 +24,7 @@ SAMPLER_PID=$!
|
||||
|
||||
SINK="fairmq-ex-1-1-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
|
@@ -39,8 +39,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-1-n-1.json ${CMAKE_CURRENT_BINARY_
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-n-1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh)
|
||||
|
||||
add_test(NAME Example-1-n-1 COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh)
|
||||
set_tests_properties(Example-1-n-1 PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
add_test(NAME Example-1-n-1-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh zeromq)
|
||||
set_tests_properties(Example-1-n-1-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-1-n-1-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh nanomsg)
|
||||
set_tests_properties(Example-1-n-1-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
endif()
|
||||
|
||||
add_test(NAME Example-1-n-1-shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh shmem)
|
||||
set_tests_properties(Example-1-n-1-shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,6 +2,12 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
ex2config="@CMAKE_CURRENT_BINARY_DIR@/ex-1-n-1.json"
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
@@ -9,6 +15,7 @@ trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $PROCESSOR1_PID;
|
||||
|
||||
SAMPLER="fairmq-ex-1-n-1-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 2"
|
||||
@@ -18,6 +25,7 @@ SAMPLER_PID=$!
|
||||
|
||||
PROCESSOR1="fairmq-ex-1-n-1-processor"
|
||||
PROCESSOR1+=" --id processor1"
|
||||
PROCESSOR1+=" --transport $transport"
|
||||
PROCESSOR1+=" --verbosity veryhigh"
|
||||
PROCESSOR1+=" --control static --color false"
|
||||
PROCESSOR1+=" --mq-config $ex2config"
|
||||
@@ -27,6 +35,7 @@ PROCESSOR1_PID=$!
|
||||
|
||||
PROCESSOR2="fairmq-ex-1-n-1-processor"
|
||||
PROCESSOR2+=" --id processor2"
|
||||
PROCESSOR2+=" --transport $transport"
|
||||
PROCESSOR2+=" --verbosity veryhigh"
|
||||
PROCESSOR2+=" --control static --color false"
|
||||
PROCESSOR2+=" --mq-config $ex2config"
|
||||
@@ -36,6 +45,7 @@ PROCESSOR2_PID=$!
|
||||
|
||||
SINK="fairmq-ex-1-n-1-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 2"
|
||||
|
@@ -12,6 +12,8 @@ add_subdirectory(copypush)
|
||||
add_subdirectory(dds)
|
||||
add_subdirectory(multipart)
|
||||
add_subdirectory(multiple-channels)
|
||||
add_subdirectory(multiple-transports)
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_subdirectory(multiple-transports)
|
||||
endif()
|
||||
add_subdirectory(region)
|
||||
add_subdirectory(req-rep)
|
||||
|
@@ -32,8 +32,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-copypush.sh.in ${CMAK
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-copypush.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh)
|
||||
|
||||
add_test(NAME Example-CopyPush COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh)
|
||||
set_tests_properties(Example-CopyPush PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
add_test(NAME Example-CopyPush-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh zeromq)
|
||||
set_tests_properties(Example-CopyPush-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-CopyPush-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh nanomsg)
|
||||
set_tests_properties(Example-CopyPush-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
endif()
|
||||
|
||||
add_test(NAME Example-CopyPush-shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh shmem)
|
||||
set_tests_properties(Example-CopyPush-shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,11 +2,18 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK1_PID; kill -TERM $SINK2_PID; wait $SAMPLER_PID; wait $SINK1_PID; wait $SINK2_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-copypush-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
@@ -16,6 +23,7 @@ SAMPLER_PID=$!
|
||||
|
||||
SINK1="fairmq-ex-copypush-sink"
|
||||
SINK1+=" --id sink1"
|
||||
SINK1+=" --transport $transport"
|
||||
SINK1+=" --verbosity veryhigh"
|
||||
SINK1+=" --control static --color false"
|
||||
SINK1+=" --max-iterations 1"
|
||||
@@ -25,6 +33,7 @@ SINK1_PID=$!
|
||||
|
||||
SINK2="fairmq-ex-copypush-sink"
|
||||
SINK2+=" --id sink2"
|
||||
SINK2+=" --transport $transport"
|
||||
SINK2+=" --verbosity veryhigh"
|
||||
SINK2+=" --control static --color false"
|
||||
SINK2+=" --max-iterations 1"
|
||||
|
@@ -1,23 +1,17 @@
|
||||
DDS Example
|
||||
===========
|
||||
|
||||
This example demonstrates usage of the Dynamic Deployment System ([DDS](http://dds.gsi.de/)) to dynamically deploy and configure a topology of devices. The topology is similar to those of Example 2, but now it can be easily distributed on different computing nodes without the need for manual socket reconfiguration of the devices.
|
||||
|
||||
To make use of DDS functionality the example executables need to find the DDS plugin libraries that are compiled with FairRoot when FairRoot find DDS installed. Custom DDS location can be given to CMake as follows:
|
||||
|
||||
```bash
|
||||
cmake -DDDS_ROOT="/path/to/dds/install/dir/" ..
|
||||
```
|
||||
This example demonstrates usage of the Dynamic Deployment System ([DDS](http://dds.gsi.de/)) to dynamically deploy and configure a topology of devices. The topology is similar to the one in Example 1-n-1, but now it can be easily distributed on different computing nodes without the need for manual addresses reconfiguration of the devices.
|
||||
|
||||
The description below outlines the minimal steps needed to run the example with DDS. For general DDS help please refer to DDS documentation on [DDS Website](http://dds.gsi.de/).
|
||||
|
||||
##### 1. The device handles the socket addresses and ports configuration via DDS Plugin.
|
||||
##### 1. The device handles the channel addresses and ports configuration via DDS Plugin.
|
||||
|
||||
It is sufficient to provide the `-S "<@FAIRROOT_INSTALL_DIR@/lib" -P dds` (`<` prepends the following path to the default plugin search paths; put in the path which points to the library dir of your FairRoot installation) command line arguments to let the devices be configured dynamically. No code changes in the device are necessary. See the XML topology file for example of using the command line arguments.
|
||||
It is sufficient to provide the `-S "<@FAIRMQ_INSTALL_DIR@/lib" -P dds` (`<` prepends the following path to the default plugin search paths; put in the path which points to the library dir of your FairRoot installation) command line arguments to let the devices be configured dynamically. No code changes in the device are necessary. See the XML topology file for example of using the command line arguments.
|
||||
|
||||
##### 2a. Write DDS hosts file that contains a list of worker nodes to run the topology on (When deploying using the SSH plug-in).
|
||||
|
||||
We run this example on the local machine for simplicity. The file below defines three workers, sampler, processor and sink, with a total of 12 DDS agents (thus able to accept 12 tasks). The parameters for each worker node are:
|
||||
We run this example on the local machine for simplicity. The file below defines 3 workers - sampler, processor and sink - with a total of 12 DDS agents (thus able to accept 12 tasks). The parameters for each worker node are:
|
||||
- user-chosen worker ID (must be unique)
|
||||
- a host name with or without a login, in a form: login@host.fqdn (password-less SSH access to these hosts must be possible)
|
||||
- additional SSH params (can be empty)
|
||||
@@ -40,23 +34,27 @@ If you want to deploy on a single host DDS 1.6+ provides a localhost rms plug-in
|
||||
|
||||
##### 3. Write DDS topology file that describes which tasks (processes) to run and their topology and configuration.
|
||||
|
||||
Take a look at `ex-dds-topology.xml`. It consists of a definition part (properties, tasks, collections and more) and execution part (main). In our example Sampler, Processor and Sink tasks are defines, containing their executables and exchanged properties. The `<main>` of the topology uses the defined tasks. Besides one Sampler and one Sink task, a group containing Processor task is defined. The group has a multiplicity of 10, meaninig 10 Processors will be executed. Each of the Processors will receive the properties with Sampler and Sink addresses.
|
||||
Take a look at `ex-dds-topology.xml`. It consists of a definition part (properties, tasks, collections and more) and execution part (main). In our example Sampler, Processor and Sink tasks are defined, containing their executables and exchanged properties. The `<main>` of the topology uses the defined tasks. Besides one Sampler and one Sink task, a group containing Processor task is defined. The group has a multiplicity of 10, meaninig 10 Processors will be executed. Each of the Processors will receive the properties with Sampler and Sink addresses.
|
||||
|
||||
The configuration of the channel connection addresses is done by the DDS plugin via the channel names. The task property names must correspond to the channel names (data1, data2), with binding channels writing the properties and connecting channel reading the properties (see the example XML and JSON files).
|
||||
The configuration of the channel connection addresses is done by the DDS plugin via the channel names. The task property names must correspond to the channel names (data1, data2), with binding channels writing the properties and connecting channel reading the properties.
|
||||
|
||||
If `eth0` network interface (default for binding) is not available on your system, specify another one in the topology file for each task. For example: `--network-interface lo0`.
|
||||
|
||||
If you chose step 2b earlier, then modify the provided `ex-dds-topology.xml` in the top that the following lines read as following:
|
||||
**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 id="SamplerWorker" type="wnname" value=".*"/>
|
||||
<declrequirement id="ProcessorWorker" type="wnname" value=".*"/>
|
||||
<declrequirement id="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.
|
||||
|
||||
##### 4. Start DDS server.
|
||||
|
||||
First you need to initialize DDS environment:
|
||||
|
||||
```bash
|
||||
source DDS_env.sh # this script is located in the DDS installation directory
|
||||
```
|
||||
|
||||
The DDS server is started with:
|
||||
|
||||
```bash
|
||||
@@ -71,7 +69,7 @@ dds-submit --rms ssh --config ex-dds-hosts.cfg
|
||||
```
|
||||
The `--rms` option defines a destination resource management system. The `--config` specifies an SSH plug-in resource definition file.
|
||||
|
||||
If you chose step 2b earlier, run the following command instead:
|
||||
**If you chose step 2b earlier**, run the following command instead:
|
||||
|
||||
```bash
|
||||
dds-submit --rms localhost -n 12
|
||||
@@ -85,13 +83,30 @@ dds-topology --activate ex-dds-topology.xml
|
||||
|
||||
##### 7. Run
|
||||
|
||||
After activation, agents will execute the defined tasks on the worker nodes. Output of the tasks will be stored in the directory that was specified in the hosts file.
|
||||
After activation, agents will execute the defined tasks on the worker nodes. Output of the tasks will be stored in the directory that was specified in the hosts file (or in the system temporary directory when using the localhost plugin).
|
||||
|
||||
##### 8. (optional) Use example command UI to check state of the devices
|
||||
|
||||
A simple utility (fairmq-dds-command-ui) is included with FairRoot to send commands to devices and receive replies from them. The utility uses the DDS intercom library to send "check-state" string to all devices, to which they reply with their ID and state they are in. The utility also allows requesting state changes from devices. To let the device listen to the commands from the utility, start the device with `-S "<@FAIRROOT_INSTALL_DIR@/lib" -P dds` cmd option (see example XML topology).
|
||||
A simple utility (fairmq-dds-command-ui) is included with FairMQ to send commands to devices and receive replies from them. The utility uses the DDS intercom library to query state/config of devices and allows changing their state. To let the device listen to the commands from the utility, start the device with `-S "<@FAIRMQ_INSTALL_DIR@/lib" -P dds` cmd option (see example XML topology).
|
||||
|
||||
To see it in action, start the fairmq-dds-command-ui while the topology is running.
|
||||
To see it in action, start the fairmq-dds-command-ui while the topology is running. Run the utility with `-h` to see everything that it can do.
|
||||
|
||||
The utility requires a session parameter to connect to appropriate DDS session. The session value is given when starting dds-server.
|
||||
|
||||
By default the command UI sends commands to all tasks. This can be further refined by giving a specific topology path via `-p` argument.
|
||||
Given our topology file, here are some examples of valid paths:
|
||||
```bash
|
||||
# get state of all devices
|
||||
./fairmq/plugins/DDS/fairmq-dds-command-ui -s 937ffbca-b524-44d8-9898-1d69aedc3751 -c c
|
||||
# get state of sampler
|
||||
./fairmq/plugins/DDS/fairmq-dds-command-ui -s 937ffbca-b524-44d8-9898-1d69aedc3751 -c c -p main/Sampler
|
||||
# get state of sink
|
||||
./fairmq/plugins/DDS/fairmq-dds-command-ui -s 937ffbca-b524-44d8-9898-1d69aedc3751 -c c -p main/Sink
|
||||
# get state all processors
|
||||
./fairmq/plugins/DDS/fairmq-dds-command-ui -s 937ffbca-b524-44d8-9898-1d69aedc3751 -c c -p main/ProcessorGroup/Processor
|
||||
# get state of a specific processor
|
||||
./fairmq/plugins/DDS/fairmq-dds-command-ui -s 937ffbca-b524-44d8-9898-1d69aedc3751 -c c -p main/ProcessorGroup/Processor_9
|
||||
```
|
||||
|
||||
##### 9. Stop DDS server/topology.
|
||||
|
||||
|
@@ -31,8 +31,16 @@ 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 COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh)
|
||||
set_tests_properties(Example-Multipart PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 2 parts")
|
||||
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 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 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 2 parts")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,11 +2,18 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SINK_PID;' TERM
|
||||
|
||||
SAMPLER="fairmq-ex-multipart-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
@@ -16,6 +23,7 @@ SAMPLER_PID=$!
|
||||
|
||||
SINK="fairmq-ex-multipart-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --channel-config name=data,type=pull,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
|
||||
|
@@ -36,8 +36,13 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-channels.sh.
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-channels.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh)
|
||||
|
||||
add_test(NAME Example-Multiple-Channels COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh)
|
||||
set_tests_properties(Example-Multiple-Channels PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
add_test(NAME Example-Multiple-Channels-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh zeromq)
|
||||
set_tests_properties(Example-Multiple-Channels-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-Multiple-Channels-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh nanomsg)
|
||||
set_tests_properties(Example-Multiple-Channels-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
|
||||
endif()
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,12 +2,19 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; kill -TERM $BROADCASTER_PID; wait $SAMPLER_PID; wait $SINK_PID; wait $BROADCASTER_PID;' TERM
|
||||
|
||||
|
||||
SINK="fairmq-ex-multiple-channels-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --control static --color false"
|
||||
@@ -20,6 +27,7 @@ sleep 1
|
||||
|
||||
SAMPLER="fairmq-ex-multiple-channels-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --verbosity veryhigh"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --control static --color false"
|
||||
@@ -30,6 +38,7 @@ SAMPLER_PID=$!
|
||||
|
||||
BROADCASTER="fairmq-ex-multiple-channels-broadcaster"
|
||||
BROADCASTER+=" --id broadcaster1"
|
||||
BROADCASTER+=" --transport $transport"
|
||||
BROADCASTER+=" --verbosity veryhigh"
|
||||
BROADCASTER+=" --control static --color false"
|
||||
BROADCASTER+=" --channel-config name=broadcast,type=pub,method=bind,rateLogging=0,address=tcp://*:5005"
|
||||
|
@@ -23,8 +23,6 @@ Sink::Sink()
|
||||
: fMaxIterations(0)
|
||||
, fNumIterations1(0)
|
||||
, fNumIterations2(0)
|
||||
, fReceived1(false)
|
||||
, fReceived2(false)
|
||||
{
|
||||
// register a handler for data arriving on "data" channel
|
||||
OnData("data1", &Sink::HandleData1);
|
||||
|
@@ -36,8 +36,6 @@ class Sink : public FairMQDevice
|
||||
uint64_t fMaxIterations;
|
||||
uint64_t fNumIterations1;
|
||||
uint64_t fNumIterations2;
|
||||
bool fReceived1;
|
||||
bool fReceived2;
|
||||
};
|
||||
|
||||
} // namespace example_multiple_transports
|
||||
|
@@ -24,4 +24,4 @@ SINK+=" --transport shmem"
|
||||
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
|
||||
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=nanomsg"
|
||||
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
|
||||
xterm -geometry 80x30+500+0 -hold -e @EX_BIN_DIR@/$SINK &
|
||||
xterm -geometry 80x30+500+225 -hold -e @EX_BIN_DIR@/$SINK &
|
||||
|
@@ -32,8 +32,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-region.sh.in ${CMAKE_
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh)
|
||||
|
||||
add_test(NAME Example-Region COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh)
|
||||
set_tests_properties(Example-Region PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack")
|
||||
add_test(NAME Example-Region-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh zeromq)
|
||||
set_tests_properties(Example-Region-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-Region-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh nanomsg)
|
||||
set_tests_properties(Example-Region-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack")
|
||||
endif()
|
||||
|
||||
add_test(NAME Example-Region-shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh shmem)
|
||||
set_tests_properties(Example-Region-shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -38,7 +38,7 @@ void Sampler::InitTask()
|
||||
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
|
||||
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport
|
||||
--fNumUnackedMsgs;
|
||||
if (fMaxIterations > 0)
|
||||
{
|
||||
|
@@ -2,6 +2,12 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
msgSize="1000000"
|
||||
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
|
||||
|
||||
@@ -10,23 +16,23 @@ trap 'kill -TERM $SAMPLER_PID; kill -TERM $SINK_PID; wait $SAMPLER_PID; wait $SI
|
||||
|
||||
SAMPLER="fairmq-ex-region-sampler"
|
||||
SAMPLER+=" --id sampler1"
|
||||
SAMPLER+=" --transport $transport"
|
||||
SAMPLER+=" --severity debug"
|
||||
SAMPLER+=" --session $SESSION"
|
||||
SAMPLER+=" --control static --color false"
|
||||
SAMPLER+=" --max-iterations 1"
|
||||
SAMPLER+=" --msg-size $msgSize"
|
||||
SAMPLER+=" --transport shmem"
|
||||
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
|
||||
SAMPLER_PID=$!
|
||||
|
||||
SINK="fairmq-ex-region-sink"
|
||||
SINK+=" --id sink1"
|
||||
SINK+=" --transport $transport"
|
||||
SINK+=" --session $SESSION"
|
||||
SINK+=" --verbosity veryhigh"
|
||||
SINK+=" --control static --color false"
|
||||
SINK+=" --max-iterations 1"
|
||||
SINK+=" --transport shmem"
|
||||
SINK+=" --channel-config name=data,type=pull,method=connect,address=tcp://127.0.0.1:7777"
|
||||
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
|
||||
SINK_PID=$!
|
||||
|
@@ -32,8 +32,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-req-rep.sh.in ${CMAKE
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-req-rep.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh)
|
||||
|
||||
add_test(NAME Example-ReqRep COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh)
|
||||
set_tests_properties(Example-ReqRep PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
add_test(NAME Example-ReqRep-zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh zeromq)
|
||||
set_tests_properties(Example-ReqRep-zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
add_test(NAME Example-ReqRep-nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh nanomsg)
|
||||
set_tests_properties(Example-ReqRep-nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
endif()
|
||||
|
||||
add_test(NAME Example-ReqRep-shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh shmem)
|
||||
set_tests_properties(Example-ReqRep-shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
|
||||
|
||||
# install
|
||||
|
||||
|
@@ -2,11 +2,18 @@
|
||||
|
||||
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
|
||||
|
||||
transport="zeromq"
|
||||
|
||||
if [[ $1 =~ ^[a-z]+$ ]]; then
|
||||
transport=$1
|
||||
fi
|
||||
|
||||
# setup a trap to kill everything if the test fails/timeouts
|
||||
trap 'kill -TERM $CLIENT_PID; kill -TERM $SERVER_PID; wait $CLIENT_PID; wait $SERVER_PID;' TERM
|
||||
|
||||
CLIENT="fairmq-ex-req-rep-client"
|
||||
CLIENT+=" --id client"
|
||||
CLIENT+=" --transport $transport"
|
||||
CLIENT+=" --verbosity veryhigh"
|
||||
CLIENT+=" --control static --color false"
|
||||
CLIENT+=" --max-iterations 1"
|
||||
@@ -16,6 +23,7 @@ CLIENT_PID=$!
|
||||
|
||||
SERVER="fairmq-ex-req-rep-server"
|
||||
SERVER+=" --id server"
|
||||
SERVER+=" --transport $transport"
|
||||
SERVER+=" --verbosity veryhigh"
|
||||
SERVER+=" --control static --color false"
|
||||
SERVER+=" --max-iterations 1"
|
||||
|
@@ -1,54 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
#AccessModifierOffset: -4
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
|
||||
# It is broken on windows. Breaks all #include "header.h"
|
||||
#AlwaysBreakBeforeMultilineStrings: true
|
||||
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BinPackParameters: false
|
||||
ColumnLimit: 160
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
DerivePointerBinding: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
IndentCaseLabels: true
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerBindsToType: true
|
||||
SpacesBeforeTrailingComments: 1
|
||||
Cpp11BracedListStyle: false
|
||||
Standard: Cpp11
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Allman
|
||||
IndentFunctionDeclarationAfterType: true
|
||||
SpacesInParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
SpaceBeforeParens: ControlStatements
|
||||
...
|
@@ -37,142 +37,145 @@ endif()
|
||||
##########################
|
||||
# libFairMQ header files #
|
||||
##########################
|
||||
set(FAIRMQ_HEADER_FILES
|
||||
DeviceRunner.h
|
||||
EventManager.h
|
||||
FairMQChannel.h
|
||||
FairMQDevice.h
|
||||
FairMQLogger.h
|
||||
FairMQMessage.h
|
||||
FairMQParts.h
|
||||
FairMQPoller.h
|
||||
FairMQUnmanagedRegion.h
|
||||
FairMQSocket.h
|
||||
FairMQStateMachine.h
|
||||
FairMQTransportFactory.h
|
||||
Tools.h
|
||||
Transports.h
|
||||
devices/FairMQBenchmarkSampler.h
|
||||
devices/FairMQMerger.h
|
||||
devices/FairMQMultiplier.h
|
||||
devices/FairMQProxy.h
|
||||
devices/FairMQSink.h
|
||||
devices/FairMQSplitter.h
|
||||
options/FairMQParser.h
|
||||
options/FairMQProgOptions.h
|
||||
options/FairMQSuboptParser.h
|
||||
options/FairProgOptions.h
|
||||
options/FairProgOptionsHelper.h
|
||||
Plugin.h
|
||||
PluginManager.h
|
||||
PluginServices.h
|
||||
plugins/Builtin.h
|
||||
plugins/Control.h
|
||||
runFairMQDevice.h
|
||||
StateMachine.h
|
||||
shmem/FairMQMessageSHM.h
|
||||
shmem/FairMQPollerSHM.h
|
||||
shmem/FairMQUnmanagedRegionSHM.h
|
||||
shmem/FairMQSocketSHM.h
|
||||
shmem/FairMQTransportFactorySHM.h
|
||||
shmem/Common.h
|
||||
shmem/Manager.h
|
||||
shmem/Monitor.h
|
||||
shmem/Region.h
|
||||
tools/CppSTL.h
|
||||
tools/Network.h
|
||||
tools/Process.h
|
||||
tools/Strings.h
|
||||
tools/Unique.h
|
||||
tools/Version.h
|
||||
zeromq/FairMQMessageZMQ.h
|
||||
zeromq/FairMQPollerZMQ.h
|
||||
zeromq/FairMQUnmanagedRegionZMQ.h
|
||||
zeromq/FairMQSocketZMQ.h
|
||||
zeromq/FairMQTransportFactoryZMQ.h
|
||||
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
|
||||
FairMQStateMachine.h
|
||||
FairMQTransportFactory.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(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
|
||||
StateMachine.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
|
||||
)
|
||||
|
||||
if(BUILD_NANOMSG_TRANSPORT)
|
||||
set(FAIRMQ_HEADER_FILES ${FAIRMQ_HEADER_FILES}
|
||||
nanomsg/FairMQMessageNN.h
|
||||
nanomsg/FairMQPollerNN.h
|
||||
nanomsg/FairMQUnmanagedRegionNN.h
|
||||
nanomsg/FairMQSocketNN.h
|
||||
nanomsg/FairMQTransportFactoryNN.h
|
||||
)
|
||||
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_HEADER_FILES ${FAIRMQ_HEADER_FILES}
|
||||
ofi/Context.h
|
||||
ofi/Message.h
|
||||
ofi/Poller.h
|
||||
ofi/Socket.h
|
||||
ofi/TransportFactory.h
|
||||
)
|
||||
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
|
||||
FairMQStateMachine.cxx
|
||||
FairMQTransportFactory.cxx
|
||||
devices/FairMQBenchmarkSampler.cxx
|
||||
devices/FairMQMerger.cxx
|
||||
devices/FairMQMultiplier.cxx
|
||||
devices/FairMQProxy.cxx
|
||||
# devices/FairMQSink.cxx
|
||||
devices/FairMQSplitter.cxx
|
||||
options/FairMQParser.cxx
|
||||
options/FairMQProgOptions.cxx
|
||||
options/FairMQSuboptParser.cxx
|
||||
options/FairProgOptions.cxx
|
||||
Plugin.cxx
|
||||
PluginManager.cxx
|
||||
PluginServices.cxx
|
||||
plugins/Control.cxx
|
||||
StateMachine.cxx
|
||||
shmem/FairMQMessageSHM.cxx
|
||||
shmem/FairMQPollerSHM.cxx
|
||||
shmem/FairMQUnmanagedRegionSHM.cxx
|
||||
shmem/FairMQSocketSHM.cxx
|
||||
shmem/FairMQTransportFactorySHM.cxx
|
||||
shmem/Manager.cxx
|
||||
shmem/Monitor.cxx
|
||||
shmem/Region.cxx
|
||||
zeromq/FairMQMessageZMQ.cxx
|
||||
zeromq/FairMQPollerZMQ.cxx
|
||||
zeromq/FairMQUnmanagedRegionZMQ.cxx
|
||||
zeromq/FairMQSocketZMQ.cxx
|
||||
zeromq/FairMQTransportFactoryZMQ.cxx
|
||||
DeviceRunner.cxx
|
||||
FairMQChannel.cxx
|
||||
FairMQDevice.cxx
|
||||
FairMQLogger.cxx
|
||||
FairMQMessage.cxx
|
||||
FairMQPoller.cxx
|
||||
FairMQSocket.cxx
|
||||
FairMQStateMachine.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
|
||||
StateMachine.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
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
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
|
||||
)
|
||||
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
|
||||
ofi/Context.cxx
|
||||
ofi/Message.cxx
|
||||
ofi/Poller.cxx
|
||||
ofi/Socket.cxx
|
||||
ofi/TransportFactory.cxx
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -187,61 +190,93 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/options/startConfigExample.sh.in ${CM
|
||||
#################################
|
||||
# define libFairMQ build target #
|
||||
#################################
|
||||
add_library(FairMQ SHARED
|
||||
if(FAST_BUILD)
|
||||
set(_target FairMQ_)
|
||||
else()
|
||||
set(_target FairMQ)
|
||||
endif()
|
||||
add_library(${_target}
|
||||
${FAIRMQ_SOURCE_FILES}
|
||||
${FAIRMQ_HEADER_FILES} # for IDE integration
|
||||
${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(FairMQ
|
||||
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>
|
||||
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)
|
||||
set(NANOMSG_DEPS nanomsg msgpackc-cxx)
|
||||
endif()
|
||||
if(BUILD_OFI_TRANSPORT)
|
||||
set(OFI_DEPS OFI::libfabric protobuf::libprotobuf $<TARGET_OBJECTS:OfiTransport>)
|
||||
endif()
|
||||
target_link_libraries(FairMQ
|
||||
INTERFACE # only consumers link against interface dependencies
|
||||
set(optional_deps ${NANOMSG_DEPS} ${OFI_DEPS})
|
||||
if(optional_deps)
|
||||
list(REMOVE_DUPLICATES optional_deps)
|
||||
endif()
|
||||
|
||||
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
|
||||
dl
|
||||
Boost::boost
|
||||
Boost::program_options
|
||||
Boost::thread
|
||||
Boost::system
|
||||
Boost::filesystem
|
||||
Boost::regex
|
||||
Boost::date_time
|
||||
Boost::signals
|
||||
FairLogger::FairLogger
|
||||
target_link_libraries(${_target}
|
||||
INTERFACE # only consumers link against interface dependencies
|
||||
|
||||
PRIVATE # only libFairMQ links against private dependencies
|
||||
libzmq
|
||||
${NANOMSG_DEPS}
|
||||
${OFI_DEPS}
|
||||
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
|
||||
Threads::Threads
|
||||
dl
|
||||
$<$<PLATFORM_ID:Linux>:rt>
|
||||
Boost::boost
|
||||
Boost::program_options
|
||||
Boost::thread
|
||||
Boost::system
|
||||
Boost::filesystem
|
||||
Boost::regex
|
||||
Boost::date_time
|
||||
Boost::signals
|
||||
FairLogger::FairLogger
|
||||
|
||||
PRIVATE # only libFairMQ links against private dependencies
|
||||
libzmq
|
||||
${NANOMSG_DEPS}
|
||||
${OFI_DEPS}
|
||||
)
|
||||
set_target_properties(FairMQ PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
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
|
||||
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)
|
||||
|
||||
@@ -263,37 +298,48 @@ target_link_libraries(fairmq-splitter FairMQ)
|
||||
add_executable(runConfigExample options/runConfigEx.cxx)
|
||||
target_link_libraries(runConfigExample FairMQ)
|
||||
|
||||
add_executable(fairmq-shmmonitor shmem/runMonitor.cxx)
|
||||
target_link_libraries(fairmq-shmmonitor 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 # FairMQFull, tests are not installed
|
||||
FairMQ
|
||||
fairmq-bsampler
|
||||
fairmq-merger
|
||||
fairmq-multiplier
|
||||
fairmq-proxy
|
||||
fairmq-sink
|
||||
fairmq-splitter
|
||||
fairmq-shmmonitor
|
||||
fairmq-uuid-gen
|
||||
TARGETS
|
||||
FairMQ
|
||||
fairmq-bsampler
|
||||
fairmq-merger
|
||||
fairmq-multiplier
|
||||
fairmq-proxy
|
||||
fairmq-sink
|
||||
fairmq-splitter
|
||||
fairmq-shmmonitor
|
||||
fairmq-uuid-gen
|
||||
|
||||
EXPORT ${PROJECT_EXPORT_SET}
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
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_HEADER_FILES})
|
||||
get_filename_component(_path ${HEADER} DIRECTORY)
|
||||
file(TO_CMAKE_PATH ${PROJECT_INSTALL_INCDIR}/${_path} _destination)
|
||||
install(FILES ${HEADER}
|
||||
DESTINATION ${_destination}
|
||||
)
|
||||
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()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -7,17 +7,21 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "DeviceRunner.h"
|
||||
#include <fairmq/Tools.h>
|
||||
|
||||
#include <exception>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <fairmq/Version.h>
|
||||
|
||||
using namespace fair::mq;
|
||||
|
||||
DeviceRunner::DeviceRunner(int argc, char* const argv[])
|
||||
: fRawCmdLineArgs{tools::ToStrVector(argc, argv, false)}
|
||||
, fPluginManager{PluginManager::MakeFromCommandLineOptions(fRawCmdLineArgs)}
|
||||
, fDevice{nullptr}
|
||||
{
|
||||
}
|
||||
DeviceRunner::DeviceRunner(int argc, char* const argv[], bool printLogo)
|
||||
: fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))
|
||||
, fConfig()
|
||||
, fDevice(nullptr)
|
||||
, fPluginManager(fRawCmdLineArgs)
|
||||
, fPrintLogo(printLogo)
|
||||
, fEvents()
|
||||
{}
|
||||
|
||||
auto DeviceRunner::Run() -> int
|
||||
{
|
||||
@@ -26,48 +30,56 @@ auto DeviceRunner::Run() -> int
|
||||
////////////////////////
|
||||
|
||||
// Load builtin plugins last
|
||||
fPluginManager->LoadPlugin("s:control");
|
||||
fPluginManager.LoadPlugin("s:control");
|
||||
|
||||
////// CALL HOOK ///////
|
||||
fEvents.Emit<hooks::SetCustomCmdLineOptions>(*this);
|
||||
////////////////////////
|
||||
|
||||
fPluginManager->ForEachPluginProgOptions([&](boost::program_options::options_description options){
|
||||
fConfig.AddToCmdLineOptions(options);
|
||||
});
|
||||
fConfig.AddToCmdLineOptions(fPluginManager->ProgramOptions());
|
||||
fPluginManager.ForEachPluginProgOptions(
|
||||
[&](boost::program_options::options_description options) {
|
||||
fConfig.AddToCmdLineOptions(options);
|
||||
});
|
||||
fConfig.AddToCmdLineOptions(fPluginManager.ProgramOptions());
|
||||
|
||||
////// CALL HOOK ///////
|
||||
fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);
|
||||
////////////////////////
|
||||
|
||||
if (fConfig.ParseAll(fRawCmdLineArgs, true))
|
||||
{
|
||||
if (fConfig.ParseAll(fRawCmdLineArgs, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
////////////////////////
|
||||
|
||||
if (!fDevice)
|
||||
{
|
||||
if (!fDevice) {
|
||||
LOG(error) << "getDevice(): no valid device provided. Exiting.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
fDevice->SetRawCmdLineArgs(fRawCmdLineArgs);
|
||||
|
||||
// Handle --print-channels
|
||||
fDevice->RegisterChannelEndpoints();
|
||||
if (fConfig.Count("print-channels"))
|
||||
{
|
||||
if (fConfig.Count("print-channels")) {
|
||||
fDevice->PrintRegisteredChannels();
|
||||
fDevice->ChangeState(FairMQDevice::END);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle --version
|
||||
if (fConfig.Count("version"))
|
||||
{
|
||||
if (fConfig.Count("version")) {
|
||||
std::cout << "User device version: " << fDevice->GetVersion() << std::endl;
|
||||
std::cout << "FAIRMQ_INTERFACE_VERSION: " << FAIRMQ_INTERFACE_VERSION << std::endl;
|
||||
fDevice->ChangeState(FairMQDevice::END);
|
||||
@@ -80,31 +92,31 @@ auto DeviceRunner::Run() -> int
|
||||
fDevice->SetConfig(fConfig);
|
||||
|
||||
// Initialize plugin services
|
||||
fPluginManager->EmplacePluginServices(&fConfig, fDevice);
|
||||
fPluginManager.EmplacePluginServices(fConfig, *fDevice);
|
||||
|
||||
// Instantiate and run plugins
|
||||
fPluginManager->InstantiatePlugins();
|
||||
fPluginManager.InstantiatePlugins();
|
||||
|
||||
// Run the device
|
||||
fDevice->RunStateMachine();
|
||||
|
||||
// Wait for control plugin to release device control
|
||||
fPluginManager->WaitForPluginsToReleaseDeviceControl();
|
||||
fPluginManager.WaitForPluginsToReleaseDeviceControl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto DeviceRunner::RunWithExceptionHandlers() -> int
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
return Run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(error) << "Unhandled exception reached the top of main: " << e.what() << ", application will now exit";
|
||||
} catch (std::exception& e) {
|
||||
LOG(error) << "Unhandled exception reached the top of main: " << e.what()
|
||||
<< ", application will now exit";
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG(error) << "Non-exception instance being thrown. Please make sure you use std::runtime_exception() instead. Application will now exit.";
|
||||
} catch (...) {
|
||||
LOG(error) << "Non-exception instance being thrown. Please make sure you use "
|
||||
"std::runtime_exception() instead. Application will now exit.";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -20,10 +20,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
namespace fair {
|
||||
namespace mq {
|
||||
|
||||
/**
|
||||
* @class DeviceRunner DeviceRunner.h <fairmq/DeviceRunner.h>
|
||||
@@ -31,7 +29,8 @@ namespace mq
|
||||
*
|
||||
* Runs a single FairMQ device with config and plugin support.
|
||||
*
|
||||
* For customization user hooks are executed at various steps during device launch/shutdown in the following sequence:
|
||||
* For customization user hooks are executed at various steps during device launch/shutdown in the
|
||||
* following sequence:
|
||||
*
|
||||
* LoadPlugins
|
||||
* |
|
||||
@@ -44,34 +43,41 @@ namespace mq
|
||||
* v
|
||||
* InstatiateDevice
|
||||
*
|
||||
* Each hook has access to all members of the DeviceRunner and really only differs by the point in time it is called.
|
||||
* Each hook has access to all members of the DeviceRunner and really only differs by the point in
|
||||
* time it is called.
|
||||
*
|
||||
* For an example usage of this class see the fairmq/runFairMQDevice.h header.
|
||||
*/
|
||||
class DeviceRunner
|
||||
{
|
||||
public:
|
||||
DeviceRunner(int argc, char* const argv[]);
|
||||
DeviceRunner(int argc, char* const argv[], bool printLogo = true);
|
||||
|
||||
auto Run() -> int;
|
||||
auto RunWithExceptionHandlers() -> int;
|
||||
|
||||
template<typename H>
|
||||
auto AddHook(std::function<void(DeviceRunner&)> hook) -> void { fEvents.Subscribe<H>("runner", hook); }
|
||||
auto AddHook(std::function<void(DeviceRunner&)> hook) -> void
|
||||
{
|
||||
fEvents.Subscribe<H>("runner", hook);
|
||||
}
|
||||
template<typename H>
|
||||
auto RemoveHook() -> void { fEvents.Unsubscribe<H>("runner"); }
|
||||
auto RemoveHook() -> void
|
||||
{
|
||||
fEvents.Unsubscribe<H>("runner");
|
||||
}
|
||||
|
||||
std::vector<std::string> fRawCmdLineArgs;
|
||||
std::shared_ptr<PluginManager> fPluginManager;
|
||||
FairMQProgOptions fConfig;
|
||||
std::shared_ptr<FairMQDevice> fDevice;
|
||||
std::unique_ptr<FairMQDevice> fDevice;
|
||||
PluginManager fPluginManager;
|
||||
const bool fPrintLogo;
|
||||
|
||||
private:
|
||||
EventManager fEvents;
|
||||
};
|
||||
|
||||
namespace hooks
|
||||
{
|
||||
namespace hooks {
|
||||
struct LoadPlugins : Event<DeviceRunner&> {};
|
||||
struct SetCustomCmdLineOptions : Event<DeviceRunner&> {};
|
||||
struct ModifyRawCmdLineArgs : Event<DeviceRunner&> {};
|
||||
|
@@ -28,7 +28,7 @@ FairMQChannel::FairMQChannel()
|
||||
, fType("unspecified")
|
||||
, fMethod("unspecified")
|
||||
, fAddress("unspecified")
|
||||
, fTransport("default")
|
||||
, fTransportType(fair::mq::Transport::DEFAULT)
|
||||
, fSndBufSize(1000)
|
||||
, fRcvBufSize(1000)
|
||||
, fSndKernelSize(0)
|
||||
@@ -36,7 +36,6 @@ FairMQChannel::FairMQChannel()
|
||||
, fRateLogging(1)
|
||||
, fName("")
|
||||
, fIsValid(false)
|
||||
, fTransportType(FairMQ::Transport::DEFAULT)
|
||||
, fTransportFactory(nullptr)
|
||||
, fMultipart(false)
|
||||
, fModified(true)
|
||||
@@ -49,7 +48,7 @@ FairMQChannel::FairMQChannel(const string& type, const string& method, const str
|
||||
, fType(type)
|
||||
, fMethod(method)
|
||||
, fAddress(address)
|
||||
, fTransport("default")
|
||||
, fTransportType(fair::mq::Transport::DEFAULT)
|
||||
, fSndBufSize(1000)
|
||||
, fRcvBufSize(1000)
|
||||
, fSndKernelSize(0)
|
||||
@@ -57,7 +56,6 @@ FairMQChannel::FairMQChannel(const string& type, const string& method, const str
|
||||
, fRateLogging(1)
|
||||
, fName("")
|
||||
, fIsValid(false)
|
||||
, fTransportType(FairMQ::Transport::DEFAULT)
|
||||
, fTransportFactory(nullptr)
|
||||
, fMultipart(false)
|
||||
, fModified(true)
|
||||
@@ -70,7 +68,7 @@ FairMQChannel::FairMQChannel(const string& name, const string& type, std::shared
|
||||
, fType(type)
|
||||
, fMethod("unspecified")
|
||||
, fAddress("unspecified")
|
||||
, fTransport("default") // TODO refactor, either use string representation or enum type
|
||||
, fTransportType(factory->GetType())
|
||||
, fSndBufSize(1000)
|
||||
, fRcvBufSize(1000)
|
||||
, fSndKernelSize(0)
|
||||
@@ -78,7 +76,6 @@ FairMQChannel::FairMQChannel(const string& name, const string& type, std::shared
|
||||
, fRateLogging(1)
|
||||
, fName(name)
|
||||
, fIsValid(false)
|
||||
, fTransportType(factory->GetType())
|
||||
, fTransportFactory(factory)
|
||||
, fMultipart(false)
|
||||
, fModified(true)
|
||||
@@ -91,7 +88,7 @@ FairMQChannel::FairMQChannel(const FairMQChannel& chan)
|
||||
, fType(chan.fType)
|
||||
, fMethod(chan.fMethod)
|
||||
, fAddress(chan.fAddress)
|
||||
, fTransport(chan.fTransport)
|
||||
, fTransportType(chan.fTransportType)
|
||||
, fSndBufSize(chan.fSndBufSize)
|
||||
, fRcvBufSize(chan.fRcvBufSize)
|
||||
, fSndKernelSize(chan.fSndKernelSize)
|
||||
@@ -99,7 +96,6 @@ FairMQChannel::FairMQChannel(const FairMQChannel& chan)
|
||||
, fRateLogging(chan.fRateLogging)
|
||||
, fName(chan.fName)
|
||||
, fIsValid(false)
|
||||
, fTransportType(FairMQ::Transport::DEFAULT)
|
||||
, fTransportFactory(nullptr)
|
||||
, fMultipart(chan.fMultipart)
|
||||
, fModified(chan.fModified)
|
||||
@@ -111,7 +107,6 @@ FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
|
||||
fType = chan.fType;
|
||||
fMethod = chan.fMethod;
|
||||
fAddress = chan.fAddress;
|
||||
fTransport = chan.fTransport;
|
||||
fSndBufSize = chan.fSndBufSize;
|
||||
fRcvBufSize = chan.fRcvBufSize;
|
||||
fSndKernelSize = chan.fSndKernelSize;
|
||||
@@ -120,7 +115,7 @@ FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
|
||||
fSocket = nullptr;
|
||||
fName = chan.fName;
|
||||
fIsValid = false;
|
||||
fTransportType = FairMQ::Transport::DEFAULT;
|
||||
fTransportType = chan.fTransportType;
|
||||
fTransportFactory = nullptr;
|
||||
|
||||
return *this;
|
||||
@@ -194,16 +189,16 @@ string FairMQChannel::GetAddress() const
|
||||
}
|
||||
}
|
||||
|
||||
string FairMQChannel::GetTransport() const
|
||||
string FairMQChannel::GetTransportName() const
|
||||
{
|
||||
try
|
||||
{
|
||||
unique_lock<mutex> lock(fChannelMutex);
|
||||
return fTransport;
|
||||
return fair::mq::TransportNames.at(fTransportType);
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Exception caught in FairMQChannel::GetTransport: " << e.what();
|
||||
LOG(error) << "Exception caught in FairMQChannel::GetTransportName: " << e.what();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -332,7 +327,7 @@ void FairMQChannel::UpdateTransport(const string& transport)
|
||||
{
|
||||
unique_lock<mutex> lock(fChannelMutex);
|
||||
fIsValid = false;
|
||||
fTransport = transport;
|
||||
fTransportType = fair::mq::TransportTypes.at(transport);
|
||||
fModified = true;
|
||||
}
|
||||
catch (exception& e)
|
||||
@@ -504,7 +499,7 @@ bool FairMQChannel::ValidateChannel()
|
||||
else
|
||||
{
|
||||
vector<string> endpoints;
|
||||
boost::algorithm::split(endpoints, fAddress, boost::algorithm::is_any_of(","));
|
||||
boost::algorithm::split(endpoints, fAddress, boost::algorithm::is_any_of(";"));
|
||||
for (const auto endpoint : endpoints)
|
||||
{
|
||||
string address;
|
||||
@@ -586,17 +581,6 @@ bool FairMQChannel::ValidateChannel()
|
||||
}
|
||||
}
|
||||
|
||||
// validate channel transport
|
||||
// const string channelTransportNames[] = { "default", "zeromq", "nanomsg", "shmem" };
|
||||
// const set<string> channelTransports(channelTransportNames, channelTransportNames + sizeof(channelTransportNames) / sizeof(string));
|
||||
if (FairMQ::TransportTypes.find(fTransport) == FairMQ::TransportTypes.end())
|
||||
{
|
||||
ss << "INVALID";
|
||||
LOG(debug) << ss.str();
|
||||
LOG(error) << "Invalid channel transport: \"" << fTransport << "\"";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// validate socket buffer size for sending
|
||||
if (fSndBufSize < 0)
|
||||
{
|
||||
@@ -669,13 +653,13 @@ void FairMQChannel::ResetChannel()
|
||||
|
||||
int FairMQChannel::Send(unique_ptr<FairMQMessage>& msg) const
|
||||
{
|
||||
CheckCompatibility(msg);
|
||||
CheckSendCompatibility(msg);
|
||||
return fSocket->Send(msg);
|
||||
}
|
||||
|
||||
int FairMQChannel::Receive(unique_ptr<FairMQMessage>& msg) const
|
||||
{
|
||||
CheckCompatibility(msg);
|
||||
CheckReceiveCompatibility(msg);
|
||||
return fSocket->Receive(msg);
|
||||
}
|
||||
|
||||
@@ -691,25 +675,25 @@ int FairMQChannel::Receive(unique_ptr<FairMQMessage>& msg, int rcvTimeoutInMs) c
|
||||
|
||||
int FairMQChannel::SendAsync(unique_ptr<FairMQMessage>& msg) const
|
||||
{
|
||||
CheckCompatibility(msg);
|
||||
CheckSendCompatibility(msg);
|
||||
return fSocket->TrySend(msg);
|
||||
}
|
||||
|
||||
int FairMQChannel::ReceiveAsync(unique_ptr<FairMQMessage>& msg) const
|
||||
{
|
||||
CheckCompatibility(msg);
|
||||
CheckReceiveCompatibility(msg);
|
||||
return fSocket->TryReceive(msg);
|
||||
}
|
||||
|
||||
int64_t FairMQChannel::Send(vector<unique_ptr<FairMQMessage>>& msgVec) const
|
||||
{
|
||||
CheckCompatibility(msgVec);
|
||||
CheckSendCompatibility(msgVec);
|
||||
return fSocket->Send(msgVec);
|
||||
}
|
||||
|
||||
int64_t FairMQChannel::Receive(vector<unique_ptr<FairMQMessage>>& msgVec) const
|
||||
{
|
||||
CheckCompatibility(msgVec);
|
||||
CheckReceiveCompatibility(msgVec);
|
||||
return fSocket->Receive(msgVec);
|
||||
}
|
||||
|
||||
@@ -725,7 +709,7 @@ int64_t FairMQChannel::Receive(vector<unique_ptr<FairMQMessage>>& msgVec, int rc
|
||||
|
||||
int64_t FairMQChannel::SendAsync(vector<unique_ptr<FairMQMessage>>& msgVec) const
|
||||
{
|
||||
CheckCompatibility(msgVec);
|
||||
CheckSendCompatibility(msgVec);
|
||||
return fSocket->TrySend(msgVec);
|
||||
}
|
||||
|
||||
@@ -736,7 +720,7 @@ int64_t FairMQChannel::SendAsync(vector<unique_ptr<FairMQMessage>>& msgVec) cons
|
||||
/// In case of errors, returns -1.
|
||||
int64_t FairMQChannel::ReceiveAsync(vector<unique_ptr<FairMQMessage>>& msgVec) const
|
||||
{
|
||||
CheckCompatibility(msgVec);
|
||||
CheckReceiveCompatibility(msgVec);
|
||||
return fSocket->TryReceive(msgVec);
|
||||
}
|
||||
|
||||
@@ -764,44 +748,58 @@ unsigned long FairMQChannel::GetMessagesRx() const
|
||||
return fSocket->GetMessagesRx();
|
||||
}
|
||||
|
||||
bool FairMQChannel::CheckCompatibility(unique_ptr<FairMQMessage>& msg) const
|
||||
void FairMQChannel::CheckSendCompatibility(FairMQMessagePtr& msg) const
|
||||
{
|
||||
if (fTransportType == msg->GetType())
|
||||
if (fTransportType != msg->GetType())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// LOG(warn) << "Channel type does not match message type. Copying...";
|
||||
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage(msg->GetSize()));
|
||||
memcpy(msgCopy->GetData(), msg->GetData(), msg->GetSize());
|
||||
msg = move(msgCopy);
|
||||
return false;
|
||||
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
||||
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
||||
msg->GetSize(),
|
||||
[](void* /*data*/, void* _msg) { delete static_cast<FairMQMessage*>(_msg); },
|
||||
msg.get()
|
||||
));
|
||||
msg.release();
|
||||
msg = move(msgWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
bool FairMQChannel::CheckCompatibility(vector<unique_ptr<FairMQMessage>>& msgVec) const
|
||||
void FairMQChannel::CheckSendCompatibility(vector<FairMQMessagePtr>& msgVec) const
|
||||
{
|
||||
bool match = true;
|
||||
|
||||
if (msgVec.size() > 0)
|
||||
for (auto& msg : msgVec)
|
||||
{
|
||||
for (unsigned int i = 0; i < msgVec.size(); ++i)
|
||||
if (fTransportType != msg->GetType())
|
||||
{
|
||||
if (fTransportType != msgVec.at(i)->GetType())
|
||||
{
|
||||
// LOG(warn) << "Channel type does not match message type. Copying...";
|
||||
FairMQMessagePtr newMsg(fTransportFactory->CreateMessage(msgVec[i]->GetSize()));
|
||||
memcpy(newMsg->GetData(), msgVec[i]->GetData(), msgVec[i]->GetSize());
|
||||
msgVec[i] = move(newMsg);
|
||||
match = false;
|
||||
}
|
||||
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
||||
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
||||
msg->GetSize(),
|
||||
[](void* /*data*/, void* _msg) { delete static_cast<FairMQMessage*>(_msg); },
|
||||
msg.get()
|
||||
));
|
||||
msg.release();
|
||||
msg = move(msgWrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FairMQChannel::CheckReceiveCompatibility(FairMQMessagePtr& msg) const
|
||||
{
|
||||
if (fTransportType != msg->GetType())
|
||||
{
|
||||
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
||||
FairMQMessagePtr newMsg(NewMessage());
|
||||
msg = move(newMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void FairMQChannel::CheckReceiveCompatibility(vector<FairMQMessagePtr>& msgVec) const
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <fairmq/Transports.h>
|
||||
#include <FairMQLogger.h>
|
||||
#include <FairMQParts.h>
|
||||
#include <FairMQMessage.h>
|
||||
|
||||
class FairMQChannel
|
||||
{
|
||||
@@ -92,7 +93,7 @@ class FairMQChannel
|
||||
|
||||
/// Get channel transport ("default", "zeromq", "nanomsg" or "shmem")
|
||||
/// @return Returns channel transport (e.g. "default", "zeromq", "nanomsg" or "shmem")
|
||||
std::string GetTransport() const;
|
||||
std::string GetTransportName() const;
|
||||
|
||||
/// Get socket send buffer size (in number of messages)
|
||||
/// @return Returns socket send buffer size (in number of messages)
|
||||
@@ -165,8 +166,8 @@ class FairMQChannel
|
||||
/// Resets the channel (requires validation to be used again).
|
||||
void ResetChannel();
|
||||
|
||||
int Send(std::unique_ptr<FairMQMessage>& msg) const;
|
||||
int Receive(std::unique_ptr<FairMQMessage>& msg) const;
|
||||
int Send(FairMQMessagePtr& msg) const;
|
||||
int Receive(FairMQMessagePtr& msg) const;
|
||||
|
||||
/// Sends a message to the socket queue.
|
||||
/// @details Send method attempts to send a message by
|
||||
@@ -176,7 +177,7 @@ class FairMQChannel
|
||||
/// @param msg Constant reference of unique_ptr to a FairMQMessage
|
||||
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out.
|
||||
/// In case of errors, returns -1.
|
||||
int Send(std::unique_ptr<FairMQMessage>& msg, int sndTimeoutInMs) const;
|
||||
int Send(FairMQMessagePtr& msg, int sndTimeoutInMs) const;
|
||||
|
||||
/// Receives a message from the socket queue.
|
||||
/// @details Receive method attempts to receive a message from the input queue.
|
||||
@@ -185,7 +186,7 @@ class FairMQChannel
|
||||
/// @param msg Constant reference of unique_ptr to a FairMQMessage
|
||||
/// @return Number of bytes that have been received. -2 If reading from the queue was not possible or timed out.
|
||||
/// In case of errors, returns -1.
|
||||
int Receive(std::unique_ptr<FairMQMessage>& msg, int rcvTimeoutInMs) const;
|
||||
int Receive(FairMQMessagePtr& msg, int rcvTimeoutInMs) const;
|
||||
|
||||
/// Sends a message in non-blocking mode.
|
||||
/// @details SendAsync method attempts to send a message without blocking by
|
||||
@@ -195,31 +196,31 @@ class FairMQChannel
|
||||
/// @return Number of bytes that have been queued. If queueing failed due to
|
||||
/// full queue or no connected peers (when binding), returns -2.
|
||||
/// In case of errors, returns -1.
|
||||
int SendAsync(std::unique_ptr<FairMQMessage>& msg) const;
|
||||
int SendAsync(FairMQMessagePtr& msg) const;
|
||||
|
||||
/// Receives a message in non-blocking mode.
|
||||
///
|
||||
/// @param msg Constant reference of unique_ptr to a FairMQMessage
|
||||
/// @return Number of bytes that have been received. If queue is empty, returns -2.
|
||||
/// In case of errors, returns -1.
|
||||
int ReceiveAsync(std::unique_ptr<FairMQMessage>& msg) const;
|
||||
int ReceiveAsync(FairMQMessagePtr& msg) const;
|
||||
|
||||
int64_t Send(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
|
||||
int64_t Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
|
||||
int64_t Send(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
int64_t Receive(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
|
||||
/// Send a vector of messages
|
||||
///
|
||||
/// @param msgVec message vector reference
|
||||
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out.
|
||||
/// In case of errors, returns -1.
|
||||
int64_t Send(std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int sndTimeoutInMs) const;
|
||||
int64_t Send(std::vector<FairMQMessagePtr>& msgVec, int sndTimeoutInMs) const;
|
||||
|
||||
/// Receive a vector of messages
|
||||
///
|
||||
/// @param msgVec message vector reference
|
||||
/// @return Number of bytes that have been received. -2 If reading from the queue was not possible or timed out.
|
||||
/// In case of errors, returns -1.
|
||||
int64_t Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int rcvTimeoutInMs) const;
|
||||
int64_t Receive(std::vector<FairMQMessagePtr>& msgVec, int rcvTimeoutInMs) const;
|
||||
|
||||
/// Sends a vector of message in non-blocking mode.
|
||||
/// @details SendAsync method attempts to send a vector of messages without blocking by
|
||||
@@ -228,14 +229,14 @@ class FairMQChannel
|
||||
/// @param msgVec message vector reference
|
||||
/// @return Number of bytes that have been queued. If queueing failed due to
|
||||
/// full queue or no connected peers (when binding), returns -2. In case of errors, returns -1.
|
||||
int64_t SendAsync(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
|
||||
int64_t SendAsync(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
|
||||
/// Receives a vector of messages in non-blocking mode.
|
||||
///
|
||||
/// @param msgVec message vector reference
|
||||
/// @return Number of bytes that have been received. If queue is empty, returns -2.
|
||||
/// In case of errors, returns -1.
|
||||
int64_t ReceiveAsync(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
|
||||
int64_t ReceiveAsync(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
|
||||
int64_t Send(FairMQParts& parts) const
|
||||
{
|
||||
@@ -301,7 +302,7 @@ class FairMQChannel
|
||||
std::string fType;
|
||||
std::string fMethod;
|
||||
std::string fAddress;
|
||||
std::string fTransport;
|
||||
fair::mq::Transport fTransportType;
|
||||
int fSndBufSize;
|
||||
int fRcvBufSize;
|
||||
int fSndKernelSize;
|
||||
@@ -311,11 +312,12 @@ class FairMQChannel
|
||||
std::string fName;
|
||||
std::atomic<bool> fIsValid;
|
||||
|
||||
FairMQ::Transport fTransportType;
|
||||
std::shared_ptr<FairMQTransportFactory> fTransportFactory;
|
||||
|
||||
bool CheckCompatibility(std::unique_ptr<FairMQMessage>& msg) const;
|
||||
bool CheckCompatibility(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
|
||||
void CheckSendCompatibility(FairMQMessagePtr& msg) const;
|
||||
void CheckSendCompatibility(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
void CheckReceiveCompatibility(FairMQMessagePtr& msg) const;
|
||||
void CheckReceiveCompatibility(std::vector<FairMQMessagePtr>& msgVec) const;
|
||||
|
||||
void InitTransport(std::shared_ptr<FairMQTransportFactory> factory);
|
||||
|
||||
|
@@ -8,9 +8,6 @@
|
||||
|
||||
#include <FairMQDevice.h>
|
||||
|
||||
#include <fairmq/Tools.h>
|
||||
#include <fairmq/Transports.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp> // join/split
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
@@ -26,54 +23,44 @@
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm> // std::max
|
||||
|
||||
using namespace std;
|
||||
|
||||
FairMQDevice::FairMQDevice()
|
||||
: fTransportFactory(nullptr)
|
||||
, fTransports()
|
||||
, fChannels()
|
||||
, fConfig(nullptr)
|
||||
, fId()
|
||||
, fNumIoThreads(1)
|
||||
, fInitialValidationFinished(false)
|
||||
, fInitialValidationCondition()
|
||||
, fInitialValidationMutex()
|
||||
, fPortRangeMin(22000)
|
||||
, fPortRangeMax(32000)
|
||||
, fNetworkInterface()
|
||||
, fDefaultTransport("default")
|
||||
, fInitializationTimeoutInS(120)
|
||||
, fDataCallbacks(false)
|
||||
, fMsgInputs()
|
||||
, fMultipartInputs()
|
||||
, fMultitransportInputs()
|
||||
, fChannelRegistry()
|
||||
, fInputChannelKeys()
|
||||
, fMultitransportMutex()
|
||||
, fMultitransportProceed(false)
|
||||
, fExternalConfig(false)
|
||||
, fVersion({0, 0, 0})
|
||||
, fRate(0.)
|
||||
, fLastTime(0)
|
||||
: FairMQDevice(nullptr, {0, 0, 0})
|
||||
{
|
||||
}
|
||||
|
||||
FairMQDevice::FairMQDevice(FairMQProgOptions& config)
|
||||
: FairMQDevice(&config, {0, 0, 0})
|
||||
{
|
||||
}
|
||||
|
||||
FairMQDevice::FairMQDevice(const fair::mq::tools::Version version)
|
||||
: FairMQDevice(nullptr, version)
|
||||
{
|
||||
}
|
||||
|
||||
FairMQDevice::FairMQDevice(FairMQProgOptions& config, const fair::mq::tools::Version version)
|
||||
: FairMQDevice(&config, version)
|
||||
{
|
||||
}
|
||||
|
||||
FairMQDevice::FairMQDevice(FairMQProgOptions* config, const fair::mq::tools::Version version)
|
||||
: fTransportFactory(nullptr)
|
||||
, fTransports()
|
||||
, fChannels()
|
||||
, fConfig(nullptr)
|
||||
, fInternalConfig(config ? nullptr : fair::mq::tools::make_unique<FairMQProgOptions>())
|
||||
, fConfig(config ? config : fInternalConfig.get())
|
||||
, fId()
|
||||
, fNumIoThreads(1)
|
||||
, fInitialValidationFinished(false)
|
||||
, fInitialValidationCondition()
|
||||
, fInitialValidationMutex()
|
||||
, fPortRangeMin(22000)
|
||||
, fPortRangeMax(32000)
|
||||
, fNetworkInterface()
|
||||
, fDefaultTransport("default")
|
||||
, fInitializationTimeoutInS(120)
|
||||
, fDefaultTransportType(fair::mq::Transport::DEFAULT)
|
||||
, fDataCallbacks(false)
|
||||
, fMsgInputs()
|
||||
, fMultipartInputs()
|
||||
@@ -82,25 +69,54 @@ FairMQDevice::FairMQDevice(const fair::mq::tools::Version version)
|
||||
, fInputChannelKeys()
|
||||
, fMultitransportMutex()
|
||||
, fMultitransportProceed(false)
|
||||
, fExternalConfig(false)
|
||||
, fVersion(version)
|
||||
, fRate(0.)
|
||||
, fLastTime(0)
|
||||
, fRawCmdLineArgs()
|
||||
, fInterrupted(false)
|
||||
, fInterruptedCV()
|
||||
, fInterruptedMtx()
|
||||
{
|
||||
}
|
||||
|
||||
void FairMQDevice::InitWrapper()
|
||||
{
|
||||
if (!fTransportFactory)
|
||||
fId = fConfig->GetValue<string>("id");
|
||||
fRate = fConfig->GetValue<float>("rate");
|
||||
fPortRangeMin = fConfig->GetValue<int>("port-range-min");
|
||||
fPortRangeMax = fConfig->GetValue<int>("port-range-max");
|
||||
|
||||
try
|
||||
{
|
||||
LOG(error) << "Transport not initialized. Did you call SetTransport()?";
|
||||
exit(EXIT_FAILURE);
|
||||
fDefaultTransportType = fair::mq::TransportTypes.at(fConfig->GetValue<string>("transport"));
|
||||
}
|
||||
catch (const exception& e)
|
||||
{
|
||||
LOG(error) << "invalid transport type provided: " << fConfig->GetValue<string>("transport");
|
||||
}
|
||||
|
||||
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) << "Requesting '" << fair::mq::TransportNames.at(fDefaultTransportType) << "' as default transport for the device";
|
||||
fTransportFactory = AddTransport(fDefaultTransportType);
|
||||
|
||||
// Containers to store the uninitialized channels.
|
||||
vector<FairMQChannel*> uninitializedBindingChannels;
|
||||
vector<FairMQChannel*> uninitializedConnectingChannels;
|
||||
|
||||
string networkInterface = fConfig->GetValue<string>("network-interface");
|
||||
|
||||
// Fill the uninitialized channel containers
|
||||
for (auto& mi : fChannels)
|
||||
{
|
||||
@@ -121,11 +137,11 @@ void FairMQDevice::InitWrapper()
|
||||
if (vi->fAddress == "unspecified" || vi->fAddress == "")
|
||||
{
|
||||
// if the configured network interface is default, get its name from the default route
|
||||
if (fNetworkInterface == "default")
|
||||
if (networkInterface == "default")
|
||||
{
|
||||
fNetworkInterface = fair::mq::tools::getDefaultRouteNetworkInterface();
|
||||
networkInterface = fair::mq::tools::getDefaultRouteNetworkInterface();
|
||||
}
|
||||
vi->fAddress = "tcp://" + fair::mq::tools::getInterfaceIP(fNetworkInterface) + ":1";
|
||||
vi->fAddress = "tcp://" + fair::mq::tools::getInterfaceIP(networkInterface) + ":1";
|
||||
}
|
||||
// fill the uninitialized list
|
||||
uninitializedBindingChannels.push_back(&(*vi));
|
||||
@@ -143,7 +159,8 @@ void FairMQDevice::InitWrapper()
|
||||
else
|
||||
{
|
||||
LOG(error) << "Cannot update configuration. Socket method (bind/connect) not specified.";
|
||||
throw runtime_error("Cannot update configuration. Socket method (bind/connect) not specified.");
|
||||
ChangeState(ERROR_FOUND);
|
||||
// throw runtime_error("Cannot update configuration. Socket method (bind/connect) not specified.");
|
||||
}
|
||||
// }
|
||||
}
|
||||
@@ -156,7 +173,8 @@ void FairMQDevice::InitWrapper()
|
||||
if (uninitializedBindingChannels.size() > 0)
|
||||
{
|
||||
LOG(error) << uninitializedBindingChannels.size() << " of the binding channels could not initialize. Initial configuration incomplete.";
|
||||
throw runtime_error(fair::mq::tools::ToString(uninitializedBindingChannels.size(), " of the binding channels could not initialize. Initial configuration incomplete."));
|
||||
ChangeState(ERROR_FOUND);
|
||||
// throw runtime_error(fair::mq::tools::ToString(uninitializedBindingChannels.size(), " of the binding channels could not initialize. Initial configuration incomplete."));
|
||||
}
|
||||
|
||||
CallStateChangeCallbacks(INITIALIZING_DEVICE);
|
||||
@@ -168,10 +186,12 @@ void FairMQDevice::InitWrapper()
|
||||
fInitialValidationCondition.notify_one();
|
||||
}
|
||||
|
||||
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(uninitializedConnectingChannels);
|
||||
// if not all channels could be connected, update their address values from config and retry
|
||||
@@ -194,8 +214,9 @@ void FairMQDevice::InitWrapper()
|
||||
|
||||
if (numAttempts++ > maxAttempts)
|
||||
{
|
||||
LOG(error) << "could not connect all channels after " << fInitializationTimeoutInS << " attempts";
|
||||
throw runtime_error(fair::mq::tools::ToString("could not connect all channels after ", fInitializationTimeoutInS, " attempts"));
|
||||
LOG(error) << "could not connect all channels after " << initializationTimeoutInS << " attempts";
|
||||
ChangeState(ERROR_FOUND);
|
||||
// throw runtime_error(fair::mq::tools::ToString("could not connect all channels after ", initializationTimeoutInS, " attempts"));
|
||||
}
|
||||
|
||||
AttachChannels(uninitializedConnectingChannels);
|
||||
@@ -244,19 +265,15 @@ void FairMQDevice::AttachChannels(vector<FairMQChannel*>& chans)
|
||||
|
||||
bool FairMQDevice::AttachChannel(FairMQChannel& ch)
|
||||
{
|
||||
if (!ch.fTransportFactory)
|
||||
if (ch.fTransportType == fair::mq::Transport::DEFAULT || ch.fTransportType == fTransportFactory->GetType())
|
||||
{
|
||||
if (ch.fTransport == "default" || ch.fTransport == fDefaultTransport)
|
||||
{
|
||||
LOG(debug) << ch.fName << ": using default transport";
|
||||
ch.InitTransport(fTransportFactory);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(debug) << ch.fName << ": channel transport (" << fDefaultTransport << ") overriden to " << ch.fTransport;
|
||||
ch.InitTransport(AddTransport(ch.fTransport));
|
||||
}
|
||||
ch.fTransportType = ch.fTransportFactory->GetType();
|
||||
LOG(debug) << ch.fName << ": using default transport";
|
||||
ch.InitTransport(fTransportFactory);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(debug) << ch.fName << ": channel transport (" << fair::mq::TransportNames.at(fDefaultTransportType) << ") overriden to " << fair::mq::TransportNames.at(ch.fTransportType);
|
||||
ch.InitTransport(AddTransport(ch.fTransportType));
|
||||
}
|
||||
|
||||
vector<string> endpoints;
|
||||
@@ -266,7 +283,15 @@ bool FairMQDevice::AttachChannel(FairMQChannel& ch)
|
||||
//(re-)init socket
|
||||
if (!ch.fSocket)
|
||||
{
|
||||
ch.fSocket = ch.fTransportFactory->CreateSocket(ch.fType, ch.fName);
|
||||
try
|
||||
{
|
||||
ch.fSocket = ch.fTransportFactory->CreateSocket(ch.fType, ch.fName);
|
||||
}
|
||||
catch (fair::mq::SocketError& se)
|
||||
{
|
||||
LOG(error) << se.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// set high water marks
|
||||
@@ -469,6 +494,10 @@ void FairMQDevice::RunWrapper()
|
||||
thread rateLogger(&FairMQDevice::LogSocketRates, this);
|
||||
|
||||
// notify transports to resume transfers
|
||||
{
|
||||
lock_guard<mutex> guard(fInterruptedMtx);
|
||||
fInterrupted = false;
|
||||
}
|
||||
for (auto& t : fTransports)
|
||||
{
|
||||
t.second->Resume();
|
||||
@@ -493,20 +522,14 @@ void FairMQDevice::RunWrapper()
|
||||
}
|
||||
else
|
||||
{
|
||||
using Clock = chrono::steady_clock;
|
||||
using TimeScale = chrono::microseconds;
|
||||
const TimeScale::rep period = TimeScale::period::den / fRate;
|
||||
const auto reftime = Clock::now();
|
||||
fair::mq::tools::RateLimiter rateLimiter(fRate);
|
||||
|
||||
while (CheckCurrentState(RUNNING) && ConditionalRun())
|
||||
{
|
||||
if (fRate > 0.001) {
|
||||
auto timespan = chrono::duration_cast<TimeScale>(Clock::now() - reftime).count() - fLastTime;
|
||||
if (timespan < period) {
|
||||
TimeScale sleepfor(period - timespan);
|
||||
this_thread::sleep_for(sleepfor);
|
||||
if (fRate > 0.001)
|
||||
{
|
||||
rateLimiter.maybe_sleep();
|
||||
}
|
||||
fLastTime = chrono::duration_cast<TimeScale>(Clock::now() - reftime).count();
|
||||
}
|
||||
}
|
||||
|
||||
Run();
|
||||
@@ -555,10 +578,10 @@ void FairMQDevice::HandleMultipleChannelInput()
|
||||
fMultitransportInputs.clear();
|
||||
for (const auto& k : fInputChannelKeys)
|
||||
{
|
||||
FairMQ::Transport t = fChannels.at(k).at(0).fTransportType;
|
||||
fair::mq::Transport t = fChannels.at(k).at(0).fTransportType;
|
||||
if (fMultitransportInputs.find(t) == fMultitransportInputs.end())
|
||||
{
|
||||
fMultitransportInputs.insert(pair<FairMQ::Transport, vector<string>>(t, vector<string>()));
|
||||
fMultitransportInputs.insert(pair<fair::mq::Transport, vector<string>>(t, vector<string>()));
|
||||
fMultitransportInputs.at(t).push_back(k);
|
||||
}
|
||||
else
|
||||
@@ -760,92 +783,32 @@ void FairMQDevice::Pause()
|
||||
LOG(debug) << "Unpausing";
|
||||
}
|
||||
|
||||
shared_ptr<FairMQTransportFactory> FairMQDevice::AddTransport(const string& transport)
|
||||
shared_ptr<FairMQTransportFactory> FairMQDevice::AddTransport(const fair::mq::Transport transport)
|
||||
{
|
||||
auto i = fTransports.find(FairMQ::TransportTypes.at(transport));
|
||||
auto i = fTransports.find(transport);
|
||||
|
||||
if (i == fTransports.end())
|
||||
{
|
||||
auto tr = FairMQTransportFactory::CreateTransportFactory(transport, fId, fConfig);
|
||||
auto tr = FairMQTransportFactory::CreateTransportFactory(fair::mq::TransportNames.at(transport), fId, fConfig);
|
||||
|
||||
LOG(debug) << "Adding '" << transport << "' transport to the device.";
|
||||
LOG(debug) << "Adding '" << fair::mq::TransportNames.at(transport) << "' transport to the device.";
|
||||
|
||||
pair<FairMQ::Transport, shared_ptr<FairMQTransportFactory>> trPair(FairMQ::TransportTypes.at(transport), tr);
|
||||
pair<fair::mq::Transport, shared_ptr<FairMQTransportFactory>> trPair(transport, tr);
|
||||
fTransports.insert(trPair);
|
||||
|
||||
return tr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(debug) << "Reusing existing '" << transport << "' transport.";
|
||||
LOG(debug) << "Reusing existing '" << fair::mq::TransportNames.at(transport) << "' transport.";
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
|
||||
void FairMQDevice::CreateOwnConfig()
|
||||
{
|
||||
// TODO: make fConfig a shared_ptr when no old user code has FairMQProgOptions ptr*
|
||||
fConfig = new FairMQProgOptions();
|
||||
|
||||
string id{boost::uuids::to_string(boost::uuids::random_generator()())};
|
||||
LOG(warn) << "No FairMQProgOptions provided, creating one internally and setting device ID to " << id;
|
||||
|
||||
// dummy argc+argv
|
||||
char arg0[] = "undefined"; // executable name
|
||||
char arg1[] = "--id";
|
||||
char* arg2 = const_cast<char*>(id.c_str()); // device ID
|
||||
const char* argv[] = { &arg0[0], &arg1[0], arg2, nullptr };
|
||||
int argc = static_cast<int>((sizeof(argv) / sizeof(argv[0])) - 1);
|
||||
|
||||
fConfig->ParseAll(argc, &argv[0]);
|
||||
|
||||
fId = fConfig->GetValue<string>("id");
|
||||
fNetworkInterface = fConfig->GetValue<string>("network-interface");
|
||||
fNumIoThreads = fConfig->GetValue<int>("io-threads");
|
||||
fInitializationTimeoutInS = fConfig->GetValue<int>("initialization-timeout");
|
||||
fRate = fConfig->GetValue<float>("rate");
|
||||
fDefaultTransport = fConfig->GetValue<string>("transport");
|
||||
}
|
||||
|
||||
void FairMQDevice::SetTransport(const string& transport)
|
||||
{
|
||||
// This method is the first to be called, if FairMQProgOptions are not used (either SetTransport() or SetConfig() make sense, not both).
|
||||
// Make sure here that at least internal config is available.
|
||||
if (!fExternalConfig && !fConfig)
|
||||
{
|
||||
CreateOwnConfig();
|
||||
}
|
||||
|
||||
if (fTransports.empty())
|
||||
{
|
||||
LOG(debug) << "Requesting '" << transport << "' as default transport for the device";
|
||||
fTransportFactory = AddTransport(transport);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(error) << "Transports container is not empty when setting transport. Setting default twice?";
|
||||
ChangeState(ERROR_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
void FairMQDevice::SetConfig(FairMQProgOptions& config)
|
||||
{
|
||||
fExternalConfig = true;
|
||||
fInternalConfig.reset();
|
||||
fConfig = &config;
|
||||
for (auto& c : config.GetFairMQMap())
|
||||
{
|
||||
if (!fChannels.insert(c).second)
|
||||
{
|
||||
LOG(warn) << "did not insert channel '" << c.first << "', it is already in the device.";
|
||||
}
|
||||
}
|
||||
fId = config.GetValue<string>("id");
|
||||
fNetworkInterface = config.GetValue<string>("network-interface");
|
||||
fNumIoThreads = config.GetValue<int>("io-threads");
|
||||
fInitializationTimeoutInS = config.GetValue<int>("initialization-timeout");
|
||||
fRate = fConfig->GetValue<float>("rate");
|
||||
fDefaultTransport = config.GetValue<string>("transport");
|
||||
SetTransport(fDefaultTransport);
|
||||
}
|
||||
|
||||
void FairMQDevice::LogSocketRates()
|
||||
@@ -860,6 +823,8 @@ void FairMQDevice::LogSocketRates()
|
||||
vector<int> logIntervals;
|
||||
vector<int> intervalCounters;
|
||||
|
||||
size_t chanNameLen = 0;
|
||||
|
||||
// iterate over the channels map
|
||||
for (const auto& mi : fChannels)
|
||||
{
|
||||
@@ -872,6 +837,7 @@ void FairMQDevice::LogSocketRates()
|
||||
logIntervals.push_back(vi->fRateLogging);
|
||||
intervalCounters.push_back(0);
|
||||
filteredChannelNames.push_back(fair::mq::tools::ToString(mi.first, "[", vi - (mi.second).begin(), "]"));
|
||||
chanNameLen = max(chanNameLen, filteredChannelNames.back().length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -940,9 +906,9 @@ void FairMQDevice::LogSocketRates()
|
||||
bytesOut.at(i) = bytesOutNew.at(i);
|
||||
msgOut.at(i) = msgOutNew.at(i);
|
||||
|
||||
LOG(info) << filteredChannelNames.at(i) << ": "
|
||||
<< "in: " << msgPerSecIn.at(i) << " (" << mbPerSecIn.at(i) << " MB) "
|
||||
<< "out: " << msgPerSecOut.at(i) << " (" << mbPerSecOut.at(i) << " MB)";
|
||||
LOG(info) << setw(chanNameLen) << filteredChannelNames.at(i) << ": "
|
||||
<< "in: " << msgPerSecIn.at(i) << " (" << mbPerSecIn.at(i) << " MB) "
|
||||
<< "out: " << msgPerSecOut.at(i) << " (" << mbPerSecOut.at(i) << " MB)";
|
||||
}
|
||||
|
||||
++i;
|
||||
@@ -950,6 +916,7 @@ void FairMQDevice::LogSocketRates()
|
||||
|
||||
t0 = t1;
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
// WaitFor(chrono::milliseconds(1000)); TODO: enable this when nanomsg linger is fixed
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -960,6 +927,11 @@ void FairMQDevice::Unblock()
|
||||
{
|
||||
t.second->Interrupt();
|
||||
}
|
||||
{
|
||||
lock_guard<mutex> guard(fInterruptedMtx);
|
||||
fInterrupted = true;
|
||||
}
|
||||
fInterruptedCV.notify_all();
|
||||
}
|
||||
|
||||
void FairMQDevice::ResetTaskWrapper()
|
||||
@@ -993,7 +965,7 @@ void FairMQDevice::Reset()
|
||||
for (auto& vi : mi.second)
|
||||
{
|
||||
// vi.fReset = true;
|
||||
vi.fSocket.reset();
|
||||
vi.fSocket.reset(); // destroy FairMQSocket
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1005,10 +977,6 @@ const FairMQChannel& FairMQDevice::GetChannel(const string& channelName, const i
|
||||
|
||||
void FairMQDevice::Exit()
|
||||
{
|
||||
if (!fExternalConfig && fConfig)
|
||||
{
|
||||
delete fConfig;
|
||||
}
|
||||
}
|
||||
|
||||
FairMQDevice::~FairMQDevice()
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <memory> // unique_ptr
|
||||
#include <algorithm> // std::sort()
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
@@ -48,9 +49,19 @@ class FairMQDevice : public FairMQStateMachine
|
||||
public:
|
||||
/// Default constructor
|
||||
FairMQDevice();
|
||||
/// 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 FairMQProgOptions
|
||||
FairMQDevice(FairMQProgOptions& config, const fair::mq::tools::Version version);
|
||||
|
||||
private:
|
||||
FairMQDevice(FairMQProgOptions* config, const fair::mq::tools::Version version);
|
||||
|
||||
public:
|
||||
/// Copy constructor (disabled)
|
||||
FairMQDevice(const FairMQDevice&) = delete;
|
||||
/// Assignment operator (disabled)
|
||||
@@ -196,7 +207,7 @@ class FairMQDevice : public FairMQStateMachine
|
||||
/// @brief Getter for default transport factory
|
||||
auto Transport() const -> const FairMQTransportFactory*
|
||||
{
|
||||
return fTransports.at(fair::mq::TransportTypes[GetDefaultTransport()]).get();
|
||||
return fTransportFactory.get();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@@ -208,7 +219,7 @@ class FairMQDevice : public FairMQStateMachine
|
||||
template<typename... Args>
|
||||
FairMQMessagePtr NewMessageFor(const std::string& channel, int index, Args&&... args) const
|
||||
{
|
||||
return fChannels.at(channel).at(index).Transport()->CreateMessage(std::forward<Args>(args)...);
|
||||
return fChannels.at(channel).at(index).NewMessage(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -253,7 +264,7 @@ class FairMQDevice : public FairMQStateMachine
|
||||
// if more than one channel provided, check compatibility
|
||||
if (chans.size() > 1)
|
||||
{
|
||||
FairMQ::Transport type = fChannels.at(chans.at(0)).at(0).Transport()->GetType();
|
||||
fair::mq::Transport type = fChannels.at(chans.at(0)).at(0).Transport()->GetType();
|
||||
|
||||
for (unsigned int i = 1; i < chans.size(); ++i)
|
||||
{
|
||||
@@ -273,7 +284,7 @@ class FairMQDevice : public FairMQStateMachine
|
||||
// if more than one channel provided, check compatibility
|
||||
if (channels.size() > 1)
|
||||
{
|
||||
FairMQ::Transport type = channels.at(0)->Transport()->GetType();
|
||||
fair::mq::Transport type = channels.at(0)->Transport()->GetType();
|
||||
|
||||
for (unsigned int i = 1; i < channels.size(); ++i)
|
||||
{
|
||||
@@ -293,13 +304,12 @@ class FairMQDevice : public FairMQStateMachine
|
||||
|
||||
/// Adds a transport to the device if it doesn't exist
|
||||
/// @param transport Transport string ("zeromq"/"nanomsg"/"shmem")
|
||||
std::shared_ptr<FairMQTransportFactory> AddTransport(const std::string& transport);
|
||||
/// Sets the default transport for the device
|
||||
/// @param transport Transport string ("zeromq"/"nanomsg"/"shmem")
|
||||
void SetTransport(const std::string& transport = "zeromq");
|
||||
std::shared_ptr<FairMQTransportFactory> AddTransport(const fair::mq::Transport transport);
|
||||
|
||||
/// Assigns config to the device
|
||||
void SetConfig(FairMQProgOptions& config);
|
||||
const FairMQProgOptions* GetConfig() const
|
||||
/// Get pointer to the config
|
||||
FairMQProgOptions* GetConfig() const
|
||||
{
|
||||
return fConfig;
|
||||
}
|
||||
@@ -395,37 +405,62 @@ class FairMQDevice : public FairMQStateMachine
|
||||
|
||||
const fair::mq::tools::Version GetVersion() const { return fVersion; }
|
||||
|
||||
void SetNumIoThreads(int numIoThreads) { fNumIoThreads = numIoThreads; }
|
||||
int GetNumIoThreads() const { return fNumIoThreads; }
|
||||
void SetNumIoThreads(int numIoThreads) { fConfig->SetValue<int>("io-threads", numIoThreads);}
|
||||
int GetNumIoThreads() const { return fConfig->GetValue<int>("io-threads"); }
|
||||
|
||||
void SetPortRangeMin(int portRangeMin) { fPortRangeMin = portRangeMin; }
|
||||
int GetPortRangeMin() const { return fPortRangeMin; }
|
||||
void SetPortRangeMin(int portRangeMin) { fConfig->SetValue<int>("port-range-min", portRangeMin); }
|
||||
int GetPortRangeMin() const { return fConfig->GetValue<int>("port-range-min"); }
|
||||
|
||||
void SetPortRangeMax(int portRangeMax) { fPortRangeMax = portRangeMax; }
|
||||
int GetPortRangeMax() const { return fPortRangeMax; }
|
||||
void SetPortRangeMax(int portRangeMax) { fConfig->SetValue<int>("port-range-max", portRangeMax); }
|
||||
int GetPortRangeMax() const { return fConfig->GetValue<int>("port-range-max"); }
|
||||
|
||||
void SetNetworkInterface(const std::string& networkInterface) { fNetworkInterface = networkInterface; }
|
||||
std::string GetNetworkInterface() const { return fNetworkInterface; }
|
||||
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& defaultTransport) { fDefaultTransport = defaultTransport; }
|
||||
std::string GetDefaultTransport() const { return fDefaultTransport; }
|
||||
void SetDefaultTransport(const std::string& name) { fConfig->SetValue<std::string>("transport", name); }
|
||||
std::string GetDefaultTransport() const { return fConfig->GetValue<std::string>("transport"); }
|
||||
|
||||
void SetInitializationTimeoutInS(int initializationTimeoutInS) { fInitializationTimeoutInS = initializationTimeoutInS; }
|
||||
int GetInitializationTimeoutInS() const { return fInitializationTimeoutInS; }
|
||||
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->SetValue<std::string>("transport", transport); }
|
||||
/// Gets the default transport name
|
||||
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; }
|
||||
|
||||
void RunStateMachine() { ProcessWork(); };
|
||||
|
||||
/// Wait for the supplied amount of time or for interruption.
|
||||
/// If interrupted, returns false, otherwise true.
|
||||
/// @param duration wait duration
|
||||
template<class Rep, class Period>
|
||||
bool WaitFor(std::chrono::duration<Rep, Period> const& duration)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fInterruptedMtx);
|
||||
return !fInterruptedCV.wait_for(lock, duration, [&] { return fInterrupted.load(); }); // return true if no interruption happened
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<FairMQTransportFactory> fTransportFactory; ///< Transport factory
|
||||
std::unordered_map<FairMQ::Transport, std::shared_ptr<FairMQTransportFactory>> fTransports; ///< Container for transports
|
||||
std::shared_ptr<FairMQTransportFactory> fTransportFactory; ///< Default transport factory
|
||||
std::unordered_map<fair::mq::Transport, std::shared_ptr<FairMQTransportFactory>> fTransports; ///< Container for transports
|
||||
|
||||
public:
|
||||
std::unordered_map<std::string, std::vector<FairMQChannel>> fChannels; ///< Device channels
|
||||
FairMQProgOptions* fConfig; ///< Program options configuration
|
||||
std::unique_ptr<FairMQProgOptions> fInternalConfig; ///< Internal program options configuration
|
||||
FairMQProgOptions* fConfig; ///< Pointer to config (internal or external)
|
||||
|
||||
void AddChannel(const std::string& channelName, const FairMQChannel& channel)
|
||||
{
|
||||
fConfig->AddChannel(channelName, channel);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string fId; ///< Device ID
|
||||
|
||||
int fNumIoThreads; ///< Number of ZeroMQ I/O threads
|
||||
|
||||
/// Additional user initialization (can be overloaded in child classes). Prefer to use InitTask().
|
||||
/// Executed in a worker thread
|
||||
virtual void Init();
|
||||
@@ -471,10 +506,7 @@ class FairMQDevice : public FairMQStateMachine
|
||||
int fPortRangeMin; ///< Minimum value for the port range (if dynamic)
|
||||
int fPortRangeMax; ///< Maximum value for the port range (if dynamic)
|
||||
|
||||
std::string fNetworkInterface; ///< Network interface to use for dynamic binding
|
||||
std::string fDefaultTransport; ///< Default transport for the device
|
||||
|
||||
int fInitializationTimeoutInS; ///< Timeout for the initialization (in seconds)
|
||||
fair::mq::Transport fDefaultTransportType; ///< Default transport for the device
|
||||
|
||||
/// Handles the initialization and the Init() method
|
||||
void InitWrapper();
|
||||
@@ -521,17 +553,19 @@ class FairMQDevice : public FairMQStateMachine
|
||||
bool fDataCallbacks;
|
||||
std::unordered_map<std::string, InputMsgCallback> fMsgInputs;
|
||||
std::unordered_map<std::string, InputMultipartCallback> fMultipartInputs;
|
||||
std::unordered_map<FairMQ::Transport, std::vector<std::string>> fMultitransportInputs;
|
||||
std::unordered_map<fair::mq::Transport, std::vector<std::string>> fMultitransportInputs;
|
||||
std::unordered_map<std::string, std::pair<uint16_t, uint16_t>> fChannelRegistry;
|
||||
std::vector<std::string> fInputChannelKeys;
|
||||
std::mutex fMultitransportMutex;
|
||||
std::atomic<bool> fMultitransportProceed;
|
||||
|
||||
bool fExternalConfig;
|
||||
|
||||
const fair::mq::tools::Version fVersion;
|
||||
float fRate; ///< Rate limiting for ConditionalRun
|
||||
size_t fLastTime; ///< Rate limiting for ConditionalRun
|
||||
std::vector<std::string> fRawCmdLineArgs;
|
||||
|
||||
std::atomic<bool> fInterrupted;
|
||||
std::condition_variable fInterruptedCV;
|
||||
std::mutex fInterruptedMtx;
|
||||
};
|
||||
|
||||
#endif /* FAIRMQDEVICE_H_ */
|
||||
|
@@ -28,7 +28,7 @@ class FairMQMessage
|
||||
|
||||
virtual bool SetUsedSize(const size_t size) = 0;
|
||||
|
||||
virtual FairMQ::Transport GetType() const = 0;
|
||||
virtual fair::mq::Transport GetType() const = 0;
|
||||
|
||||
virtual void Copy(const std::unique_ptr<FairMQMessage>& msg) __attribute__((deprecated("Use 'Copy(const FairMQMessage& msg)'"))) = 0;
|
||||
virtual void Copy(const FairMQMessage& msg) = 0;
|
||||
|
@@ -13,15 +13,421 @@
|
||||
*/
|
||||
|
||||
#include "FairMQStateMachine.h"
|
||||
#include <fairmq/Tools.h>
|
||||
|
||||
// Increase maximum number of boost::msm states (default is 10)
|
||||
// This #define has to be before any msm header includes
|
||||
#define FUSION_MAX_VECTOR_SIZE 20
|
||||
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/back/tools.hpp>
|
||||
#include <boost/msm/back/metafunctions.hpp>
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/functor_row.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/signals2.hpp> // signal/slot for onStateChange callbacks
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::msm::front;
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<FairMQStateMachine::Event> : fair::mq::tools::HashEnum<FairMQStateMachine::Event> {};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
namespace fsm
|
||||
{
|
||||
|
||||
// list of FSM states
|
||||
struct OK_FSM_STATE : public state<> { static string Name() { return "OK"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::OK; } };
|
||||
struct ERROR_FSM_STATE : public terminate_state<> { static string Name() { return "ERROR"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::Error; } };
|
||||
|
||||
struct IDLE_FSM_STATE : public state<> { static string Name() { return "IDLE"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::IDLE; } };
|
||||
struct INITIALIZING_DEVICE_FSM_STATE : public state<> { static string Name() { return "INITIALIZING_DEVICE"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::INITIALIZING_DEVICE; } };
|
||||
struct DEVICE_READY_FSM_STATE : public state<> { static string Name() { return "DEVICE_READY"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::DEVICE_READY; } };
|
||||
struct INITIALIZING_TASK_FSM_STATE : public state<> { static string Name() { return "INITIALIZING_TASK"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::INITIALIZING_TASK; } };
|
||||
struct READY_FSM_STATE : public state<> { static string Name() { return "READY"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::READY; } };
|
||||
struct RUNNING_FSM_STATE : public state<> { static string Name() { return "RUNNING"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::RUNNING; } };
|
||||
struct PAUSED_FSM_STATE : public state<> { static string Name() { return "PAUSED"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::PAUSED; } };
|
||||
struct RESETTING_TASK_FSM_STATE : public state<> { static string Name() { return "RESETTING_TASK"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::RESETTING_TASK; } };
|
||||
struct RESETTING_DEVICE_FSM_STATE : public state<> { static string Name() { return "RESETTING_DEVICE"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::RESETTING_DEVICE; } };
|
||||
struct EXITING_FSM_STATE : public state<> { static string Name() { return "EXITING"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::EXITING; } };
|
||||
|
||||
// list of FSM events
|
||||
struct INIT_DEVICE_FSM_EVENT { static string Name() { return "INIT_DEVICE"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::INIT_DEVICE; } };
|
||||
struct internal_DEVICE_READY_FSM_EVENT { static string Name() { return "internal_DEVICE_READY"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::internal_DEVICE_READY; } };
|
||||
struct INIT_TASK_FSM_EVENT { static string Name() { return "INIT_TASK"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::INIT_TASK; } };
|
||||
struct internal_READY_FSM_EVENT { static string Name() { return "internal_READY"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::internal_READY; } };
|
||||
struct RUN_FSM_EVENT { static string Name() { return "RUN"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::RUN; } };
|
||||
struct PAUSE_FSM_EVENT { static string Name() { return "PAUSE"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::PAUSE; } };
|
||||
struct STOP_FSM_EVENT { static string Name() { return "STOP"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::STOP; } };
|
||||
struct RESET_TASK_FSM_EVENT { static string Name() { return "RESET_TASK"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::RESET_TASK; } };
|
||||
struct RESET_DEVICE_FSM_EVENT { static string Name() { return "RESET_DEVICE"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::RESET_DEVICE; } };
|
||||
struct internal_IDLE_FSM_EVENT { static string Name() { return "internal_IDLE"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::internal_IDLE; } };
|
||||
struct END_FSM_EVENT { static string Name() { return "END"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::END; } };
|
||||
struct ERROR_FOUND_FSM_EVENT { static string Name() { return "ERROR_FOUND"; } static FairMQStateMachine::Event Type() { return FairMQStateMachine::Event::ERROR_FOUND; } };
|
||||
|
||||
static array<string, 12> stateNames =
|
||||
{
|
||||
{
|
||||
"OK",
|
||||
"Error",
|
||||
"IDLE",
|
||||
"INITIALIZING_DEVICE",
|
||||
"DEVICE_READY",
|
||||
"INITIALIZING_TASK",
|
||||
"READY",
|
||||
"RUNNING",
|
||||
"PAUSED",
|
||||
"RESETTING_TASK",
|
||||
"RESETTING_DEVICE",
|
||||
"EXITING"
|
||||
}
|
||||
};
|
||||
|
||||
static array<string, 12> eventNames =
|
||||
{
|
||||
{
|
||||
"INIT_DEVICE",
|
||||
"internal_DEVICE_READY",
|
||||
"INIT_TASK",
|
||||
"internal_READY",
|
||||
"RUN",
|
||||
"PAUSE",
|
||||
"STOP",
|
||||
"RESET_TASK",
|
||||
"RESET_DEVICE",
|
||||
"internal_IDLE",
|
||||
"END",
|
||||
"ERROR_FOUND"
|
||||
}
|
||||
};
|
||||
|
||||
static map<string, int> stateNumbers =
|
||||
{
|
||||
{ "OK", FairMQStateMachine::State::OK },
|
||||
{ "Error", FairMQStateMachine::State::Error },
|
||||
{ "IDLE", FairMQStateMachine::State::IDLE },
|
||||
{ "INITIALIZING_DEVICE", FairMQStateMachine::State::INITIALIZING_DEVICE },
|
||||
{ "DEVICE_READY", FairMQStateMachine::State::DEVICE_READY },
|
||||
{ "INITIALIZING_TASK", FairMQStateMachine::State::INITIALIZING_TASK },
|
||||
{ "READY", FairMQStateMachine::State::READY },
|
||||
{ "RUNNING", FairMQStateMachine::State::RUNNING },
|
||||
{ "PAUSED", FairMQStateMachine::State::PAUSED },
|
||||
{ "RESETTING_TASK", FairMQStateMachine::State::RESETTING_TASK },
|
||||
{ "RESETTING_DEVICE", FairMQStateMachine::State::RESETTING_DEVICE },
|
||||
{ "EXITING", FairMQStateMachine::State::EXITING }
|
||||
};
|
||||
|
||||
static map<string, int> eventNumbers =
|
||||
{
|
||||
{ "INIT_DEVICE", FairMQStateMachine::Event::INIT_DEVICE },
|
||||
{ "internal_DEVICE_READY", FairMQStateMachine::Event::internal_DEVICE_READY },
|
||||
{ "INIT_TASK", FairMQStateMachine::Event::INIT_TASK },
|
||||
{ "internal_READY", FairMQStateMachine::Event::internal_READY },
|
||||
{ "RUN", FairMQStateMachine::Event::RUN },
|
||||
{ "PAUSE", FairMQStateMachine::Event::PAUSE },
|
||||
{ "STOP", FairMQStateMachine::Event::STOP },
|
||||
{ "RESET_TASK", FairMQStateMachine::Event::RESET_TASK },
|
||||
{ "RESET_DEVICE", FairMQStateMachine::Event::RESET_DEVICE },
|
||||
{ "internal_IDLE", FairMQStateMachine::Event::internal_IDLE },
|
||||
{ "END", FairMQStateMachine::Event::END },
|
||||
{ "ERROR_FOUND", FairMQStateMachine::Event::ERROR_FOUND }
|
||||
};
|
||||
|
||||
// defining the boost MSM state machine
|
||||
struct Machine_ : public state_machine_def<Machine_>
|
||||
{
|
||||
public:
|
||||
Machine_()
|
||||
: fUnblockHandler()
|
||||
, fStateHandlers()
|
||||
, fWork()
|
||||
, fWorkAvailableCondition()
|
||||
, fWorkDoneCondition()
|
||||
, fWorkMutex()
|
||||
, fWorkerTerminated(false)
|
||||
, fWorkActive(false)
|
||||
, fWorkAvailable(false)
|
||||
, fStateChangeSignal()
|
||||
, fStateChangeSignalsMap()
|
||||
, fState()
|
||||
{}
|
||||
|
||||
virtual ~Machine_()
|
||||
{}
|
||||
|
||||
// initial states
|
||||
using initial_state = boost::mpl::vector<IDLE_FSM_STATE, OK_FSM_STATE>;
|
||||
|
||||
template<typename Event, typename FSM>
|
||||
void on_entry(Event const&, FSM& fsm)
|
||||
{
|
||||
LOG(state) << "Starting FairMQ state machine";
|
||||
fState = FairMQStateMachine::IDLE;
|
||||
LOG(state) << "Entering IDLE state";
|
||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::IDLE);
|
||||
}
|
||||
|
||||
template<typename Event, typename FSM>
|
||||
void on_exit(Event const&, FSM& /*fsm*/)
|
||||
{
|
||||
LOG(state) << "Exiting FairMQ state machine";
|
||||
}
|
||||
|
||||
// actions
|
||||
struct AutomaticFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
}
|
||||
};
|
||||
|
||||
struct DefaultFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const& e, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
|
||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
fsm.fWork = fsm.fStateHandlers.at(e.Type());
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct PauseFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
|
||||
fsm.fUnblockHandler();
|
||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
fsm.fWork = fsm.fPauseWrapperHandler;
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct StopFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
|
||||
fsm.fUnblockHandler();
|
||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
}
|
||||
};
|
||||
|
||||
struct InternalStopFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
fsm.fUnblockHandler();
|
||||
LOG(state) << "RUNNING state finished without an external event, entering " << ts.Name() << " state";
|
||||
}
|
||||
};
|
||||
|
||||
struct ExitingFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const& e, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
fsm.fState = ts.Type();
|
||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::EXITING);
|
||||
|
||||
// Stop ProcessWork()
|
||||
{
|
||||
lock_guard<mutex> lock(fsm.fWorkMutex);
|
||||
fsm.fWorkerTerminated = true;
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
|
||||
fsm.fStateHandlers.at(e.Type())();
|
||||
}
|
||||
};
|
||||
|
||||
struct ErrorFoundFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||
{
|
||||
fsm.fState = ts.Type();
|
||||
LOG(state) << "Entering " << ts.Name() << " state";
|
||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::Error);
|
||||
}
|
||||
};
|
||||
|
||||
// Transition table for Machine_
|
||||
struct transition_table : boost::mpl::vector<
|
||||
// Start Event Next Action Guard
|
||||
Row<IDLE_FSM_STATE, INIT_DEVICE_FSM_EVENT, INITIALIZING_DEVICE_FSM_STATE, DefaultFct, none>,
|
||||
Row<IDLE_FSM_STATE, END_FSM_EVENT, EXITING_FSM_STATE, ExitingFct, none>,
|
||||
Row<INITIALIZING_DEVICE_FSM_STATE, internal_DEVICE_READY_FSM_EVENT, DEVICE_READY_FSM_STATE, AutomaticFct, none>,
|
||||
Row<DEVICE_READY_FSM_STATE, INIT_TASK_FSM_EVENT, INITIALIZING_TASK_FSM_STATE, DefaultFct, none>,
|
||||
Row<DEVICE_READY_FSM_STATE, RESET_DEVICE_FSM_EVENT, RESETTING_DEVICE_FSM_STATE, DefaultFct, none>,
|
||||
Row<INITIALIZING_TASK_FSM_STATE, internal_READY_FSM_EVENT, READY_FSM_STATE, AutomaticFct, none>,
|
||||
Row<READY_FSM_STATE, RUN_FSM_EVENT, RUNNING_FSM_STATE, DefaultFct, none>,
|
||||
Row<READY_FSM_STATE, RESET_TASK_FSM_EVENT, RESETTING_TASK_FSM_STATE, DefaultFct, none>,
|
||||
Row<RUNNING_FSM_STATE, PAUSE_FSM_EVENT, PAUSED_FSM_STATE, DefaultFct, none>,
|
||||
Row<RUNNING_FSM_STATE, STOP_FSM_EVENT, READY_FSM_STATE, StopFct, none>,
|
||||
Row<RUNNING_FSM_STATE, internal_READY_FSM_EVENT, READY_FSM_STATE, InternalStopFct, none>,
|
||||
Row<PAUSED_FSM_STATE, RUN_FSM_EVENT, RUNNING_FSM_STATE, DefaultFct, none>,
|
||||
Row<RESETTING_TASK_FSM_STATE, internal_DEVICE_READY_FSM_EVENT, DEVICE_READY_FSM_STATE, AutomaticFct, none>,
|
||||
Row<RESETTING_DEVICE_FSM_STATE, internal_IDLE_FSM_EVENT, IDLE_FSM_STATE, AutomaticFct, none>,
|
||||
Row<OK_FSM_STATE, ERROR_FOUND_FSM_EVENT, ERROR_FSM_STATE, ErrorFoundFct, none>>
|
||||
{};
|
||||
|
||||
// replaces the default no-transition response.
|
||||
template<typename FSM, typename Event>
|
||||
void no_transition(Event const& e, FSM&, int state)
|
||||
{
|
||||
using recursive_stt = typename boost::msm::back::recursive_get_transition_table<FSM>::type;
|
||||
using all_states = typename boost::msm::back::generate_state_set<recursive_stt>::type;
|
||||
|
||||
string stateName;
|
||||
|
||||
boost::mpl::for_each<all_states, boost::msm::wrap<boost::mpl::placeholders::_1>>(boost::msm::back::get_state_name<recursive_stt>(stateName, state));
|
||||
|
||||
stateName = boost::core::demangle(stateName.c_str());
|
||||
size_t pos = stateName.rfind(":");
|
||||
if (pos != string::npos)
|
||||
{
|
||||
stateName = stateName.substr(pos + 1);
|
||||
stateName = stateName.substr(0, stateName.size() - 10);
|
||||
}
|
||||
|
||||
if (stateName != "OK")
|
||||
{
|
||||
LOG(state) << "No transition from state " << stateName << " on event " << e.Name();
|
||||
}
|
||||
}
|
||||
|
||||
void CallStateChangeCallbacks(const FairMQStateMachine::State state) const
|
||||
{
|
||||
if (!fStateChangeSignal.empty())
|
||||
{
|
||||
fStateChangeSignal(state);
|
||||
}
|
||||
}
|
||||
|
||||
function<void(void)> fUnblockHandler;
|
||||
unordered_map<FairMQStateMachine::Event, function<void(void)>> fStateHandlers;
|
||||
|
||||
// function to execute user states in a worker thread
|
||||
function<void(void)> fWork;
|
||||
condition_variable fWorkAvailableCondition;
|
||||
condition_variable fWorkDoneCondition;
|
||||
mutex fWorkMutex;
|
||||
bool fWorkerTerminated;
|
||||
bool fWorkActive;
|
||||
bool fWorkAvailable;
|
||||
|
||||
boost::signals2::signal<void(const FairMQStateMachine::State)> fStateChangeSignal;
|
||||
unordered_map<string, boost::signals2::connection> fStateChangeSignalsMap;
|
||||
|
||||
atomic<FairMQStateMachine::State> fState;
|
||||
|
||||
void ProcessWork()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
unique_lock<mutex> lock(fWorkMutex);
|
||||
// Wait for work to be done.
|
||||
while (!fWorkAvailable && !fWorkerTerminated)
|
||||
{
|
||||
fWorkAvailableCondition.wait_for(lock, chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
if (fWorkerTerminated)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
fWorkActive = true;
|
||||
}
|
||||
|
||||
fWork();
|
||||
|
||||
{
|
||||
lock_guard<mutex> lock(fWorkMutex);
|
||||
fWorkActive = false;
|
||||
fWorkAvailable = false;
|
||||
fWorkDoneCondition.notify_one();
|
||||
}
|
||||
CallStateChangeCallbacks(fState);
|
||||
}
|
||||
}
|
||||
}; // Machine_
|
||||
|
||||
using FairMQFSM = boost::msm::back::state_machine<Machine_>;
|
||||
|
||||
} // namespace fsm
|
||||
} // namespace mq
|
||||
} // namespace fair
|
||||
|
||||
using namespace fair::mq::fsm;
|
||||
|
||||
FairMQStateMachine::FairMQStateMachine()
|
||||
: fChangeStateMutex()
|
||||
, fFsm(new FairMQFSM)
|
||||
{
|
||||
start();
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(INIT_DEVICE, bind(&FairMQStateMachine::InitWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(INIT_TASK, bind(&FairMQStateMachine::InitTaskWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RUN, bind(&FairMQStateMachine::RunWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(PAUSE, bind(&FairMQStateMachine::PauseWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RESET_TASK, bind(&FairMQStateMachine::ResetTaskWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RESET_DEVICE, bind(&FairMQStateMachine::ResetWrapper, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(END, bind(&FairMQStateMachine::Exit, this));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fUnblockHandler = bind(&FairMQStateMachine::Unblock, this);
|
||||
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->start();
|
||||
}
|
||||
|
||||
FairMQStateMachine::~FairMQStateMachine()
|
||||
{
|
||||
stop();
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->stop();
|
||||
}
|
||||
|
||||
int FairMQStateMachine::GetInterfaceVersion() const
|
||||
@@ -37,85 +443,85 @@ bool FairMQStateMachine::ChangeState(int event)
|
||||
{
|
||||
case INIT_DEVICE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::INIT_DEVICE());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_DEVICE_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case internal_DEVICE_READY:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::internal_DEVICE_READY());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_DEVICE_READY_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case INIT_TASK:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::INIT_TASK());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_TASK_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case internal_READY:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::internal_READY());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_READY_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case RUN:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::RUN());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RUN_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case PAUSE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::PAUSE());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(PAUSE_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case STOP:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::STOP());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(STOP_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case RESET_DEVICE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::RESET_DEVICE());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_DEVICE_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case RESET_TASK:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::RESET_TASK());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_TASK_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case internal_IDLE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::internal_IDLE());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_IDLE_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case END:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::END());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(END_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
case ERROR_FOUND:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fChangeStateMutex);
|
||||
process_event(fair::mq::fsm::ERROR_FOUND());
|
||||
lock_guard<mutex> lock(fChangeStateMutex);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(ERROR_FOUND_FSM_EVENT());
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LOG(error) << "Requested state transition with an unsupported event: " << event << std::endl
|
||||
<< "Supported are: INIT_DEVICE, INIT_TASK, RUN, PAUSE, STOP, RESET_TASK, RESET_DEVICE, END, ERROR_FOUND";
|
||||
LOG(error) << "Requested state transition with an unsupported event: " << event << endl
|
||||
<< "Supported are: INIT_DEVICE, INIT_TASK, RUN, PAUSE, STOP, RESET_TASK, RESET_DEVICE, END, ERROR_FOUND";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Exception in FairMQStateMachine::ChangeState(): " << e.what();
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -123,7 +529,7 @@ bool FairMQStateMachine::ChangeState(int event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FairMQStateMachine::ChangeState(const std::string& event)
|
||||
bool FairMQStateMachine::ChangeState(const string& event)
|
||||
{
|
||||
return ChangeState(GetEventNumber(event));
|
||||
}
|
||||
@@ -140,10 +546,10 @@ void FairMQStateMachine::WaitForEndOfState(int event)
|
||||
case RESET_TASK:
|
||||
case RESET_DEVICE:
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fWorkMutex);
|
||||
while (fWorkActive || fWorkAvailable)
|
||||
unique_lock<mutex> lock(static_pointer_cast<FairMQFSM>(fFsm)->fWorkMutex);
|
||||
while (static_pointer_cast<FairMQFSM>(fFsm)->fWorkActive || static_pointer_cast<FairMQFSM>(fFsm)->fWorkAvailable)
|
||||
{
|
||||
fWorkDoneCondition.wait_for(lock, std::chrono::seconds(1));
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fWorkDoneCondition.wait_for(lock, chrono::seconds(1));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -153,13 +559,13 @@ void FairMQStateMachine::WaitForEndOfState(int event)
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Exception in FairMQStateMachine::WaitForEndOfState(): " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void FairMQStateMachine::WaitForEndOfState(const std::string& event)
|
||||
void FairMQStateMachine::WaitForEndOfState(const string& event)
|
||||
{
|
||||
return WaitForEndOfState(GetEventNumber(event));
|
||||
}
|
||||
@@ -176,11 +582,11 @@ bool FairMQStateMachine::WaitForEndOfStateForMs(int event, int durationInMs)
|
||||
case RESET_TASK:
|
||||
case RESET_DEVICE:
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fWorkMutex);
|
||||
while (fWorkActive || fWorkAvailable)
|
||||
unique_lock<mutex> lock(static_pointer_cast<FairMQFSM>(fFsm)->fWorkMutex);
|
||||
while (static_pointer_cast<FairMQFSM>(fFsm)->fWorkActive || static_pointer_cast<FairMQFSM>(fFsm)->fWorkAvailable)
|
||||
{
|
||||
fWorkDoneCondition.wait_for(lock, std::chrono::milliseconds(durationInMs));
|
||||
if (fWorkActive)
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fWorkDoneCondition.wait_for(lock, chrono::milliseconds(durationInMs));
|
||||
if (static_pointer_cast<FairMQFSM>(fFsm)->fWorkActive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -192,43 +598,63 @@ bool FairMQStateMachine::WaitForEndOfStateForMs(int event, int durationInMs)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Exception in FairMQStateMachine::WaitForEndOfStateForMs(): " << e.what();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FairMQStateMachine::WaitForEndOfStateForMs(const std::string& event, int durationInMs)
|
||||
bool FairMQStateMachine::WaitForEndOfStateForMs(const string& event, int durationInMs)
|
||||
{
|
||||
return WaitForEndOfStateForMs(GetEventNumber(event), durationInMs);
|
||||
}
|
||||
|
||||
void FairMQStateMachine::SubscribeToStateChange(const std::string& key, std::function<void(const State)> callback)
|
||||
void FairMQStateMachine::SubscribeToStateChange(const string& key, function<void(const State)> callback)
|
||||
{
|
||||
fStateChangeSignalsMap.insert({key, fStateChangeSignal.connect(callback)});
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateChangeSignalsMap.insert({key, static_pointer_cast<FairMQFSM>(fFsm)->fStateChangeSignal.connect(callback)});
|
||||
}
|
||||
void FairMQStateMachine::UnsubscribeFromStateChange(const std::string& key)
|
||||
void FairMQStateMachine::UnsubscribeFromStateChange(const string& key)
|
||||
{
|
||||
if (fStateChangeSignalsMap.count(key))
|
||||
if (static_pointer_cast<FairMQFSM>(fFsm)->fStateChangeSignalsMap.count(key))
|
||||
{
|
||||
fStateChangeSignalsMap.at(key).disconnect();
|
||||
fStateChangeSignalsMap.erase(key);
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateChangeSignalsMap.at(key).disconnect();
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->fStateChangeSignalsMap.erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
int FairMQStateMachine::GetEventNumber(const std::string& event)
|
||||
void FairMQStateMachine::CallStateChangeCallbacks(const State state) const
|
||||
{
|
||||
if (event == "INIT_DEVICE") return INIT_DEVICE;
|
||||
if (event == "INIT_TASK") return INIT_TASK;
|
||||
if (event == "RUN") return RUN;
|
||||
if (event == "PAUSE") return PAUSE;
|
||||
if (event == "STOP") return STOP;
|
||||
if (event == "RESET_DEVICE") return RESET_DEVICE;
|
||||
if (event == "RESET_TASK") return RESET_TASK;
|
||||
if (event == "END") return END;
|
||||
if (event == "ERROR_FOUND") return ERROR_FOUND;
|
||||
LOG(error) << "Requested number for non-existent event... " << event << std::endl
|
||||
<< "Supported are: INIT_DEVICE, INIT_TASK, RUN, PAUSE, STOP, RESET_DEVICE, RESET_TASK, END, ERROR_FOUND";
|
||||
return -1;
|
||||
}
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->CallStateChangeCallbacks(state);
|
||||
}
|
||||
|
||||
string FairMQStateMachine::GetCurrentStateName() const
|
||||
{
|
||||
return GetStateName(static_pointer_cast<FairMQFSM>(fFsm)->fState);
|
||||
}
|
||||
string FairMQStateMachine::GetStateName(const State state)
|
||||
{
|
||||
return stateNames.at(state);
|
||||
}
|
||||
int FairMQStateMachine::GetCurrentState() const
|
||||
{
|
||||
return static_pointer_cast<FairMQFSM>(fFsm)->fState;
|
||||
}
|
||||
bool FairMQStateMachine::CheckCurrentState(int state) const
|
||||
{
|
||||
return state == static_pointer_cast<FairMQFSM>(fFsm)->fState;
|
||||
}
|
||||
bool FairMQStateMachine::CheckCurrentState(string state) const
|
||||
{
|
||||
return state == GetCurrentStateName();
|
||||
}
|
||||
|
||||
void FairMQStateMachine::ProcessWork()
|
||||
{
|
||||
static_pointer_cast<FairMQFSM>(fFsm)->ProcessWork();
|
||||
}
|
||||
|
||||
int FairMQStateMachine::GetEventNumber(const string& event)
|
||||
{
|
||||
return eventNumbers.at(event);
|
||||
}
|
||||
|
@@ -17,555 +17,14 @@
|
||||
|
||||
#define FAIRMQ_INTERFACE_VERSION 3
|
||||
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
// Increase maximum number of boost::msm states (default is 10)
|
||||
// This #define has to be before any msm header includes
|
||||
#define FUSION_MAX_VECTOR_SIZE 20
|
||||
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/back/tools.hpp>
|
||||
#include <boost/msm/back/metafunctions.hpp>
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/functor_row.hpp>
|
||||
|
||||
#include <boost/signals2.hpp> // signal/slot for onStateChange callbacks
|
||||
|
||||
#include "FairMQLogger.h"
|
||||
|
||||
namespace msmf = boost::msm::front;
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
namespace fsm
|
||||
{
|
||||
|
||||
// defining events for the boost MSM state machine
|
||||
struct INIT_DEVICE { std::string name() const { return "INIT_DEVICE"; } };
|
||||
struct internal_DEVICE_READY { std::string name() const { return "internal_DEVICE_READY"; } };
|
||||
struct INIT_TASK { std::string name() const { return "INIT_TASK"; } };
|
||||
struct internal_READY { std::string name() const { return "internal_READY"; } };
|
||||
struct RUN { std::string name() const { return "RUN"; } };
|
||||
struct PAUSE { std::string name() const { return "PAUSE"; } };
|
||||
struct STOP { std::string name() const { return "STOP"; } };
|
||||
struct RESET_TASK { std::string name() const { return "RESET_TASK"; } };
|
||||
struct RESET_DEVICE { std::string name() const { return "RESET_DEVICE"; } };
|
||||
struct internal_IDLE { std::string name() const { return "internal_IDLE"; } };
|
||||
struct END { std::string name() const { return "END"; } };
|
||||
struct ERROR_FOUND { std::string name() const { return "ERROR_FOUND"; } };
|
||||
|
||||
// deactivate the warning for non-virtual destructor thrown in the boost library
|
||||
#if defined(__clang__)
|
||||
_Pragma("clang diagnostic push")
|
||||
_Pragma("clang diagnostic ignored \"-Wnon-virtual-dtor\"")
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
_Pragma("GCC diagnostic push")
|
||||
_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
|
||||
#endif
|
||||
|
||||
// defining the boost MSM state machine
|
||||
struct FairMQFSM : public msmf::state_machine_def<FairMQFSM>
|
||||
{
|
||||
public:
|
||||
FairMQFSM()
|
||||
: fState()
|
||||
, fChangeStateMutex()
|
||||
, fWork()
|
||||
, fWorkAvailableCondition()
|
||||
, fWorkDoneCondition()
|
||||
, fWorkMutex()
|
||||
, fWorkerTerminated(false)
|
||||
, fWorkActive(false)
|
||||
, fWorkAvailable(false)
|
||||
, fStateChangeSignal()
|
||||
, fStateChangeSignalsMap()
|
||||
, fTerminationRequested(false)
|
||||
, fWorkerThread()
|
||||
{}
|
||||
|
||||
virtual ~FairMQFSM()
|
||||
{}
|
||||
|
||||
template<typename Event, typename FSM>
|
||||
void on_entry(Event const&, FSM& fsm)
|
||||
{
|
||||
LOG(state) << "Starting FairMQ state machine";
|
||||
fState = IDLE;
|
||||
fsm.CallStateChangeCallbacks(IDLE);
|
||||
|
||||
// start a worker thread to execute user states in.
|
||||
fsm.fWorkerThread = std::thread(&FairMQFSM::Worker, &fsm);
|
||||
}
|
||||
|
||||
template<typename Event, typename FSM>
|
||||
void on_exit(Event const&, FSM& /*fsm*/)
|
||||
{
|
||||
LOG(state) << "Exiting FairMQ state machine";
|
||||
}
|
||||
|
||||
// list of FSM states
|
||||
struct OK_FSM : public msmf::state<> {};
|
||||
struct ERROR_FSM : public msmf::terminate_state<> {};
|
||||
|
||||
struct IDLE_FSM : public msmf::state<> {};
|
||||
struct INITIALIZING_DEVICE_FSM : public msmf::state<> {};
|
||||
struct DEVICE_READY_FSM : public msmf::state<> {};
|
||||
struct INITIALIZING_TASK_FSM : public msmf::state<> {};
|
||||
struct READY_FSM : public msmf::state<> {};
|
||||
struct RUNNING_FSM : public msmf::state<> {};
|
||||
struct PAUSED_FSM : public msmf::state<> {};
|
||||
struct RESETTING_TASK_FSM : public msmf::state<> {};
|
||||
struct RESETTING_DEVICE_FSM : public msmf::state<> {};
|
||||
struct EXITING_FSM : public msmf::state<> {};
|
||||
|
||||
// initial states
|
||||
using initial_state = boost::mpl::vector<IDLE_FSM, OK_FSM>;
|
||||
|
||||
// actions
|
||||
struct IdleFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
LOG(state) << "Entering IDLE state";
|
||||
fsm.fState = IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
struct InitDeviceFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = INITIALIZING_DEVICE;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering INITIALIZING DEVICE state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::InitWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct DeviceReadyFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
LOG(state) << "Entering DEVICE READY state";
|
||||
fsm.fState = DEVICE_READY;
|
||||
}
|
||||
};
|
||||
|
||||
struct InitTaskFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = INITIALIZING_TASK;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering INITIALIZING TASK state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::InitTaskWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct ReadyFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
LOG(state) << "Entering READY state";
|
||||
fsm.fState = READY;
|
||||
}
|
||||
};
|
||||
|
||||
struct RunFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = RUNNING;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering RUNNING state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::RunWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct PauseFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = PAUSED;
|
||||
|
||||
fsm.Unblock();
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering PAUSED state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::PauseWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct ResumeFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = RUNNING;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering RUNNING state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::RunWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct StopFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = READY;
|
||||
|
||||
fsm.Unblock();
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
LOG(state) << "Entering READY state";
|
||||
}
|
||||
};
|
||||
|
||||
struct InternalStopFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = READY;
|
||||
fsm.Unblock();
|
||||
LOG(state) << "RUNNING state finished without an external event, entering READY state";
|
||||
}
|
||||
};
|
||||
|
||||
struct ResetTaskFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = RESETTING_TASK;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering RESETTING TASK state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::ResetTaskWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct ResetDeviceFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
fsm.fState = RESETTING_DEVICE;
|
||||
|
||||
std::unique_lock<std::mutex> lock(fsm.fWorkMutex);
|
||||
while (fsm.fWorkActive)
|
||||
{
|
||||
fsm.fWorkDoneCondition.wait(lock);
|
||||
}
|
||||
fsm.fWorkAvailable = true;
|
||||
LOG(state) << "Entering RESETTING DEVICE state";
|
||||
fsm.fWork = std::bind(&FairMQFSM::ResetWrapper, &fsm);
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct ExitingFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
LOG(state) << "Entering EXITING state";
|
||||
fsm.fState = EXITING;
|
||||
fsm.fTerminationRequested = true;
|
||||
fsm.CallStateChangeCallbacks(EXITING);
|
||||
|
||||
// terminate worker thread
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fsm.fWorkMutex);
|
||||
fsm.fWorkerTerminated = true;
|
||||
fsm.fWorkAvailableCondition.notify_one();
|
||||
}
|
||||
|
||||
// join the worker thread (executing user states)
|
||||
if (fsm.fWorkerThread.joinable())
|
||||
{
|
||||
fsm.fWorkerThread.join();
|
||||
}
|
||||
|
||||
fsm.Exit();
|
||||
}
|
||||
};
|
||||
|
||||
struct ErrorFoundFct
|
||||
{
|
||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
LOG(state) << "Entering ERROR state";
|
||||
fsm.fState = Error;
|
||||
fsm.CallStateChangeCallbacks(Error);
|
||||
}
|
||||
};
|
||||
|
||||
// Transition table for FairMQFSM
|
||||
struct transition_table : boost::mpl::vector<
|
||||
// Start Event Next Action Guard
|
||||
msmf::Row<IDLE_FSM, INIT_DEVICE, INITIALIZING_DEVICE_FSM, InitDeviceFct, msmf::none>,
|
||||
msmf::Row<IDLE_FSM, END, EXITING_FSM, ExitingFct, msmf::none>,
|
||||
msmf::Row<INITIALIZING_DEVICE_FSM, internal_DEVICE_READY, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
|
||||
msmf::Row<DEVICE_READY_FSM, INIT_TASK, INITIALIZING_TASK_FSM, InitTaskFct, msmf::none>,
|
||||
msmf::Row<DEVICE_READY_FSM, RESET_DEVICE, RESETTING_DEVICE_FSM, ResetDeviceFct, msmf::none>,
|
||||
msmf::Row<INITIALIZING_TASK_FSM, internal_READY, READY_FSM, ReadyFct, msmf::none>,
|
||||
msmf::Row<READY_FSM, RUN, RUNNING_FSM, RunFct, msmf::none>,
|
||||
msmf::Row<READY_FSM, RESET_TASK, RESETTING_TASK_FSM, ResetTaskFct, msmf::none>,
|
||||
msmf::Row<RUNNING_FSM, PAUSE, PAUSED_FSM, PauseFct, msmf::none>,
|
||||
msmf::Row<RUNNING_FSM, STOP, READY_FSM, StopFct, msmf::none>,
|
||||
msmf::Row<RUNNING_FSM, internal_READY, READY_FSM, InternalStopFct, msmf::none>,
|
||||
msmf::Row<PAUSED_FSM, RUN, RUNNING_FSM, ResumeFct, msmf::none>,
|
||||
msmf::Row<RESETTING_TASK_FSM, internal_DEVICE_READY, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
|
||||
msmf::Row<RESETTING_DEVICE_FSM, internal_IDLE, IDLE_FSM, IdleFct, msmf::none>,
|
||||
msmf::Row<OK_FSM, ERROR_FOUND, ERROR_FSM, ErrorFoundFct, msmf::none>>
|
||||
{};
|
||||
|
||||
// replaces the default no-transition response.
|
||||
template<typename FSM, typename Event>
|
||||
void no_transition(Event const& e, FSM&, int state)
|
||||
{
|
||||
using recursive_stt = typename boost::msm::back::recursive_get_transition_table<FSM>::type;
|
||||
using all_states = typename boost::msm::back::generate_state_set<recursive_stt>::type;
|
||||
|
||||
std::string stateName;
|
||||
|
||||
boost::mpl::for_each<all_states, boost::msm::wrap<boost::mpl::placeholders::_1>>(boost::msm::back::get_state_name<recursive_stt>(stateName, state));
|
||||
|
||||
stateName = stateName.substr(24);
|
||||
std::size_t pos = stateName.find("_FSME");
|
||||
stateName.erase(pos);
|
||||
|
||||
if (stateName == "1RUNNING" || stateName == "6DEVICE_READY" || stateName == "0PAUSED" || stateName == "8RESETTING_TASK" || stateName == "0RESETTING_DEVICE")
|
||||
{
|
||||
stateName = stateName.substr(1);
|
||||
}
|
||||
|
||||
if (stateName != "OK")
|
||||
{
|
||||
LOG(state) << "No transition from state " << stateName << " on event " << e.name();
|
||||
}
|
||||
|
||||
// LOG(state) << "no transition from state " << GetStateName(state) << " (" << state << ") on event " << e.name();
|
||||
}
|
||||
|
||||
// backward compatibility to FairMQStateMachine
|
||||
enum State
|
||||
{
|
||||
OK,
|
||||
Error,
|
||||
IDLE,
|
||||
INITIALIZING_DEVICE,
|
||||
DEVICE_READY,
|
||||
INITIALIZING_TASK,
|
||||
READY,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
RESETTING_TASK,
|
||||
RESETTING_DEVICE,
|
||||
EXITING
|
||||
};
|
||||
|
||||
static std::string GetStateName(const int state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case OK:
|
||||
return "OK";
|
||||
case Error:
|
||||
return "Error";
|
||||
case IDLE:
|
||||
return "IDLE";
|
||||
case INITIALIZING_DEVICE:
|
||||
return "INITIALIZING_DEVICE";
|
||||
case DEVICE_READY:
|
||||
return "DEVICE_READY";
|
||||
case INITIALIZING_TASK:
|
||||
return "INITIALIZING_TASK";
|
||||
case READY:
|
||||
return "READY";
|
||||
case RUNNING:
|
||||
return "RUNNING";
|
||||
case PAUSED:
|
||||
return "PAUSED";
|
||||
case RESETTING_TASK:
|
||||
return "RESETTING_TASK";
|
||||
case RESETTING_DEVICE:
|
||||
return "RESETTING_DEVICE";
|
||||
case EXITING:
|
||||
return "EXITING";
|
||||
default:
|
||||
return "requested name for non-existent state...";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetCurrentStateName() const
|
||||
{
|
||||
return GetStateName(fState);
|
||||
}
|
||||
int GetCurrentState() const
|
||||
{
|
||||
return fState;
|
||||
}
|
||||
bool CheckCurrentState(int state) const
|
||||
{
|
||||
return state == fState;
|
||||
}
|
||||
bool CheckCurrentState(std::string state) const
|
||||
{
|
||||
return state == GetCurrentStateName();
|
||||
}
|
||||
|
||||
// actions to be overwritten by derived classes
|
||||
virtual void InitWrapper() {}
|
||||
virtual void InitTaskWrapper() {}
|
||||
virtual void RunWrapper() {}
|
||||
virtual void PauseWrapper() {}
|
||||
virtual void ResetWrapper() {}
|
||||
virtual void ResetTaskWrapper() {}
|
||||
virtual void Exit() {}
|
||||
virtual void Unblock() {}
|
||||
|
||||
bool Terminated()
|
||||
{
|
||||
return fTerminationRequested;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::atomic<State> fState;
|
||||
std::mutex fChangeStateMutex;
|
||||
|
||||
// function to execute user states in a worker thread
|
||||
std::function<void(void)> fWork;
|
||||
std::condition_variable fWorkAvailableCondition;
|
||||
std::condition_variable fWorkDoneCondition;
|
||||
std::mutex fWorkMutex;
|
||||
bool fWorkerTerminated;
|
||||
bool fWorkActive;
|
||||
bool fWorkAvailable;
|
||||
|
||||
boost::signals2::signal<void(const State)> fStateChangeSignal;
|
||||
std::unordered_map<std::string, boost::signals2::connection> fStateChangeSignalsMap;
|
||||
std::atomic<bool> fTerminationRequested;
|
||||
|
||||
void CallStateChangeCallbacks(const State state) const
|
||||
{
|
||||
if (!fStateChangeSignal.empty())
|
||||
{
|
||||
fStateChangeSignal(state);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void Worker()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fWorkMutex);
|
||||
// Wait for work to be done.
|
||||
while (!fWorkAvailable && !fWorkerTerminated)
|
||||
{
|
||||
fWorkAvailableCondition.wait(lock);
|
||||
}
|
||||
|
||||
if (fWorkerTerminated)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
fWorkActive = true;
|
||||
}
|
||||
|
||||
fWork();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fWorkMutex);
|
||||
fWorkActive = false;
|
||||
fWorkAvailable = false;
|
||||
fWorkDoneCondition.notify_one();
|
||||
}
|
||||
CallStateChangeCallbacks(fState);
|
||||
}
|
||||
}
|
||||
|
||||
// run state handlers in a separate thread
|
||||
std::thread fWorkerThread;
|
||||
};
|
||||
|
||||
// reactivate the warning for non-virtual destructor
|
||||
#if defined(__clang__)
|
||||
_Pragma("clang diagnostic pop")
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
_Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
|
||||
} // namespace fsm
|
||||
} // namespace mq
|
||||
} // namespace fair
|
||||
|
||||
class FairMQStateMachine : public boost::msm::back::state_machine<fair::mq::fsm::FairMQFSM>
|
||||
class FairMQStateMachine
|
||||
{
|
||||
public:
|
||||
enum Event
|
||||
@@ -584,6 +43,22 @@ class FairMQStateMachine : public boost::msm::back::state_machine<fair::mq::fsm:
|
||||
ERROR_FOUND
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
OK,
|
||||
Error,
|
||||
IDLE,
|
||||
INITIALIZING_DEVICE,
|
||||
DEVICE_READY,
|
||||
INITIALIZING_TASK,
|
||||
READY,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
RESETTING_TASK,
|
||||
RESETTING_DEVICE,
|
||||
EXITING
|
||||
};
|
||||
|
||||
FairMQStateMachine();
|
||||
virtual ~FairMQStateMachine();
|
||||
|
||||
@@ -601,8 +76,32 @@ class FairMQStateMachine : public boost::msm::back::state_machine<fair::mq::fsm:
|
||||
void SubscribeToStateChange(const std::string& key, std::function<void(const State)> callback);
|
||||
void UnsubscribeFromStateChange(const std::string& key);
|
||||
|
||||
void CallStateChangeCallbacks(const State state) const;
|
||||
|
||||
std::string GetCurrentStateName() const;
|
||||
static std::string GetStateName(const State);
|
||||
int GetCurrentState() const;
|
||||
bool CheckCurrentState(int state) const;
|
||||
bool CheckCurrentState(std::string state) const;
|
||||
|
||||
// actions to be overwritten by derived classes
|
||||
virtual void InitWrapper() {}
|
||||
virtual void InitTaskWrapper() {}
|
||||
virtual void RunWrapper() {}
|
||||
virtual void PauseWrapper() {}
|
||||
virtual void ResetWrapper() {}
|
||||
virtual void ResetTaskWrapper() {}
|
||||
virtual void Exit() {}
|
||||
virtual void Unblock() {}
|
||||
|
||||
void ProcessWork();
|
||||
|
||||
private:
|
||||
int GetEventNumber(const std::string& event);
|
||||
static int GetEventNumber(const std::string& event);
|
||||
|
||||
std::mutex fChangeStateMutex;
|
||||
|
||||
std::shared_ptr<void> fFsm;
|
||||
};
|
||||
|
||||
#endif /* FAIRMQSTATEMACHINE_H_ */
|
||||
|
@@ -29,7 +29,7 @@ class FairMQTransportFactory
|
||||
private:
|
||||
/// Topology wide unique id
|
||||
const std::string fkId;
|
||||
|
||||
|
||||
public:
|
||||
/// ctor
|
||||
/// @param id Topology wide unique id, usually the device id.
|
||||
@@ -69,7 +69,7 @@ class FairMQTransportFactory
|
||||
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr) const = 0;
|
||||
|
||||
/// Get transport type
|
||||
virtual FairMQ::Transport GetType() const = 0;
|
||||
virtual fair::mq::Transport GetType() const = 0;
|
||||
|
||||
virtual void Interrupt() = 0;
|
||||
virtual void Resume() = 0;
|
||||
|
@@ -99,6 +99,11 @@ class Plugin
|
||||
auto SubscribeToPropertyChangeAsString(std::function<void(const std::string& key, std::string newValue)> callback) -> void { fPluginServices->SubscribeToPropertyChangeAsString(fkName, callback); }
|
||||
auto UnsubscribeFromPropertyChangeAsString() -> void { fPluginServices->UnsubscribeFromPropertyChangeAsString(fkName); }
|
||||
|
||||
auto CycleLogConsoleSeverityUp() -> void { fPluginServices->CycleLogConsoleSeverityUp(); }
|
||||
auto CycleLogConsoleSeverityDown() -> void { fPluginServices->CycleLogConsoleSeverityDown(); }
|
||||
auto CycleLogVerbosityUp() -> void { fPluginServices->CycleLogVerbosityUp(); }
|
||||
auto CycleLogVerbosityDown() -> void { fPluginServices->CycleLogVerbosityDown(); }
|
||||
|
||||
private:
|
||||
const std::string fkName;
|
||||
const Version fkVersion;
|
||||
@@ -111,9 +116,9 @@ class Plugin
|
||||
} /* namespace fair */
|
||||
|
||||
#define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \
|
||||
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr<fair::mq::Plugin> \
|
||||
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::unique_ptr<fair::mq::Plugin> \
|
||||
{ \
|
||||
return std::make_shared<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \
|
||||
return fair::mq::tools::make_unique<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \
|
||||
} \
|
||||
BOOST_DLL_ALIAS(Make_##NAME##_Plugin, make_##NAME##_plugin) \
|
||||
BOOST_DLL_ALIAS(PROGOPTIONS, get_##NAME##_plugin_progoptions)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include <fairmq/plugins/Builtin.h>
|
||||
#include <fairmq/PluginManager.h>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <boost/program_options.hpp>
|
||||
@@ -30,13 +31,55 @@ const std::string fair::mq::PluginManager::fgkLibPrefix = "FairMQPlugin_";
|
||||
fair::mq::PluginManager::PluginManager()
|
||||
: fSearchPaths{{"."}}
|
||||
, fPluginFactories()
|
||||
, fPluginServices()
|
||||
, fPlugins()
|
||||
, fPluginOrder()
|
||||
, fPluginProgOptions()
|
||||
, fPluginServices()
|
||||
{
|
||||
}
|
||||
|
||||
fair::mq::PluginManager::PluginManager(const vector<string> args)
|
||||
: fSearchPaths{{"."}}
|
||||
, fPluginFactories()
|
||||
, fPluginServices()
|
||||
, fPlugins()
|
||||
, fPluginOrder()
|
||||
, fPluginProgOptions()
|
||||
{
|
||||
// Parse command line options
|
||||
auto options = ProgramOptions();
|
||||
auto vm = po::variables_map{};
|
||||
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)
|
||||
{
|
||||
throw ProgramOptionsParseError{ToString("Error occured while parsing the 'Plugin Manager' program options: ", e.what())};
|
||||
}
|
||||
|
||||
// Process plugin search paths
|
||||
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 (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); }
|
||||
}
|
||||
}
|
||||
|
||||
// Set supplied options
|
||||
SetSearchPaths(searchPaths);
|
||||
for(const auto& path : prepend) { PrependSearchPath(path); }
|
||||
for(const auto& path : append) { AppendSearchPath(path); }
|
||||
if (vm.count("plugin")) { LoadPlugins(vm["plugin"].as<vector<string>>()); }
|
||||
}
|
||||
|
||||
auto fair::mq::PluginManager::ValidateSearchPath(const fs::path& path) -> void
|
||||
{
|
||||
if (path.empty()) throw BadSearchPath{"Specified path is empty."};
|
||||
@@ -80,46 +123,6 @@ auto fair::mq::PluginManager::ProgramOptions() -> po::options_description
|
||||
return plugin_options;
|
||||
}
|
||||
|
||||
auto fair::mq::PluginManager::MakeFromCommandLineOptions(const vector<string> args) -> shared_ptr<PluginManager>
|
||||
{
|
||||
// Parse command line options
|
||||
auto options = ProgramOptions();
|
||||
auto vm = po::variables_map{};
|
||||
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)
|
||||
{
|
||||
throw ProgramOptionsParseError{ToString("Error occured while parsing the 'Plugin Manager' program options: ", e.what())};
|
||||
}
|
||||
|
||||
// Process plugin search paths
|
||||
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 (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); }
|
||||
}
|
||||
}
|
||||
|
||||
// Create PluginManager with supplied options
|
||||
auto mgr = make_shared<PluginManager>();
|
||||
mgr->SetSearchPaths(searchPaths);
|
||||
for(const auto& path : prepend) { mgr->PrependSearchPath(path); }
|
||||
for(const auto& path : append) { mgr->AppendSearchPath(path); }
|
||||
if (vm.count("plugin")) { mgr->LoadPlugins(vm["plugin"].as<vector<string>>()); }
|
||||
|
||||
// Return the plugin manager and command line options, that have not been recognized.
|
||||
return mgr;
|
||||
}
|
||||
|
||||
auto fair::mq::PluginManager::LoadPlugin(const string& pluginName) -> void
|
||||
{
|
||||
if (pluginName.substr(0,2) == "p:")
|
||||
|
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <fairmq/PluginServices.h>
|
||||
#include <fairmq/plugins/Builtin.h>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <FairMQDevice.h>
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
@@ -48,9 +47,15 @@ namespace mq
|
||||
class PluginManager
|
||||
{
|
||||
public:
|
||||
using PluginFactory = std::shared_ptr<fair::mq::Plugin>(PluginServices&);
|
||||
using PluginFactory = std::unique_ptr<fair::mq::Plugin>(PluginServices&);
|
||||
|
||||
PluginManager();
|
||||
PluginManager(const std::vector<std::string> args);
|
||||
|
||||
~PluginManager()
|
||||
{
|
||||
LOG(debug) << "Shutting down Plugin Manager";
|
||||
}
|
||||
|
||||
auto SetSearchPaths(const std::vector<boost::filesystem::path>&) -> void;
|
||||
auto AppendSearchPath(const boost::filesystem::path&) -> void;
|
||||
@@ -65,7 +70,6 @@ class PluginManager
|
||||
struct PluginInstantiationError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
static auto ProgramOptions() -> boost::program_options::options_description;
|
||||
static auto MakeFromCommandLineOptions(const std::vector<std::string>) -> std::shared_ptr<PluginManager>;
|
||||
struct ProgramOptionsParseError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
static auto LibPrefix() -> const std::string& { return fgkLibPrefix; }
|
||||
@@ -112,10 +116,10 @@ class PluginManager
|
||||
static const std::string fgkLibPrefix;
|
||||
std::vector<boost::filesystem::path> fSearchPaths;
|
||||
std::map<std::string, std::function<PluginFactory>> fPluginFactories;
|
||||
std::map<std::string, std::shared_ptr<Plugin>> fPlugins;
|
||||
std::unique_ptr<PluginServices> fPluginServices;
|
||||
std::map<std::string, std::unique_ptr<Plugin>> fPlugins;
|
||||
std::vector<std::string> fPluginOrder;
|
||||
std::map<std::string, boost::program_options::options_description> fPluginProgOptions;
|
||||
std::unique_ptr<PluginServices> fPluginServices;
|
||||
}; /* class PluginManager */
|
||||
|
||||
} /* namespace mq */
|
||||
|
@@ -98,7 +98,7 @@ auto PluginServices::ChangeDeviceState(const std::string& controller, const Devi
|
||||
|
||||
if (fDeviceController == controller)
|
||||
{
|
||||
fDevice->ChangeState(fkDeviceStateTransitionMap.at(next));
|
||||
fDevice.ChangeState(fkDeviceStateTransitionMap.at(next));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -38,15 +38,20 @@ class PluginServices
|
||||
{
|
||||
public:
|
||||
PluginServices() = delete;
|
||||
PluginServices(FairMQProgOptions* config, std::shared_ptr<FairMQDevice> device)
|
||||
: fConfig{config}
|
||||
, fDevice{device}
|
||||
PluginServices(FairMQProgOptions& config, FairMQDevice& device)
|
||||
: fConfig(config)
|
||||
, fDevice(device)
|
||||
, fDeviceController()
|
||||
, fDeviceControllerMutex()
|
||||
, fReleaseDeviceControlCondition()
|
||||
{
|
||||
}
|
||||
|
||||
~PluginServices()
|
||||
{
|
||||
LOG(debug) << "Shutting down Plugin Services";
|
||||
}
|
||||
|
||||
PluginServices(const PluginServices&) = delete;
|
||||
PluginServices operator=(const PluginServices&) = delete;
|
||||
|
||||
@@ -109,7 +114,7 @@ class PluginServices
|
||||
friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); }
|
||||
|
||||
/// @return current device state
|
||||
auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<FairMQDevice::State>(fDevice->GetCurrentState())); }
|
||||
auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<FairMQDevice::State>(fDevice.GetCurrentState())); }
|
||||
|
||||
/// @brief Become device controller
|
||||
/// @param controller id
|
||||
@@ -155,19 +160,19 @@ class PluginServices
|
||||
/// the state is running in.
|
||||
auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function<void(DeviceState /*newState*/)> callback) -> void
|
||||
{
|
||||
fDevice->SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){
|
||||
fDevice.SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){
|
||||
callback(fkDeviceStateMap.at(newState));
|
||||
});
|
||||
}
|
||||
|
||||
/// @brief Unsubscribe from device state changes
|
||||
/// @param subscriber id
|
||||
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice->UnsubscribeFromStateChange(subscriber); }
|
||||
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice.UnsubscribeFromStateChange(subscriber); }
|
||||
|
||||
// Config API
|
||||
struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
auto PropertyExists(const std::string& key) const -> bool { return fConfig->Count(key) > 0; }
|
||||
auto PropertyExists(const std::string& key) const -> bool { return fConfig.Count(key) > 0; }
|
||||
|
||||
/// @brief Set config property
|
||||
/// @param key
|
||||
@@ -182,7 +187,7 @@ class PluginServices
|
||||
auto currentState = GetCurrentDeviceState();
|
||||
if (currentState == DeviceState::InitializingDevice)
|
||||
{
|
||||
fConfig->SetValue(key, val);
|
||||
fConfig.SetValue(key, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -200,7 +205,7 @@ class PluginServices
|
||||
template<typename T>
|
||||
auto GetProperty(const std::string& key) const -> T {
|
||||
if (PropertyExists(key)) {
|
||||
return fConfig->GetValue<T>(key);
|
||||
return fConfig.GetValue<T>(key);
|
||||
}
|
||||
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
|
||||
}
|
||||
@@ -212,16 +217,16 @@ class PluginServices
|
||||
/// 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);
|
||||
return fConfig.GetStringValue(key);
|
||||
}
|
||||
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
|
||||
}
|
||||
|
||||
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig->GetChannelInfo(); }
|
||||
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig.GetChannelInfo(); }
|
||||
|
||||
/// @brief Discover the list of property keys
|
||||
/// @return list of property keys
|
||||
auto GetPropertyKeys() const -> std::vector<std::string> { return fConfig->GetPropertyKeys(); }
|
||||
auto GetPropertyKeys() const -> std::vector<std::string> { return fConfig.GetPropertyKeys(); }
|
||||
|
||||
/// @brief Subscribe to property updates of type T
|
||||
/// @param subscriber
|
||||
@@ -231,13 +236,13 @@ class PluginServices
|
||||
template<typename T>
|
||||
auto SubscribeToPropertyChange(const std::string& subscriber, std::function<void(const std::string& key, T)> callback) const -> void
|
||||
{
|
||||
fConfig->Subscribe<T>(subscriber, callback);
|
||||
fConfig.Subscribe<T>(subscriber, callback);
|
||||
}
|
||||
|
||||
/// @brief Unsubscribe from property updates of type T
|
||||
/// @param subscriber
|
||||
template<typename T>
|
||||
auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig->Unsubscribe<T>(subscriber); }
|
||||
auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig.Unsubscribe<T>(subscriber); }
|
||||
|
||||
/// @brief Subscribe to property updates
|
||||
/// @param subscriber
|
||||
@@ -246,13 +251,17 @@ class PluginServices
|
||||
/// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string.
|
||||
auto SubscribeToPropertyChangeAsString(const std::string& subscriber, std::function<void(const std::string& key, std::string)> callback) const -> void
|
||||
{
|
||||
fConfig->SubscribeAsString(subscriber, callback);
|
||||
fConfig.SubscribeAsString(subscriber, callback);
|
||||
}
|
||||
|
||||
/// @brief Unsubscribe from property updates that convert to string
|
||||
/// @param subscriber
|
||||
auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig->UnsubscribeAsString(subscriber); }
|
||||
auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig.UnsubscribeAsString(subscriber); }
|
||||
|
||||
auto CycleLogConsoleSeverityUp() -> void { Logger::CycleConsoleSeverityUp(); }
|
||||
auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); }
|
||||
auto CycleLogVerbosityUp() -> void { Logger::CycleVerbosityUp(); }
|
||||
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;
|
||||
@@ -262,8 +271,8 @@ class PluginServices
|
||||
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
|
||||
|
||||
private:
|
||||
FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up
|
||||
std::shared_ptr<FairMQDevice> fDevice;
|
||||
FairMQProgOptions& fConfig;
|
||||
FairMQDevice& fDevice;
|
||||
boost::optional<std::string> fDeviceController;
|
||||
mutable std::mutex fDeviceControllerMutex;
|
||||
std::condition_variable fReleaseDeviceControlCondition;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <fairmq/tools/CppSTL.h>
|
||||
#include <fairmq/tools/Network.h>
|
||||
#include <fairmq/tools/Process.h>
|
||||
#include <fairmq/tools/RateLimit.h>
|
||||
#include <fairmq/tools/Strings.h>
|
||||
#include <fairmq/tools/Unique.h>
|
||||
#include <fairmq/tools/Version.h>
|
||||
|
@@ -15,8 +15,9 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
/// TODO deprecate this namespace
|
||||
namespace FairMQ
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
|
||||
enum class Transport
|
||||
@@ -28,6 +29,21 @@ enum class Transport
|
||||
OFI
|
||||
};
|
||||
|
||||
} /* namespace mq */
|
||||
} /* namespace fair */
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<fair::mq::Transport> : fair::mq::tools::HashEnum<fair::mq::Transport> {};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
|
||||
static std::unordered_map<std::string, Transport> TransportTypes {
|
||||
{ "default", Transport::DEFAULT },
|
||||
@@ -37,25 +53,15 @@ static std::unordered_map<std::string, Transport> TransportTypes {
|
||||
{ "ofi", Transport::OFI }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
|
||||
using Transport = ::FairMQ::Transport;
|
||||
using ::FairMQ::TransportTypes;
|
||||
static std::unordered_map<Transport, std::string> TransportNames {
|
||||
{ Transport::DEFAULT, "default" },
|
||||
{ Transport::ZMQ, "zeromq" },
|
||||
{ Transport::NN, "nanomsg" },
|
||||
{ Transport::SHM, "shmem" },
|
||||
{ Transport::OFI, "ofi" }
|
||||
};
|
||||
|
||||
} /* namespace mq */
|
||||
} /* namespace fair */
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<FairMQ::Transport> : fair::mq::tools::HashEnum<FairMQ::Transport> {};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
#endif /* FAIR_MQ_TRANSPORTS_H */
|
||||
|
@@ -9,11 +9,19 @@
|
||||
#ifndef FAIR_MQ_VERSION_H
|
||||
|
||||
#define FAIRMQ_VERSION "@PROJECT_VERSION@"
|
||||
#define FAIRMQ_VERSION_DEC (@PROJECT_VERSION_MAJOR@ * 10000) + (@PROJECT_VERSION_MINOR@ * 100) + @PROJECT_VERSION_PATCH@
|
||||
#define FAIRMQ_VERSION_DEC (@PROJECT_VERSION_MAJOR@ * 100000) \
|
||||
+ (@PROJECT_VERSION_MINOR@ * 1000) \
|
||||
+ (@PROJECT_VERSION_PATCH@ * 10) \
|
||||
+ @PROJECT_VERSION_HOTFIX@
|
||||
#define FAIRMQ_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define FAIRMQ_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define FAIRMQ_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define FAIRMQ_VERSION_HOTFIX @PROJECT_VERSION_HOTFIX@
|
||||
#define FAIRMQ_GIT_VERSION "@PROJECT_GIT_VERSION@"
|
||||
#define FAIRMQ_GIT_DATE "@PROJECT_GIT_DATE@"
|
||||
#define FAIRMQ_REPO_URL "https://github.com/FairRootGroup/FairMQ"
|
||||
#define FAIRMQ_LICENSE "LGPL-3.0"
|
||||
#define FAIRMQ_COPYRIGHT "2012-2018 GSI"
|
||||
#define FAIRMQ_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
|
||||
|
||||
#endif // FAIR_MQ_VERSION_H
|
||||
|
@@ -1,36 +1,29 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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, *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
/**
|
||||
* FairMQBenchmarkSampler.cpp
|
||||
*
|
||||
* @since 2013-04-23
|
||||
* @author D. Klein, A. Rybalchenko
|
||||
*/
|
||||
|
||||
#include "FairMQBenchmarkSampler.h"
|
||||
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
#include <fairmq/Tools.h>
|
||||
#include "../FairMQLogger.h"
|
||||
#include "../options/FairMQProgOptions.h"
|
||||
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std;
|
||||
|
||||
FairMQBenchmarkSampler::FairMQBenchmarkSampler()
|
||||
: fSameMessage(true)
|
||||
, fMsgSize(10000)
|
||||
, fMsgCounter(0)
|
||||
, fMsgRate(1)
|
||||
, fMsgRate(0)
|
||||
, fNumIterations(0)
|
||||
, fMaxIterations(0)
|
||||
, fOutChannelName()
|
||||
, fResetMsgCounter()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -42,31 +35,28 @@ void FairMQBenchmarkSampler::InitTask()
|
||||
{
|
||||
fSameMessage = fConfig->GetValue<bool>("same-msg");
|
||||
fMsgSize = fConfig->GetValue<int>("msg-size");
|
||||
fMsgRate = fConfig->GetValue<int>("msg-rate");
|
||||
fMsgRate = fConfig->GetValue<float>("msg-rate");
|
||||
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
|
||||
fOutChannelName = fConfig->GetValue<string>("out-channel");
|
||||
}
|
||||
|
||||
void FairMQBenchmarkSampler::PreRun()
|
||||
{
|
||||
fResetMsgCounter = std::thread(&FairMQBenchmarkSampler::ResetMsgCounter, this);
|
||||
}
|
||||
|
||||
void FairMQBenchmarkSampler::Run()
|
||||
{
|
||||
// store the channel reference to avoid traversing the map on every loop iteration
|
||||
FairMQChannel& dataOutChannel = fChannels.at(fOutChannelName).at(0);
|
||||
|
||||
FairMQMessagePtr baseMsg(dataOutChannel.Transport()->CreateMessage(fMsgSize));
|
||||
FairMQMessagePtr baseMsg(dataOutChannel.NewMessage(fMsgSize));
|
||||
|
||||
LOG(info) << "Starting the benchmark with message size of " << fMsgSize << " and " << fMaxIterations << " iterations.";
|
||||
auto tStart = chrono::high_resolution_clock::now();
|
||||
|
||||
fair::mq::tools::RateLimiter rateLimiter(fMsgRate);
|
||||
|
||||
while (CheckCurrentState(RUNNING))
|
||||
{
|
||||
if (fSameMessage)
|
||||
{
|
||||
FairMQMessagePtr msg(dataOutChannel.Transport()->CreateMessage());
|
||||
FairMQMessagePtr msg(dataOutChannel.NewMessage());
|
||||
msg->Copy(*baseMsg);
|
||||
|
||||
if (dataOutChannel.Send(msg) >= 0)
|
||||
@@ -83,7 +73,7 @@ void FairMQBenchmarkSampler::Run()
|
||||
}
|
||||
else
|
||||
{
|
||||
FairMQMessagePtr msg(dataOutChannel.Transport()->CreateMessage(fMsgSize));
|
||||
FairMQMessagePtr msg(dataOutChannel.NewMessage(fMsgSize));
|
||||
|
||||
if (dataOutChannel.Send(msg) >= 0)
|
||||
{
|
||||
@@ -98,31 +88,14 @@ void FairMQBenchmarkSampler::Run()
|
||||
}
|
||||
}
|
||||
|
||||
--fMsgCounter;
|
||||
|
||||
while (fMsgCounter == 0)
|
||||
if (fMsgRate > 0)
|
||||
{
|
||||
this_thread::sleep_for(chrono::milliseconds(1));
|
||||
rateLimiter.maybe_sleep();
|
||||
}
|
||||
}
|
||||
|
||||
auto tEnd = chrono::high_resolution_clock::now();
|
||||
|
||||
LOG(info) << "Done " << fNumIterations << " iterations in " << chrono::duration<double, milli>(tEnd - tStart).count() << "ms.";
|
||||
|
||||
}
|
||||
|
||||
void FairMQBenchmarkSampler::PostRun()
|
||||
{
|
||||
fResetMsgCounter.join();
|
||||
}
|
||||
|
||||
void FairMQBenchmarkSampler::ResetMsgCounter()
|
||||
{
|
||||
while (CheckCurrentState(RUNNING))
|
||||
{
|
||||
fMsgCounter = fMsgRate / 100;
|
||||
this_thread::sleep_for(chrono::milliseconds(10));
|
||||
}
|
||||
fMsgCounter = -1;
|
||||
}
|
||||
|
@@ -1,22 +1,17 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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" *
|
||||
********************************************************************************/
|
||||
/**
|
||||
* FairMQBenchmarkSampler.h
|
||||
*
|
||||
* @since 2013-04-23
|
||||
* @author D. Klein, A. Rybalchenko
|
||||
*/
|
||||
|
||||
#ifndef FAIRMQBENCHMARKSAMPLER_H_
|
||||
#define FAIRMQBENCHMARKSAMPLER_H_
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
#include "FairMQDevice.h"
|
||||
|
||||
@@ -30,20 +25,14 @@ class FairMQBenchmarkSampler : public FairMQDevice
|
||||
FairMQBenchmarkSampler();
|
||||
virtual ~FairMQBenchmarkSampler();
|
||||
|
||||
void PreRun() override;
|
||||
void PostRun() override;
|
||||
|
||||
void ResetMsgCounter();
|
||||
|
||||
protected:
|
||||
bool fSameMessage;
|
||||
int fMsgSize;
|
||||
int fMsgCounter;
|
||||
int fMsgRate;
|
||||
std::atomic<int> fMsgCounter;
|
||||
float fMsgRate;
|
||||
uint64_t fNumIterations;
|
||||
uint64_t fMaxIterations;
|
||||
std::string fOutChannelName;
|
||||
std::thread fResetMsgCounter;
|
||||
|
||||
virtual void InitTask() override;
|
||||
virtual void Run() override;
|
||||
|
@@ -1,69 +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" *
|
||||
********************************************************************************/
|
||||
/**
|
||||
* FairMQSink.cxx
|
||||
*
|
||||
* @since 2013-01-09
|
||||
* @author D. Klein, A. Rybalchenko
|
||||
*/
|
||||
|
||||
#include "FairMQSink.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "../FairMQLogger.h"
|
||||
#include "../options/FairMQProgOptions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
FairMQSink::FairMQSink()
|
||||
: fNumMsgs(0)
|
||||
, fInChannelName()
|
||||
{
|
||||
}
|
||||
|
||||
void FairMQSink::InitTask()
|
||||
{
|
||||
fNumMsgs = fConfig->GetValue<uint64_t>("num-msgs");
|
||||
fInChannelName = fConfig->GetValue<string>("in-channel");
|
||||
}
|
||||
|
||||
void FairMQSink::Run()
|
||||
{
|
||||
uint64_t numReceivedMsgs = 0;
|
||||
// store the channel reference to avoid traversing the map on every loop iteration
|
||||
FairMQChannel& dataInChannel = fChannels.at(fInChannelName).at(0);
|
||||
|
||||
LOG(info) << "Starting the benchmark and expecting to receive " << fNumMsgs << " messages.";
|
||||
auto tStart = chrono::high_resolution_clock::now();
|
||||
|
||||
while (CheckCurrentState(RUNNING))
|
||||
{
|
||||
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
|
||||
|
||||
if (dataInChannel.Receive(msg) >= 0)
|
||||
{
|
||||
if (fNumMsgs > 0)
|
||||
{
|
||||
if (numReceivedMsgs >= fNumMsgs)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
numReceivedMsgs++;
|
||||
}
|
||||
}
|
||||
|
||||
auto tEnd = chrono::high_resolution_clock::now();
|
||||
|
||||
LOG(info) << "Leaving RUNNING state. Received " << numReceivedMsgs << " messages in " << chrono::duration<double, milli>(tEnd - tStart).count() << "ms.";
|
||||
}
|
||||
|
||||
FairMQSink::~FairMQSink()
|
||||
{
|
||||
}
|
@@ -56,7 +56,7 @@ class FairMQSink : public FairMQDevice//, public OutputPolicy
|
||||
|
||||
while (CheckCurrentState(RUNNING))
|
||||
{
|
||||
FairMQMessagePtr msg(dataInChannel.Transport()->CreateMessage());
|
||||
FairMQMessagePtr msg(dataInChannel.NewMessage());
|
||||
|
||||
if (dataInChannel.Receive(msg) >= 0)
|
||||
{
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
FairMQ::Transport FairMQMessageNN::fTransportType = FairMQ::Transport::NN;
|
||||
fair::mq::Transport FairMQMessageNN::fTransportType = fair::mq::Transport::NN;
|
||||
|
||||
FairMQMessageNN::FairMQMessageNN()
|
||||
: fMessage(nullptr)
|
||||
@@ -172,7 +172,7 @@ void FairMQMessageNN::SetMessage(void* data, const size_t size)
|
||||
fSize = size;
|
||||
}
|
||||
|
||||
FairMQ::Transport FairMQMessageNN::GetType() const
|
||||
fair::mq::Transport FairMQMessageNN::GetType() const
|
||||
{
|
||||
return fTransportType;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ class FairMQMessageNN : public FairMQMessage
|
||||
|
||||
bool SetUsedSize(const size_t size) override;
|
||||
|
||||
FairMQ::Transport GetType() const override;
|
||||
fair::mq::Transport GetType() const override;
|
||||
|
||||
void Copy(const FairMQMessage& msg) override;
|
||||
void Copy(const FairMQMessagePtr& msg) override;
|
||||
@@ -59,7 +59,7 @@ class FairMQMessageNN : public FairMQMessage
|
||||
size_t fHint;
|
||||
bool fReceiving;
|
||||
FairMQUnmanagedRegion* fRegionPtr;
|
||||
static FairMQ::Transport fTransportType;
|
||||
static fair::mq::Transport fTransportType;
|
||||
|
||||
void* GetMessage() const;
|
||||
void CloseMessage();
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
FairMQ::Transport FairMQTransportFactoryNN::fTransportType = FairMQ::Transport::NN;
|
||||
fair::mq::Transport FairMQTransportFactoryNN::fTransportType = fair::mq::Transport::NN;
|
||||
|
||||
FairMQTransportFactoryNN::FairMQTransportFactoryNN(const string& id, const FairMQProgOptions* /*config*/)
|
||||
: FairMQTransportFactory(id)
|
||||
@@ -70,7 +70,7 @@ FairMQUnmanagedRegionPtr FairMQTransportFactoryNN::CreateUnmanagedRegion(const s
|
||||
return unique_ptr<FairMQUnmanagedRegion>(new FairMQUnmanagedRegionNN(size, callback));
|
||||
}
|
||||
|
||||
FairMQ::Transport FairMQTransportFactoryNN::GetType() const
|
||||
fair::mq::Transport FairMQTransportFactoryNN::GetType() const
|
||||
{
|
||||
return fTransportType;
|
||||
}
|
||||
|
@@ -39,13 +39,13 @@ class FairMQTransportFactoryNN : public FairMQTransportFactory
|
||||
|
||||
FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback) const override;
|
||||
|
||||
FairMQ::Transport GetType() const override;
|
||||
fair::mq::Transport GetType() const override;
|
||||
|
||||
void Interrupt() override { FairMQSocketNN::Interrupt(); }
|
||||
void Resume() override { FairMQSocketNN::Resume(); }
|
||||
|
||||
private:
|
||||
static FairMQ::Transport fTransportType;
|
||||
static fair::mq::Transport fTransportType;
|
||||
};
|
||||
|
||||
#endif /* FAIRMQTRANSPORTFACTORYNN_H_ */
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <fairmq/Tools.h>
|
||||
#include <FairMQLogger.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <zmq.h>
|
||||
|
||||
@@ -53,7 +54,7 @@ Message::Message(void* data, const size_t size, fairmq_free_fn* ffn, void* hint)
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(FairMQUnmanagedRegionPtr& region, void* data, const size_t size, void* hint)
|
||||
Message::Message(FairMQUnmanagedRegionPtr& /*region*/, void* /*data*/, const size_t /*size*/, void* /*hint*/)
|
||||
{
|
||||
throw MessageError{"Not yet implemented."};
|
||||
}
|
||||
@@ -91,7 +92,7 @@ auto Message::Rebuild(const size_t size) -> void
|
||||
fHint = nullptr;
|
||||
}
|
||||
|
||||
auto Message::Rebuild(void* data, const size_t size, fairmq_free_fn* ffn, void* hint) -> void
|
||||
auto Message::Rebuild(void* /*data*/, const size_t size, fairmq_free_fn* ffn, void* hint) -> void
|
||||
{
|
||||
if (fFreeFunction) {
|
||||
fFreeFunction(fData, fHint);
|
||||
@@ -132,12 +133,12 @@ auto Message::SetUsedSize(const size_t size) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
auto Message::Copy(const fair::mq::Message& msg) -> void
|
||||
auto Message::Copy(const fair::mq::Message& /*msg*/) -> void
|
||||
{
|
||||
throw MessageError{"Not yet implemented."};
|
||||
}
|
||||
|
||||
auto Message::Copy(const fair::mq::MessagePtr& msg) -> void
|
||||
auto Message::Copy(const fair::mq::MessagePtr& /*msg*/) -> void
|
||||
{
|
||||
throw MessageError{"Not yet implemented."};
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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, *
|
||||
@@ -14,7 +14,10 @@
|
||||
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQLogger.h"
|
||||
#include <fairmq/Tools.h>
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -26,11 +29,16 @@ namespace parser
|
||||
{
|
||||
|
||||
// TODO : add key-value map<string,string> parameter for replacing/updating values from keys
|
||||
// function that convert property tree (given the json structure) to FairMQMap
|
||||
FairMQMap ptreeToMQMap(const boost::property_tree::ptree& pt, const string& id, const string& rootNode)
|
||||
// function that convert property tree (given the json structure) to FairMQChannelMap
|
||||
FairMQChannelMap ptreeToMQMap(const boost::property_tree::ptree& pt, const string& id, const string& rootNode)
|
||||
{
|
||||
if (id == "")
|
||||
{
|
||||
throw ParserError("no device ID provided. Provide with `--id` cmd option");
|
||||
}
|
||||
|
||||
// Create fair mq map
|
||||
FairMQMap channelMap;
|
||||
FairMQChannelMap channelMap;
|
||||
// boost::property_tree::json_parser::write_json(std::cout, pt);
|
||||
// Helper::PrintDeviceList(pt.get_child(rootNode));
|
||||
// Extract value from boost::property_tree
|
||||
@@ -45,20 +53,13 @@ FairMQMap ptreeToMQMap(const boost::property_tree::ptree& pt, const string& id,
|
||||
return channelMap;
|
||||
}
|
||||
|
||||
FairMQMap JSON::UserParser(const string& filename, const string& deviceId, const string& rootNode)
|
||||
FairMQChannelMap JSON::UserParser(const string& filename, const string& deviceId, const string& rootNode)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_json(filename, pt);
|
||||
return ptreeToMQMap(pt, deviceId, rootNode);
|
||||
}
|
||||
|
||||
FairMQMap JSON::UserParser(stringstream& input, const string& deviceId, const string& rootNode)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_json(input, pt);
|
||||
return ptreeToMQMap(pt, deviceId, rootNode);
|
||||
}
|
||||
|
||||
namespace Helper
|
||||
{
|
||||
|
||||
@@ -89,7 +90,7 @@ void PrintDeviceList(const boost::property_tree::ptree& tree)
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const string& deviceId)
|
||||
void DeviceParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap, const string& deviceId)
|
||||
{
|
||||
string deviceIdKey;
|
||||
|
||||
@@ -128,7 +129,7 @@ void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap)
|
||||
void ChannelParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap)
|
||||
{
|
||||
string channelKey;
|
||||
|
||||
@@ -147,7 +148,7 @@ void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMa
|
||||
commonChannel.UpdateType(q.second.get<string>("type", commonChannel.GetType()));
|
||||
commonChannel.UpdateMethod(q.second.get<string>("method", commonChannel.GetMethod()));
|
||||
commonChannel.UpdateAddress(q.second.get<string>("address", commonChannel.GetAddress()));
|
||||
commonChannel.UpdateTransport(q.second.get<string>("transport", commonChannel.GetTransport()));
|
||||
commonChannel.UpdateTransport(q.second.get<string>("transport", commonChannel.GetTransportName()));
|
||||
commonChannel.UpdateSndBufSize(q.second.get<int>("sndBufSize", commonChannel.GetSndBufSize()));
|
||||
commonChannel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", commonChannel.GetRcvBufSize()));
|
||||
commonChannel.UpdateSndKernelSize(q.second.get<int>("sndKernelSize", commonChannel.GetSndKernelSize()));
|
||||
@@ -166,7 +167,7 @@ void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMa
|
||||
LOG(debug) << "\ttype = " << commonChannel.GetType();
|
||||
LOG(debug) << "\tmethod = " << commonChannel.GetMethod();
|
||||
LOG(debug) << "\taddress = " << commonChannel.GetAddress();
|
||||
LOG(debug) << "\ttransport = " << commonChannel.GetTransport();
|
||||
LOG(debug) << "\ttransport = " << commonChannel.GetTransportName();
|
||||
LOG(debug) << "\tsndBufSize = " << commonChannel.GetSndBufSize();
|
||||
LOG(debug) << "\trcvBufSize = " << commonChannel.GetRcvBufSize();
|
||||
LOG(debug) << "\tsndKernelSize = " << commonChannel.GetSndKernelSize();
|
||||
@@ -208,7 +209,7 @@ void SocketParser(const boost::property_tree::ptree& tree, vector<FairMQChannel>
|
||||
channel.UpdateType(q.second.get<string>("type", channel.GetType()));
|
||||
channel.UpdateMethod(q.second.get<string>("method", channel.GetMethod()));
|
||||
channel.UpdateAddress(q.second.get<string>("address", channel.GetAddress()));
|
||||
channel.UpdateTransport(q.second.get<string>("transport", channel.GetTransport()));
|
||||
channel.UpdateTransport(q.second.get<string>("transport", channel.GetTransportName()));
|
||||
channel.UpdateSndBufSize(q.second.get<int>("sndBufSize", channel.GetSndBufSize()));
|
||||
channel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", channel.GetRcvBufSize()));
|
||||
channel.UpdateSndKernelSize(q.second.get<int>("sndKernelSize", channel.GetSndKernelSize()));
|
||||
@@ -219,7 +220,7 @@ void SocketParser(const boost::property_tree::ptree& tree, vector<FairMQChannel>
|
||||
LOG(debug) << "\ttype = " << channel.GetType();
|
||||
LOG(debug) << "\tmethod = " << channel.GetMethod();
|
||||
LOG(debug) << "\taddress = " << channel.GetAddress();
|
||||
LOG(debug) << "\ttransport = " << channel.GetTransport();
|
||||
LOG(debug) << "\ttransport = " << channel.GetTransportName();
|
||||
LOG(debug) << "\tsndBufSize = " << channel.GetSndBufSize();
|
||||
LOG(debug) << "\trcvBufSize = " << channel.GetRcvBufSize();
|
||||
LOG(debug) << "\tsndKernelSize = " << channel.GetSndKernelSize();
|
||||
@@ -247,7 +248,7 @@ void SocketParser(const boost::property_tree::ptree& tree, vector<FairMQChannel>
|
||||
LOG(debug) << "\ttype = " << channel.GetType();
|
||||
LOG(debug) << "\tmethod = " << channel.GetMethod();
|
||||
LOG(debug) << "\taddress = " << channel.GetAddress();
|
||||
LOG(debug) << "\ttransport = " << channel.GetTransport();
|
||||
LOG(debug) << "\ttransport = " << channel.GetTransportName();
|
||||
LOG(debug) << "\tsndBufSize = " << channel.GetSndBufSize();
|
||||
LOG(debug) << "\trcvBufSize = " << channel.GetRcvBufSize();
|
||||
LOG(debug) << "\tsndKernelSize = " << channel.GetSndKernelSize();
|
||||
|
@@ -10,10 +10,10 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
|
||||
#include "FairMQChannel.h"
|
||||
|
||||
@@ -24,22 +24,23 @@ namespace mq
|
||||
namespace parser
|
||||
{
|
||||
|
||||
using FairMQMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
|
||||
using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
|
||||
|
||||
FairMQMap ptreeToMQMap(const boost::property_tree::ptree& pt, const std::string& deviceId, const std::string& rootNode);
|
||||
struct ParserError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
FairMQChannelMap ptreeToMQMap(const boost::property_tree::ptree& pt, const std::string& deviceId, const std::string& rootNode);
|
||||
|
||||
struct JSON
|
||||
{
|
||||
FairMQMap UserParser(const std::string& filename, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||
FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||
FairMQChannelMap UserParser(const std::string& filename, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||
};
|
||||
|
||||
namespace Helper
|
||||
{
|
||||
|
||||
void PrintDeviceList(const boost::property_tree::ptree& tree);
|
||||
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const std::string& deviceId);
|
||||
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap);
|
||||
void DeviceParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap, const std::string& deviceId);
|
||||
void ChannelParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap);
|
||||
void SocketParser(const boost::property_tree::ptree& tree, std::vector<FairMQChannel>& channelList, const std::string& channelName, const FairMQChannel& commonChannel);
|
||||
|
||||
} // Helper namespace
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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, *
|
||||
@@ -12,25 +12,73 @@
|
||||
* Created on March 11, 2015, 10:20 PM
|
||||
*/
|
||||
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQProgOptions.h"
|
||||
#include "FairProgOptionsHelper.h"
|
||||
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQSuboptParser.h"
|
||||
#include "FairMQLogger.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp> // join/split
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
FairMQProgOptions::FairMQProgOptions()
|
||||
: FairProgOptions()
|
||||
, fMQCmdOptions("FairMQ device options")
|
||||
, fMQParserOptions("FairMQ config parser options")
|
||||
, fFairMQMap()
|
||||
: fVarMap()
|
||||
, fFairMQChannelMap()
|
||||
, fAllOptions("FairMQ Command Line Options")
|
||||
, fGeneralOptions("General options")
|
||||
, fMQOptions("FairMQ device options")
|
||||
, fParserOptions("FairMQ channel config parser options")
|
||||
, fConfigMutex()
|
||||
, fChannelInfo()
|
||||
, fMQKeyMap()
|
||||
, fChannelKeyMap()
|
||||
, fUnregisteredOptions()
|
||||
, fEvents()
|
||||
{
|
||||
InitOptionDescription();
|
||||
fGeneralOptions.add_options()
|
||||
("help,h", "Print help")
|
||||
("version,v", "Print version")
|
||||
("severity", po::value<string>()->default_value("debug"), "Log severity level: 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>)");
|
||||
|
||||
fMQOptions.add_options()
|
||||
("id", po::value<string>(), "Device ID (required argument).")
|
||||
("io-threads", po::value<int >()->default_value(1), "Number of I/O threads.")
|
||||
("transport", po::value<string>()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg'/'shmem') .")
|
||||
("network-interface", po::value<string>()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).")
|
||||
("config-key", po::value<string>(), "Use provided value instead of device id for fetching the configuration from the config file.")
|
||||
("initialization-timeout", po::value<int >()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).")
|
||||
("port-range-min", po::value<int >()->default_value(22000), "Start of the port range for dynamic initialization.")
|
||||
("port-range-max", po::value<int >()->default_value(32000), "End of the port range for dynamic initialization.")
|
||||
("print-channels", po::value<bool >()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (<channel name>:<min num subchannels>:<max num subchannels>)")
|
||||
("shm-segment-size", po::value<size_t>()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).")
|
||||
("shm-monitor", po::value<bool >()->default_value(true), "Shared memory: run monitor daemon.")
|
||||
("rate", po::value<float >()->default_value(0.), "Rate for conditional run loop (Hz).")
|
||||
("session", po::value<string>()->default_value("default"), "Session name.");
|
||||
|
||||
fParserOptions.add_options()
|
||||
("mq-config", po::value<string>(), "JSON input as file.")
|
||||
("channel-config", po::value<vector<string>>()->multitoken()->composing(), "Configuration of single or multiple channel(s) by comma separated key=value list");
|
||||
|
||||
fAllOptions.add(fGeneralOptions);
|
||||
fAllOptions.add(fMQOptions);
|
||||
fAllOptions.add(fParserOptions);
|
||||
|
||||
ParseDefaults();
|
||||
}
|
||||
|
||||
@@ -52,12 +100,20 @@ int FairMQProgOptions::ParseAll(const vector<string>& cmdLineArgs, bool allowUnr
|
||||
|
||||
int FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool allowUnregistered)
|
||||
{
|
||||
if (FairProgOptions::ParseCmdLine(argc, argv, allowUnregistered))
|
||||
ParseCmdLine(argc, argv, allowUnregistered);
|
||||
|
||||
// if this option is provided, handle them and return stop value
|
||||
if (fVarMap.count("help"))
|
||||
{
|
||||
// ParseCmdLine returns 0 if no immediate switches found.
|
||||
cout << fAllOptions << endl;
|
||||
return 1;
|
||||
}
|
||||
// if this option is provided, handle them and return stop value
|
||||
if (fVarMap.count("print-options"))
|
||||
{
|
||||
PrintOptionsRaw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if these options are provided, do no further checks and let the device handle them
|
||||
if (fVarMap.count("print-channels") || fVarMap.count("version"))
|
||||
{
|
||||
@@ -83,16 +139,16 @@ int FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool al
|
||||
fair::Logger::SetConsoleSeverity(severity);
|
||||
}
|
||||
|
||||
string id;
|
||||
string idForParser;
|
||||
|
||||
// check if config-key for config parser is provided
|
||||
if (fVarMap.count("config-key"))
|
||||
{
|
||||
id = fVarMap["config-key"].as<string>();
|
||||
idForParser = fVarMap["config-key"].as<string>();
|
||||
}
|
||||
else
|
||||
else if (fVarMap.count("id"))
|
||||
{
|
||||
id = fVarMap["id"].as<string>();
|
||||
idForParser = fVarMap["id"].as<string>();
|
||||
}
|
||||
|
||||
// check if any config parser is selected
|
||||
@@ -101,54 +157,85 @@ int FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool al
|
||||
if (fVarMap.count("mq-config"))
|
||||
{
|
||||
LOG(debug) << "mq-config: Using default JSON parser";
|
||||
Store(fair::mq::parser::JSON().UserParser(fVarMap["mq-config"].as<string>(), id));
|
||||
}
|
||||
else if (fVarMap.count("config-json-string"))
|
||||
{
|
||||
LOG(debug) << "config-json-string: Parsing JSON string";
|
||||
string value = fair::mq::ConvertVariableValue<fair::mq::VarInfoToString>()(fVarMap.at("config-json-string"));
|
||||
stringstream ss;
|
||||
ss << value;
|
||||
Store(fair::mq::parser::JSON().UserParser(ss, id));
|
||||
UpdateChannelMap(parser::JSON().UserParser(fVarMap.at("mq-config").as<string>(), idForParser));
|
||||
}
|
||||
else if (fVarMap.count("channel-config"))
|
||||
{
|
||||
LOG(debug) << "channel-config: Parsing channel configuration";
|
||||
Store(fair::mq::parser::SUBOPT().UserParser(fVarMap.at("channel-config").as<vector<string>>(), id));
|
||||
UpdateChannelMap(parser::SUBOPT().UserParser(fVarMap.at("channel-config").as<vector<string>>(), idForParser));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(warn) << "FairMQProgOptions: no channels configuration provided via neither of:";
|
||||
for (const auto& p : fMQParserOptions.options())
|
||||
for (const auto& p : fParserOptions.options())
|
||||
{
|
||||
LOG(warn) << "--" << p->canonical_display_name();
|
||||
}
|
||||
LOG(warn) << "No channels will be created (You can create them manually).";
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << e.what();
|
||||
return 1;
|
||||
}
|
||||
|
||||
FairProgOptions::PrintOptions();
|
||||
PrintOptions();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FairMQProgOptions::Store(const FairMQMap& channels)
|
||||
void FairMQProgOptions::ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered)
|
||||
{
|
||||
fFairMQMap = channels;
|
||||
UpdateChannelInfo();
|
||||
UpdateMQValues();
|
||||
return 0;
|
||||
fVarMap.clear();
|
||||
|
||||
// get options from cmd line and store in variable map
|
||||
// here we use command_line_parser instead of parse_command_line, to allow unregistered and positional options
|
||||
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);
|
||||
}
|
||||
|
||||
po::notify(fVarMap);
|
||||
}
|
||||
|
||||
void FairMQProgOptions::ParseDefaults()
|
||||
{
|
||||
vector<string> emptyArgs = {"dummy", "--id", boost::uuids::to_string(boost::uuids::random_generator()())};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
unordered_map<string, vector<FairMQChannel>> FairMQProgOptions::GetFairMQMap() const
|
||||
{
|
||||
return fFairMQChannelMap;
|
||||
}
|
||||
|
||||
unordered_map<string, int> FairMQProgOptions::GetChannelInfo() const
|
||||
{
|
||||
return fChannelInfo;
|
||||
}
|
||||
|
||||
// replace FairMQChannelMap, and update variable map accordingly
|
||||
int FairMQProgOptions::UpdateChannelMap(const FairMQMap& channels)
|
||||
int FairMQProgOptions::UpdateChannelMap(const unordered_map<string, vector<FairMQChannel>>& channels)
|
||||
{
|
||||
fFairMQMap = channels;
|
||||
fFairMQChannelMap = channels;
|
||||
UpdateChannelInfo();
|
||||
UpdateMQValues();
|
||||
return 0;
|
||||
@@ -157,7 +244,7 @@ int FairMQProgOptions::UpdateChannelMap(const FairMQMap& channels)
|
||||
void FairMQProgOptions::UpdateChannelInfo()
|
||||
{
|
||||
fChannelInfo.clear();
|
||||
for (const auto& c : fFairMQMap)
|
||||
for (const auto& c : fFairMQChannelMap)
|
||||
{
|
||||
fChannelInfo.insert(make_pair(c.first, c.second.size()));
|
||||
}
|
||||
@@ -167,7 +254,7 @@ void FairMQProgOptions::UpdateChannelInfo()
|
||||
// create key for variable map as follow : channelName.index.memberName
|
||||
void FairMQProgOptions::UpdateMQValues()
|
||||
{
|
||||
for (const auto& p : fFairMQMap)
|
||||
for (const auto& p : fFairMQChannelMap)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
@@ -183,20 +270,20 @@ void FairMQProgOptions::UpdateMQValues()
|
||||
string rcvKernelSizeKey = "chans." + p.first + "." + to_string(index) + ".rcvKernelSize";
|
||||
string rateLoggingKey = "chans." + p.first + "." + to_string(index) + ".rateLogging";
|
||||
|
||||
fMQKeyMap[typeKey] = MQKey{p.first, index, "type"};
|
||||
fMQKeyMap[methodKey] = MQKey{p.first, index, "method"};
|
||||
fMQKeyMap[addressKey] = MQKey{p.first, index, "address"};
|
||||
fMQKeyMap[transportKey] = MQKey{p.first, index, "transport"};
|
||||
fMQKeyMap[sndBufSizeKey] = MQKey{p.first, index, "sndBufSize"};
|
||||
fMQKeyMap[rcvBufSizeKey] = MQKey{p.first, index, "rcvBufSize"};
|
||||
fMQKeyMap[sndKernelSizeKey] = MQKey{p.first, index, "sndKernelSize"};
|
||||
fMQKeyMap[rcvKernelSizeKey] = MQKey{p.first, index, "rcvkernelSize"};
|
||||
fMQKeyMap[rateLoggingKey] = MQKey{p.first, index, "rateLogging"};
|
||||
fChannelKeyMap[typeKey] = ChannelKey{p.first, index, "type"};
|
||||
fChannelKeyMap[methodKey] = ChannelKey{p.first, index, "method"};
|
||||
fChannelKeyMap[addressKey] = ChannelKey{p.first, index, "address"};
|
||||
fChannelKeyMap[transportKey] = ChannelKey{p.first, index, "transport"};
|
||||
fChannelKeyMap[sndBufSizeKey] = ChannelKey{p.first, index, "sndBufSize"};
|
||||
fChannelKeyMap[rcvBufSizeKey] = ChannelKey{p.first, index, "rcvBufSize"};
|
||||
fChannelKeyMap[sndKernelSizeKey] = ChannelKey{p.first, index, "sndKernelSize"};
|
||||
fChannelKeyMap[rcvKernelSizeKey] = ChannelKey{p.first, index, "rcvkernelSize"};
|
||||
fChannelKeyMap[rateLoggingKey] = ChannelKey{p.first, index, "rateLogging"};
|
||||
|
||||
UpdateVarMap<string>(typeKey, channel.GetType());
|
||||
UpdateVarMap<string>(methodKey, channel.GetMethod());
|
||||
UpdateVarMap<string>(addressKey, channel.GetAddress());
|
||||
UpdateVarMap<string>(transportKey, channel.GetTransport());
|
||||
UpdateVarMap<string>(transportKey, channel.GetTransportName());
|
||||
UpdateVarMap<int>(sndBufSizeKey, channel.GetSndBufSize());
|
||||
UpdateVarMap<int>(rcvBufSizeKey, channel.GetRcvBufSize());
|
||||
UpdateVarMap<int>(sndKernelSizeKey, channel.GetSndKernelSize());
|
||||
@@ -209,103 +296,56 @@ void FairMQProgOptions::UpdateMQValues()
|
||||
}
|
||||
}
|
||||
|
||||
int FairMQProgOptions::ImmediateOptions()
|
||||
{
|
||||
if (fVarMap.count("help"))
|
||||
{
|
||||
cout << "===== FairMQ Program Options =====" << endl << fAllOptions;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fVarMap.count("print-options"))
|
||||
{
|
||||
PrintOptionsRaw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FairMQProgOptions::InitOptionDescription()
|
||||
{
|
||||
fMQCmdOptions.add_options()
|
||||
("id", po::value<string>(), "Device ID (required argument).")
|
||||
("io-threads", po::value<int >()->default_value(1), "Number of I/O threads.")
|
||||
("transport", po::value<string>()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').")
|
||||
("config", po::value<string>()->default_value("static"), "Config source ('static'/<config library filename>).")
|
||||
("network-interface", po::value<string>()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).")
|
||||
("config-key", po::value<string>(), "Use provided value instead of device id for fetching the configuration from the config file.")
|
||||
("initialization-timeout", po::value<int >()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).")
|
||||
("port-range-min", po::value<int >()->default_value(22000), "Start of the port range for dynamic initialization.")
|
||||
("port-range-max", po::value<int >()->default_value(32000), "End of the port range for dynamic initialization.")
|
||||
("print-channels", po::value<bool >()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (<channel name>:<min num subchannels>:<max num subchannels>)")
|
||||
("shm-segment-size", po::value<size_t>()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).")
|
||||
("shm-monitor", po::value<bool >()->default_value(true), "Shared memory: run monitor daemon.")
|
||||
("rate", po::value<float >()->default_value(0.), "Rate for conditional run loop (Hz).")
|
||||
("session", po::value<string>()->default_value("default"), "Session name.")
|
||||
;
|
||||
|
||||
fMQParserOptions.add_options()
|
||||
("config-json-string", po::value<vector<string>>()->multitoken(), "JSON input as command line string.")
|
||||
("mq-config", po::value<string>(), "JSON/XML input as file. The configuration object will check xml or json file extention and will call the json or xml parser accordingly")
|
||||
("channel-config", po::value<vector<string>>()->multitoken()->composing(), "Configuration of single or multiple channel(s) by comma separated key=value list")
|
||||
;
|
||||
|
||||
AddToCmdLineOptions(fMQCmdOptions);
|
||||
AddToCmdLineOptions(fMQParserOptions);
|
||||
}
|
||||
|
||||
int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, const string& member, const string& val)
|
||||
int FairMQProgOptions::UpdateChannelValue(const string& channelName, int index, const string& member, const string& val)
|
||||
{
|
||||
if (member == "type")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateType(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateType(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (member == "method")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateMethod(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateMethod(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (member == "address")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateAddress(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateAddress(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (member == "transport")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateTransport(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateTransport(val);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if we get there it means something is wrong
|
||||
LOG(error) << "update of FairMQChannel map failed for the following key: "
|
||||
<< channelName << "." << index << "." << member;
|
||||
LOG(error) << "update of FairMQChannel map failed for the following key: " << channelName << "." << index << "." << member;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, const string& member, int val)
|
||||
int FairMQProgOptions::UpdateChannelValue(const string& channelName, int index, const string& member, int val)
|
||||
{
|
||||
if (member == "sndBufSize")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateSndBufSize(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateSndBufSize(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (member == "rcvBufSize")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateRcvBufSize(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateRcvBufSize(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (member == "rateLogging")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateRateLogging(val);
|
||||
fFairMQChannelMap.at(channelName).at(index).UpdateRateLogging(val);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -315,3 +355,135 @@ int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, co
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> FairMQProgOptions::GetPropertyKeys() const
|
||||
{
|
||||
lock_guard<mutex> lock{fConfigMutex};
|
||||
|
||||
vector<string> result;
|
||||
|
||||
for (const auto& it : fVarMap)
|
||||
{
|
||||
result.push_back(it.first.c_str());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Add option descriptions
|
||||
int FairMQProgOptions::AddToCmdLineOptions(const po::options_description optDesc, bool /* visible */)
|
||||
{
|
||||
fAllOptions.add(optDesc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
po::options_description& FairMQProgOptions::GetCmdLineOptions()
|
||||
{
|
||||
return fAllOptions;
|
||||
}
|
||||
|
||||
int FairMQProgOptions::PrintOptions()
|
||||
{
|
||||
// -> loop over variable map and print its content
|
||||
// -> In this example the following types are supported:
|
||||
// string, int, float, double, short, boost::filesystem::path
|
||||
// vector<string>, vector<int>, vector<float>, vector<double>, vector<short>
|
||||
|
||||
map<string, VarValInfo> mapinfo;
|
||||
|
||||
// get string length for formatting and convert varmap values into string
|
||||
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()));
|
||||
|
||||
VarValInfo valinfo = ConvertVariableValue<options::ToVarValInfo>()((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.defaulted.length()));
|
||||
}
|
||||
|
||||
// TODO : limit the value len field in a better way
|
||||
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)
|
||||
{
|
||||
ss << setfill(' ') << left
|
||||
<< setw(maxLenKey) << p.first << " = "
|
||||
<< setw(maxLenValue) << p.second.value << " "
|
||||
<< setw(maxLenType) << p.second.type
|
||||
<< setw(maxLenDefault) << p.second.defaulted
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
LOG(info) << ss.str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FairMQProgOptions::PrintOptionsRaw()
|
||||
{
|
||||
const vector<boost::shared_ptr<po::option_description>>& options = fAllOptions.options();
|
||||
|
||||
for (const auto& o : options)
|
||||
{
|
||||
VarValInfo value;
|
||||
if (fVarMap.count(o->canonical_display_name()))
|
||||
{
|
||||
value = ConvertVariableValue<options::ToVarValInfo>()((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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
string FairMQProgOptions::GetStringValue(const string& key)
|
||||
{
|
||||
unique_lock<mutex> lock(fConfigMutex);
|
||||
|
||||
string valueStr;
|
||||
try
|
||||
{
|
||||
if (fVarMap.count(key))
|
||||
{
|
||||
valueStr = ConvertVariableValue<options::ToString>()(fVarMap.at(key));
|
||||
}
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Exception thrown for the key '" << key << "'";
|
||||
LOG(error) << e.what();
|
||||
}
|
||||
|
||||
return valueStr;
|
||||
}
|
||||
|
||||
int FairMQProgOptions::Count(const string& key) const
|
||||
{
|
||||
unique_lock<mutex> lock(fConfigMutex);
|
||||
|
||||
return fVarMap.count(key);
|
||||
}
|
||||
|
@@ -1,31 +1,27 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* 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: FairMQProgOptions.h
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on March 11, 2015, 10:20 PM
|
||||
*/
|
||||
|
||||
#ifndef FAIRMQPROGOPTIONS_H
|
||||
#define FAIRMQPROGOPTIONS_H
|
||||
|
||||
#include <fairmq/EventManager.h>
|
||||
|
||||
#include "FairProgOptions.h"
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQChannel.h"
|
||||
#include <fairmq/Tools.h>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
|
||||
namespace fair
|
||||
{
|
||||
@@ -38,10 +34,10 @@ struct PropertyChangeAsString : Event<std::string> {};
|
||||
} /* namespace mq */
|
||||
} /* namespace fair */
|
||||
|
||||
class FairMQProgOptions : public FairProgOptions
|
||||
class FairMQProgOptions
|
||||
{
|
||||
protected:
|
||||
using FairMQMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
|
||||
private:
|
||||
using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
|
||||
|
||||
public:
|
||||
FairMQProgOptions();
|
||||
@@ -49,52 +45,11 @@ class FairMQProgOptions : public FairProgOptions
|
||||
|
||||
int ParseAll(const std::vector<std::string>& cmdLineArgs, bool allowUnregistered);
|
||||
// parse command line.
|
||||
// default parser for the mq-configuration file (JSON/XML) is called if command line key mq-config is called
|
||||
int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) override;
|
||||
// default parser for the mq-configuration file (JSON) is called if command line key mq-config is called
|
||||
int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = true);
|
||||
|
||||
FairMQMap GetFairMQMap() const
|
||||
{
|
||||
return fFairMQMap;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, int> GetChannelInfo() const
|
||||
{
|
||||
return fChannelInfo;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int UpdateValue(const std::string& key, T val)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fConfigMutex);
|
||||
|
||||
if (fVarMap.count(key))
|
||||
{
|
||||
// update variable map
|
||||
UpdateVarMap<typename std::decay<T>::type>(key, val);
|
||||
|
||||
// update FairMQChannel map, check first if data are int or string
|
||||
if (std::is_same<T, int>::value || std::is_same<T, std::string>::value)
|
||||
{
|
||||
if (fMQKeyMap.count(key))
|
||||
{
|
||||
UpdateChannelMap(fMQKeyMap.at(key).channel, fMQKeyMap.at(key).index, fMQKeyMap.at(key).member, val);
|
||||
}
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
//if (std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
|
||||
fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);
|
||||
fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetStringValue(key));
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(error) << "UpdateValue failed: key '" << key << "' not found in the variable map";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
FairMQChannelMap GetFairMQMap() const;
|
||||
std::unordered_map<std::string, int> GetChannelInfo() const;
|
||||
|
||||
template<typename T>
|
||||
int SetValue(const std::string& key, T val)
|
||||
@@ -104,12 +59,12 @@ class FairMQProgOptions : public FairProgOptions
|
||||
// update variable map
|
||||
UpdateVarMap<typename std::decay<T>::type>(key, val);
|
||||
|
||||
// update FairMQChannel map, check first if data are int or string
|
||||
// update FairMQChannel map if the key is a channel key
|
||||
if (std::is_same<T, int>::value || std::is_same<T, std::string>::value)
|
||||
{
|
||||
if (fMQKeyMap.count(key))
|
||||
if (fChannelKeyMap.count(key))
|
||||
{
|
||||
UpdateChannelMap(fMQKeyMap.at(key).channel, fMQKeyMap.at(key).index, fMQKeyMap.at(key).member, val);
|
||||
UpdateChannelValue(fChannelKeyMap.at(key).channel, fChannelKeyMap.at(key).index, fChannelKeyMap.at(key).member, val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,57 +110,119 @@ class FairMQProgOptions : public FairProgOptions
|
||||
fEvents.Unsubscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber);
|
||||
}
|
||||
|
||||
// replace FairMQChannelMap, and update variable map accordingly
|
||||
int UpdateChannelMap(const FairMQMap& map);
|
||||
std::vector<std::string> GetPropertyKeys() const;
|
||||
|
||||
protected:
|
||||
struct MQKey
|
||||
// get value corresponding to the key
|
||||
template<typename T>
|
||||
T GetValue(const std::string& key) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fConfigMutex);
|
||||
|
||||
T val = T();
|
||||
|
||||
if (fVarMap.count(key))
|
||||
{
|
||||
val = fVarMap[key].as<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// Given a key, convert the variable value to string
|
||||
std::string GetStringValue(const std::string& key);
|
||||
|
||||
int Count(const std::string& key) const;
|
||||
|
||||
template<typename T>
|
||||
T ConvertTo(const std::string& strValue)
|
||||
{
|
||||
if (std::is_arithmetic<T>::value)
|
||||
{
|
||||
std::istringstream iss(strValue);
|
||||
T val;
|
||||
iss >> val;
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(error) << "the provided string " << strValue << " cannot be converted to the requested type. The target type must be arithmetic type.";
|
||||
}
|
||||
}
|
||||
|
||||
// add options_description
|
||||
int AddToCmdLineOptions(const boost::program_options::options_description optDesc, bool visible = true);
|
||||
boost::program_options::options_description& GetCmdLineOptions();
|
||||
|
||||
const boost::program_options::variables_map& GetVarMap() const { return fVarMap; }
|
||||
|
||||
int PrintOptions();
|
||||
int PrintOptionsRaw();
|
||||
|
||||
void AddChannel(const std::string& channelName, const FairMQChannel& channel)
|
||||
{
|
||||
fFairMQChannelMap[channelName].push_back(channel);
|
||||
}
|
||||
|
||||
private:
|
||||
struct ChannelKey
|
||||
{
|
||||
std::string channel;
|
||||
int index;
|
||||
std::string member;
|
||||
};
|
||||
|
||||
po::options_description fMQCmdOptions;
|
||||
po::options_description fMQParserOptions;
|
||||
FairMQMap fFairMQMap;
|
||||
boost::program_options::variables_map fVarMap; ///< options container
|
||||
FairMQChannelMap fFairMQChannelMap;
|
||||
|
||||
// map of read channel info - channel name - number of subchannels
|
||||
std::unordered_map<std::string, int> fChannelInfo;
|
||||
boost::program_options::options_description fAllOptions; ///< all options descriptions
|
||||
boost::program_options::options_description fGeneralOptions; ///< general options descriptions
|
||||
boost::program_options::options_description fMQOptions; ///< MQ options descriptions
|
||||
boost::program_options::options_description fParserOptions; ///< MQ Parser options descriptions
|
||||
|
||||
std::map<std::string, MQKey> fMQKeyMap;// key=full path - val=key info
|
||||
mutable std::mutex fConfigMutex;
|
||||
|
||||
int ImmediateOptions() override; // for custom help & version printing
|
||||
void InitOptionDescription();
|
||||
std::unordered_map<std::string, int> fChannelInfo; ///< channel name - number of subchannels
|
||||
std::unordered_map<std::string, ChannelKey> fChannelKeyMap;// key=full path - val=key info
|
||||
std::vector<std::string> fUnregisteredOptions; ///< container with unregistered options
|
||||
|
||||
fair::mq::EventManager fEvents;
|
||||
|
||||
void ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered = true);
|
||||
void ParseDefaults();
|
||||
|
||||
// read FairMQChannelMap and insert/update corresponding values in variable map
|
||||
// create key for variable map as follow : channelName.index.memberName
|
||||
void UpdateMQValues();
|
||||
int Store(const FairMQMap& channels);
|
||||
int Store(const FairMQChannelMap& channels);
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
void EmitUpdate(const std::string& key, T val)
|
||||
{
|
||||
//compile time check whether T is const char* or char*, and in that case a compile time error is thrown.
|
||||
// compile time check whether T is const char* or char*, and in that case a compile time error is thrown.
|
||||
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
|
||||
"In template member FairMQProgOptions::EmitUpdate<T>(key,val) the types const char* or char* for the calback signatures are not supported.");
|
||||
fEvents.Emit<fair::mq::PropertyChange, T>(key, val);
|
||||
fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetStringValue(key));
|
||||
}
|
||||
|
||||
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, const std::string& val);
|
||||
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, int val);
|
||||
// for cases other than int and string
|
||||
template<typename T>
|
||||
int UpdateChannelMap(const std::string& /*channelName*/, int /*index*/, const std::string& /*member*/, T /*val*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int UpdateChannelMap(const FairMQChannelMap& map);
|
||||
int UpdateChannelValue(const std::string& channelName, int index, const std::string& member, const std::string& val);
|
||||
int UpdateChannelValue(const std::string& channelName, int index, const std::string& member, int val);
|
||||
|
||||
void UpdateChannelInfo();
|
||||
|
||||
fair::mq::EventManager fEvents;
|
||||
// helper to modify the value of variable map after calling boost::program_options::store
|
||||
template<typename T>
|
||||
void UpdateVarMap(const std::string& key, const T& val)
|
||||
{
|
||||
std::map<std::string, boost::program_options::variable_value>& vm = fVarMap;
|
||||
vm[key].value() = boost::any(val);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* FAIRMQPROGOPTIONS_H */
|
||||
|
@@ -29,7 +29,7 @@ namespace parser
|
||||
|
||||
constexpr const char* SUBOPT::channelOptionKeys[];
|
||||
|
||||
FairMQMap SUBOPT::UserParser(const vector<string>& channelConfig, const string& deviceId, const string& rootNode)
|
||||
FairMQChannelMap SUBOPT::UserParser(const vector<string>& channelConfig, const string& deviceId, const string& rootNode)
|
||||
{
|
||||
ptree pt;
|
||||
|
||||
|
@@ -14,14 +14,12 @@
|
||||
#ifndef FAIRMQPARSER_SUBOPT_H
|
||||
#define FAIRMQPARSER_SUBOPT_H
|
||||
|
||||
#include "FairMQParser.h" // for FairMQMap
|
||||
#include "FairMQParser.h" // for FairMQChannelMap
|
||||
#include <boost/program_options.hpp>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
@@ -78,7 +76,7 @@ struct SUBOPT
|
||||
nullptr
|
||||
};
|
||||
|
||||
FairMQMap UserParser(const std::vector<std::string>& channelConfig, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||
FairMQChannelMap UserParser(const std::vector<std::string>& channelConfig, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -1,178 +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" *
|
||||
********************************************************************************/
|
||||
/*
|
||||
* File: FairProgOptions.cxx
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on March 11, 2015, 5:38 PM
|
||||
*/
|
||||
|
||||
#include "FairProgOptions.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace fair::mq;
|
||||
|
||||
FairProgOptions::FairProgOptions()
|
||||
: fVarMap()
|
||||
, fGeneralOptions("General options")
|
||||
, fAllOptions("Command line options")
|
||||
, fConfigMutex()
|
||||
{
|
||||
fGeneralOptions.add_options()
|
||||
("help,h", "produce help")
|
||||
("version,v", "print version")
|
||||
("severity", po::value<string>()->default_value("debug"), "Log severity level: 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>)");
|
||||
|
||||
fAllOptions.add(fGeneralOptions);
|
||||
}
|
||||
|
||||
FairProgOptions::~FairProgOptions()
|
||||
{
|
||||
}
|
||||
|
||||
/// Add option descriptions
|
||||
int FairProgOptions::AddToCmdLineOptions(const po::options_description optDesc, bool /* visible */)
|
||||
{
|
||||
fAllOptions.add(optDesc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
po::options_description& FairProgOptions::GetCmdLineOptions()
|
||||
{
|
||||
return fAllOptions;
|
||||
}
|
||||
|
||||
int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered)
|
||||
{
|
||||
// get options from cmd line and store in variable map
|
||||
// here we use command_line_parser instead of parse_command_line, to allow unregistered and positional options
|
||||
if (allowUnregistered)
|
||||
{
|
||||
po::command_line_parser parser{argc, argv};
|
||||
parser.options(fAllOptions).allow_unregistered();
|
||||
po::parsed_options parsedOptions = parser.run();
|
||||
po::store(parsedOptions, fVarMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
po::store(po::parse_command_line(argc, argv, fAllOptions), fVarMap);
|
||||
}
|
||||
|
||||
// Handles options like "--help" or "--version"
|
||||
// return 1 if switch options found in fVarMap
|
||||
if (ImmediateOptions())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
po::notify(fVarMap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FairProgOptions::ParseDefaults()
|
||||
{
|
||||
vector<string> emptyArgs;
|
||||
emptyArgs.push_back("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);
|
||||
}
|
||||
|
||||
int FairProgOptions::PrintOptions()
|
||||
{
|
||||
// -> loop over variable map and print its content
|
||||
// -> In this example the following types are supported:
|
||||
// string, int, float, double, short, boost::filesystem::path
|
||||
// vector<string>, vector<int>, vector<float>, vector<double>, vector<short>
|
||||
|
||||
map<string, VarValInfo> mapinfo;
|
||||
|
||||
// get string length for formatting and convert varmap values into string
|
||||
int maxLen1st = 0;
|
||||
int maxLen2nd = 0;
|
||||
int maxLenTypeInfo = 0;
|
||||
int maxLenDefault = 0;
|
||||
int maxLenEmpty = 0;
|
||||
for (const auto& m : fVarMap)
|
||||
{
|
||||
Max(maxLen1st, m.first.length());
|
||||
|
||||
VarValInfo valinfo = GetVariableValueInfo(m.second);
|
||||
mapinfo[m.first] = valinfo;
|
||||
|
||||
Max(maxLen2nd, valinfo.value.length());
|
||||
Max(maxLenTypeInfo, valinfo.type.length());
|
||||
Max(maxLenDefault, valinfo.defaulted.length());
|
||||
Max(maxLenEmpty, valinfo.empty.length());
|
||||
}
|
||||
|
||||
// TODO : limit the value len field in a better way
|
||||
if (maxLen2nd > 100)
|
||||
{
|
||||
maxLen2nd = 100;
|
||||
}
|
||||
|
||||
stringstream ss;
|
||||
ss << "Configuration: \n";
|
||||
|
||||
for (const auto& p : mapinfo)
|
||||
{
|
||||
ss << setfill(' ')
|
||||
<< setw(maxLen1st) << left << p.first << " = "
|
||||
<< setw(maxLen2nd) << p.second.value
|
||||
<< setw(maxLenTypeInfo) << p.second.type
|
||||
<< setw(maxLenDefault) << p.second.defaulted
|
||||
<< setw(maxLenEmpty) << p.second.empty
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
LOG(info) << ss.str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FairProgOptions::PrintOptionsRaw()
|
||||
{
|
||||
const std::vector<boost::shared_ptr<po::option_description>>& options = fAllOptions.options();
|
||||
|
||||
for (const auto& o : options)
|
||||
{
|
||||
VarValInfo value;
|
||||
if (fVarMap.count(o->canonical_display_name()))
|
||||
{
|
||||
value = GetVariableValueInfo(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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VarValInfo FairProgOptions::GetVariableValueInfo(const po::variable_value& varValue)
|
||||
{
|
||||
return ConvertVariableValue<ToVarValInfo>()(varValue);
|
||||
}
|
@@ -1,172 +1 @@
|
||||
/********************************************************************************
|
||||
* 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" *
|
||||
********************************************************************************/
|
||||
/*
|
||||
* File: FairProgOptions.h
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on March 11, 2015, 5:38 PM
|
||||
*/
|
||||
|
||||
#ifndef FAIRPROGOPTIONS_H
|
||||
#define FAIRPROGOPTIONS_H
|
||||
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairProgOptionsHelper.h"
|
||||
#include <fairmq/Tools.h>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <exception>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
class FairProgOptions
|
||||
{
|
||||
public:
|
||||
FairProgOptions();
|
||||
virtual ~FairProgOptions();
|
||||
|
||||
auto GetPropertyKeys() const -> std::vector<std::string>
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{fConfigMutex};
|
||||
|
||||
std::vector<std::string> result;
|
||||
|
||||
for (const auto& it : fVarMap)
|
||||
{
|
||||
result.push_back(it.first.c_str());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// add options_description
|
||||
int AddToCmdLineOptions(const po::options_description optDesc, bool visible = true);
|
||||
po::options_description& GetCmdLineOptions();
|
||||
|
||||
// get value corresponding to the key
|
||||
template<typename T>
|
||||
T GetValue(const std::string& key) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fConfigMutex);
|
||||
|
||||
T val = T();
|
||||
|
||||
if (fVarMap.count(key))
|
||||
{
|
||||
val = fVarMap[key].as<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// Given a key, convert the variable value to string
|
||||
std::string GetStringValue(const std::string& key)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fConfigMutex);
|
||||
|
||||
std::string valueStr;
|
||||
try
|
||||
{
|
||||
if (fVarMap.count(key))
|
||||
{
|
||||
valueStr = fair::mq::ConvertVariableValue<fair::mq::VarInfoToString>()(fVarMap.at(key));
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(error) << "Exception thrown for the key '" << key << "'";
|
||||
LOG(error) << e.what();
|
||||
}
|
||||
|
||||
return valueStr;
|
||||
}
|
||||
|
||||
int Count(const std::string& key) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fConfigMutex);
|
||||
|
||||
return fVarMap.count(key);
|
||||
}
|
||||
|
||||
//restrict conversion to fundamental types
|
||||
template<typename T>
|
||||
T ConvertTo(const std::string& strValue)
|
||||
{
|
||||
if (std::is_arithmetic<T>::value)
|
||||
{
|
||||
std::istringstream iss(strValue);
|
||||
T val;
|
||||
iss >> val;
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(error) << "the provided string " << strValue << " cannot be converted in the requested type. The target types must be arithmetic types";
|
||||
}
|
||||
}
|
||||
|
||||
const po::variables_map& GetVarMap() const { return fVarMap; }
|
||||
|
||||
int ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered = false);
|
||||
void ParseDefaults();
|
||||
|
||||
virtual int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) = 0;
|
||||
|
||||
virtual int PrintOptions();
|
||||
virtual int PrintOptionsRaw();
|
||||
|
||||
protected:
|
||||
// options container
|
||||
po::variables_map fVarMap;
|
||||
|
||||
// options descriptions
|
||||
po::options_description fGeneralOptions;
|
||||
po::options_description fAllOptions;
|
||||
|
||||
mutable std::mutex fConfigMutex;
|
||||
|
||||
virtual int ImmediateOptions() = 0;
|
||||
|
||||
// UpdateVarMap() and Replace() --> helper functions to modify the value of variable map after calling po::store
|
||||
template<typename T>
|
||||
void UpdateVarMap(const std::string& key, const T& val)
|
||||
{
|
||||
Replace(fVarMap, key, val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Replace(std::map<std::string, po::variable_value>& vm, const std::string& key, const T& val)
|
||||
{
|
||||
vm[key].value() = boost::any(val);
|
||||
}
|
||||
|
||||
private:
|
||||
fair::mq::VarValInfo GetVariableValueInfo(const po::variable_value& varValue);
|
||||
|
||||
static void Max(int& val, const int& comp)
|
||||
{
|
||||
if (comp > val)
|
||||
{
|
||||
val = comp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FAIRPROGOPTIONS_H */
|
||||
#warning "This header file is deprecated. Use FairMQProgOptions class directly which now contains all FairProgOptions functionality. Note, that FairMQProgOptions is also available if you include FairMQDevice."
|
||||
|
@@ -17,211 +17,171 @@
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/spirit/home/support/detail/hold_any.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <iterator>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
|
||||
template<class T>
|
||||
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
|
||||
{
|
||||
for (const auto& i : v)
|
||||
{
|
||||
os << i << " ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
struct VarValInfo
|
||||
{
|
||||
std::string value;
|
||||
std::string type;
|
||||
std::string defaulted;
|
||||
std::string empty;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
|
||||
{
|
||||
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(os, " "));
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool typeIs(const boost::program_options::variable_value& varValue)
|
||||
std::string ConvertVariableValueToString(const boost::program_options::variable_value& varVal)
|
||||
{
|
||||
auto& value = varValue.value();
|
||||
if (auto q = boost::any_cast<T>(&value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
std::ostringstream oss;
|
||||
if (auto q = boost::any_cast<T>(&varVal.value())) {
|
||||
oss << *q;
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string ConvertVariableValueToString(const boost::program_options::variable_value& varValue)
|
||||
namespace options
|
||||
{
|
||||
auto& value = varValue.value();
|
||||
std::ostringstream ostr;
|
||||
if (auto q = boost::any_cast<T>(&value))
|
||||
{
|
||||
ostr << *q;
|
||||
}
|
||||
std::string valueStr = ostr.str();
|
||||
return valueStr;
|
||||
}
|
||||
|
||||
// string specialization
|
||||
template<>
|
||||
inline std::string ConvertVariableValueToString<std::string>(const boost::program_options::variable_value& varValue)
|
||||
{
|
||||
auto& value = varValue.value();
|
||||
std::string valueStr;
|
||||
if (auto q = boost::any_cast<std::string>(&value))
|
||||
{
|
||||
valueStr = *q;
|
||||
}
|
||||
return valueStr;
|
||||
}
|
||||
|
||||
// boost::filesystem::path specialization
|
||||
template<>
|
||||
inline std::string ConvertVariableValueToString<boost::filesystem::path>(const boost::program_options::variable_value& varValue)
|
||||
{
|
||||
auto& value = varValue.value();
|
||||
std::string valueStr;
|
||||
if (auto q = boost::any_cast<boost::filesystem::path>(&value))
|
||||
{
|
||||
valueStr = (*q).string();
|
||||
}
|
||||
return valueStr;
|
||||
}
|
||||
|
||||
// policy to convert boost variable value into string
|
||||
struct VarInfoToString
|
||||
struct ToString
|
||||
{
|
||||
using returned_type = std::string;
|
||||
|
||||
template<typename T>
|
||||
std::string Value(const boost::program_options::variable_value& varValue, const std::string&, const std::string&, const std::string&)
|
||||
std::string Value(const boost::program_options::variable_value& varVal, const std::string&, const std::string&)
|
||||
{
|
||||
return ConvertVariableValueToString<T>(varValue);
|
||||
return ConvertVariableValueToString<T>(varVal);
|
||||
}
|
||||
|
||||
returned_type DefaultValue(const std::string&, const std::string&)
|
||||
returned_type DefaultValue(const std::string&)
|
||||
{
|
||||
return std::string("empty value");
|
||||
return std::string("[unidentified]");
|
||||
}
|
||||
};
|
||||
|
||||
// policy to convert variable value content into VarValInfo
|
||||
struct ToVarValInfo
|
||||
{
|
||||
using returned_type = fair::mq::VarValInfo;
|
||||
using returned_type = VarValInfo;
|
||||
|
||||
template<typename T>
|
||||
returned_type Value(const boost::program_options::variable_value& varValue, const std::string& type, const std::string& defaulted, const std::string& empty)
|
||||
returned_type Value(const boost::program_options::variable_value& varVal, const std::string& type, const std::string& defaulted)
|
||||
{
|
||||
std::string valueStr = ConvertVariableValueToString<T>(varValue);
|
||||
return fair::mq::VarValInfo{valueStr, type, defaulted, empty};
|
||||
return VarValInfo{ConvertVariableValueToString<T>(varVal), type, defaulted};
|
||||
}
|
||||
|
||||
returned_type DefaultValue(const std::string& defaulted, const std::string& empty)
|
||||
returned_type DefaultValue(const std::string& defaulted)
|
||||
{
|
||||
return fair::mq::VarValInfo{std::string("Unknown value"), std::string(" [Unknown]"), defaulted, empty};
|
||||
return VarValInfo{std::string("[unidentified]"), std::string("[unidentified]"), defaulted};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace options
|
||||
|
||||
// host class that take one of the two policy defined above
|
||||
template<typename T>
|
||||
struct ConvertVariableValue : T
|
||||
{
|
||||
auto operator()(const boost::program_options::variable_value& varValue) -> typename T::returned_type
|
||||
auto operator()(const boost::program_options::variable_value& varVal) -> typename T::returned_type
|
||||
{
|
||||
std::string defaulted;
|
||||
std::string empty;
|
||||
|
||||
if (varValue.empty())
|
||||
if (varVal.defaulted())
|
||||
{
|
||||
empty = " [empty]";
|
||||
defaulted = " [default]";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (varValue.defaulted())
|
||||
{
|
||||
defaulted = " [default]";
|
||||
}
|
||||
else
|
||||
{
|
||||
defaulted = " [provided]";
|
||||
}
|
||||
defaulted = " [provided]";
|
||||
}
|
||||
|
||||
if (typeIs<std::string>(varValue))
|
||||
return T::template Value<std::string>(varValue, std::string("<string>"), defaulted, empty);
|
||||
if (typeid(std::string) == varVal.value().type())
|
||||
return T::template Value<std::string>(varVal, std::string("<string>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<std::string>>(varValue))
|
||||
return T::template Value<std::vector<std::string>>(varValue, std::string("<vector<string>>"), defaulted, empty);
|
||||
if (typeid(std::vector<std::string>) == varVal.value().type())
|
||||
return T::template Value<std::vector<std::string>>(varVal, std::string("<vector<string>>"), defaulted);
|
||||
|
||||
if (typeIs<int>(varValue))
|
||||
return T::template Value<int>(varValue, std::string("<int>"), defaulted, empty);
|
||||
if (typeid(int) == varVal.value().type())
|
||||
return T::template Value<int>(varVal, std::string("<int>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<int>>(varValue))
|
||||
return T::template Value<std::vector<int>>(varValue, std::string("<vector<int>>"), defaulted, empty);
|
||||
if (typeid(std::vector<int>) == varVal.value().type())
|
||||
return T::template Value<std::vector<int>>(varVal, std::string("<vector<int>>"), defaulted);
|
||||
|
||||
if (typeIs<float>(varValue))
|
||||
return T::template Value<float>(varValue, std::string("<float>"), defaulted, empty);
|
||||
if (typeid(float) == varVal.value().type())
|
||||
return T::template Value<float>(varVal, std::string("<float>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<float>>(varValue))
|
||||
return T::template Value<std::vector<float>>(varValue, std::string("<vector<float>>"), defaulted, empty);
|
||||
if (typeid(std::vector<float>) == varVal.value().type())
|
||||
return T::template Value<std::vector<float>>(varVal, std::string("<vector<float>>"), defaulted);
|
||||
|
||||
if (typeIs<double>(varValue))
|
||||
return T::template Value<double>(varValue, std::string("<double>"), defaulted, empty);
|
||||
if (typeid(double) == varVal.value().type())
|
||||
return T::template Value<double>(varVal, std::string("<double>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<double>>(varValue))
|
||||
return T::template Value<std::vector<double>>(varValue, std::string("<vector<double>>"), defaulted, empty);
|
||||
if (typeid(std::vector<double>) == varVal.value().type())
|
||||
return T::template Value<std::vector<double>>(varVal, std::string("<vector<double>>"), defaulted);
|
||||
|
||||
if (typeIs<short>(varValue))
|
||||
return T::template Value<short>(varValue, std::string("<short>"), defaulted, empty);
|
||||
if (typeid(short) == varVal.value().type())
|
||||
return T::template Value<short>(varVal, std::string("<short>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<short>>(varValue))
|
||||
return T::template Value<std::vector<short>>(varValue, std::string("<vector<short>>"), defaulted, empty);
|
||||
if (typeid(std::vector<short>) == varVal.value().type())
|
||||
return T::template Value<std::vector<short>>(varVal, std::string("<vector<short>>"), defaulted);
|
||||
|
||||
if (typeIs<long>(varValue))
|
||||
return T::template Value<long>(varValue, std::string("<long>"), defaulted, empty);
|
||||
if (typeid(long) == varVal.value().type())
|
||||
return T::template Value<long>(varVal, std::string("<long>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<long>>(varValue))
|
||||
return T::template Value<std::vector<long>>(varValue, std::string("<vector<long>>"), defaulted, empty);
|
||||
if (typeid(std::vector<long>) == varVal.value().type())
|
||||
return T::template Value<std::vector<long>>(varVal, std::string("<vector<long>>"), defaulted);
|
||||
|
||||
if (typeIs<std::size_t>(varValue))
|
||||
return T::template Value<std::size_t>(varValue, std::string("<std::size_t>"), defaulted, empty);
|
||||
if (typeid(std::size_t) == varVal.value().type())
|
||||
return T::template Value<std::size_t>(varVal, std::string("<std::size_t>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<std::size_t>>(varValue))
|
||||
return T::template Value<std::vector<std::size_t>>(varValue, std::string("<vector<std::size_t>>"), defaulted, empty);
|
||||
if (typeid(std::vector<std::size_t>) == varVal.value().type())
|
||||
return T::template Value<std::vector<std::size_t>>(varVal, std::string("<vector<std::size_t>>"), defaulted);
|
||||
|
||||
if (typeIs<std::uint32_t>(varValue))
|
||||
return T::template Value<std::uint32_t>(varValue, std::string("<std::uint32_t>"), defaulted, empty);
|
||||
if (typeid(std::uint32_t) == varVal.value().type())
|
||||
return T::template Value<std::uint32_t>(varVal, std::string("<std::uint32_t>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<std::uint32_t>>(varValue))
|
||||
return T::template Value<std::vector<std::uint32_t>>(varValue, std::string("<vector<std::uint32_t>>"), defaulted, empty);
|
||||
if (typeid(std::vector<std::uint32_t>) == varVal.value().type())
|
||||
return T::template Value<std::vector<std::uint32_t>>(varVal, std::string("<vector<std::uint32_t>>"), defaulted);
|
||||
|
||||
if (typeIs<std::uint64_t>(varValue))
|
||||
return T::template Value<std::uint64_t>(varValue, std::string("<std::uint64_t>"), defaulted, empty);
|
||||
if (typeid(std::uint64_t) == varVal.value().type())
|
||||
return T::template Value<std::uint64_t>(varVal, std::string("<std::uint64_t>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<std::uint64_t>>(varValue))
|
||||
return T::template Value<std::vector<std::uint64_t>>(varValue, std::string("<vector<std::uint64_t>>"), defaulted, empty);
|
||||
if (typeid(std::vector<std::uint64_t>) == varVal.value().type())
|
||||
return T::template Value<std::vector<std::uint64_t>>(varVal, std::string("<vector<std::uint64_t>>"), defaulted);
|
||||
|
||||
if (typeIs<bool>(varValue))
|
||||
return T::template Value<bool>(varValue, std::string("<bool>"), defaulted, empty);
|
||||
if (typeid(bool) == varVal.value().type())
|
||||
return T::template Value<bool>(varVal, std::string("<bool>"), defaulted);
|
||||
|
||||
if (typeIs<std::vector<bool>>(varValue))
|
||||
return T::template Value<std::vector<bool>>(varValue, std::string("<vector<bool>>"), defaulted, empty);
|
||||
if (typeid(std::vector<bool>) == varVal.value().type())
|
||||
return T::template Value<std::vector<bool>>(varVal, std::string("<vector<bool>>"), defaulted);
|
||||
|
||||
if (typeIs<boost::filesystem::path>(varValue))
|
||||
return T::template Value<boost::filesystem::path>(varValue, std::string("<boost::filesystem::path>"), defaulted, empty);
|
||||
if (typeid(boost::filesystem::path) == varVal.value().type())
|
||||
return T::template Value<boost::filesystem::path>(varVal, std::string("<boost::filesystem::path>"), defaulted);
|
||||
|
||||
if (typeid(std::vector<boost::filesystem::path>) == varVal.value().type())
|
||||
return T::template Value<std::vector<boost::filesystem::path>>(varVal, std::string("<std::vector<boost::filesystem::path>>"), defaulted);
|
||||
|
||||
// if we get here, the type is not supported return unknown info
|
||||
return T::DefaultValue(defaulted, empty);
|
||||
return T::DefaultValue(defaulted);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,98 +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" #
|
||||
################################################################################
|
||||
# Create a library called "ProgOptionTest"
|
||||
|
||||
# Test fair-prog-opt
|
||||
|
||||
# scripts
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testMQOptions1.sh.in ${CMAKE_BINARY_DIR}/bin/testMQOptions1.sh )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testMQOptions2.sh.in ${CMAKE_BINARY_DIR}/bin/testMQOptions2.sh )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testMQOptions3.sh.in ${CMAKE_BINARY_DIR}/bin/testMQOptions3.sh )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testMQOptions4.sh.in ${CMAKE_BINARY_DIR}/bin/testMQOptions4.sh )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testMQOptions5.sh.in ${CMAKE_BINARY_DIR}/bin/testMQOptions5.sh )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/start-bsampler-sink.sh.in ${CMAKE_BINARY_DIR}/bin/start-bsampler-sink.sh )
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/testMQOptions1.sh")
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/testMQOptions2.sh")
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/testMQOptions3.sh")
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/testMQOptions4.sh")
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/testMQOptions5.sh")
|
||||
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${CMAKE_BINARY_DIR}/bin/start-bsampler-sink.sh")
|
||||
|
||||
# Config/xml/json example file
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/ConfigFileTest.cfg.in ${CMAKE_BINARY_DIR}/bin/ConfigFileTest.cfg)
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testXML.xml ${CMAKE_BINARY_DIR}/bin/testXML.xml )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/testJSON.json ${CMAKE_BINARY_DIR}/bin/testJSON.json )
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/macro/bsampler-sink.json ${CMAKE_BINARY_DIR}/bin/bsampler-sink.json )
|
||||
|
||||
|
||||
|
||||
set(INCLUDE_DIRECTORIES
|
||||
${CMAKE_SOURCE_DIR}/fairmq
|
||||
${CMAKE_SOURCE_DIR}/fairmq/options
|
||||
${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/lib
|
||||
${CMAKE_SOURCE_DIR}/fairmq/options/ProgOptionTest/run
|
||||
)
|
||||
|
||||
Set(SYSTEM_INCLUDE_DIRECTORIES
|
||||
${SYSTEM_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
|
||||
include_directories(${INCLUDE_DIRECTORIES})
|
||||
include_directories(${SYSTEM_INCLUDE_DIRECTORIES})
|
||||
|
||||
set(LINK_DIRECTORIES
|
||||
${Boost_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
link_directories(${LINK_DIRECTORIES})
|
||||
|
||||
Set(SRCS
|
||||
lib/FairMQParserExample.cxx
|
||||
)
|
||||
|
||||
Set(LIBRARY_NAME ProgOptionTest)
|
||||
|
||||
If (Boost_FOUND)
|
||||
Set(DEPENDENCIES
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||
FairMQ
|
||||
)
|
||||
EndIf (Boost_FOUND)
|
||||
|
||||
GENERATE_LIBRARY()
|
||||
|
||||
|
||||
If (Boost_FOUND)
|
||||
Set(Exe_Names
|
||||
runtestMQOption1
|
||||
runtestMQOption2
|
||||
runOptTestSampler
|
||||
runOptTestSink
|
||||
)
|
||||
|
||||
|
||||
set(Exe_Source
|
||||
run/testMQoptions1.cxx
|
||||
run/testMQoptions2.cxx
|
||||
run/runOptTestSampler.cxx
|
||||
run/runOptTestSink.cxx
|
||||
)
|
||||
|
||||
List(LENGTH Exe_Names _length)
|
||||
Math(EXPR _length ${_length}-1)
|
||||
|
||||
ForEach(_file RANGE 0 ${_length})
|
||||
List(GET Exe_Names ${_file} _name)
|
||||
List(GET Exe_Source ${_file} _src)
|
||||
Set(EXE_NAME ${_name})
|
||||
Set(SRCS ${_src})
|
||||
Set(DEPENDENCIES ProgOptionTest)
|
||||
GENERATE_EXECUTABLE()
|
||||
EndForEach(_file RANGE 0 ${_length})
|
||||
EndIf (Boost_FOUND)
|
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* File: FairMQParserExample.cxx
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on May 14, 2015, 5:01 PM
|
||||
*/
|
||||
|
||||
#include "FairMQParserExample.h"
|
||||
#include "FairMQLogger.h"
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
|
||||
|
||||
namespace FairMQParser
|
||||
{
|
||||
|
||||
// other xml examples
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
boost::property_tree::ptree MQXML2::UserParser(const std::string& filename)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_xml(filename, pt);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO : finish implementation
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
boost::property_tree::ptree MQXML3::UserParser(const std::string& filename, const std::string& devicename)
|
||||
{
|
||||
// Create an empty property tree object
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_xml(filename, pt);
|
||||
|
||||
|
||||
// Create fair mq map
|
||||
|
||||
auto xml = pt.get_child("");
|
||||
std::vector<std::pair<std::string, boost::property_tree::ptree>> match;
|
||||
std::pair<std::string, boost::property_tree::ptree> device_match;
|
||||
|
||||
ProcessTree(xml.begin (), xml.end (), std::back_inserter(match),
|
||||
[] (const std::string& key) { return key == "device"; });
|
||||
|
||||
|
||||
// for each device
|
||||
for (const auto& pair: match)
|
||||
{
|
||||
if(pair.second.get<std::string>("<xmlattr>.name") == devicename)
|
||||
{
|
||||
device_match=pair;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//match.erase(std::remove(match.begin(), match.end(), pair), match.end());
|
||||
continue;
|
||||
}
|
||||
|
||||
//std::cout << "pair.first " << pair.first << std::endl;//device
|
||||
//std::cout << "\t node = " << pair.first
|
||||
// << "\t name = " << pair.second.get<std::string>("<xmlattr>.name")
|
||||
// << "\t id = " << pair.second.get<std::string>("<xmlattr>.id");
|
||||
//std::cout<<std::endl;
|
||||
}
|
||||
|
||||
return device_match.second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end FairMQParser namespace
|
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* File: FairMQParserExample.h
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on May 14, 2015, 5:01 PM
|
||||
*/
|
||||
|
||||
#ifndef FAIRMQPARSEREXAMPLE_H
|
||||
#define FAIRMQPARSEREXAMPLE_H
|
||||
|
||||
// FairRoot
|
||||
#include "FairMQChannel.h"
|
||||
#include "FairMQParser.h"
|
||||
|
||||
// Boost
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
// std
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace FairMQParser
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////// XML ////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// xml example 2
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
struct MQXML2
|
||||
{
|
||||
boost::property_tree::ptree UserParser(const std::string& filename);
|
||||
};
|
||||
|
||||
// xml example 3
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
struct MQXML3
|
||||
{
|
||||
boost::property_tree::ptree UserParser(const std::string& filename, const std::string& root_node);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// template function iterating over the whole boost property tree
|
||||
template <typename Input_tree_It, typename Output_tree_It, typename Compare_key>
|
||||
void ProcessTree(Input_tree_It first, Input_tree_It last, Output_tree_It dest, Compare_key compare)
|
||||
{
|
||||
//typedef typename std::iterator_traits<Input_tree_It>::reference reference;
|
||||
|
||||
if (first == last)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto begin = first->second.begin ();
|
||||
auto end = first->second.end ();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
ProcessTree (begin, end, dest, compare);
|
||||
}
|
||||
|
||||
if (compare (first->first))
|
||||
{
|
||||
dest = *first;
|
||||
}
|
||||
|
||||
ProcessTree (++first, last, dest, compare);
|
||||
}
|
||||
|
||||
class no_id_exception: public std::exception
|
||||
{
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "Empty string for the device-id in FairMQParser::ptreeToMQMap(...) function";
|
||||
}
|
||||
};
|
||||
|
||||
} // end FairMQParser namespace
|
||||
#endif /* FAIRMQPARSEREXAMPLE_H */
|
||||
|
@@ -1,38 +0,0 @@
|
||||
#----------------------------------------------------
|
||||
# comments :
|
||||
# brackets [] are used to group options. For example :
|
||||
#
|
||||
# [xml.config]
|
||||
# node.root = fairMQOptions
|
||||
#
|
||||
# is equivalent to
|
||||
# xml.config.node.root = fairMQOptions
|
||||
#----------------------------------------------------
|
||||
|
||||
config-json-file = @CMAKE_BINARY_DIR@/bin/testJSON.json
|
||||
config-xml-file = @CMAKE_BINARY_DIR@/bin/testXML.xml
|
||||
|
||||
#
|
||||
device-id = merger
|
||||
|
||||
#-------------------
|
||||
[xml.config]
|
||||
|
||||
#filename = @CMAKE_BINARY_DIR@/bin/testXML.xml
|
||||
node.root = fairMQOptions
|
||||
|
||||
|
||||
#-------------------
|
||||
[input.file]
|
||||
|
||||
name = sampler_file_name.root
|
||||
tree = sampler_tree
|
||||
branch = sampler_branch
|
||||
|
||||
|
||||
#-------------------
|
||||
[output.file]
|
||||
|
||||
name = sink_filename.root
|
||||
tree = sink_tree
|
||||
branch = sink_branch
|
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
JSONFILE="@CMAKE_BINARY_DIR@/bin/bsampler-sink.json"
|
||||
|
||||
# Note: device-id value must correspond to the device id given in the json file
|
||||
|
||||
BSAMPLER="runOptTestSampler"
|
||||
BSAMPLER+=" --config-json-file $JSONFILE"
|
||||
BSAMPLER+=" --id bsampler1"
|
||||
|
||||
xterm -geometry 150x23+0+0 -hold -e @CMAKE_BINARY_DIR@/bin/$BSAMPLER &
|
||||
|
||||
|
||||
SINK="runOptTestSink"
|
||||
SINK+=" --config-json-file $JSONFILE"
|
||||
SINK+=" --id sink1"
|
||||
|
||||
xterm -geometry 150x23+0+350 -hold -e @CMAKE_BINARY_DIR@/bin/$SINK &
|
@@ -1,63 +0,0 @@
|
||||
{
|
||||
"fairMQOptions": {
|
||||
"devices": [
|
||||
{
|
||||
"id": "merger1",
|
||||
"channels": [
|
||||
{
|
||||
"name": "two_inputs_channel",
|
||||
"sockets": [
|
||||
{
|
||||
"type": "pull",
|
||||
"method": "",
|
||||
"address": "tcp://*:5569",
|
||||
"sndBufSize": 1000,
|
||||
"rcvBufSize": 1000,
|
||||
"rateLogging": 1
|
||||
},
|
||||
{
|
||||
"type": "pull",
|
||||
"method": "bind",
|
||||
"address": "tcp://*:5570",
|
||||
"sndBufSize": 1000,
|
||||
"rcvBufSize": 1000,
|
||||
"rateLogging": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "one_output_channel",
|
||||
"sockets": [
|
||||
{
|
||||
"type": "push",
|
||||
"method": "connect",
|
||||
"address": "tcp://*:5571",
|
||||
"sndBufSize": 1000,
|
||||
"rcvBufSize": 1000,
|
||||
"rateLogging": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "sink1",
|
||||
"channels": [
|
||||
{
|
||||
"name": "one_input",
|
||||
"sockets": [
|
||||
{
|
||||
"type": "pull",
|
||||
"method": "bind",
|
||||
"address": "tcp://localhost:5571",
|
||||
"sndBufSize": 1000,
|
||||
"rcvBufSize": 1000,
|
||||
"rateLogging": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUN_TEST="runtestMQOption1"
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RUN_TEST+=" $*"
|
||||
fi
|
||||
|
||||
RUN_TEST+=" --config-xml-file @CMAKE_BINARY_DIR@/bin/testXML.xml"
|
||||
|
||||
@CMAKE_BINARY_DIR@/bin/$RUN_TEST
|
@@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUN_TEST="runtestMQOption1"
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RUN_TEST+=" $*"
|
||||
fi
|
||||
|
||||
XML_CMD_LINE="<fairMQOptions>"
|
||||
XML_CMD_LINE+="<device name=\"merger\" id=\"1234\" >"
|
||||
XML_CMD_LINE+=" <channel name=\"two_inputs_channel\" >"
|
||||
XML_CMD_LINE+=" <socket name=\"input1\" >"
|
||||
XML_CMD_LINE+=" <type>pull</type>"
|
||||
XML_CMD_LINE+=" <method>bind</method>"
|
||||
XML_CMD_LINE+=" <address>tcp://*:5569</address>"
|
||||
XML_CMD_LINE+=" <sndBufSize>1000</sndBufSize>"
|
||||
XML_CMD_LINE+=" <rcvBufSize>1000</rcvBufSize>"
|
||||
XML_CMD_LINE+=" <rateLogging>1</rateLogging>"
|
||||
XML_CMD_LINE+=" </socket>"
|
||||
XML_CMD_LINE+=" <socket name=\"input2\" >"
|
||||
XML_CMD_LINE+=" <type>pull</type>"
|
||||
XML_CMD_LINE+=" <method>bind</method>"
|
||||
XML_CMD_LINE+=" <address>tcp://*:5570</address>"
|
||||
XML_CMD_LINE+=" <sndBufSize>1000</sndBufSize>"
|
||||
XML_CMD_LINE+=" <rcvBufSize>1000</rcvBufSize>"
|
||||
XML_CMD_LINE+=" <rateLogging>1</rateLogging>"
|
||||
XML_CMD_LINE+=" </socket>"
|
||||
XML_CMD_LINE+=" </channel>"
|
||||
XML_CMD_LINE+=" <channel name=\"one_output_channel\" >"
|
||||
XML_CMD_LINE+=" <socket name=\"output1\" >"
|
||||
XML_CMD_LINE+=" <type>push</type>"
|
||||
XML_CMD_LINE+=" <method>connect</method>"
|
||||
XML_CMD_LINE+=" <address>tcp://*:5571</address>"
|
||||
XML_CMD_LINE+=" <sndBufSize>1000</sndBufSize>"
|
||||
XML_CMD_LINE+=" <rcvBufSize>1000</rcvBufSize>"
|
||||
XML_CMD_LINE+=" <rateLogging>1</rateLogging>"
|
||||
XML_CMD_LINE+=" </socket>"
|
||||
XML_CMD_LINE+=" </channel>"
|
||||
XML_CMD_LINE+=" </device>"
|
||||
XML_CMD_LINE+=" <device name=\"sink\" id=\"4567\" >"
|
||||
XML_CMD_LINE+=" <channel name=\"one_input\" >"
|
||||
XML_CMD_LINE+=" <socket name=\"input1\" >"
|
||||
XML_CMD_LINE+=" <type>pull</type>"
|
||||
XML_CMD_LINE+=" <method>bind</method>"
|
||||
XML_CMD_LINE+=" <address>tcp://localhost:5571</address>"
|
||||
XML_CMD_LINE+=" <sndBufSize>1000</sndBufSize>"
|
||||
XML_CMD_LINE+=" <rcvBufSize>1000</rcvBufSize>"
|
||||
XML_CMD_LINE+=" <rateLogging>1</rateLogging>"
|
||||
XML_CMD_LINE+=" </socket>"
|
||||
XML_CMD_LINE+=" </channel>"
|
||||
XML_CMD_LINE+=" </device>"
|
||||
XML_CMD_LINE+="</fairmq_option>"
|
||||
|
||||
|
||||
|
||||
RUN_TEST+=" --config-xml-string $XML_CMD_LINE"
|
||||
|
||||
|
||||
@CMAKE_BINARY_DIR@/bin/$RUN_TEST
|
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUN_TEST="runtestMQOption2"
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RUN_TEST+=" $*"
|
||||
fi
|
||||
RUN_TEST+=" --config @CMAKE_BINARY_DIR@/bin/ConfigFileTest.cfg"
|
||||
|
||||
@CMAKE_BINARY_DIR@/bin/$RUN_TEST
|
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUN_TEST="runtestMQOption1"
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RUN_TEST+=" $*"
|
||||
fi
|
||||
|
||||
RUN_TEST+=" --config-json-file @CMAKE_BINARY_DIR@/bin/testJSON.json"
|
||||
|
||||
@CMAKE_BINARY_DIR@/bin/$RUN_TEST
|
@@ -1,77 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUN_TEST="runtestMQOption1"
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RUN_TEST+=" $*"
|
||||
fi
|
||||
|
||||
JSON_CMD_LINE="{"
|
||||
JSON_CMD_LINE+=" \"fairMQOptions\": {"
|
||||
JSON_CMD_LINE+=" \"device\": "
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"merger\","
|
||||
JSON_CMD_LINE+=" \"id\": \"1234\","
|
||||
JSON_CMD_LINE+=" \"channel\": "
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"two_inputs_channel\","
|
||||
JSON_CMD_LINE+=" \"socket\": "
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"input1\","
|
||||
JSON_CMD_LINE+=" \"type\": \"pull\","
|
||||
JSON_CMD_LINE+=" \"method\": \"bind\","
|
||||
JSON_CMD_LINE+=" \"address\": \"tcp://*:5569\","
|
||||
JSON_CMD_LINE+=" \"sndBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rcvBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rateLogging\": \"1\" "
|
||||
JSON_CMD_LINE+=" },"
|
||||
JSON_CMD_LINE+=" \"socket\": "
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"input2\","
|
||||
JSON_CMD_LINE+=" \"type\": \"pull\","
|
||||
JSON_CMD_LINE+=" \"method\": \"bind\","
|
||||
JSON_CMD_LINE+=" \"address\": \"tcp://*:5570\","
|
||||
JSON_CMD_LINE+=" \"sndBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rcvBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rateLogging\": \"1\" "
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" },"
|
||||
JSON_CMD_LINE+=" \"channel\":"
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"one_output_channel\","
|
||||
JSON_CMD_LINE+=" \"socket\": {"
|
||||
JSON_CMD_LINE+=" \"name\": \"output1\","
|
||||
JSON_CMD_LINE+=" \"type\": \"push\","
|
||||
JSON_CMD_LINE+=" \"method\": \"connect\","
|
||||
JSON_CMD_LINE+=" \"address\": \"tcp://*:5571\","
|
||||
JSON_CMD_LINE+=" \"sndBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rcvBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rateLogging\": \"1\" "
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" },"
|
||||
JSON_CMD_LINE+=" \"device\":"
|
||||
JSON_CMD_LINE+=" {"
|
||||
JSON_CMD_LINE+=" \"name\": \"sink\","
|
||||
JSON_CMD_LINE+=" \"id\": \"4567\","
|
||||
JSON_CMD_LINE+=" \"channel\": {"
|
||||
JSON_CMD_LINE+=" \"name\": \"one_input\","
|
||||
JSON_CMD_LINE+=" \"socket\": {"
|
||||
JSON_CMD_LINE+=" \"name\": \"input1\","
|
||||
JSON_CMD_LINE+=" \"type\": \"pull\","
|
||||
JSON_CMD_LINE+=" \"method\": \"bind\","
|
||||
JSON_CMD_LINE+=" \"address\": \"tcp://localhost:5571\","
|
||||
JSON_CMD_LINE+=" \"sndBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rcvBufSize\": \"1000\","
|
||||
JSON_CMD_LINE+=" \"rateLogging\": \"1\" "
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+=" }"
|
||||
JSON_CMD_LINE+="}"
|
||||
|
||||
|
||||
RUN_TEST+=" --config-json-string $JSON_CMD_LINE"
|
||||
|
||||
|
||||
@CMAKE_BINARY_DIR@/bin/$RUN_TEST
|
@@ -1,44 +0,0 @@
|
||||
<fairMQOptions>
|
||||
<device name="merger" id="merger">
|
||||
<channel name="two_inputs_channel">
|
||||
<socket name="input1">
|
||||
<type>pull</type>
|
||||
<method>bind</method>
|
||||
<address>tcp://*:5569</address>
|
||||
<sndBufSize>1000</sndBufSize>
|
||||
<rcvBufSize>1000</rcvBufSize>
|
||||
<rateLogging>1</rateLogging>
|
||||
</socket>
|
||||
<socket name="input2">
|
||||
<type>pull</type>
|
||||
<method>bind</method>
|
||||
<address>tcp://*:5570</address>
|
||||
<sndBufSize>1000</sndBufSize>
|
||||
<rcvBufSize>1000</rcvBufSize>
|
||||
<rateLogging>1</rateLogging>
|
||||
</socket>
|
||||
</channel>
|
||||
<channel name="one_output_channel">
|
||||
<socket name="output1">
|
||||
<type>push</type>
|
||||
<method>connect</method>
|
||||
<address>tcp://*:5571</address>
|
||||
<sndBufSize>1000</sndBufSize>
|
||||
<rcvBufSize>1000</rcvBufSize>
|
||||
<rateLogging>1</rateLogging>
|
||||
</socket>
|
||||
</channel>
|
||||
</device>
|
||||
<device name="sink" id="sink">
|
||||
<channel name="one_input">
|
||||
<socket name="input1">
|
||||
<type>pull</type>
|
||||
<method>bind</method>
|
||||
<address>tcp://localhost:5571</address>
|
||||
<sndBufSize>1000</sndBufSize>
|
||||
<rcvBufSize>1000</rcvBufSize>
|
||||
<rateLogging>1</rateLogging>
|
||||
</socket>
|
||||
</channel>
|
||||
</device>
|
||||
</fairMQOptions>
|
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* File: runOptTestSampler.cxx
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on June 10, 2015, 3:34 PM
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
/// std
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
/// boost
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
/// FairRoot/FairMQ
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQProgOptions.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// main
|
||||
//////////////////////////////////////////////////////////////
|
||||
using namespace std;
|
||||
using namespace FairMQParser;
|
||||
using namespace boost::program_options;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FairMQProgOptions config;
|
||||
try
|
||||
{
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// define key specific to the BenchmarkSampler in options_description
|
||||
|
||||
int eventSize;
|
||||
int eventRate;
|
||||
int ioThreads;
|
||||
options_description sampler_options("Sampler options");
|
||||
sampler_options.add_options()
|
||||
("event-size", value<int>(&eventSize)->default_value(1000), "Event size in bytes")
|
||||
("event-rate", value<int>(&eventRate)->default_value(0), "Event rate limit in maximum number of events per second")
|
||||
("io-threads", value<int>(&ioThreads)->default_value(1), "Number of I/O threads");
|
||||
|
||||
// and add it to cmdline option of FairMQProgOptions
|
||||
config.AddToCmdLineOptions(sampler_options);
|
||||
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// enable simple config txt/INI file
|
||||
//config.EnableCfgFile();
|
||||
//config.AddToCfgFileOptions(sampler_options,false);
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// Parse command line options and store in variable map
|
||||
if(config.ParseAll(argc,argv,true))
|
||||
return 0;
|
||||
|
||||
// keys defined in FairMQProgOptions
|
||||
string filename=config.GetValue<string>("config-json-file");
|
||||
string deviceID=config.GetValue<string>("id");
|
||||
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// User defined parsing method.
|
||||
|
||||
config.UserParser<JSON>(filename,deviceID);
|
||||
FairMQMap channels=config.GetFairMQMap();
|
||||
//set device here
|
||||
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << e.what();
|
||||
LOG(info) << "Command line options are the following : ";
|
||||
config.PrintHelp();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* File: runOptTestSink.cxx
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on June 10, 2015, 3:34 PM
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
/// std
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
/// boost
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
/// FairRoot/FairMQ
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQProgOptions.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// main
|
||||
//////////////////////////////////////////////////////////////
|
||||
using namespace std;
|
||||
using namespace FairMQParser;
|
||||
using namespace boost::program_options;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FairMQProgOptions config;
|
||||
try
|
||||
{
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// define key specific to the BenchmarkSampler in options_description
|
||||
|
||||
int eventSize;
|
||||
int eventRate;
|
||||
int ioThreads;
|
||||
options_description Sink_options("Sink options");
|
||||
Sink_options.add_options()
|
||||
("io-threads", value<int>(&ioThreads)->default_value(1), "Number of I/O threads");
|
||||
|
||||
// and add it to cmdline option of FairMQProgOptions
|
||||
config.AddToCmdLineOptions(Sink_options);
|
||||
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// Parse command line options and store in variable map
|
||||
if(config.ParseAll(argc,argv,true))
|
||||
return 0;
|
||||
|
||||
// keys defined in FairMQProgOptions
|
||||
string filename=config.GetValue<string>("config-json-file");
|
||||
string deviceID=config.GetValue<string>("id");
|
||||
|
||||
// //////////////////////////////////////////////////////////////
|
||||
// User defined parsing method.
|
||||
|
||||
config.UserParser<JSON>(filename,deviceID);
|
||||
FairMQMap channels=config.GetFairMQMap();
|
||||
//set device here
|
||||
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << e.what();
|
||||
LOG(info) << "Command line options are the following : ";
|
||||
config.PrintHelp();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,141 +0,0 @@
|
||||
/// std
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
/// boost
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
/// FairRoot/FairMQ
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQProgOptions.h"
|
||||
|
||||
// Parse xml from file
|
||||
int testXML1(FairMQProgOptions* config)
|
||||
{
|
||||
LOG(info)<<"--------- test XML1 ---------\n";
|
||||
std::string filename;
|
||||
std::string XMLrootNode;
|
||||
|
||||
filename=config->GetValue<std::string>("config-xml-file");
|
||||
XMLrootNode=config->GetValue<std::string>("xml.config.node.root");
|
||||
std::string id=config->GetValue<std::string>("id");
|
||||
config->UserParser<FairMQParser::XML>(filename,id,XMLrootNode);
|
||||
// other xml parser test
|
||||
config->UserParser<FairMQParser::MQXML2>(filename);
|
||||
config->UserParser<FairMQParser::MQXML3>(filename,"merger");
|
||||
|
||||
LOG(info)<<"--------- test XML1 end ---------\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse xml from command line
|
||||
int testXML2(FairMQProgOptions* config)
|
||||
{
|
||||
LOG(info)<<"--------- test XML2 ---------\n";
|
||||
std::string XML;
|
||||
std::string XMLrootNode;
|
||||
std::string id=config->GetValue<std::string>("id");
|
||||
XMLrootNode=config->GetValue<std::string>("xml.config.node.root");
|
||||
|
||||
// Note: convert the vector<string> into one string with GetStringValue(key)
|
||||
XML=config->GetStringValue("config-xml-string");
|
||||
|
||||
std::stringstream iss;
|
||||
iss << XML;
|
||||
config->UserParser<FairMQParser::XML>(iss,id,XMLrootNode);
|
||||
|
||||
LOG(info)<<"--------- test XML2 end ---------\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse json from file
|
||||
int testJSON1(FairMQProgOptions* config)
|
||||
{
|
||||
LOG(info)<<"--------- test JSON1 ---------\n";
|
||||
std::string filename;
|
||||
std::string JSONrootNode;
|
||||
std::string id=config->GetValue<std::string>("id");
|
||||
|
||||
filename=config->GetValue<std::string>("config-json-file");
|
||||
JSONrootNode=config->GetValue<std::string>("json.config.node.root");
|
||||
|
||||
config->UserParser<FairMQParser::JSON>(filename,id,JSONrootNode);
|
||||
|
||||
LOG(info)<<"--------- test JSON1 end ---------\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse json from command line
|
||||
int testJSON2(FairMQProgOptions* config)
|
||||
{
|
||||
LOG(info)<<"--------- test JSON2 ---------\n";
|
||||
std::string JSON;
|
||||
std::string JSONrootNode;
|
||||
std::string id=config->GetValue<std::string>("id");
|
||||
JSONrootNode=config->GetValue<std::string>("json.config.node.root");
|
||||
|
||||
// Note: convert the vector<string> into one string with GetStringValue(key)
|
||||
JSON=config->GetStringValue("config-json-string");
|
||||
|
||||
std::stringstream iss;
|
||||
iss << JSON;
|
||||
config->UserParser<FairMQParser::JSON>(iss,id,JSONrootNode);
|
||||
|
||||
LOG(info)<<"--------- test JSON2 end ---------\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FairMQProgOptions* config= new FairMQProgOptions();
|
||||
try
|
||||
{
|
||||
po::options_description format_desc("XML or JSON input");
|
||||
format_desc.add_options()
|
||||
("xml.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "xml root node ")
|
||||
("json.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "json root node ")
|
||||
;
|
||||
|
||||
config->AddToCmdLineOptions(format_desc);
|
||||
|
||||
// Parse command line
|
||||
if (config->ParseAll(argc,argv))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set severity level (Default is 0=DEBUG)
|
||||
int severity = config->GetValue<int>("severity");
|
||||
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(severity);
|
||||
SET_LOGGER_LEVEL(lvl);
|
||||
|
||||
// Parse xml or json from cmd line or file
|
||||
if (config->GetVarMap().count("config-xml-file"))
|
||||
{
|
||||
testXML1(config);
|
||||
}
|
||||
|
||||
if (config->GetVarMap().count("config-xml-string"))
|
||||
{
|
||||
testXML2(config);
|
||||
}
|
||||
|
||||
if (config->GetVarMap().count("config-json-file"))
|
||||
{
|
||||
testJSON1(config);
|
||||
}
|
||||
|
||||
if (config->GetVarMap().count("config-json-string"))
|
||||
{
|
||||
testJSON2(config);
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(error) << e.what();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
/// std
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
/// boost
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
/// FairRoot/FairMQ
|
||||
#include "FairMQLogger.h"
|
||||
#include "FairMQParser.h"
|
||||
#include "FairMQProgOptions.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// main
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
FairMQProgOptions config;
|
||||
|
||||
po::options_description format_desc("XML input");
|
||||
format_desc.add_options()
|
||||
("xml.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "xml root node ")
|
||||
;
|
||||
|
||||
po::options_description io_file_opt_desc("I/O file Options");
|
||||
io_file_opt_desc.add_options()
|
||||
("input.file.name", po::value<std::string>(), "input file name")
|
||||
("input.file.tree", po::value<std::string>(), "input tree name")
|
||||
("input.file.branch", po::value<std::string>(), "input branch name")
|
||||
("output.file.name", po::value<std::string>(), "output file name")
|
||||
("output.file.tree", po::value<std::string>(), "output tree name")
|
||||
("output.file.branch", po::value<std::string>(), "output branch name")
|
||||
;
|
||||
|
||||
config.AddToCmdLineOptions(format_desc);
|
||||
config.AddToCmdLineOptions(io_file_opt_desc);
|
||||
|
||||
config.EnableCfgFile();// UseConfigFile (by default config file is not defined)
|
||||
config.AddToCfgFileOptions(format_desc,false);//false because already added to visible
|
||||
config.AddToCfgFileOptions(io_file_opt_desc,false);
|
||||
|
||||
// Parse command line and config file
|
||||
if(config.ParseAll(argc,argv))
|
||||
return 0;
|
||||
|
||||
// Set severity level (Default is 0=DEBUG)
|
||||
int severity = config.GetValue<int>("severity");
|
||||
FairMQLogger::Level lvl = static_cast<FairMQLogger::Level>(severity);
|
||||
SET_LOGGER_LEVEL(lvl);
|
||||
|
||||
// parse XML file
|
||||
std::string filename;
|
||||
std::string XMLrootNode;
|
||||
|
||||
filename=config.GetValue<std::string>("config-xml-file");
|
||||
XMLrootNode=config.GetValue<std::string>("xml.config.node.root");
|
||||
std::string id=config.GetValue<std::string>("id");
|
||||
config.UserParser<FairMQParser::XML>(filename,id,XMLrootNode);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(error) << e.what();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -63,21 +63,18 @@ int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
// create option manager object
|
||||
FairMQProgOptions config;
|
||||
|
||||
// add key description to cmd line options
|
||||
config.GetCmdLineOptions().add_options()
|
||||
("data-rate", po::value<double>()->default_value(0.5), "Data rate");
|
||||
("data-rate", boost::program_options::value<double>()->default_value(0.5), "Data rate");
|
||||
|
||||
// parse command lines, parse json file and init FairMQMap
|
||||
config.ParseAll(argc, argv, true);
|
||||
|
||||
// // get FairMQMap
|
||||
// auto map1 = config.GetFairMQMap();
|
||||
|
||||
// // update value in variable map, and propagate the update to the FairMQMap
|
||||
// config.UpdateValue<string>("chans.data.0.address","tcp://localhost:1234");
|
||||
// config.SetValue<string>("chans.data.0.address","tcp://localhost:1234");
|
||||
|
||||
// // get the updated FairMQMap
|
||||
// auto map2 = config.GetFairMQMap();
|
||||
@@ -89,7 +86,6 @@ int main(int argc, char** argv)
|
||||
// config.UpdateChannelMap(map2);
|
||||
|
||||
MyDevice device;
|
||||
// device.CatchSignals();
|
||||
device.SetConfig(config);
|
||||
|
||||
// getting as string and conversion helpers
|
||||
@@ -130,45 +126,30 @@ int main(int argc, char** argv)
|
||||
|
||||
LOG(info) << "Starting value updates...\n";
|
||||
|
||||
config.UpdateValue<string>("chans.data.0.address", "tcp://localhost:4321");
|
||||
config.SetValue<string>("chans.data.0.address", "tcp://localhost:4321");
|
||||
LOG(info) << "config: " << config.GetValue<string>("chans.data.0.address");
|
||||
LOG(info) << "device: " << device.fChannels.at("data").at(0).GetAddress() << endl;
|
||||
|
||||
config.UpdateValue<int>("chans.data.0.rcvBufSize", 100);
|
||||
config.SetValue<int>("chans.data.0.rcvBufSize", 100);
|
||||
LOG(info) << "config: " << config.GetValue<int>("chans.data.0.rcvBufSize");
|
||||
LOG(info) << "device: " << device.fChannels.at("data").at(0).GetRcvBufSize() << endl;
|
||||
|
||||
config.UpdateValue<double>("data-rate", 0.9);
|
||||
config.SetValue<double>("data-rate", 0.9);
|
||||
LOG(info) << "config: " << config.GetValue<double>("data-rate");
|
||||
LOG(info) << "device: " << device.GetRate() << endl;
|
||||
// device.Print();
|
||||
device.Print();
|
||||
|
||||
LOG(info) << "nase: " << config.GetValue<double>("nase");
|
||||
|
||||
config.Unsubscribe<string>("test");
|
||||
config.Unsubscribe<int>("test");
|
||||
config.Unsubscribe<double>("test");
|
||||
// advanced commands
|
||||
|
||||
// LOG(info) << "-------------------- start custom 1";
|
||||
|
||||
// config.Connect<EventId::Custom, MyDevice&, double>("myNewKey", [](MyDevice& d, double val)
|
||||
// {
|
||||
// d.SetRate(val);
|
||||
// d.Print();
|
||||
// });
|
||||
|
||||
// config.Emit<EventId::Custom, MyDevice&, double>("myNewKey", device, 0.123);
|
||||
|
||||
// LOG(info) << "-------------------- start custom 2 with function";
|
||||
// config.Connect<EventId::Custom, MyDevice&, double>("function example", &MyCallBack);
|
||||
|
||||
// config.Emit<EventId::Custom, MyDevice&, double>("function example", device, 6.66);
|
||||
device.ChangeState("END");
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
LOG(error) << "Unhandled Exception reached the top of main: "
|
||||
<< e.what() << ", application will now exit";
|
||||
LOG(error) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user