R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BUcesbLauncher.cxx
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
3 * Copyright (C) 2019-2025 Members of R3B Collaboration *
4 * *
5 * This software is distributed under the terms of the *
6 * GNU General Public Licence (GPL) version 3, *
7 * copied verbatim in the file "LICENSE". *
8 * *
9 * In applying this license GSI does not waive the privileges and immunities *
10 * granted to it by virtue of its status as an Intergovernmental Organization *
11 * or submit itself to any jurisdiction. *
12 ******************************************************************************/
13
14#include "R3BUcesbLauncher.h"
15#include <R3BException.h>
16#include <R3BLogger.h>
17#include <R3BShared.h>
18#include <algorithm>
19#include <boost/algorithm/string.hpp>
20#include <boost/algorithm/string/classification.hpp>
21#include <boost/algorithm/string/constants.hpp>
22#include <boost/algorithm/string/split.hpp>
23#include <boost/algorithm/string/trim.hpp>
24#include <boost/process/v2/process.hpp>
25#include <boost/process/v2/stdio.hpp>
26#include <chrono>
27#include <fairlogger/Logger.h>
28#include <filesystem>
29#include <fmt/core.h>
30#include <fmt/format.h>
31#include <fmt/os.h>
32#include <fmt/ranges.h>
33#include <memory>
34#include <regex>
35
36#include <ext_data_clnt.hh>
37#include <string>
38#include <string_view>
39#include <system_error>
40#include <utility>
41#include <vector>
42
43constexpr auto CHILD_CLOSE_WAITING_TIME = std::chrono::seconds(5);
44
45namespace fs = std::filesystem;
46namespace
47{
48 bool Check_exist(std::string_view exe)
49 {
50 auto exe_path = fs::path{ exe };
51 return fs::exists(exe_path) || fs::is_symlink(exe_path);
52 }
53
54 // TODO: C++23 insert range
55 template <typename T>
56 void Append_elements(std::vector<T>& base, std::vector<T> to_append)
57 {
58 base.reserve(base.size() + to_append.size());
59 for (auto& ele : to_append)
60 {
61 base.emplace_back(std::move(ele));
62 }
63 }
64
65 void Append_lmds(std::vector<std::string>& lmds, std::string_view filename_regex)
66 {
67 // expand filenames on regex
68 Append_elements(lmds, R3B::GetFilesFromRegex(filename_regex));
69 }
70
71 auto parse_splits(std::vector<std::string> splits) -> R3B::UcesbServerLauncher::ResolveResult
72 {
74
75 auto option_regex = std::regex{ "^--[0-9A-z,=\\-]+" };
76 auto lmd_regex = std::regex{ "^.*\\.lmd$" };
77
78 for (auto& split_item : splits)
79 {
80 if (std::regex_match(split_item, option_regex))
81 {
82 result.options.emplace_back(std::move(split_item));
83 }
84 else if (std::regex_match(split_item, lmd_regex))
85 {
86 Append_lmds(result.lmds, split_item);
87 }
88 else if (Check_exist(split_item))
89 {
90 // it must be an executable then
91 if (not result.executable.empty())
92 {
93 R3BLOG(info, fmt::format("Ucesb Executable has been set to \"{}\" ", result.executable));
94 R3BLOG(error, fmt::format("Found another executable \"{}\" but only one is allowed!", split_item));
95 continue;
96 }
97 R3BLOG(info, fmt::format("Ucesb Executable is set to \"{}\" ", split_item));
98 result.executable = std::move(split_item);
99 }
100 else
101 {
102 // In other cases, let ucesb deal with this
103 result.others.emplace_back(std::move(split_item));
104 }
105 }
106 return result;
107 }
108
109 void lmd_filenames_sorting(std::vector<std::string>& filenames)
110 {
111 // simple lexicographically sorting
112 std::sort(filenames.begin(), filenames.end());
113 }
114
115 auto resolve_exe_options_lmd(std::string cmd) -> R3B::UcesbServerLauncher::ResolveResult
116 {
117 if (cmd.empty())
118 {
119 throw R3B::logic_error("Ucesb command string is empty!");
120 }
121 R3BLOG(debug, fmt::format("Resolving string command: {}", cmd));
122 boost::trim(cmd);
123 auto splits = std::vector<std::string>{};
124 boost::split(splits, cmd, boost::is_any_of(" "), boost::token_compress_on);
125 if (splits.empty())
126 {
127 throw R3B::runtime_error(fmt::format("Get 0 element from splitting string {}", cmd));
128 }
129 auto results = parse_splits(std::move(splits));
130 lmd_filenames_sorting(results.lmds);
131
132 return results;
133 }
134} // namespace
135
136namespace R3B
137{
138 void UcesbServerLauncher::SetLaunchCmd(const std::string& command_string)
139 {
140 launch_strings_ = resolve_exe_options_lmd(command_string);
141 if (launch_strings_.executable.empty())
142 {
143 R3BLOG(error, fmt::format("An unpacker executable doesn't exist in options {:?}", command_string));
144 }
145 Append_elements(launch_args, std::move(launch_strings_.options));
146 Append_elements(launch_args, std::move(launch_strings_.lmds));
147 Append_elements(launch_args, std::move(launch_strings_.others));
148
149 R3BLOG(debug,
150 fmt::format("Ucesb command after resolving wildcard filename: \n {} {}",
151 launch_strings_.executable,
152 fmt::join(launch_args, " ")));
153 }
154
156 {
158 std::make_unique<bpv2::process>(ios_,
159 launch_strings_.executable,
161 bpv2::process_stdio{ .in = nullptr, .out = server_pipe_, .err = stderr });
162 R3BLOG(info, fmt::format("Launching an ucesb server with pid: {}", ucesb_server_->id()));
163 if (auto is_status_ok = client_->connect(server_pipe_.native_handle()); not is_status_ok)
164 {
165 R3BLOG(error, "ext_data_clnt::connect() failed");
166 const auto* msg = (client_->last_error() == nullptr) ? UCESB_NULL_STR_MSG : client_->last_error();
167 throw R3B::runtime_error(fmt::format("UCESB error: {}", msg));
168 }
169 }
170
171 // void UcesbServerLauncher::Setup(ext_data_struct_info& struct_info, size_t event_struct_size) {}
172
174 {
175 if (auto ret_val = client_->close(); ret_val != 0)
176 {
177 R3BLOG(error, "ext_data_clnt::close() failed");
178 }
179 auto err_code = std::error_code{};
180 ucesb_server_->async_wait(
181 [](const std::error_code& err, int ret)
182 {
183 if (err)
184 {
185 LOGP(error, "Error occured from ucesb server. Error message: {}", err.message());
186 }
187 LOGP(info, "Ucesb server is closed successfully with the return value: {}", ret);
188 });
190 }
191} // namespace R3B
#define R3BLOG(severity, x)
Definition R3BLogger.h:32
constexpr auto CHILD_CLOSE_WAITING_TIME
constexpr auto UCESB_NULL_STR_MSG
std::unique_ptr< bpv2::process > ucesb_server_
void SetLaunchCmd(const std::string &command_string)
boost::asio::io_context ios_
boost::asio::readable_pipe server_pipe_
std::vector< std::string > launch_args
auto GetFilesFromRegex(std::string_view filename_regex) -> std::vector< std::string >
Definition R3BShared.h:203