feat(top): Add new fairmq-top tool

This commit is contained in:
Dennis Klein 2021-06-18 15:13:54 +02:00
parent bc91799e56
commit cb2eca9c4a
11 changed files with 566 additions and 12 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ install
.vscode
/compile_commands.json
.cache
imgui.ini

View File

@ -47,6 +47,8 @@ fairmq_build_option(USE_EXTERNAL_GTEST "Do not use bundled GTest. Not recommend
DEFAULT OFF)
fairmq_build_option(FAIRMQ_DEBUG_MODE "Compile in debug mode (may decrease performance)."
DEFAULT OFF)
fairmq_build_option(BUILD_SDK_TOP_TOOL "Build the fairmq-top tool."
DEFAULT OFF REQUIRES "BUILD_SDK")
################################################################################
@ -116,6 +118,9 @@ endif()
if(BUILD_TIDY_TOOL)
list(APPEND PROJECT_PACKAGE_COMPONENTS tidy_tool)
endif()
if(BUILD_SDK_TOP_TOOL)
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk_top_tool)
endif()
################################################################################

View File

@ -77,9 +77,16 @@ if(BUILD_TIDY_TOOL)
find_package2(PRIVATE LLVM REQUIRED)
find_package2(PRIVATE Clang REQUIRED)
set(Clang_VERSION ${LLVM_VERSION})
endif()
if(BUILD_TIDY_TOOL OR BUILD_SDK_TOP_TOOL)
find_package2(PRIVATE CLI11 REQUIRED)
endif()
if(BUILD_SDK_TOP_TOOL)
find_package2(PRIVATE imtui REQUIRED)
endif()
find_package2_implicit_dependencies() # Always call last after latest find_package2
if(PROJECT_PACKAGE_DEPENDENCIES)

View File

@ -106,7 +106,9 @@ if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
endif()
list(JOIN _sanitizers "," _sanitizers)
if(_sanitizers)
set(_sanitizers "-fsanitize=${_sanitizers}")
endif()
# Configure build types
set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo")

View File

@ -70,11 +70,17 @@ macro(fairmq_summary_components)
endif()
message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}")
if(BUILD_TIDY_TOOL)
set(sdk_tidy_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_TIDY_TOOL=OFF${CR})")
set(tidy_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_TIDY_TOOL=OFF${CR})")
else()
set(sdk_tidy_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_TIDY_TOOL=ON${CR})")
set(tidy_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_TIDY_TOOL=ON${CR})")
endif()
message(STATUS " ${BWhite}tidy_tool${CR} ${sdk_tidy_summary}")
message(STATUS " ${BWhite}tidy_tool${CR} ${tidy_summary}")
if(BUILD_SDK_TOP_TOOL)
set(sdk_top_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_SDK_TOP_TOOL=OFF${CR})")
else()
set(sdk_top_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_SDK_TOP_TOOL=ON${CR})")
endif()
message(STATUS " ${BWhite}sdk_top_tool${CR} ${sdk_top_summary}")
endmacro()
macro(fairmq_summary_static_analysis)

58
cmake/Findimtui.cmake Normal file
View File

@ -0,0 +1,58 @@
################################################################################
# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
set(pkg imtui)
find_path(${pkg}_INCLUDE_DIR
NAMES ${pkg}.h
PATH_SUFFIXES include/${pkg}
DOC "imtui include directory"
)
get_filename_component(${pkg}_INCLUDE_DIR "${${pkg}_INCLUDE_DIR}/.." ABSOLUTE)
find_library(${pkg}_LIBRARY
NAMES lib${pkg}.so
PATH_SUFFIXES lib lib64
DOC "Path to libimtui.a"
)
find_library(${pkg}_ncurses_LIBRARY
NAMES lib${pkg}-ncurses.so
PATH_SUFFIXES lib lib64
DOC "Path to libimtui-ncurses.a"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(${pkg} REQUIRED_VARS
${pkg}_INCLUDE_DIR
${pkg}_LIBRARY
${pkg}_ncurses_LIBRARY
)
get_filename_component(${pkg}_PREFIX "${${pkg}_INCLUDE_DIR}/.." ABSOLUTE)
if(${pkg}_FOUND AND NOT TARGET ${pkg}::${pkg}-ncurses)
add_library(${pkg}::${pkg}-ncurses SHARED IMPORTED)
set_target_properties(${pkg}::${pkg}-ncurses PROPERTIES
IMPORTED_LOCATION ${${pkg}_ncurses_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${${pkg}_INCLUDE_DIR}
)
endif()
if(${pkg}_FOUND AND NOT TARGET ${pkg}::${pkg})
add_library(${pkg}::${pkg} SHARED IMPORTED)
set_target_properties(${pkg}::${pkg} PROPERTIES
IMPORTED_LOCATION ${${pkg}_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${${pkg}_INCLUDE_DIR}
)
endif()
mark_as_advanced(
${pkg}_INCLUDE_DIR
${pkg}_LIBRARY
${pkg}_ncurses_LIBRARY
)

View File

@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# Copyright (C) 2019-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
@ -84,18 +84,35 @@ endif()
###############
# executables #
###############
add_executable(fairmq-dds-command-ui ${CMAKE_CURRENT_SOURCE_DIR}/runDDSCommandUI.cxx)
target_link_libraries(fairmq-dds-command-ui
FairMQ
Commands
SDK
StateMachine
set(target fairmq-dds-command-ui)
add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/runDDSCommandUI.cxx)
target_link_libraries(${target} PRIVATE FairMQ Commands SDK StateMachine)
target_compile_features(${target} PRIVATE cxx_std_17)
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
fairmq_target_tidy(TARGET ${target})
endif()
if(BUILD_SDK_TOP_TOOL)
set(fairmq_top "fairmq-top")
add_executable(${fairmq_top}
top/runTool.cxx
top/Tool.h
)
target_link_libraries(${fairmq_top} PRIVATE
SDK asio::asio CLI11::CLI11 imtui::imtui imtui::imtui-ncurses)
target_compile_features(${fairmq_top} PRIVATE cxx_std_17)
if(BUILD_TIDY_TOOL AND RUN_FAIRMQ_TIDY)
fairmq_target_tidy(TARGET ${fairmq_top})
endif()
else()
set(fairmq_top)
endif()
install(
TARGETS
SDK
fairmq-dds-command-ui
${fairmq_top}
EXPORT ${PROJECT_EXPORT_SET}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}

19
fairmq/sdk/top/README.md Normal file
View File

@ -0,0 +1,19 @@
### `fairmq-top`
`htop`-like TUI to monitor/control a running FairMQ topology.
EXPERIMENTAL - Currently mainly used as internal development tool.
Enable building by passing `-DBUILD_FAIRMQ=ON -DBUILD_SDK_COMMANDS=ON -DBUILD_SDK=ON -DBUILD_DDS_PLUGIN=ON -DBUILD_SDK_TOP_TOOL=ON`.
---
How to build [imtui](https://github.com/ggerganov/imtui) (requires ncurses devel package installed):
```
git clone https://github.com/ggerganov/imtui
cmake -S imtui -B <builddir> -DIMTUI_INSTALL_IMGUI_HEADERS=ON -DIMTUI_SUPPORT_NCURSES=ON -DCMAKE_INSTALL_PREFIX=<installdir>
cmake --build <builddir> --target install
```
and then pass `-Dimtui_ROOT=<installdir>` to the FairMQ configure above.

200
fairmq/sdk/top/Tool.h Normal file
View File

@ -0,0 +1,200 @@
/********************************************************************************
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIR_MQ_SDK_TOP_TOOL_H
#define FAIR_MQ_SDK_TOP_TOOL_H
#include <asio/io_context.hpp>
#include <asio/post.hpp>
#include <asio/signal_set.hpp>
#include <asio/steady_timer.hpp>
#include <chrono>
#include <exception>
#include <fairmq/Tools.h>
#include <fairmq/Version.h>
#include <fairmq/sdk/DDSAgent.h>
#include <fairmq/sdk/DDSEnvironment.h>
#include <fairmq/sdk/DDSSession.h>
#include <fairmq/sdk/DDSTask.h>
#include <fairmq/sdk/DDSTopology.h>
#include <fairmq/sdk/Topology.h>
#include <imgui/imgui.h>
#include <imtui/imtui-impl-ncurses.h>
#include <imtui/imtui.h>
#include <map>
#include <memory>
#include <system_error>
namespace fair::mq::sdk::top {
using namespace std::chrono_literals;
struct Tool
{
static constexpr auto DefaultFrameDrawInterval = 200ms; // 5Hz
static constexpr auto DefaultInputPollInterval = 10ms; // 100Hz
static constexpr auto DefaultDataPollInterval = 333ms; // 3Hz
Tool(DDSSession::Id session_id)
: fScreen(Tool::MakeScreen())
, fSignals(fIoCtx, SIGINT, SIGTERM, SIGSEGV)
, fFrameDrawInterval(DefaultFrameDrawInterval)
, fFrameDrawTimer(fIoCtx)
, fInputPollInterval(DefaultInputPollInterval)
, fInputPollTimer(fIoCtx)
, fDdsSessionId(std::move(session_id))
, fDataPollInterval(DefaultInputPollInterval)
, fDataPollTimer(fIoCtx)
{
fSignals.async_wait([&](std::error_code const&, int) {
fIoCtx.stop();
Tool::ShutdownImTui();
});
}
Tool(Tool const&) = delete;
Tool& operator=(Tool const&) = delete;
Tool(Tool&&) = delete;
Tool& operator=(Tool&&) = delete;
~Tool() { Tool::ShutdownImTui(); }
auto DrawFrame() -> void
{
fFrameDrawTimer.expires_from_now(fFrameDrawInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
ImTui_ImplNcurses_NewFrame();
ImTui_ImplText_NewFrame();
ImGui::NewFrame();
ImGui::SetNextWindowPos({0.0f, 0.0f});
ImGui::SetNextWindowSize(ImGui::GetContentRegionAvail());
ImGui::Begin(
tools::ToString("fairmq-top v", FAIRMQ_VERSION, " session: ", fDdsSessionId, " active topo: ", fDdsTopo->GetName()).c_str(),
nullptr,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
ImGui::TextUnformatted(tools::ToString(this).c_str());
// auto tasks(fDdsTopo->GetTasks());
// for (auto const& task : tasks) {
// ImGui::TextUnformatted(tools::ToString(task.GetId(), task.GetCollectionId()).c_str());
// }
// auto const agents(fDdsSession->RequestAgentInfo());
// for (auto const& agent : agents) {
// ImGui::TextUnformatted(tools::ToString(agent).c_str());
// }
// for (auto const& dev : fFmqTopoState) {
// ImGui::TextUnformatted(
// tools::ToString(dev.state, " ", fDdsTasks.at(dev.taskId)).c_str());
// }
ImGui::End();
ImGui::Render();
ImTui_ImplText_RenderDrawData(ImGui::GetDrawData(), &fScreen);
ImTui_ImplNcurses_DrawScreen();
fFrameDrawTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->DrawFrame();
}
});
}
auto PollInput() -> void
{
fInputPollTimer.expires_from_now(fInputPollInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
if (ImGui::IsKeyPressed('q', false)) {
asio::post([&]() { fIoCtx.stop(); });
}
fInputPollTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->PollInput();
}
});
}
auto PollData() -> void
{
fDataPollTimer.expires_from_now(fDataPollInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
fFmqTopoState = fFmqTopo->GetCurrentState();
fDataPollTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->PollData();
}
});
}
auto LoadSession(DDSTopology::Path const& topo) -> void
{
if (fDdsSessionId.empty()) {
fDdsSession = std::make_unique<DDSSession>(getMostRecentRunningDDSSession(fDdsEnv));
fDdsSessionId = fDdsSession->GetId();
} else {
fDdsSession = std::make_unique<DDSSession>(fDdsSessionId);
}
fDdsTopo = std::make_unique<DDSTopology>(topo, fDdsEnv);
fFmqTopo = std::make_unique<Topology>(fIoCtx.get_executor(), *fDdsTopo, *fDdsSession);
this->PollData();
}
auto Run(DDSTopology::Path const& topo) -> int
{
asio::post([&]() { this->PollInput(); });
asio::post([&]() { this->LoadSession(topo); });
asio::post([&]() { this->DrawFrame(); });
try {
fIoCtx.run();
} catch (...) {
Tool::ShutdownImTui();
throw;
}
return 0;
}
private:
asio::io_context fIoCtx;
ImTui::TScreen& fScreen;
asio::signal_set fSignals;
std::chrono::milliseconds fFrameDrawInterval;
asio::steady_timer fFrameDrawTimer;
std::chrono::milliseconds fInputPollInterval;
asio::steady_timer fInputPollTimer;
DDSSession::Id fDdsSessionId;
// TODO refactor ff members into separate class
DDSEnvironment fDdsEnv;
std::unique_ptr<DDSSession> fDdsSession;
std::unique_ptr<DDSTopology> fDdsTopo;
std::unique_ptr<Topology> fFmqTopo;
std::chrono::milliseconds fDataPollInterval;
asio::steady_timer fDataPollTimer;
TopologyState fFmqTopoState;
std::map<DDSTask::Id, DDSCollection::Id> fDdsTasks;
static auto MakeScreen() -> ImTui::TScreen&
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
auto& screen(*ImTui_ImplNcurses_Init(true));
ImTui_ImplText_Init();
return screen;
}
static auto ShutdownImTui() -> void
{
ImTui_ImplText_Shutdown();
ImTui_ImplNcurses_Shutdown();
}
};
} // namespace fair::mq::sdk::top
#endif /* FAIR_MQ_SDK_TOP_TOOL_H */

200
fairmq/sdk/top/TopTable.h Normal file
View File

@ -0,0 +1,200 @@
/********************************************************************************
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIR_MQ_SDK_TOP_TOOL_H
#define FAIR_MQ_SDK_TOP_TOOL_H
#include <asio/io_context.hpp>
#include <asio/post.hpp>
#include <asio/signal_set.hpp>
#include <asio/steady_timer.hpp>
#include <chrono>
#include <exception>
#include <fairmq/Tools.h>
#include <fairmq/Version.h>
#include <fairmq/sdk/DDSAgent.h>
#include <fairmq/sdk/DDSEnvironment.h>
#include <fairmq/sdk/DDSSession.h>
#include <fairmq/sdk/DDSTask.h>
#include <fairmq/sdk/DDSTopology.h>
#include <fairmq/sdk/Topology.h>
#include <imgui/imgui.h>
#include <imtui/imtui-impl-ncurses.h>
#include <imtui/imtui.h>
#include <map>
#include <memory>
#include <system_error>
namespace fair::mq::sdk::top {
using namespace std::chrono_literals;
struct Tool
{
static constexpr auto DefaultFrameDrawInterval = 200ms; // 5Hz
static constexpr auto DefaultInputPollInterval = 10ms; // 100Hz
static constexpr auto DefaultDataPollInterval = 333ms; // 3Hz
Tool(DDSSession::Id session_id)
: fScreen(Tool::MakeScreen())
, fSignals(fIoCtx, SIGINT, SIGTERM, SIGSEGV)
, fFrameDrawInterval(DefaultFrameDrawInterval)
, fFrameDrawTimer(fIoCtx)
, fInputPollInterval(DefaultInputPollInterval)
, fInputPollTimer(fIoCtx)
, fDdsSessionId(std::move(session_id))
, fDataPollInterval(DefaultInputPollInterval)
, fDataPollTimer(fIoCtx)
{
fSignals.async_wait([&](std::error_code const&, int) {
fIoCtx.stop();
Tool::ShutdownImTui();
});
}
Tool(Tool const&) = delete;
Tool& operator=(Tool const&) = delete;
Tool(Tool&&) = delete;
Tool& operator=(Tool&&) = delete;
~Tool() { Tool::ShutdownImTui(); }
auto DrawFrame() -> void
{
fFrameDrawTimer.expires_from_now(fFrameDrawInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
ImTui_ImplNcurses_NewFrame();
ImTui_ImplText_NewFrame();
ImGui::NewFrame();
ImGui::SetNextWindowPos({0.0f, 0.0f});
ImGui::SetNextWindowSize(ImGui::GetContentRegionAvail());
ImGui::Begin(
tools::ToString("fairmq-top v", FAIRMQ_VERSION, " session: ", fDdsSessionId, " active topo: ", fDdsTopo->GetName()).c_str(),
nullptr,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
ImGui::TextUnformatted(tools::ToString(this).c_str());
// auto tasks(fDdsTopo->GetTasks());
// for (auto const& task : tasks) {
// ImGui::TextUnformatted(tools::ToString(task.GetId(), task.GetCollectionId()).c_str());
// }
// auto const agents(fDdsSession->RequestAgentInfo());
// for (auto const& agent : agents) {
// ImGui::TextUnformatted(tools::ToString(agent).c_str());
// }
// for (auto const& dev : fFmqTopoState) {
// ImGui::TextUnformatted(
// tools::ToString(dev.state, " ", fDdsTasks.at(dev.taskId)).c_str());
// }
ImGui::End();
ImGui::Render();
ImTui_ImplText_RenderDrawData(ImGui::GetDrawData(), &fScreen);
ImTui_ImplNcurses_DrawScreen();
fFrameDrawTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->DrawFrame();
}
});
}
auto PollInput() -> void
{
fInputPollTimer.expires_from_now(fInputPollInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
if (ImGui::IsKeyPressed('q', false)) {
asio::post([&]() { fIoCtx.stop(); });
}
fInputPollTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->PollInput();
}
});
}
auto PollData() -> void
{
fDataPollTimer.expires_from_now(fDataPollInterval); // this will drift a bit (depending
// on outstanding work in fIoCtx)
fFmqTopoState = fFmqTopo->GetCurrentState();
fDataPollTimer.async_wait([&](std::error_code const& e) {
if (!e) {
this->PollData();
}
});
}
auto LoadSession(DDSTopology::Path const& topo) -> void
{
if (fDdsSessionId.empty()) {
fDdsSession = std::make_unique<DDSSession>(getMostRecentRunningDDSSession(fDdsEnv));
fDdsSessionId = fDdsSession->GetId();
} else {
fDdsSession = std::make_unique<DDSSession>(fDdsSessionId);
}
fDdsTopo = std::make_unique<DDSTopology>(topo, fDdsEnv);
fFmqTopo = std::make_unique<Topology>(fIoCtx.get_executor(), *fDdsTopo, *fDdsSession);
this->PollData();
}
auto Run(DDSTopology::Path const& topo) -> int
{
asio::post([&]() { this->PollInput(); });
asio::post([&]() { this->LoadSession(topo); });
asio::post([&]() { this->DrawFrame(); });
try {
fIoCtx.run();
} catch (...) {
Tool::ShutdownImTui();
throw;
}
return 0;
}
private:
asio::io_context fIoCtx;
ImTui::TScreen& fScreen;
asio::signal_set fSignals;
std::chrono::milliseconds fFrameDrawInterval;
asio::steady_timer fFrameDrawTimer;
std::chrono::milliseconds fInputPollInterval;
asio::steady_timer fInputPollTimer;
DDSSession::Id fDdsSessionId;
// TODO refactor ff members into separate class
DDSEnvironment fDdsEnv;
std::unique_ptr<DDSSession> fDdsSession;
std::unique_ptr<DDSTopology> fDdsTopo;
std::unique_ptr<Topology> fFmqTopo;
std::chrono::milliseconds fDataPollInterval;
asio::steady_timer fDataPollTimer;
TopologyState fFmqTopoState;
std::map<DDSTask::Id, DDSCollection::Id> fDdsTasks;
static auto MakeScreen() -> ImTui::TScreen&
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
auto& screen(*ImTui_ImplNcurses_Init(true));
ImTui_ImplText_Init();
return screen;
}
static auto ShutdownImTui() -> void
{
ImTui_ImplText_Shutdown();
ImTui_ImplNcurses_Shutdown();
}
};
} // namespace fair::mq::sdk::top
#endif /* FAIR_MQ_SDK_TOP_TOOL_H */

View File

@ -0,0 +1,39 @@
/********************************************************************************
* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include <CLI/App.hpp>
#include <CLI/Config.hpp>
#include <CLI/Formatter.hpp>
#include <fairmq/Version.h>
#include <fairmq/sdk/top/Tool.h>
auto main(int argc, char** argv) -> int
{
CLI::App app("htop-like TUI to monitor/control a running FairMQ topology\n", "fairmq-top");
auto session(app.add_option("-s,--session", "DDS session id")
->default_val(fair::mq::sdk::DDSSession::Id())
->envname("DDS_SESSION_ID"));
auto topo(app.add_option("-t,--topology", "DDS topology file")->check(CLI::ExistingFile));
auto version(app.add_flag("-v,--version", "Print version")->excludes(session)->excludes(topo));
try {
app.parse(argc, argv);
} catch (CLI::ParseError const& e) {
return app.exit(e);
}
if (version->as<bool>()) {
std::cout << FAIRMQ_GIT_VERSION << '\n';
return EXIT_SUCCESS;
}
fair::mq::sdk::top::Tool tool(session->as<fair::mq::sdk::DDSSession::Id>());
return tool.Run(topo->as<fair::mq::sdk::DDSTopology::Path>());
}