mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-18 02:51:46 +00:00
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 |
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
|
||||||
|
...
|
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
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.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**System information (please complete the following information):**
|
||||||
|
- OS: [e.g. MacOS, Fedora28, Ubuntu14.04]
|
||||||
|
- Environment: [e.g. FairSoft version, alfadist revision]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
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
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@@ -1,4 +1,6 @@
|
|||||||
Replace me with your description.
|
Describe your proposal.
|
||||||
|
|
||||||
|
Mention any issue this PR is resolves or is related to.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@@ -34,10 +34,30 @@ 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_DDS_PLUGIN "Build DDS plugin." OFF "BUILD_FAIRMQ" OFF)
|
||||||
cmake_dependent_option(BUILD_EXAMPLES "Build FairMQ examples." ON "BUILD_FAIRMQ" OFF)
|
cmake_dependent_option(BUILD_EXAMPLES "Build FairMQ examples." ON "BUILD_FAIRMQ" OFF)
|
||||||
option(BUILD_DOCS "Build FairMQ documentation." OFF)
|
option(BUILD_DOCS "Build FairMQ documentation." OFF)
|
||||||
|
option(FAST_BUILD "Fast production build. Not recommended for development." OFF)
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|
||||||
# Dependencies #################################################################
|
# Dependencies #################################################################
|
||||||
|
if(FAST_BUILD)
|
||||||
|
include(cotire)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
macro(find_msgpack)
|
||||||
|
if(NOT msgpack_FOUND)
|
||||||
|
find_package2(PRIVATE msgpack VERSION 3.0.0)
|
||||||
|
set(PROJECT_msgpack_VERSION 2.1.5)
|
||||||
|
if(NOT msgpack_FOUND)
|
||||||
|
find_package2(PRIVATE msgpack VERSION 2.1.5 REQUIRED)
|
||||||
|
endif()
|
||||||
|
set(msgpack_ROOT ${PACKAGE_PREFIX_DIR})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
if(BUILD_FAIRMQ)
|
if(BUILD_FAIRMQ)
|
||||||
find_package2(PUBLIC Boost VERSION 1.64 REQUIRED
|
find_package2(PUBLIC Boost VERSION 1.64 REQUIRED
|
||||||
COMPONENTS program_options thread system filesystem regex date_time signals
|
COMPONENTS program_options thread system filesystem regex date_time signals
|
||||||
@@ -166,6 +186,29 @@ install_cmake_package()
|
|||||||
|
|
||||||
|
|
||||||
# Summary ######################################################################
|
# 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)
|
if(PROJECT_PACKAGE_DEPENDENCIES)
|
||||||
message(STATUS " ")
|
message(STATUS " ")
|
||||||
message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}")
|
message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}")
|
||||||
|
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.
|
26
Dart.sh
26
Dart.sh
@@ -41,13 +41,15 @@ if [ "$#" -lt "2" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# test if a valid ctest model is defined
|
# 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
|
case "$1" in
|
||||||
echo ""
|
Experimental|Nightly|Continuous|Profile|alfa_ci|codecov)
|
||||||
else
|
;;
|
||||||
|
*)
|
||||||
echo "-- Error -- This ctest model is not supported."
|
echo "-- Error -- This ctest model is not supported."
|
||||||
echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile."
|
echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# test if the input file exists and execute it
|
# test if the input file exists and execute it
|
||||||
if [ -e "$2" ];then
|
if [ -e "$2" ];then
|
||||||
@@ -61,6 +63,9 @@ fi
|
|||||||
# set the ctest model to command line parameter
|
# set the ctest model to command line parameter
|
||||||
if [ "$1" == "alfa_ci" ]; then
|
if [ "$1" == "alfa_ci" ]; then
|
||||||
export ctest_model=Experimental
|
export ctest_model=Experimental
|
||||||
|
elif [ "$1" == "codecov" ]; then
|
||||||
|
export ctest_model=Profile
|
||||||
|
export do_codecov_upload=1
|
||||||
else
|
else
|
||||||
export ctest_model=$1
|
export ctest_model=$1
|
||||||
fi
|
fi
|
||||||
@@ -83,13 +88,20 @@ else
|
|||||||
COMPILER=$CXX$($CXX -dumpversion)
|
COMPILER=$CXX$($CXX -dumpversion)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" == "alfa_ci" ]; then
|
case "$1" in
|
||||||
|
alfa_ci)
|
||||||
export LABEL1=alfa_ci-$COMPILER-FairMQ_$GIT_BRANCH
|
export LABEL1=alfa_ci-$COMPILER-FairMQ_$GIT_BRANCH
|
||||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||||
else
|
;;
|
||||||
|
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 LABEL1=${LINUX_FLAVOUR}-$chip-$COMPILER-FairMQ_$GIT_BRANCH
|
||||||
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# get the number of processors
|
# get the number of processors
|
||||||
# and information about the host
|
# 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};-DCMAKE_PREFIX_PATH=$ENV{SIMPATH}")
|
||||||
Set(configure_options "${configure_options};-DBUILD_NANOMSG_TRANSPORT=ON")
|
Set(configure_options "${configure_options};-DBUILD_NANOMSG_TRANSPORT=ON")
|
||||||
Set(configure_options "${configure_options};-DBUILD_DDS_PLUGIN=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})
|
Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS})
|
||||||
If(EXTRA_FLAGS)
|
If(EXTRA_FLAGS)
|
||||||
Set(configure_options "${configure_options};${EXTRA_FLAGS}")
|
Set(configure_options "${configure_options};${EXTRA_FLAGS}")
|
||||||
EndIf()
|
EndIf()
|
||||||
|
|
||||||
If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile)
|
If($ENV{ctest_model} MATCHES Profile)
|
||||||
|
|
||||||
Find_Program(GCOV_COMMAND gcov)
|
Find_Program(GCOV_COMMAND gcov)
|
||||||
If(GCOV_COMMAND)
|
If(GCOV_COMMAND)
|
||||||
Message("Found GCOV: ${GCOV_COMMAND}")
|
Message("Found GCOV: ${GCOV_COMMAND}")
|
||||||
Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND})
|
Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND})
|
||||||
EndIf(GCOV_COMMAND)
|
EndIf(GCOV_COMMAND)
|
||||||
|
EndIf()
|
||||||
|
|
||||||
Set(ENV{ctest_model} Nightly)
|
If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile)
|
||||||
|
Ctest_Empty_Binary_Directory(${CTEST_BINARY_DIRECTORY})
|
||||||
CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
|
|
||||||
|
|
||||||
EndIf()
|
EndIf()
|
||||||
|
|
||||||
Ctest_Start($ENV{ctest_model})
|
Ctest_Start($ENV{ctest_model})
|
||||||
@@ -60,9 +60,26 @@ Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
|
|||||||
PARALLEL_LEVEL $ENV{number_of_processors}
|
PARALLEL_LEVEL $ENV{number_of_processors}
|
||||||
RETURN_VALUE _ctest_test_ret_val
|
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)
|
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()
|
EndIf()
|
||||||
|
|
||||||
Ctest_Submit()
|
Ctest_Submit()
|
||||||
|
40
Jenkinsfile
vendored
40
Jenkinsfile
vendored
@@ -4,24 +4,31 @@ def specToLabel(Map spec) {
|
|||||||
return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}"
|
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 = [:]
|
def nodes = [:]
|
||||||
for (spec in specs) {
|
for (spec in specs) {
|
||||||
def label = specToLabel(spec)
|
def label = specToLabel(spec)
|
||||||
nodes[label] = {
|
nodes["${prefix}/${label}"] = {
|
||||||
node(label) {
|
node(label) {
|
||||||
githubNotify(context: "alfa-ci/${label}", description: 'Building ...', status: 'PENDING')
|
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
|
||||||
try {
|
try {
|
||||||
deleteDir()
|
deleteDir()
|
||||||
checkout scm
|
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)
|
callback.call(spec, label)
|
||||||
|
|
||||||
deleteDir()
|
deleteDir()
|
||||||
githubNotify(context: "alfa-ci/${label}", description: 'Success', status: 'SUCCESS')
|
githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
deleteDir()
|
deleteDir()
|
||||||
githubNotify(context: "alfa-ci/${label}", description: 'Error', status: 'ERROR')
|
githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR')
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,22 +40,25 @@ def buildMatrix(List specs, Closure callback) {
|
|||||||
pipeline{
|
pipeline{
|
||||||
agent none
|
agent none
|
||||||
stages {
|
stages {
|
||||||
stage("Run Build/Test Matrix") {
|
stage("Run CI Matrix") {
|
||||||
steps{
|
steps{
|
||||||
script {
|
script {
|
||||||
parallel(buildMatrix([
|
def build_jobs = jobMatrix('alfa-ci/build', [
|
||||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'may18'],
|
[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'],
|
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'may18'],
|
||||||
]) { spec, label ->
|
]) { 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'
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
README.md
51
README.md
@@ -1,12 +1,14 @@
|
|||||||
<!-- {#mainpage} -->
|
<!-- {#mainpage} -->
|
||||||
# FairMQ
|
# FairMQ [](COPYRIGHT)
|
||||||
|
|
||||||
C++ Message passing framework
|
C++ Message Queuing Library and Framework
|
||||||
|
|
||||||
| Branch | Build Status |
|
| Branch | Version | Docs | Status |
|
||||||
| :---: | :--- |
|
| :---: | :--- | :--- | :--- |
|
||||||
| `master` |  |
|
| `master` | [](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) | [](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [](https://codecov.io/gh/FairRootGroup/FairMQ/branch/master) |
|
||||||
| `dev` |  |
|
| `dev` | [](https://github.com/FairRootGroup/FairMQ/tags) | [Book](https://github.com/FairRootGroup/FairMQ/blob/dev/README.md#documentation) | [](https://alfa-ci.gsi.de/blue/organizations/jenkins/FairRootGroup%2FFairMQ/branches) [](https://codecov.io/gh/FairRootGroup/FairMQ/branch/dev) |
|
||||||
|
|
||||||
|
## 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
|
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,
|
* provide **an asynchronous message passing abstraction** of different data transport technologies,
|
||||||
@@ -29,32 +31,17 @@ configuration and control services.
|
|||||||
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
|
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
|
||||||
a simulation, reconstruction and analysis framework.
|
a simulation, reconstruction and analysis framework.
|
||||||
|
|
||||||
|
Find all FairMQ releases and development tags [here](https://github.com/FairRootGroup/FairMQ/releases).
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
* [**Boost**](https://www.boost.org/) (PUBLIC)
|
* PUBLIC: [**Boost**](https://www.boost.org/), [**FairLogger**](https://github.com/FairRootGroup/FairLogger)
|
||||||
* [**FairLogger**](https://github.com/FairRootGroup/FairLogger) (PUBLIC)
|
* BUILD: [CMake](https://cmake.org/), [GTest](https://github.com/google/googletest), [Doxygen](http://www.doxygen.org/)
|
||||||
* [CMake](https://cmake.org/) (BUILD)
|
* PRIVATE: [ZeroMQ](http://zeromq.org/), [Msgpack](https://msgpack.org/index.html), [nanomsg](http://nanomsg.org/),
|
||||||
* [GTest](https://github.com/google/googletest) (BUILD, optional, `tests`)
|
[OFI](https://ofiwg.github.io/libfabric/), [Protobuf](https://developers.google.com/protocol-buffers/), [DDS](http://dds.gsi.de)
|
||||||
* [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`)
|
|
||||||
|
|
||||||
Supported platforms: Linux and MacOS.
|
Supported platforms: Linux and MacOS.
|
||||||
|
|
||||||
## Releases
|
|
||||||
|
|
||||||
| Stable release | Date | API Docs |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| [**1.2.3**](https://github.com/FairRootGroup/FairMQ/releases/tag/v1.2.3) | May 2018 | [link](https://fairrootgroup.github.io/FairMQ/v1.2.3/index.html) |
|
|
||||||
| [**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
|
## Installation from Source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -89,7 +76,7 @@ In order to succesfully compile and link against the `FairMQ::FairMQ` target, yo
|
|||||||
find_package(FairMQ)
|
find_package(FairMQ)
|
||||||
if(FairMQ_FOUND)
|
if(FairMQ_FOUND)
|
||||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_BOOST_COMPONENTS})
|
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS})
|
||||||
endif()
|
endif()
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -101,7 +88,7 @@ Optionally, you can require certain FairMQ package components and a minimum vers
|
|||||||
find_package(FairMQ 1.1.0 COMPONENTS nanomsg_transport dds_plugin)
|
find_package(FairMQ 1.1.0 COMPONENTS nanomsg_transport dds_plugin)
|
||||||
if(FairMQ_FOUND)
|
if(FairMQ_FOUND)
|
||||||
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
|
||||||
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_BOOST_COMPONENTS})
|
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS})
|
||||||
endif()
|
endif()
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -169,9 +156,3 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
|
|||||||
4. [File output](docs/Logging.md#54-file-output)
|
4. [File output](docs/Logging.md#54-file-output)
|
||||||
5. [Custom sinks](docs/Logging.md#55-custom-sinks)
|
5. [Custom sinks](docs/Logging.md#55-custom-sinks)
|
||||||
6. [Examples](docs/Examples.md#6-examples)
|
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
|
|
||||||
|
@@ -112,7 +112,6 @@ macro(set_fairmq_defaults)
|
|||||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Handle C++ standard level
|
# Handle C++ standard level
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
@@ -158,9 +157,23 @@ macro(set_fairmq_defaults)
|
|||||||
# Define export set, only one for now
|
# Define export set, only one for now
|
||||||
set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets)
|
set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets)
|
||||||
|
|
||||||
# Override CMake defaults
|
# 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_NIGHTLY "-O2 -g -Wshadow -Wall -Wextra")
|
||||||
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs -Wshadow -Wall -Wextra -Wunused-variable")
|
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()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
function(join VALUES GLUE OUTPUT)
|
function(join VALUES GLUE OUTPUT)
|
||||||
@@ -237,7 +250,7 @@ endfunction()
|
|||||||
macro(install_cmake_package)
|
macro(install_cmake_package)
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
set(PACKAGE_INSTALL_DESTINATION
|
set(PACKAGE_INSTALL_DESTINATION
|
||||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
|
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_GIT_VERSION}
|
||||||
)
|
)
|
||||||
if(BUILD_FAIRMQ)
|
if(BUILD_FAIRMQ)
|
||||||
install(EXPORT ${PROJECT_EXPORT_SET}
|
install(EXPORT ${PROJECT_EXPORT_SET}
|
||||||
|
46
cmake/Findmsgpack.cmake
Normal file
46
cmake/Findmsgpack.cmake
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
################################################################################
|
||||||
|
# Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||||
|
# #
|
||||||
|
# This software is distributed under the terms of the #
|
||||||
|
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||||
|
# copied verbatim in the file "LICENSE" #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
unset(_args)
|
||||||
|
|
||||||
|
if(msgpack_FIND_VERSION)
|
||||||
|
list(APPEND _args ${msgpack_FIND_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(msgpack_FIND_EXACT)
|
||||||
|
list(APPEND _args "EXACT")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(msgpack_FIND_QUIETLY)
|
||||||
|
list(APPEND _args "QUIET")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(msgpack_FIND_REQUIRED)
|
||||||
|
list(APPEND _args "REQUIRED")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(msgpack_FIND_COMPONENTS)
|
||||||
|
list(APPEND _args "COMPONENTS" ${msgpack_FIND_COMPONENTS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(msgpack ${_args} CONFIG)
|
||||||
|
|
||||||
|
if(msgpack_FOUND AND NOT TARGET msgpack::msgpack)
|
||||||
|
# config mode find_package does not set $msgpack_ROOT, workaround by extracting
|
||||||
|
# root path from library target
|
||||||
|
unset(_msgpack_lib)
|
||||||
|
unset(_prefix)
|
||||||
|
get_target_property(_msgpack_lib msgpackc INTERFACE_LOCATION)
|
||||||
|
get_filename_component(_prefix ${_msgpack_lib} DIRECTORY)
|
||||||
|
get_filename_component(_prefix ${_prefix}/.. ABSOLUTE)
|
||||||
|
|
||||||
|
add_library(msgpack::msgpack INTERFACE IMPORTED)
|
||||||
|
set_target_properties(msgpack::msgpack PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${_prefix}/include"
|
||||||
|
)
|
||||||
|
endif()
|
4190
cmake/cotire.cmake
Normal file
4190
cmake/cotire.cmake
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
|
||||||
...
|
|
@@ -191,16 +191,25 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/options/startConfigExample.sh.in ${CM
|
|||||||
#################################
|
#################################
|
||||||
# define libFairMQ build target #
|
# define libFairMQ build target #
|
||||||
#################################
|
#################################
|
||||||
add_library(FairMQ SHARED
|
if(FAST_BUILD)
|
||||||
|
set(_target FairMQ_)
|
||||||
|
else()
|
||||||
|
set(_target FairMQ)
|
||||||
|
endif()
|
||||||
|
add_library(${_target} SHARED
|
||||||
${FAIRMQ_SOURCE_FILES}
|
${FAIRMQ_SOURCE_FILES}
|
||||||
${FAIRMQ_PUBLIC_HEADER_FILES} # for IDE integration
|
${FAIRMQ_PUBLIC_HEADER_FILES} # for IDE integration
|
||||||
${FAIRMQ_PRIVATE_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 #
|
# include directories #
|
||||||
#######################
|
#######################
|
||||||
target_include_directories(FairMQ
|
target_include_directories(${_target}
|
||||||
PUBLIC # consumers inherit public include directories
|
PUBLIC # consumers inherit public include directories
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
||||||
@@ -213,15 +222,21 @@ target_include_directories(FairMQ
|
|||||||
# link libraries #
|
# link libraries #
|
||||||
##################
|
##################
|
||||||
if(BUILD_NANOMSG_TRANSPORT)
|
if(BUILD_NANOMSG_TRANSPORT)
|
||||||
set(NANOMSG_DEPS nanomsg msgpackc)
|
set(NANOMSG_DEPS nanomsg msgpack::msgpack)
|
||||||
endif()
|
endif()
|
||||||
if(BUILD_OFI_TRANSPORT)
|
if(BUILD_OFI_TRANSPORT)
|
||||||
set(OFI_DEPS OFI::libfabric protobuf::libprotobuf $<TARGET_OBJECTS:OfiTransport>)
|
set(OFI_DEPS OFI::libfabric protobuf::libprotobuf $<TARGET_OBJECTS:OfiTransport>)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(FairMQ
|
set(optional_deps ${NANOMSG_DEPS} ${OFI_DEPS})
|
||||||
|
if(optional_deps)
|
||||||
|
list(REMOVE_DUPLICATES optional_deps)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${_target}
|
||||||
INTERFACE # only consumers link against interface dependencies
|
INTERFACE # only consumers link against interface dependencies
|
||||||
|
|
||||||
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
|
PUBLIC # libFairMQ AND consumers of libFairMQ link aginst public dependencies
|
||||||
|
Threads::Threads
|
||||||
dl
|
dl
|
||||||
Boost::boost
|
Boost::boost
|
||||||
Boost::program_options
|
Boost::program_options
|
||||||
@@ -238,15 +253,30 @@ target_link_libraries(FairMQ
|
|||||||
${NANOMSG_DEPS}
|
${NANOMSG_DEPS}
|
||||||
${OFI_DEPS}
|
${OFI_DEPS}
|
||||||
)
|
)
|
||||||
set_target_properties(FairMQ PROPERTIES
|
set_target_properties(${_target} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_GIT_VERSION}
|
||||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
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 #
|
# executables #
|
||||||
###############
|
###############
|
||||||
|
|
||||||
add_executable(fairmq-bsampler run/runBenchmarkSampler.cxx)
|
add_executable(fairmq-bsampler run/runBenchmarkSampler.cxx)
|
||||||
target_link_libraries(fairmq-bsampler FairMQ)
|
target_link_libraries(fairmq-bsampler FairMQ)
|
||||||
|
|
||||||
@@ -274,11 +304,12 @@ target_link_libraries(fairmq-shmmonitor FairMQ)
|
|||||||
add_executable(fairmq-uuid-gen run/runUuidGenerator.cxx)
|
add_executable(fairmq-uuid-gen run/runUuidGenerator.cxx)
|
||||||
target_link_libraries(fairmq-uuid-gen FairMQ)
|
target_link_libraries(fairmq-uuid-gen FairMQ)
|
||||||
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# install #
|
# install #
|
||||||
###########
|
###########
|
||||||
install(
|
install(
|
||||||
TARGETS # FairMQFull, tests are not installed
|
TARGETS
|
||||||
FairMQ
|
FairMQ
|
||||||
fairmq-bsampler
|
fairmq-bsampler
|
||||||
fairmq-merger
|
fairmq-merger
|
||||||
@@ -290,8 +321,8 @@ install(
|
|||||||
fairmq-uuid-gen
|
fairmq-uuid-gen
|
||||||
|
|
||||||
EXPORT ${PROJECT_EXPORT_SET}
|
EXPORT ${PROJECT_EXPORT_SET}
|
||||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
# preserve relative path and prepend fairmq
|
# preserve relative path and prepend fairmq
|
||||||
|
@@ -13,11 +13,12 @@
|
|||||||
using namespace fair::mq;
|
using namespace fair::mq;
|
||||||
|
|
||||||
DeviceRunner::DeviceRunner(int argc, char* const argv[])
|
DeviceRunner::DeviceRunner(int argc, char* const argv[])
|
||||||
: fRawCmdLineArgs{tools::ToStrVector(argc, argv, false)}
|
: fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))
|
||||||
, fPluginManager{PluginManager::MakeFromCommandLineOptions(fRawCmdLineArgs)}
|
, fConfig()
|
||||||
, fDevice{nullptr}
|
, fDevice(nullptr)
|
||||||
{
|
, fPluginManager(fRawCmdLineArgs)
|
||||||
}
|
, fEvents()
|
||||||
|
{}
|
||||||
|
|
||||||
auto DeviceRunner::Run() -> int
|
auto DeviceRunner::Run() -> int
|
||||||
{
|
{
|
||||||
@@ -26,16 +27,16 @@ auto DeviceRunner::Run() -> int
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
// Load builtin plugins last
|
// Load builtin plugins last
|
||||||
fPluginManager->LoadPlugin("s:control");
|
fPluginManager.LoadPlugin("s:control");
|
||||||
|
|
||||||
////// CALL HOOK ///////
|
////// CALL HOOK ///////
|
||||||
fEvents.Emit<hooks::SetCustomCmdLineOptions>(*this);
|
fEvents.Emit<hooks::SetCustomCmdLineOptions>(*this);
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
fPluginManager->ForEachPluginProgOptions([&](boost::program_options::options_description options){
|
fPluginManager.ForEachPluginProgOptions([&](boost::program_options::options_description options){
|
||||||
fConfig.AddToCmdLineOptions(options);
|
fConfig.AddToCmdLineOptions(options);
|
||||||
});
|
});
|
||||||
fConfig.AddToCmdLineOptions(fPluginManager->ProgramOptions());
|
fConfig.AddToCmdLineOptions(fPluginManager.ProgramOptions());
|
||||||
|
|
||||||
////// CALL HOOK ///////
|
////// CALL HOOK ///////
|
||||||
fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);
|
fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);
|
||||||
@@ -82,13 +83,16 @@ auto DeviceRunner::Run() -> int
|
|||||||
fDevice->SetConfig(fConfig);
|
fDevice->SetConfig(fConfig);
|
||||||
|
|
||||||
// Initialize plugin services
|
// Initialize plugin services
|
||||||
fPluginManager->EmplacePluginServices(&fConfig, fDevice);
|
fPluginManager.EmplacePluginServices(fConfig, *fDevice);
|
||||||
|
|
||||||
// Instantiate and run plugins
|
// Instantiate and run plugins
|
||||||
fPluginManager->InstantiatePlugins();
|
fPluginManager.InstantiatePlugins();
|
||||||
|
|
||||||
|
// Run the device
|
||||||
|
fDevice->RunStateMachine();
|
||||||
|
|
||||||
// Wait for control plugin to release device control
|
// Wait for control plugin to release device control
|
||||||
fPluginManager->WaitForPluginsToReleaseDeviceControl();
|
fPluginManager.WaitForPluginsToReleaseDeviceControl();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -62,9 +62,9 @@ class DeviceRunner
|
|||||||
auto RemoveHook() -> void { fEvents.Unsubscribe<H>("runner"); }
|
auto RemoveHook() -> void { fEvents.Unsubscribe<H>("runner"); }
|
||||||
|
|
||||||
std::vector<std::string> fRawCmdLineArgs;
|
std::vector<std::string> fRawCmdLineArgs;
|
||||||
std::shared_ptr<PluginManager> fPluginManager;
|
|
||||||
FairMQProgOptions fConfig;
|
FairMQProgOptions fConfig;
|
||||||
std::shared_ptr<FairMQDevice> fDevice;
|
std::unique_ptr<FairMQDevice> fDevice;
|
||||||
|
PluginManager fPluginManager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventManager fEvents;
|
EventManager fEvents;
|
||||||
|
@@ -755,7 +755,7 @@ void FairMQChannel::CheckSendCompatibility(FairMQMessagePtr& msg) const
|
|||||||
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
||||||
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
||||||
msg->GetSize(),
|
msg->GetSize(),
|
||||||
[](void* /*data*/, void* msg) { delete static_cast<FairMQMessage*>(msg); },
|
[](void* /*data*/, void* _msg) { delete static_cast<FairMQMessage*>(_msg); },
|
||||||
msg.get()
|
msg.get()
|
||||||
));
|
));
|
||||||
msg.release();
|
msg.release();
|
||||||
@@ -772,7 +772,7 @@ void FairMQChannel::CheckSendCompatibility(vector<FairMQMessagePtr>& msgVec) con
|
|||||||
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
// LOG(debug) << "Channel type does not match message type. Creating wrapper";
|
||||||
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
FairMQMessagePtr msgWrapper(NewMessage(msg->GetData(),
|
||||||
msg->GetSize(),
|
msg->GetSize(),
|
||||||
[](void* /*data*/, void* msg) { delete static_cast<FairMQMessage*>(msg); },
|
[](void* /*data*/, void* _msg) { delete static_cast<FairMQMessage*>(_msg); },
|
||||||
msg.get()
|
msg.get()
|
||||||
));
|
));
|
||||||
msg.release();
|
msg.release();
|
||||||
|
@@ -416,6 +416,8 @@ class FairMQDevice : public FairMQStateMachine
|
|||||||
void SetRawCmdLineArgs(const std::vector<std::string>& args) { fRawCmdLineArgs = args; }
|
void SetRawCmdLineArgs(const std::vector<std::string>& args) { fRawCmdLineArgs = args; }
|
||||||
std::vector<std::string> GetRawCmdLineArgs() const { return fRawCmdLineArgs; }
|
std::vector<std::string> GetRawCmdLineArgs() const { return fRawCmdLineArgs; }
|
||||||
|
|
||||||
|
void RunStateMachine() { ProcessWork(); };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<FairMQTransportFactory> fTransportFactory; ///< Default transport factory
|
std::shared_ptr<FairMQTransportFactory> fTransportFactory; ///< Default transport factory
|
||||||
std::unordered_map<fair::mq::Transport, std::shared_ptr<FairMQTransportFactory>> fTransports; ///< Container for transports
|
std::unordered_map<fair::mq::Transport, std::shared_ptr<FairMQTransportFactory>> fTransports; ///< Container for transports
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FairMQStateMachine.h"
|
#include "FairMQStateMachine.h"
|
||||||
|
#include <fairmq/Tools.h>
|
||||||
|
|
||||||
// Increase maximum number of boost::msm states (default is 10)
|
// Increase maximum number of boost::msm states (default is 10)
|
||||||
// This #define has to be before any msm header includes
|
// This #define has to be before any msm header includes
|
||||||
@@ -29,13 +30,20 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <thread>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <array>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace boost::msm::front;
|
||||||
|
|
||||||
namespace msmf = boost::msm::front;
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct hash<FairMQStateMachine::Event> : fair::mq::tools::HashEnum<FairMQStateMachine::Event> {};
|
||||||
|
|
||||||
|
} /* namespace std */
|
||||||
|
|
||||||
namespace fair
|
namespace fair
|
||||||
{
|
{
|
||||||
@@ -44,35 +52,111 @@ namespace mq
|
|||||||
namespace fsm
|
namespace fsm
|
||||||
{
|
{
|
||||||
|
|
||||||
// defining events for the boost MSM state machine
|
// list of FSM states
|
||||||
struct INIT_DEVICE_E { string name() const { return "INIT_DEVICE"; } };
|
struct OK_FSM_STATE : public state<> { static string Name() { return "OK"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::OK; } };
|
||||||
struct internal_DEVICE_READY_E { string name() const { return "internal_DEVICE_READY"; } };
|
struct ERROR_FSM_STATE : public terminate_state<> { static string Name() { return "ERROR"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::Error; } };
|
||||||
struct INIT_TASK_E { string name() const { return "INIT_TASK"; } };
|
|
||||||
struct internal_READY_E { string name() const { return "internal_READY"; } };
|
|
||||||
struct RUN_E { string name() const { return "RUN"; } };
|
|
||||||
struct PAUSE_E { string name() const { return "PAUSE"; } };
|
|
||||||
struct STOP_E { string name() const { return "STOP"; } };
|
|
||||||
struct RESET_TASK_E { string name() const { return "RESET_TASK"; } };
|
|
||||||
struct RESET_DEVICE_E { string name() const { return "RESET_DEVICE"; } };
|
|
||||||
struct internal_IDLE_E { string name() const { return "internal_IDLE"; } };
|
|
||||||
struct END_E { string name() const { return "END"; } };
|
|
||||||
struct ERROR_FOUND_E { string name() const { return "ERROR_FOUND"; } };
|
|
||||||
|
|
||||||
// deactivate the warning for non-virtual destructor thrown in the boost library
|
struct IDLE_FSM_STATE : public state<> { static string Name() { return "IDLE"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::IDLE; } };
|
||||||
#if defined(__clang__)
|
struct INITIALIZING_DEVICE_FSM_STATE : public state<> { static string Name() { return "INITIALIZING_DEVICE"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::INITIALIZING_DEVICE; } };
|
||||||
_Pragma("clang diagnostic push")
|
struct DEVICE_READY_FSM_STATE : public state<> { static string Name() { return "DEVICE_READY"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::DEVICE_READY; } };
|
||||||
_Pragma("clang diagnostic ignored \"-Wnon-virtual-dtor\"")
|
struct INITIALIZING_TASK_FSM_STATE : public state<> { static string Name() { return "INITIALIZING_TASK"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::INITIALIZING_TASK; } };
|
||||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
struct READY_FSM_STATE : public state<> { static string Name() { return "READY"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::READY; } };
|
||||||
_Pragma("GCC diagnostic push")
|
struct RUNNING_FSM_STATE : public state<> { static string Name() { return "RUNNING"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::RUNNING; } };
|
||||||
_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
|
struct PAUSED_FSM_STATE : public state<> { static string Name() { return "PAUSED"; } static FairMQStateMachine::State Type() { return FairMQStateMachine::State::PAUSED; } };
|
||||||
#endif
|
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
|
// defining the boost MSM state machine
|
||||||
struct Machine_ : public msmf::state_machine_def<Machine_>
|
struct Machine_ : public state_machine_def<Machine_>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Machine_()
|
Machine_()
|
||||||
: fWork()
|
: fUnblockHandler()
|
||||||
|
, fStateHandlers()
|
||||||
|
, fWork()
|
||||||
, fWorkAvailableCondition()
|
, fWorkAvailableCondition()
|
||||||
, fWorkDoneCondition()
|
, fWorkDoneCondition()
|
||||||
, fWorkMutex()
|
, fWorkMutex()
|
||||||
@@ -81,23 +165,22 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
, fWorkAvailable(false)
|
, fWorkAvailable(false)
|
||||||
, fStateChangeSignal()
|
, fStateChangeSignal()
|
||||||
, fStateChangeSignalsMap()
|
, fStateChangeSignalsMap()
|
||||||
, fTerminationRequested(false)
|
|
||||||
, fState()
|
, fState()
|
||||||
, fWorkerThread()
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~Machine_()
|
virtual ~Machine_()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
// initial states
|
||||||
|
using initial_state = boost::mpl::vector<IDLE_FSM_STATE, OK_FSM_STATE>;
|
||||||
|
|
||||||
template<typename Event, typename FSM>
|
template<typename Event, typename FSM>
|
||||||
void on_entry(Event const&, FSM& fsm)
|
void on_entry(Event const&, FSM& fsm)
|
||||||
{
|
{
|
||||||
LOG(state) << "Starting FairMQ state machine";
|
LOG(state) << "Starting FairMQ state machine";
|
||||||
fState = FairMQStateMachine::IDLE;
|
fState = FairMQStateMachine::IDLE;
|
||||||
|
LOG(state) << "Entering IDLE state";
|
||||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::IDLE);
|
fsm.CallStateChangeCallbacks(FairMQStateMachine::IDLE);
|
||||||
|
|
||||||
// start a worker thread to execute user states in.
|
|
||||||
fsm.fWorkerThread = thread(&Machine_::Worker, &fsm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Event, typename FSM>
|
template<typename Event, typename FSM>
|
||||||
@@ -106,41 +189,23 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
LOG(state) << "Exiting FairMQ state machine";
|
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
|
// actions
|
||||||
struct IdleFct
|
struct AutomaticFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
LOG(state) << "Entering IDLE state";
|
fsm.fState = ts.Type();
|
||||||
fsm.fState = FairMQStateMachine::IDLE;
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InitDeviceFct
|
struct DefaultFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const& e, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
fsm.fState = FairMQStateMachine::INITIALIZING_DEVICE;
|
fsm.fState = ts.Type();
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||||
while (fsm.fWorkActive)
|
while (fsm.fWorkActive)
|
||||||
@@ -148,66 +213,8 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
fsm.fWorkDoneCondition.wait(lock);
|
fsm.fWorkDoneCondition.wait(lock);
|
||||||
}
|
}
|
||||||
fsm.fWorkAvailable = true;
|
fsm.fWorkAvailable = true;
|
||||||
LOG(state) << "Entering INITIALIZING DEVICE state";
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
fsm.fWork = fsm.fInitWrapperHandler;
|
fsm.fWork = fsm.fStateHandlers.at(e.Type());
|
||||||
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 = FairMQStateMachine::DEVICE_READY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InitTaskFct
|
|
||||||
{
|
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
|
||||||
{
|
|
||||||
fsm.fState = FairMQStateMachine::INITIALIZING_TASK;
|
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
|
||||||
while (fsm.fWorkActive)
|
|
||||||
{
|
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
|
||||||
}
|
|
||||||
fsm.fWorkAvailable = true;
|
|
||||||
LOG(state) << "Entering INITIALIZING TASK state";
|
|
||||||
fsm.fWork = fsm.fInitTaskWrapperHandler;
|
|
||||||
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 = FairMQStateMachine::READY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RunFct
|
|
||||||
{
|
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
|
||||||
{
|
|
||||||
fsm.fState = FairMQStateMachine::RUNNING;
|
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
|
||||||
while (fsm.fWorkActive)
|
|
||||||
{
|
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
|
||||||
}
|
|
||||||
fsm.fWorkAvailable = true;
|
|
||||||
LOG(state) << "Entering RUNNING state";
|
|
||||||
fsm.fWork = fsm.fRunWrapperHandler;
|
|
||||||
fsm.fWorkAvailableCondition.notify_one();
|
fsm.fWorkAvailableCondition.notify_one();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -215,9 +222,9 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
struct PauseFct
|
struct PauseFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
fsm.fState = FairMQStateMachine::PAUSED;
|
fsm.fState = ts.Type();
|
||||||
|
|
||||||
fsm.fUnblockHandler();
|
fsm.fUnblockHandler();
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||||
@@ -226,37 +233,18 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
fsm.fWorkDoneCondition.wait(lock);
|
fsm.fWorkDoneCondition.wait(lock);
|
||||||
}
|
}
|
||||||
fsm.fWorkAvailable = true;
|
fsm.fWorkAvailable = true;
|
||||||
LOG(state) << "Entering PAUSED state";
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
fsm.fWork = fsm.fPauseWrapperHandler;
|
fsm.fWork = fsm.fPauseWrapperHandler;
|
||||||
fsm.fWorkAvailableCondition.notify_one();
|
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 = FairMQStateMachine::RUNNING;
|
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
|
||||||
while (fsm.fWorkActive)
|
|
||||||
{
|
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
|
||||||
}
|
|
||||||
fsm.fWorkAvailable = true;
|
|
||||||
LOG(state) << "Entering RUNNING state";
|
|
||||||
fsm.fWork = fsm.fRunWrapperHandler;
|
|
||||||
fsm.fWorkAvailableCondition.notify_one();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StopFct
|
struct StopFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
fsm.fState = FairMQStateMachine::READY;
|
fsm.fState = ts.Type();
|
||||||
|
|
||||||
fsm.fUnblockHandler();
|
fsm.fUnblockHandler();
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
unique_lock<mutex> lock(fsm.fWorkMutex);
|
||||||
@@ -264,93 +252,48 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
{
|
{
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
fsm.fWorkDoneCondition.wait(lock);
|
||||||
}
|
}
|
||||||
LOG(state) << "Entering READY state";
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InternalStopFct
|
struct InternalStopFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
fsm.fState = FairMQStateMachine::READY;
|
fsm.fState = ts.Type();
|
||||||
fsm.fUnblockHandler();
|
fsm.fUnblockHandler();
|
||||||
LOG(state) << "RUNNING state finished without an external event, entering READY state";
|
LOG(state) << "RUNNING state finished without an external event, entering " << ts.Name() << " state";
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ResetTaskFct
|
|
||||||
{
|
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
|
||||||
{
|
|
||||||
fsm.fState = FairMQStateMachine::RESETTING_TASK;
|
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
|
||||||
while (fsm.fWorkActive)
|
|
||||||
{
|
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
|
||||||
}
|
|
||||||
fsm.fWorkAvailable = true;
|
|
||||||
LOG(state) << "Entering RESETTING TASK state";
|
|
||||||
fsm.fWork = fsm.fResetTaskWrapperHandler;
|
|
||||||
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 = FairMQStateMachine::RESETTING_DEVICE;
|
|
||||||
|
|
||||||
unique_lock<mutex> lock(fsm.fWorkMutex);
|
|
||||||
while (fsm.fWorkActive)
|
|
||||||
{
|
|
||||||
fsm.fWorkDoneCondition.wait(lock);
|
|
||||||
}
|
|
||||||
fsm.fWorkAvailable = true;
|
|
||||||
LOG(state) << "Entering RESETTING DEVICE state";
|
|
||||||
fsm.fWork = fsm.fResetWrapperHandler;
|
|
||||||
fsm.fWorkAvailableCondition.notify_one();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExitingFct
|
struct ExitingFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const& e, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
LOG(state) << "Entering EXITING state";
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
fsm.fState = FairMQStateMachine::EXITING;
|
fsm.fState = ts.Type();
|
||||||
fsm.fTerminationRequested = true;
|
|
||||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::EXITING);
|
fsm.CallStateChangeCallbacks(FairMQStateMachine::EXITING);
|
||||||
|
|
||||||
// terminate worker thread
|
// Stop ProcessWork()
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fsm.fWorkMutex);
|
lock_guard<mutex> lock(fsm.fWorkMutex);
|
||||||
fsm.fWorkerTerminated = true;
|
fsm.fWorkerTerminated = true;
|
||||||
fsm.fWorkAvailableCondition.notify_one();
|
fsm.fWorkAvailableCondition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
// join the worker thread (executing user states)
|
fsm.fStateHandlers.at(e.Type())();
|
||||||
if (fsm.fWorkerThread.joinable())
|
|
||||||
{
|
|
||||||
fsm.fWorkerThread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
fsm.fExitHandler();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ErrorFoundFct
|
struct ErrorFoundFct
|
||||||
{
|
{
|
||||||
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
template<typename EVT, typename FSM, typename SourceState, typename TargetState>
|
||||||
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
|
void operator()(EVT const&, FSM& fsm, SourceState& /* ss */, TargetState& ts)
|
||||||
{
|
{
|
||||||
LOG(state) << "Entering ERROR state";
|
fsm.fState = ts.Type();
|
||||||
fsm.fState = FairMQStateMachine::Error;
|
LOG(state) << "Entering " << ts.Name() << " state";
|
||||||
fsm.CallStateChangeCallbacks(FairMQStateMachine::Error);
|
fsm.CallStateChangeCallbacks(FairMQStateMachine::Error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -358,21 +301,21 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
// Transition table for Machine_
|
// Transition table for Machine_
|
||||||
struct transition_table : boost::mpl::vector<
|
struct transition_table : boost::mpl::vector<
|
||||||
// Start Event Next Action Guard
|
// Start Event Next Action Guard
|
||||||
msmf::Row<IDLE_FSM, INIT_DEVICE_E, INITIALIZING_DEVICE_FSM, InitDeviceFct, msmf::none>,
|
Row<IDLE_FSM_STATE, INIT_DEVICE_FSM_EVENT, INITIALIZING_DEVICE_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<IDLE_FSM, END_E, EXITING_FSM, ExitingFct, msmf::none>,
|
Row<IDLE_FSM_STATE, END_FSM_EVENT, EXITING_FSM_STATE, ExitingFct, none>,
|
||||||
msmf::Row<INITIALIZING_DEVICE_FSM, internal_DEVICE_READY_E, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
|
Row<INITIALIZING_DEVICE_FSM_STATE, internal_DEVICE_READY_FSM_EVENT, DEVICE_READY_FSM_STATE, AutomaticFct, none>,
|
||||||
msmf::Row<DEVICE_READY_FSM, INIT_TASK_E, INITIALIZING_TASK_FSM, InitTaskFct, msmf::none>,
|
Row<DEVICE_READY_FSM_STATE, INIT_TASK_FSM_EVENT, INITIALIZING_TASK_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<DEVICE_READY_FSM, RESET_DEVICE_E, RESETTING_DEVICE_FSM, ResetDeviceFct, msmf::none>,
|
Row<DEVICE_READY_FSM_STATE, RESET_DEVICE_FSM_EVENT, RESETTING_DEVICE_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<INITIALIZING_TASK_FSM, internal_READY_E, READY_FSM, ReadyFct, msmf::none>,
|
Row<INITIALIZING_TASK_FSM_STATE, internal_READY_FSM_EVENT, READY_FSM_STATE, AutomaticFct, none>,
|
||||||
msmf::Row<READY_FSM, RUN_E, RUNNING_FSM, RunFct, msmf::none>,
|
Row<READY_FSM_STATE, RUN_FSM_EVENT, RUNNING_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<READY_FSM, RESET_TASK_E, RESETTING_TASK_FSM, ResetTaskFct, msmf::none>,
|
Row<READY_FSM_STATE, RESET_TASK_FSM_EVENT, RESETTING_TASK_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<RUNNING_FSM, PAUSE_E, PAUSED_FSM, PauseFct, msmf::none>,
|
Row<RUNNING_FSM_STATE, PAUSE_FSM_EVENT, PAUSED_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<RUNNING_FSM, STOP_E, READY_FSM, StopFct, msmf::none>,
|
Row<RUNNING_FSM_STATE, STOP_FSM_EVENT, READY_FSM_STATE, StopFct, none>,
|
||||||
msmf::Row<RUNNING_FSM, internal_READY_E, READY_FSM, InternalStopFct, msmf::none>,
|
Row<RUNNING_FSM_STATE, internal_READY_FSM_EVENT, READY_FSM_STATE, InternalStopFct, none>,
|
||||||
msmf::Row<PAUSED_FSM, RUN_E, RUNNING_FSM, ResumeFct, msmf::none>,
|
Row<PAUSED_FSM_STATE, RUN_FSM_EVENT, RUNNING_FSM_STATE, DefaultFct, none>,
|
||||||
msmf::Row<RESETTING_TASK_FSM, internal_DEVICE_READY_E, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
|
Row<RESETTING_TASK_FSM_STATE, internal_DEVICE_READY_FSM_EVENT, DEVICE_READY_FSM_STATE, AutomaticFct, none>,
|
||||||
msmf::Row<RESETTING_DEVICE_FSM, internal_IDLE_E, IDLE_FSM, IdleFct, msmf::none>,
|
Row<RESETTING_DEVICE_FSM_STATE, internal_IDLE_FSM_EVENT, IDLE_FSM_STATE, AutomaticFct, none>,
|
||||||
msmf::Row<OK_FSM, ERROR_FOUND_E, ERROR_FSM, ErrorFoundFct, msmf::none>>
|
Row<OK_FSM_STATE, ERROR_FOUND_FSM_EVENT, ERROR_FSM_STATE, ErrorFoundFct, none>>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
// replaces the default no-transition response.
|
// replaces the default no-transition response.
|
||||||
@@ -391,45 +334,12 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
if (pos != string::npos)
|
if (pos != string::npos)
|
||||||
{
|
{
|
||||||
stateName = stateName.substr(pos + 1);
|
stateName = stateName.substr(pos + 1);
|
||||||
stateName = stateName.substr(0, stateName.size() - 4);
|
stateName = stateName.substr(0, stateName.size() - 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stateName != "OK")
|
if (stateName != "OK")
|
||||||
{
|
{
|
||||||
LOG(state) << "No transition from state " << stateName << " on event " << e.name();
|
LOG(state) << "No transition from state " << stateName << " on event " << e.Name();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetStateName(const int state)
|
|
||||||
{
|
|
||||||
switch(state)
|
|
||||||
{
|
|
||||||
case FairMQStateMachine::OK:
|
|
||||||
return "OK";
|
|
||||||
case FairMQStateMachine::Error:
|
|
||||||
return "Error";
|
|
||||||
case FairMQStateMachine::IDLE:
|
|
||||||
return "IDLE";
|
|
||||||
case FairMQStateMachine::INITIALIZING_DEVICE:
|
|
||||||
return "INITIALIZING_DEVICE";
|
|
||||||
case FairMQStateMachine::DEVICE_READY:
|
|
||||||
return "DEVICE_READY";
|
|
||||||
case FairMQStateMachine::INITIALIZING_TASK:
|
|
||||||
return "INITIALIZING_TASK";
|
|
||||||
case FairMQStateMachine::READY:
|
|
||||||
return "READY";
|
|
||||||
case FairMQStateMachine::RUNNING:
|
|
||||||
return "RUNNING";
|
|
||||||
case FairMQStateMachine::PAUSED:
|
|
||||||
return "PAUSED";
|
|
||||||
case FairMQStateMachine::RESETTING_TASK:
|
|
||||||
return "RESETTING_TASK";
|
|
||||||
case FairMQStateMachine::RESETTING_DEVICE:
|
|
||||||
return "RESETTING_DEVICE";
|
|
||||||
case FairMQStateMachine::EXITING:
|
|
||||||
return "EXITING";
|
|
||||||
default:
|
|
||||||
return "requested name for non-existent state...";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,14 +351,8 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function<void(void)> fInitWrapperHandler;
|
|
||||||
function<void(void)> fInitTaskWrapperHandler;
|
|
||||||
function<void(void)> fRunWrapperHandler;
|
|
||||||
function<void(void)> fPauseWrapperHandler;
|
|
||||||
function<void(void)> fResetWrapperHandler;
|
|
||||||
function<void(void)> fResetTaskWrapperHandler;
|
|
||||||
function<void(void)> fExitHandler;
|
|
||||||
function<void(void)> fUnblockHandler;
|
function<void(void)> fUnblockHandler;
|
||||||
|
unordered_map<FairMQStateMachine::Event, function<void(void)>> fStateHandlers;
|
||||||
|
|
||||||
// function to execute user states in a worker thread
|
// function to execute user states in a worker thread
|
||||||
function<void(void)> fWork;
|
function<void(void)> fWork;
|
||||||
@@ -461,12 +365,10 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
|
|
||||||
boost::signals2::signal<void(const FairMQStateMachine::State)> fStateChangeSignal;
|
boost::signals2::signal<void(const FairMQStateMachine::State)> fStateChangeSignal;
|
||||||
unordered_map<string, boost::signals2::connection> fStateChangeSignalsMap;
|
unordered_map<string, boost::signals2::connection> fStateChangeSignalsMap;
|
||||||
atomic<bool> fTerminationRequested;
|
|
||||||
|
|
||||||
atomic<FairMQStateMachine::State> fState;
|
atomic<FairMQStateMachine::State> fState;
|
||||||
|
|
||||||
private:
|
void ProcessWork()
|
||||||
void Worker()
|
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -475,7 +377,7 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
// Wait for work to be done.
|
// Wait for work to be done.
|
||||||
while (!fWorkAvailable && !fWorkerTerminated)
|
while (!fWorkAvailable && !fWorkerTerminated)
|
||||||
{
|
{
|
||||||
fWorkAvailableCondition.wait(lock);
|
fWorkAvailableCondition.wait_for(lock, chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fWorkerTerminated)
|
if (fWorkerTerminated)
|
||||||
@@ -497,20 +399,10 @@ struct Machine_ : public msmf::state_machine_def<Machine_>
|
|||||||
CallStateChangeCallbacks(fState);
|
CallStateChangeCallbacks(fState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run state handlers in a separate thread
|
|
||||||
thread fWorkerThread;
|
|
||||||
}; // Machine_
|
}; // Machine_
|
||||||
|
|
||||||
using FairMQFSM = boost::msm::back::state_machine<Machine_>;
|
using FairMQFSM = boost::msm::back::state_machine<Machine_>;
|
||||||
|
|
||||||
// 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 fsm
|
||||||
} // namespace mq
|
} // namespace mq
|
||||||
} // namespace fair
|
} // namespace fair
|
||||||
@@ -521,13 +413,13 @@ FairMQStateMachine::FairMQStateMachine()
|
|||||||
: fChangeStateMutex()
|
: fChangeStateMutex()
|
||||||
, fFsm(new FairMQFSM)
|
, fFsm(new FairMQFSM)
|
||||||
{
|
{
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fInitWrapperHandler = bind(&FairMQStateMachine::InitWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(INIT_DEVICE, bind(&FairMQStateMachine::InitWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fInitTaskWrapperHandler = bind(&FairMQStateMachine::InitTaskWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(INIT_TASK, bind(&FairMQStateMachine::InitTaskWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fRunWrapperHandler = bind(&FairMQStateMachine::RunWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RUN, bind(&FairMQStateMachine::RunWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fPauseWrapperHandler = bind(&FairMQStateMachine::PauseWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(PAUSE, bind(&FairMQStateMachine::PauseWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fResetWrapperHandler = bind(&FairMQStateMachine::ResetWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RESET_TASK, bind(&FairMQStateMachine::ResetTaskWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fResetTaskWrapperHandler = bind(&FairMQStateMachine::ResetTaskWrapper, this);
|
static_pointer_cast<FairMQFSM>(fFsm)->fStateHandlers.emplace(RESET_DEVICE, bind(&FairMQStateMachine::ResetWrapper, this));
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->fExitHandler = bind(&FairMQStateMachine::Exit, 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)->fUnblockHandler = bind(&FairMQStateMachine::Unblock, this);
|
||||||
|
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->start();
|
static_pointer_cast<FairMQFSM>(fFsm)->start();
|
||||||
@@ -552,73 +444,73 @@ bool FairMQStateMachine::ChangeState(int event)
|
|||||||
case INIT_DEVICE:
|
case INIT_DEVICE:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_DEVICE_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_DEVICE_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case internal_DEVICE_READY:
|
case internal_DEVICE_READY:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_DEVICE_READY_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_DEVICE_READY_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case INIT_TASK:
|
case INIT_TASK:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_TASK_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(INIT_TASK_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case internal_READY:
|
case internal_READY:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_READY_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_READY_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RUN:
|
case RUN:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RUN_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RUN_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case PAUSE:
|
case PAUSE:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(PAUSE_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(PAUSE_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case STOP:
|
case STOP:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(STOP_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(STOP_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RESET_DEVICE:
|
case RESET_DEVICE:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_DEVICE_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_DEVICE_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RESET_TASK:
|
case RESET_TASK:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_TASK_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(RESET_TASK_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case internal_IDLE:
|
case internal_IDLE:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_IDLE_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(internal_IDLE_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case END:
|
case END:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(END_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(END_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case ERROR_FOUND:
|
case ERROR_FOUND:
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock(fChangeStateMutex);
|
lock_guard<mutex> lock(fChangeStateMutex);
|
||||||
static_pointer_cast<FairMQFSM>(fFsm)->process_event(ERROR_FOUND_E());
|
static_pointer_cast<FairMQFSM>(fFsm)->process_event(ERROR_FOUND_FSM_EVENT());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -738,7 +630,11 @@ void FairMQStateMachine::CallStateChangeCallbacks(const State state) const
|
|||||||
|
|
||||||
string FairMQStateMachine::GetCurrentStateName() const
|
string FairMQStateMachine::GetCurrentStateName() const
|
||||||
{
|
{
|
||||||
return static_pointer_cast<FairMQFSM>(fFsm)->GetStateName(static_pointer_cast<FairMQFSM>(fFsm)->fState);
|
return GetStateName(static_pointer_cast<FairMQFSM>(fFsm)->fState);
|
||||||
|
}
|
||||||
|
string FairMQStateMachine::GetStateName(const State state)
|
||||||
|
{
|
||||||
|
return stateNames.at(state);
|
||||||
}
|
}
|
||||||
int FairMQStateMachine::GetCurrentState() const
|
int FairMQStateMachine::GetCurrentState() const
|
||||||
{
|
{
|
||||||
@@ -753,23 +649,12 @@ bool FairMQStateMachine::CheckCurrentState(string state) const
|
|||||||
return state == GetCurrentStateName();
|
return state == GetCurrentStateName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FairMQStateMachine::Terminated()
|
void FairMQStateMachine::ProcessWork()
|
||||||
{
|
{
|
||||||
return static_pointer_cast<FairMQFSM>(fFsm)->fTerminationRequested;
|
static_pointer_cast<FairMQFSM>(fFsm)->ProcessWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
int FairMQStateMachine::GetEventNumber(const string& event)
|
int FairMQStateMachine::GetEventNumber(const string& event)
|
||||||
{
|
{
|
||||||
if (event == "INIT_DEVICE") return INIT_DEVICE;
|
return eventNumbers.at(event);
|
||||||
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 << endl
|
|
||||||
<< "Supported are: INIT_DEVICE, INIT_TASK, RUN, PAUSE, STOP, RESET_DEVICE, RESET_TASK, END, ERROR_FOUND";
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
@@ -79,10 +79,10 @@ class FairMQStateMachine
|
|||||||
void CallStateChangeCallbacks(const State state) const;
|
void CallStateChangeCallbacks(const State state) const;
|
||||||
|
|
||||||
std::string GetCurrentStateName() const;
|
std::string GetCurrentStateName() const;
|
||||||
|
static std::string GetStateName(const State);
|
||||||
int GetCurrentState() const;
|
int GetCurrentState() const;
|
||||||
bool CheckCurrentState(int state) const;
|
bool CheckCurrentState(int state) const;
|
||||||
bool CheckCurrentState(std::string state) const;
|
bool CheckCurrentState(std::string state) const;
|
||||||
bool Terminated();
|
|
||||||
|
|
||||||
// actions to be overwritten by derived classes
|
// actions to be overwritten by derived classes
|
||||||
virtual void InitWrapper() {}
|
virtual void InitWrapper() {}
|
||||||
@@ -94,8 +94,10 @@ class FairMQStateMachine
|
|||||||
virtual void Exit() {}
|
virtual void Exit() {}
|
||||||
virtual void Unblock() {}
|
virtual void Unblock() {}
|
||||||
|
|
||||||
|
void ProcessWork();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int GetEventNumber(const std::string& event);
|
static int GetEventNumber(const std::string& event);
|
||||||
|
|
||||||
std::mutex fChangeStateMutex;
|
std::mutex fChangeStateMutex;
|
||||||
|
|
||||||
|
@@ -116,9 +116,9 @@ class Plugin
|
|||||||
} /* namespace fair */
|
} /* namespace fair */
|
||||||
|
|
||||||
#define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \
|
#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(Make_##NAME##_Plugin, make_##NAME##_plugin) \
|
||||||
BOOST_DLL_ALIAS(PROGOPTIONS, get_##NAME##_plugin_progoptions)
|
BOOST_DLL_ALIAS(PROGOPTIONS, get_##NAME##_plugin_progoptions)
|
||||||
|
@@ -31,13 +31,55 @@ const std::string fair::mq::PluginManager::fgkLibPrefix = "FairMQPlugin_";
|
|||||||
fair::mq::PluginManager::PluginManager()
|
fair::mq::PluginManager::PluginManager()
|
||||||
: fSearchPaths{{"."}}
|
: fSearchPaths{{"."}}
|
||||||
, fPluginFactories()
|
, fPluginFactories()
|
||||||
|
, fPluginServices()
|
||||||
, fPlugins()
|
, fPlugins()
|
||||||
, fPluginOrder()
|
, fPluginOrder()
|
||||||
, fPluginProgOptions()
|
, 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
|
auto fair::mq::PluginManager::ValidateSearchPath(const fs::path& path) -> void
|
||||||
{
|
{
|
||||||
if (path.empty()) throw BadSearchPath{"Specified path is empty."};
|
if (path.empty()) throw BadSearchPath{"Specified path is empty."};
|
||||||
@@ -81,46 +123,6 @@ auto fair::mq::PluginManager::ProgramOptions() -> po::options_description
|
|||||||
return plugin_options;
|
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
|
auto fair::mq::PluginManager::LoadPlugin(const string& pluginName) -> void
|
||||||
{
|
{
|
||||||
if (pluginName.substr(0,2) == "p:")
|
if (pluginName.substr(0,2) == "p:")
|
||||||
|
@@ -47,9 +47,15 @@ namespace mq
|
|||||||
class PluginManager
|
class PluginManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using PluginFactory = std::shared_ptr<fair::mq::Plugin>(PluginServices&);
|
using PluginFactory = std::unique_ptr<fair::mq::Plugin>(PluginServices&);
|
||||||
|
|
||||||
PluginManager();
|
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 SetSearchPaths(const std::vector<boost::filesystem::path>&) -> void;
|
||||||
auto AppendSearchPath(const boost::filesystem::path&) -> void;
|
auto AppendSearchPath(const boost::filesystem::path&) -> void;
|
||||||
@@ -64,7 +70,6 @@ class PluginManager
|
|||||||
struct PluginInstantiationError : std::runtime_error { using std::runtime_error::runtime_error; };
|
struct PluginInstantiationError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||||
|
|
||||||
static auto ProgramOptions() -> boost::program_options::options_description;
|
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; };
|
struct ProgramOptionsParseError : std::runtime_error { using std::runtime_error::runtime_error; };
|
||||||
|
|
||||||
static auto LibPrefix() -> const std::string& { return fgkLibPrefix; }
|
static auto LibPrefix() -> const std::string& { return fgkLibPrefix; }
|
||||||
@@ -111,10 +116,10 @@ class PluginManager
|
|||||||
static const std::string fgkLibPrefix;
|
static const std::string fgkLibPrefix;
|
||||||
std::vector<boost::filesystem::path> fSearchPaths;
|
std::vector<boost::filesystem::path> fSearchPaths;
|
||||||
std::map<std::string, std::function<PluginFactory>> fPluginFactories;
|
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::vector<std::string> fPluginOrder;
|
||||||
std::map<std::string, boost::program_options::options_description> fPluginProgOptions;
|
std::map<std::string, boost::program_options::options_description> fPluginProgOptions;
|
||||||
std::unique_ptr<PluginServices> fPluginServices;
|
|
||||||
}; /* class PluginManager */
|
}; /* class PluginManager */
|
||||||
|
|
||||||
} /* namespace mq */
|
} /* namespace mq */
|
||||||
|
@@ -98,7 +98,7 @@ auto PluginServices::ChangeDeviceState(const std::string& controller, const Devi
|
|||||||
|
|
||||||
if (fDeviceController == controller)
|
if (fDeviceController == controller)
|
||||||
{
|
{
|
||||||
fDevice->ChangeState(fkDeviceStateTransitionMap.at(next));
|
fDevice.ChangeState(fkDeviceStateTransitionMap.at(next));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -38,15 +38,20 @@ class PluginServices
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PluginServices() = delete;
|
PluginServices() = delete;
|
||||||
PluginServices(FairMQProgOptions* config, std::shared_ptr<FairMQDevice> device)
|
PluginServices(FairMQProgOptions& config, FairMQDevice& device)
|
||||||
: fConfig{config}
|
: fConfig(config)
|
||||||
, fDevice{device}
|
, fDevice(device)
|
||||||
, fDeviceController()
|
, fDeviceController()
|
||||||
, fDeviceControllerMutex()
|
, fDeviceControllerMutex()
|
||||||
, fReleaseDeviceControlCondition()
|
, fReleaseDeviceControlCondition()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~PluginServices()
|
||||||
|
{
|
||||||
|
LOG(debug) << "Shutting down Plugin Services";
|
||||||
|
}
|
||||||
|
|
||||||
PluginServices(const PluginServices&) = delete;
|
PluginServices(const PluginServices&) = delete;
|
||||||
PluginServices operator=(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); }
|
friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); }
|
||||||
|
|
||||||
/// @return current device state
|
/// @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
|
/// @brief Become device controller
|
||||||
/// @param controller id
|
/// @param controller id
|
||||||
@@ -155,19 +160,19 @@ class PluginServices
|
|||||||
/// the state is running in.
|
/// the state is running in.
|
||||||
auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function<void(DeviceState /*newState*/)> callback) -> void
|
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));
|
callback(fkDeviceStateMap.at(newState));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Unsubscribe from device state changes
|
/// @brief Unsubscribe from device state changes
|
||||||
/// @param subscriber id
|
/// @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
|
// Config API
|
||||||
struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
|
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
|
/// @brief Set config property
|
||||||
/// @param key
|
/// @param key
|
||||||
@@ -182,7 +187,7 @@ class PluginServices
|
|||||||
auto currentState = GetCurrentDeviceState();
|
auto currentState = GetCurrentDeviceState();
|
||||||
if (currentState == DeviceState::InitializingDevice)
|
if (currentState == DeviceState::InitializingDevice)
|
||||||
{
|
{
|
||||||
fConfig->SetValue(key, val);
|
fConfig.SetValue(key, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -200,7 +205,7 @@ class PluginServices
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
auto GetProperty(const std::string& key) const -> T {
|
auto GetProperty(const std::string& key) const -> T {
|
||||||
if (PropertyExists(key)) {
|
if (PropertyExists(key)) {
|
||||||
return fConfig->GetValue<T>(key);
|
return fConfig.GetValue<T>(key);
|
||||||
}
|
}
|
||||||
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", 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
|
/// 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 {
|
auto GetPropertyAsString(const std::string& key) const -> std::string {
|
||||||
if (PropertyExists(key)) {
|
if (PropertyExists(key)) {
|
||||||
return fConfig->GetStringValue(key);
|
return fConfig.GetStringValue(key);
|
||||||
}
|
}
|
||||||
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", 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
|
/// @brief Discover the list of property keys
|
||||||
/// @return 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
|
/// @brief Subscribe to property updates of type T
|
||||||
/// @param subscriber
|
/// @param subscriber
|
||||||
@@ -231,13 +236,13 @@ class PluginServices
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
auto SubscribeToPropertyChange(const std::string& subscriber, std::function<void(const std::string& key, T)> callback) const -> void
|
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
|
/// @brief Unsubscribe from property updates of type T
|
||||||
/// @param subscriber
|
/// @param subscriber
|
||||||
template<typename T>
|
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
|
/// @brief Subscribe to property updates
|
||||||
/// @param subscriber
|
/// @param subscriber
|
||||||
@@ -246,12 +251,12 @@ class PluginServices
|
|||||||
/// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string.
|
/// 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
|
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
|
/// @brief Unsubscribe from property updates that convert to string
|
||||||
/// @param subscriber
|
/// @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 CycleLogConsoleSeverityUp() -> void { Logger::CycleConsoleSeverityUp(); }
|
||||||
auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); }
|
auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); }
|
||||||
@@ -266,8 +271,8 @@ class PluginServices
|
|||||||
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
|
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up
|
FairMQProgOptions& fConfig;
|
||||||
std::shared_ptr<FairMQDevice> fDevice;
|
FairMQDevice& fDevice;
|
||||||
boost::optional<std::string> fDeviceController;
|
boost::optional<std::string> fDeviceController;
|
||||||
mutable std::mutex fDeviceControllerMutex;
|
mutable std::mutex fDeviceControllerMutex;
|
||||||
std::condition_variable fReleaseDeviceControlCondition;
|
std::condition_variable fReleaseDeviceControlCondition;
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "FairMQDevice.h"
|
#include "FairMQDevice.h"
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ class FairMQBenchmarkSampler : public FairMQDevice
|
|||||||
protected:
|
protected:
|
||||||
bool fSameMessage;
|
bool fSameMessage;
|
||||||
int fMsgSize;
|
int fMsgSize;
|
||||||
int fMsgCounter;
|
std::atomic<int> fMsgCounter;
|
||||||
int fMsgRate;
|
int fMsgRate;
|
||||||
uint64_t fNumIterations;
|
uint64_t fNumIterations;
|
||||||
uint64_t fMaxIterations;
|
uint64_t fMaxIterations;
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <fairmq/Tools.h>
|
#include <fairmq/Tools.h>
|
||||||
#include <FairMQLogger.h>
|
#include <FairMQLogger.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <zmq.h>
|
#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."};
|
throw MessageError{"Not yet implemented."};
|
||||||
}
|
}
|
||||||
@@ -91,7 +92,7 @@ auto Message::Rebuild(const size_t size) -> void
|
|||||||
fHint = nullptr;
|
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) {
|
if (fFreeFunction) {
|
||||||
fFreeFunction(fData, fHint);
|
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."};
|
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."};
|
throw MessageError{"Not yet implemented."};
|
||||||
}
|
}
|
||||||
|
@@ -17,12 +17,11 @@ using namespace std;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// ugly global state, but std::signal gives us no other choice
|
volatile sig_atomic_t gSignalStatus = 0;
|
||||||
std::function<void(int)> gSignalHandlerClosure;
|
|
||||||
|
|
||||||
extern "C" auto signal_handler(int signal) -> void
|
extern "C" auto signal_handler(int signal) -> void
|
||||||
{
|
{
|
||||||
gSignalHandlerClosure(signal);
|
gSignalStatus = signal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +36,13 @@ Control::Control(const string name, const Plugin::Version version, const string
|
|||||||
: Plugin(name, version, maintainer, homepage, pluginServices)
|
: Plugin(name, version, maintainer, homepage, pluginServices)
|
||||||
, fControllerThread()
|
, fControllerThread()
|
||||||
, fSignalHandlerThread()
|
, fSignalHandlerThread()
|
||||||
|
, fShutdownThread()
|
||||||
, fEvents()
|
, fEvents()
|
||||||
, fEventsMutex()
|
, fEventsMutex()
|
||||||
|
, fShutdownMutex()
|
||||||
, fNewEvent()
|
, fNewEvent()
|
||||||
, fDeviceTerminationRequested{false}
|
, fDeviceTerminationRequested(false)
|
||||||
|
, fHasShutdown(false)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -73,7 +75,7 @@ Control::Control(const string name, const Plugin::Version version, const string
|
|||||||
LOG(debug) << "catch-signals: " << GetProperty<int>("catch-signals");
|
LOG(debug) << "catch-signals: " << GetProperty<int>("catch-signals");
|
||||||
if (GetProperty<int>("catch-signals") > 0)
|
if (GetProperty<int>("catch-signals") > 0)
|
||||||
{
|
{
|
||||||
gSignalHandlerClosure = bind(&Control::SignalHandler, this, placeholders::_1);
|
fSignalHandlerThread = thread(&Control::SignalHandler, this);
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
}
|
}
|
||||||
@@ -263,17 +265,41 @@ auto Control::StaticMode() -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Control::SignalHandler(int signal) -> void
|
auto Control::SignalHandler() -> void
|
||||||
{
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (gSignalStatus != 0 && !fHasShutdown)
|
||||||
|
{
|
||||||
|
LOG(info) << "Received device shutdown request (signal " << gSignalStatus << ").";
|
||||||
|
LOG(info) << "Waiting for graceful device shutdown. Hit Ctrl-C again to abort immediately.";
|
||||||
|
|
||||||
if (!fDeviceTerminationRequested)
|
if (!fDeviceTerminationRequested)
|
||||||
{
|
{
|
||||||
fDeviceTerminationRequested = true;
|
fDeviceTerminationRequested = true;
|
||||||
|
gSignalStatus = 0;
|
||||||
|
fShutdownThread = thread(&Control::HandleShutdownSignal, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(warn) << "Received 2nd device shutdown request (signal " << gSignalStatus << ").";
|
||||||
|
LOG(warn) << "Aborting immediately!";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fHasShutdown)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this_thread::sleep_for(chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Control::HandleShutdownSignal() -> void
|
||||||
|
{
|
||||||
StealDeviceControl();
|
StealDeviceControl();
|
||||||
|
|
||||||
LOG(info) << "Received device shutdown request (signal " << signal << ").";
|
|
||||||
LOG(info) << "Waiting for graceful device shutdown. Hit Ctrl-C again to abort immediately.";
|
|
||||||
|
|
||||||
UnsubscribeFromDeviceStateChange(); // In case, static or interactive mode have subscribed already
|
UnsubscribeFromDeviceStateChange(); // In case, static or interactive mode have subscribed already
|
||||||
SubscribeToDeviceStateChange([&](DeviceState newState)
|
SubscribeToDeviceStateChange([&](DeviceState newState)
|
||||||
{
|
{
|
||||||
@@ -284,17 +310,13 @@ auto Control::SignalHandler(int signal) -> void
|
|||||||
fNewEvent.notify_one();
|
fNewEvent.notify_one();
|
||||||
});
|
});
|
||||||
|
|
||||||
fSignalHandlerThread = thread(&Control::RunShutdownSequence, this);
|
RunShutdownSequence();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(warn) << "Received 2nd device shutdown request (signal " << signal << ").";
|
|
||||||
LOG(warn) << "Aborting immediately !";
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Control::RunShutdownSequence() -> void
|
auto Control::RunShutdownSequence() -> void
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(fShutdownMutex);
|
||||||
|
if (!fHasShutdown)
|
||||||
{
|
{
|
||||||
auto nextState = GetCurrentDeviceState();
|
auto nextState = GetCurrentDeviceState();
|
||||||
EmptyEventQueue();
|
EmptyEventQueue();
|
||||||
@@ -318,15 +340,18 @@ auto Control::RunShutdownSequence() -> void
|
|||||||
ChangeDeviceState(DeviceStateTransition::Resume);
|
ChangeDeviceState(DeviceStateTransition::Resume);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// ignore other states
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextState = WaitForNextState();
|
nextState = WaitForNextState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fHasShutdown = true;
|
||||||
UnsubscribeFromDeviceStateChange();
|
UnsubscribeFromDeviceStateChange();
|
||||||
ReleaseDeviceControl();
|
ReleaseDeviceControl();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto Control::RunStartupSequence() -> void
|
auto Control::RunStartupSequence() -> void
|
||||||
{
|
{
|
||||||
@@ -357,6 +382,7 @@ Control::~Control()
|
|||||||
{
|
{
|
||||||
if (fControllerThread.joinable()) fControllerThread.join();
|
if (fControllerThread.joinable()) fControllerThread.join();
|
||||||
if (fSignalHandlerThread.joinable()) fSignalHandlerThread.join();
|
if (fSignalHandlerThread.joinable()) fSignalHandlerThread.join();
|
||||||
|
if (fShutdownThread.joinable()) fShutdownThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace plugins */
|
} /* namespace plugins */
|
||||||
|
@@ -37,17 +37,21 @@ class Control : public Plugin
|
|||||||
auto PrintInteractiveHelp() -> void;
|
auto PrintInteractiveHelp() -> void;
|
||||||
auto StaticMode() -> void;
|
auto StaticMode() -> void;
|
||||||
auto WaitForNextState() -> DeviceState;
|
auto WaitForNextState() -> DeviceState;
|
||||||
auto SignalHandler(int signal) -> void;
|
auto SignalHandler() -> void;
|
||||||
|
auto HandleShutdownSignal() -> void;
|
||||||
auto RunShutdownSequence() -> void;
|
auto RunShutdownSequence() -> void;
|
||||||
auto RunStartupSequence() -> void;
|
auto RunStartupSequence() -> void;
|
||||||
auto EmptyEventQueue() -> void;
|
auto EmptyEventQueue() -> void;
|
||||||
|
|
||||||
std::thread fControllerThread;
|
std::thread fControllerThread;
|
||||||
std::thread fSignalHandlerThread;
|
std::thread fSignalHandlerThread;
|
||||||
|
std::thread fShutdownThread;
|
||||||
std::queue<DeviceState> fEvents;
|
std::queue<DeviceState> fEvents;
|
||||||
std::mutex fEventsMutex;
|
std::mutex fEventsMutex;
|
||||||
|
std::mutex fShutdownMutex;
|
||||||
std::condition_variable fNewEvent;
|
std::condition_variable fNewEvent;
|
||||||
std::atomic<bool> fDeviceTerminationRequested;
|
std::atomic<bool> fDeviceTerminationRequested;
|
||||||
|
std::atomic<bool> fHasShutdown;
|
||||||
}; /* class Control */
|
}; /* class Control */
|
||||||
|
|
||||||
auto ControlPluginProgramOptions() -> Plugin::ProgOptions;
|
auto ControlPluginProgramOptions() -> Plugin::ProgOptions;
|
||||||
|
@@ -46,7 +46,7 @@ int main(int argc, char* argv[])
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
runner.AddHook<InstantiateDevice>([](DeviceRunner& r){
|
runner.AddHook<InstantiateDevice>([](DeviceRunner& r){
|
||||||
r.fDevice = std::shared_ptr<FairMQDevice>{getDevice(r.fConfig)};
|
r.fDevice = std::unique_ptr<FairMQDevice>{getDevice(r.fConfig)};
|
||||||
});
|
});
|
||||||
|
|
||||||
return runner.Run();
|
return runner.Run();
|
||||||
|
@@ -19,8 +19,8 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fair::mq::shmem;
|
using namespace fair::mq::shmem;
|
||||||
|
|
||||||
namespace bipc = boost::interprocess;
|
namespace bipc = ::boost::interprocess;
|
||||||
namespace bpt = boost::posix_time;
|
namespace bpt = ::boost::posix_time;
|
||||||
|
|
||||||
atomic<bool> FairMQMessageSHM::fInterrupted(false);
|
atomic<bool> FairMQMessageSHM::fInterrupted(false);
|
||||||
fair::mq::Transport FairMQMessageSHM::fTransportType = fair::mq::Transport::SHM;
|
fair::mq::Transport FairMQMessageSHM::fTransportType = fair::mq::Transport::SHM;
|
||||||
|
@@ -351,7 +351,7 @@ int64_t FairMQSocketSHM::ReceiveImpl(vector<FairMQMessagePtr>& msgVec, const int
|
|||||||
|
|
||||||
msgVec.reserve(lNumMessages);
|
msgVec.reserve(lNumMessages);
|
||||||
|
|
||||||
for (auto m = 0; m < lNumMessages; m++)
|
for (size_t m = 0; m < lNumMessages; m++)
|
||||||
{
|
{
|
||||||
MetaHeader lMetaHeader;
|
MetaHeader lMetaHeader;
|
||||||
memcpy(&lMetaHeader, &lHdrVec[m], sizeof(MetaHeader));
|
memcpy(&lMetaHeader, &lHdrVec[m], sizeof(MetaHeader));
|
||||||
|
@@ -28,9 +28,9 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fair::mq::shmem;
|
using namespace fair::mq::shmem;
|
||||||
|
|
||||||
namespace bfs = boost::filesystem;
|
namespace bfs = ::boost::filesystem;
|
||||||
namespace bpt = boost::posix_time;
|
namespace bpt = ::boost::posix_time;
|
||||||
namespace bipc = boost::interprocess;
|
namespace bipc = ::boost::interprocess;
|
||||||
|
|
||||||
fair::mq::Transport FairMQTransportFactorySHM::fTransportType = fair::mq::Transport::SHM;
|
fair::mq::Transport FairMQTransportFactorySHM::fTransportType = fair::mq::Transport::SHM;
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fair::mq::shmem;
|
using namespace fair::mq::shmem;
|
||||||
|
|
||||||
namespace bipc = boost::interprocess;
|
namespace bipc = ::boost::interprocess;
|
||||||
|
|
||||||
FairMQUnmanagedRegionSHM::FairMQUnmanagedRegionSHM(Manager& manager, const size_t size, FairMQRegionCallback callback)
|
FairMQUnmanagedRegionSHM::FairMQUnmanagedRegionSHM(Manager& manager, const size_t size, FairMQRegionCallback callback)
|
||||||
: fManager(manager)
|
: fManager(manager)
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
#include <fairmq/shmem/Manager.h>
|
#include <fairmq/shmem/Manager.h>
|
||||||
#include <fairmq/shmem/Common.h>
|
#include <fairmq/shmem/Common.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
namespace bipc = ::boost::interprocess;
|
||||||
|
|
||||||
namespace fair
|
namespace fair
|
||||||
{
|
{
|
||||||
namespace mq
|
namespace mq
|
||||||
@@ -16,9 +19,6 @@ namespace mq
|
|||||||
namespace shmem
|
namespace shmem
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
namespace bipc = boost::interprocess;
|
|
||||||
|
|
||||||
std::unordered_map<uint64_t, Region> Manager::fRegions;
|
std::unordered_map<uint64_t, Region> Manager::fRegions;
|
||||||
|
|
||||||
Manager::Manager(const string& name, size_t size)
|
Manager::Manager(const string& name, size_t size)
|
||||||
|
@@ -26,8 +26,8 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
namespace bipc = boost::interprocess;
|
namespace bipc = ::boost::interprocess;
|
||||||
namespace bpt = boost::posix_time;
|
namespace bpt = ::boost::posix_time;
|
||||||
|
|
||||||
using CharAllocator = bipc::allocator<char, bipc::managed_shared_memory::segment_manager>;
|
using CharAllocator = bipc::allocator<char, bipc::managed_shared_memory::segment_manager>;
|
||||||
using String = bipc::basic_string<char, char_traits<char>, CharAllocator>;
|
using String = bipc::basic_string<char, char_traits<char>, CharAllocator>;
|
||||||
|
@@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace bipc = ::boost::interprocess;
|
||||||
|
namespace bpt = ::boost::posix_time;
|
||||||
|
|
||||||
namespace fair
|
namespace fair
|
||||||
{
|
{
|
||||||
namespace mq
|
namespace mq
|
||||||
@@ -19,11 +24,6 @@ namespace mq
|
|||||||
namespace shmem
|
namespace shmem
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace bipc = boost::interprocess;
|
|
||||||
namespace bpt = boost::posix_time;
|
|
||||||
|
|
||||||
Region::Region(Manager& manager, uint64_t id, uint64_t size, bool remote, FairMQRegionCallback callback)
|
Region::Region(Manager& manager, uint64_t id, uint64_t size, bool remote, FairMQRegionCallback callback)
|
||||||
: fManager(manager)
|
: fManager(manager)
|
||||||
, fRemote(remote)
|
, fRemote(remote)
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
#include <future> // std::async, std::future
|
#include <future> // std::async, std::future
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -19,6 +20,24 @@ namespace
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
void control(FairMQDevice& device)
|
||||||
|
{
|
||||||
|
device.ChangeState("INIT_DEVICE");
|
||||||
|
device.WaitForEndOfState("INIT_DEVICE");
|
||||||
|
device.ChangeState("INIT_TASK");
|
||||||
|
device.WaitForEndOfState("INIT_TASK");
|
||||||
|
|
||||||
|
device.ChangeState("RUN");
|
||||||
|
device.WaitForEndOfState("RUN");
|
||||||
|
|
||||||
|
device.ChangeState("RESET_TASK");
|
||||||
|
device.WaitForEndOfState("RESET_TASK");
|
||||||
|
device.ChangeState("RESET_DEVICE");
|
||||||
|
device.WaitForEndOfState("RESET_DEVICE");
|
||||||
|
|
||||||
|
device.ChangeState("END");
|
||||||
|
}
|
||||||
|
|
||||||
class MultipleDevices : public ::testing::Test {
|
class MultipleDevices : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
MultipleDevices()
|
MultipleDevices()
|
||||||
@@ -34,20 +53,14 @@ class MultipleDevices : public ::testing::Test {
|
|||||||
channel.UpdateRateLogging(0);
|
channel.UpdateRateLogging(0);
|
||||||
sender.fChannels["data"].push_back(channel);
|
sender.fChannels["data"].push_back(channel);
|
||||||
|
|
||||||
sender.ChangeState("INIT_DEVICE");
|
thread t(control, std::ref(sender));
|
||||||
sender.WaitForEndOfState("INIT_DEVICE");
|
|
||||||
sender.ChangeState("INIT_TASK");
|
|
||||||
sender.WaitForEndOfState("INIT_TASK");
|
|
||||||
|
|
||||||
sender.ChangeState("RUN");
|
sender.RunStateMachine();
|
||||||
sender.WaitForEndOfState("RUN");
|
|
||||||
|
|
||||||
sender.ChangeState("RESET_TASK");
|
if (t.joinable())
|
||||||
sender.WaitForEndOfState("RESET_TASK");
|
{
|
||||||
sender.ChangeState("RESET_DEVICE");
|
t.join();
|
||||||
sender.WaitForEndOfState("RESET_DEVICE");
|
}
|
||||||
|
|
||||||
sender.ChangeState("END");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -62,20 +75,14 @@ class MultipleDevices : public ::testing::Test {
|
|||||||
channel.UpdateRateLogging(0);
|
channel.UpdateRateLogging(0);
|
||||||
receiver.fChannels["data"].push_back(channel);
|
receiver.fChannels["data"].push_back(channel);
|
||||||
|
|
||||||
receiver.ChangeState("INIT_DEVICE");
|
thread t(control, std::ref(receiver));
|
||||||
receiver.WaitForEndOfState("INIT_DEVICE");
|
|
||||||
receiver.ChangeState("INIT_TASK");
|
|
||||||
receiver.WaitForEndOfState("INIT_TASK");
|
|
||||||
|
|
||||||
receiver.ChangeState("RUN");
|
receiver.RunStateMachine();
|
||||||
receiver.WaitForEndOfState("RUN");
|
|
||||||
|
|
||||||
receiver.ChangeState("RESET_TASK");
|
if (t.joinable())
|
||||||
receiver.WaitForEndOfState("RESET_TASK");
|
{
|
||||||
receiver.ChangeState("RESET_DEVICE");
|
t.join();
|
||||||
receiver.WaitForEndOfState("RESET_DEVICE");
|
}
|
||||||
|
|
||||||
receiver.ChangeState("END");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include <FairMQDevice.h>
|
#include <FairMQDevice.h>
|
||||||
#include <options/FairMQProgOptions.h>
|
#include <options/FairMQProgOptions.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace fair
|
namespace fair
|
||||||
{
|
{
|
||||||
@@ -22,35 +23,41 @@ namespace mq
|
|||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
|
|
||||||
inline auto control(std::shared_ptr<FairMQDevice> device) -> void
|
inline auto control(FairMQDevice& device) -> void
|
||||||
{
|
{
|
||||||
for (const auto event : {
|
for (const auto event : {
|
||||||
FairMQDevice::INIT_DEVICE,
|
FairMQDevice::INIT_DEVICE,
|
||||||
FairMQDevice::RESET_DEVICE,
|
FairMQDevice::RESET_DEVICE,
|
||||||
FairMQDevice::END,
|
FairMQDevice::END,
|
||||||
}) {
|
}) {
|
||||||
device->ChangeState(event);
|
device.ChangeState(event);
|
||||||
if (event != FairMQDevice::END) device->WaitForEndOfState(event);
|
if (event != FairMQDevice::END) device.WaitForEndOfState(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PluginServices : ::testing::Test {
|
struct PluginServices : ::testing::Test {
|
||||||
PluginServices()
|
PluginServices()
|
||||||
: mConfig()
|
: mConfig()
|
||||||
, mDevice{std::make_shared<FairMQDevice>()}
|
, mDevice()
|
||||||
, mServices{&mConfig, mDevice}
|
, mServices(mConfig, mDevice)
|
||||||
|
, fRunStateMachineThread()
|
||||||
{
|
{
|
||||||
mDevice->SetTransport("zeromq");
|
fRunStateMachineThread = std::thread(&FairMQDevice::RunStateMachine, &mDevice);
|
||||||
|
mDevice.SetTransport("zeromq");
|
||||||
}
|
}
|
||||||
|
|
||||||
~PluginServices()
|
~PluginServices()
|
||||||
{
|
{
|
||||||
if(mDevice->GetCurrentState() == FairMQDevice::IDLE) control(mDevice);
|
if (mDevice.GetCurrentState() == FairMQDevice::IDLE) control(mDevice);
|
||||||
|
if (fRunStateMachineThread.joinable()) {
|
||||||
|
fRunStateMachineThread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FairMQProgOptions mConfig;
|
FairMQProgOptions mConfig;
|
||||||
std::shared_ptr<FairMQDevice> mDevice;
|
FairMQDevice mDevice;
|
||||||
fair::mq::PluginServices mServices;
|
fair::mq::PluginServices mServices;
|
||||||
|
std::thread fRunStateMachineThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace test */
|
} /* namespace test */
|
||||||
|
@@ -39,9 +39,9 @@ TEST_F(PluginServices, OnlySingleController)
|
|||||||
EXPECT_EQ(mServices.GetDeviceController(), string{"foo"});
|
EXPECT_EQ(mServices.GetDeviceController(), string{"foo"});
|
||||||
|
|
||||||
// park device
|
// park device
|
||||||
mDevice->WaitForEndOfState(FairMQDevice::DEVICE_READY);
|
mDevice.WaitForEndOfState(FairMQDevice::DEVICE_READY);
|
||||||
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
|
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
|
||||||
mDevice->WaitForEndOfState(FairMQDevice::RESET_DEVICE);
|
mDevice.WaitForEndOfState(FairMQDevice::RESET_DEVICE);
|
||||||
mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
|
mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ TEST_F(PluginServices, Control)
|
|||||||
ASSERT_EQ(mServices.GetCurrentDeviceState(), DeviceState::DeviceReady);
|
ASSERT_EQ(mServices.GetCurrentDeviceState(), DeviceState::DeviceReady);
|
||||||
|
|
||||||
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
|
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
|
||||||
mDevice->WaitForEndOfState(FairMQDevice::RESET_DEVICE);
|
mDevice.WaitForEndOfState(FairMQDevice::RESET_DEVICE);
|
||||||
mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
|
mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -23,42 +24,50 @@ namespace
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fair::mq;
|
using namespace fair::mq;
|
||||||
|
|
||||||
auto control(shared_ptr<FairMQDevice> device) -> void
|
auto control(FairMQDevice& device) -> void
|
||||||
{
|
{
|
||||||
device->SetTransport("zeromq");
|
device.SetTransport("zeromq");
|
||||||
for (const auto event : {
|
for (const auto event : {
|
||||||
FairMQDevice::INIT_DEVICE,
|
FairMQDevice::INIT_DEVICE,
|
||||||
FairMQDevice::RESET_DEVICE,
|
FairMQDevice::RESET_DEVICE,
|
||||||
FairMQDevice::END,
|
FairMQDevice::END,
|
||||||
}) {
|
}) {
|
||||||
device->ChangeState(event);
|
device.ChangeState(event);
|
||||||
if (event != FairMQDevice::END) device->WaitForEndOfState(event);
|
if (event != FairMQDevice::END) device.WaitForEndOfState(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Plugin, Operators)
|
TEST(Plugin, Operators)
|
||||||
{
|
{
|
||||||
FairMQProgOptions config{};
|
FairMQProgOptions config;
|
||||||
auto device = make_shared<FairMQDevice>();
|
FairMQDevice device;
|
||||||
PluginServices services{&config, device};
|
PluginServices services{config, device};
|
||||||
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
||||||
Plugin p2{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
Plugin p2{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
||||||
Plugin p3{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", &services};
|
Plugin p3{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", &services};
|
||||||
EXPECT_EQ(p1, p2);
|
EXPECT_EQ(p1, p2);
|
||||||
EXPECT_NE(p1, p3);
|
EXPECT_NE(p1, p3);
|
||||||
control(device);
|
thread t(control, std::ref(device));
|
||||||
|
device.RunStateMachine();
|
||||||
|
if (t.joinable()) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Plugin, OstreamOperators)
|
TEST(Plugin, OstreamOperators)
|
||||||
{
|
{
|
||||||
FairMQProgOptions config{};
|
FairMQProgOptions config;
|
||||||
auto device = make_shared<FairMQDevice>();
|
FairMQDevice device;
|
||||||
PluginServices services{&config, device};
|
PluginServices services{config, device};
|
||||||
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << p1;
|
ss << p1;
|
||||||
EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar <foo.bar@test.net>', homepage 'https://git.test.net/dds.git'"});
|
EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar <foo.bar@test.net>', homepage 'https://git.test.net/dds.git'"});
|
||||||
control(device);
|
thread t(control, std::ref(device));
|
||||||
|
device.RunStateMachine();
|
||||||
|
if (t.joinable()) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginVersion, Operators)
|
TEST(PluginVersion, Operators)
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -24,25 +25,25 @@ using namespace boost::filesystem;
|
|||||||
using namespace boost::program_options;
|
using namespace boost::program_options;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
auto control(shared_ptr<FairMQDevice> device) -> void
|
auto control(FairMQDevice& device) -> void
|
||||||
{
|
{
|
||||||
device->SetTransport("zeromq");
|
device.SetTransport("zeromq");
|
||||||
for (const auto event : {
|
for (const auto event : {
|
||||||
FairMQDevice::INIT_DEVICE,
|
FairMQDevice::INIT_DEVICE,
|
||||||
FairMQDevice::RESET_DEVICE,
|
FairMQDevice::RESET_DEVICE,
|
||||||
FairMQDevice::END,
|
FairMQDevice::END,
|
||||||
}) {
|
}) {
|
||||||
device->ChangeState(event);
|
device.ChangeState(event);
|
||||||
if (event != FairMQDevice::END) device->WaitForEndOfState(event);
|
if (event != FairMQDevice::END) device.WaitForEndOfState(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginManager, LoadPluginDynamic)
|
TEST(PluginManager, LoadPluginDynamic)
|
||||||
{
|
{
|
||||||
FairMQProgOptions config{};
|
FairMQProgOptions config;
|
||||||
auto mgr = PluginManager{};
|
FairMQDevice device;
|
||||||
auto device = make_shared<FairMQDevice>();
|
PluginManager mgr;
|
||||||
mgr.EmplacePluginServices(&config, device);
|
mgr.EmplacePluginServices(config, device);
|
||||||
|
|
||||||
mgr.PrependSearchPath("./test");
|
mgr.PrependSearchPath("./test");
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ TEST(PluginManager, LoadPluginDynamic)
|
|||||||
|
|
||||||
// check order
|
// check order
|
||||||
const auto expected = vector<string>{"test_dummy", "test_dummy2"};
|
const auto expected = vector<string>{"test_dummy", "test_dummy2"};
|
||||||
auto actual = vector<string>{};
|
auto actual = vector<string>();
|
||||||
mgr.ForEachPlugin([&](Plugin& plugin){ actual.push_back(plugin.GetName()); });
|
mgr.ForEachPlugin([&](Plugin& plugin){ actual.push_back(plugin.GetName()); });
|
||||||
ASSERT_TRUE(actual == expected);
|
ASSERT_TRUE(actual == expected);
|
||||||
|
|
||||||
@@ -62,27 +63,31 @@ TEST(PluginManager, LoadPluginDynamic)
|
|||||||
mgr.ForEachPluginProgOptions([&count](const options_description& /*d*/){ ++count; });
|
mgr.ForEachPluginProgOptions([&count](const options_description& /*d*/){ ++count; });
|
||||||
ASSERT_EQ(count, 1);
|
ASSERT_EQ(count, 1);
|
||||||
|
|
||||||
control(device);
|
thread t(control, std::ref(device));
|
||||||
|
device.RunStateMachine();
|
||||||
|
if (t.joinable()) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginManager, LoadPluginStatic)
|
TEST(PluginManager, LoadPluginStatic)
|
||||||
{
|
{
|
||||||
auto mgr = PluginManager{};
|
FairMQDevice device;
|
||||||
auto device = make_shared<FairMQDevice>();
|
PluginManager mgr;
|
||||||
device->SetTransport("zeromq");
|
device.SetTransport("zeromq");
|
||||||
|
|
||||||
ASSERT_NO_THROW(mgr.LoadPlugin("s:control"));
|
ASSERT_NO_THROW(mgr.LoadPlugin("s:control"));
|
||||||
|
|
||||||
FairMQProgOptions config{};
|
FairMQProgOptions config;
|
||||||
config.SetValue<string>("control", "static");
|
config.SetValue<string>("control", "static");
|
||||||
config.SetValue("catch-signals", 0);
|
config.SetValue("catch-signals", 0);
|
||||||
mgr.EmplacePluginServices(&config, device);
|
mgr.EmplacePluginServices(config, device);
|
||||||
|
|
||||||
ASSERT_NO_THROW(mgr.InstantiatePlugins());
|
ASSERT_NO_THROW(mgr.InstantiatePlugins());
|
||||||
|
|
||||||
// check order
|
// check order
|
||||||
const auto expected = vector<string>{"control"};
|
const auto expected = vector<string>{"control"};
|
||||||
auto actual = vector<string>{};
|
auto actual = vector<string>();
|
||||||
mgr.ForEachPlugin([&](Plugin& plugin){ actual.push_back(plugin.GetName()); });
|
mgr.ForEachPlugin([&](Plugin& plugin){ actual.push_back(plugin.GetName()); });
|
||||||
ASSERT_TRUE(actual == expected);
|
ASSERT_TRUE(actual == expected);
|
||||||
|
|
||||||
@@ -91,20 +96,22 @@ TEST(PluginManager, LoadPluginStatic)
|
|||||||
mgr.ForEachPluginProgOptions([&count](const options_description&){ ++count; });
|
mgr.ForEachPluginProgOptions([&count](const options_description&){ ++count; });
|
||||||
ASSERT_EQ(count, 1);
|
ASSERT_EQ(count, 1);
|
||||||
|
|
||||||
|
device.RunStateMachine();
|
||||||
|
|
||||||
mgr.WaitForPluginsToReleaseDeviceControl();
|
mgr.WaitForPluginsToReleaseDeviceControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginManager, Factory)
|
TEST(PluginManager, Factory)
|
||||||
{
|
{
|
||||||
const auto args = vector<string>{"-l", "debug", "--help", "-S", ">/lib", "</home/user/lib", "/usr/local/lib", "/usr/lib"};
|
const auto args = vector<string>{"-l", "debug", "--help", "-S", ">/lib", "</home/user/lib", "/usr/local/lib", "/usr/lib"};
|
||||||
auto mgr = PluginManager::MakeFromCommandLineOptions(args);
|
PluginManager mgr(args);
|
||||||
const auto path1 = path{"/home/user/lib"};
|
const auto path1 = path{"/home/user/lib"};
|
||||||
const auto path2 = path{"/usr/local/lib"};
|
const auto path2 = path{"/usr/local/lib"};
|
||||||
const auto path3 = path{"/usr/lib"};
|
const auto path3 = path{"/usr/lib"};
|
||||||
const auto path4 = path{"/lib"};
|
const auto path4 = path{"/lib"};
|
||||||
const auto expected = vector<path>{path1, path2, path3, path4};
|
const auto expected = vector<path>{path1, path2, path3, path4};
|
||||||
ASSERT_TRUE(static_cast<bool>(mgr));
|
// ASSERT_TRUE(static_cast<bool>(mgr));
|
||||||
ASSERT_TRUE(mgr->SearchPaths() == expected);
|
ASSERT_TRUE(mgr.SearchPaths() == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginManager, SearchPathValidation)
|
TEST(PluginManager, SearchPathValidation)
|
||||||
@@ -112,7 +119,7 @@ TEST(PluginManager, SearchPathValidation)
|
|||||||
const auto path1 = path{"/tmp/test1"};
|
const auto path1 = path{"/tmp/test1"};
|
||||||
const auto path2 = path{"/tmp/test2"};
|
const auto path2 = path{"/tmp/test2"};
|
||||||
const auto path3 = path{"/tmp/test3"};
|
const auto path3 = path{"/tmp/test3"};
|
||||||
auto mgr = PluginManager{};
|
PluginManager mgr;
|
||||||
|
|
||||||
mgr.SetSearchPaths({path1, path2});
|
mgr.SetSearchPaths({path1, path2});
|
||||||
auto expected = vector<path>{path1, path2};
|
auto expected = vector<path>{path1, path2};
|
||||||
@@ -140,7 +147,7 @@ TEST(PluginManager, SearchPaths)
|
|||||||
fs.close();
|
fs.close();
|
||||||
const auto empty_path = path{""};
|
const auto empty_path = path{""};
|
||||||
|
|
||||||
auto mgr = PluginManager{};
|
PluginManager mgr;
|
||||||
ASSERT_NO_THROW(mgr.AppendSearchPath(non_existing_dir));
|
ASSERT_NO_THROW(mgr.AppendSearchPath(non_existing_dir));
|
||||||
ASSERT_NO_THROW(mgr.AppendSearchPath(existing_dir));
|
ASSERT_NO_THROW(mgr.AppendSearchPath(existing_dir));
|
||||||
ASSERT_THROW(mgr.AppendSearchPath(existing_file), PluginManager::BadSearchPath);
|
ASSERT_THROW(mgr.AppendSearchPath(existing_file), PluginManager::BadSearchPath);
|
||||||
|
@@ -17,7 +17,7 @@ using namespace std;
|
|||||||
|
|
||||||
TEST(PluginManager, LoadPluginPrelinkedDynamic)
|
TEST(PluginManager, LoadPluginPrelinkedDynamic)
|
||||||
{
|
{
|
||||||
auto mgr = PluginManager{};
|
PluginManager mgr;
|
||||||
|
|
||||||
ASSERT_NO_THROW(mgr.LoadPlugin("p:test_dummy"));
|
ASSERT_NO_THROW(mgr.LoadPlugin("p:test_dummy"));
|
||||||
ASSERT_NO_THROW(mgr.LoadPlugin("p:test_dummy2"));
|
ASSERT_NO_THROW(mgr.LoadPlugin("p:test_dummy2"));
|
||||||
|
Reference in New Issue
Block a user