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 <memory>
33#include <regex>
34
35#include <ext_data_clnt.hh>
36#include <string>
37#include <string_view>
38#include <system_error>
39#include <utility>
40#include <vector>
41
42constexpr auto CHILD_CLOSE_WAITING_TIME = std::chrono::seconds(5);
43
44namespace fs = std::filesystem;
45namespace
46{
47 bool Check_exist(std::string_view exe)
48 {
49 auto exe_path = fs::path{ exe };
50 return fs::exists(exe_path) || fs::is_symlink(exe_path);
51 }
52
53 // TODO: C++23 insert range
54 template <typename T>
55 void Append_elements(std::vector<T>& base, std::vector<T> to_append)
56 {
57 base.reserve(base.size() + to_append.size());
58 for (auto& ele : to_append)
59 {
60 base.emplace_back(std::move(ele));
61 }
62 }
63
64 void Append_lmds(std::vector<std::string>& lmds, std::string_view filename_regex)
65 {
66 // expand filenames on regex
67 Append_elements(lmds, R3B::GetFilesFromRegex(filename_regex));
68 }
69
70 auto parse_splits(std::vector<std::string> splits) -> R3B::UcesbServerLauncher::ResolveResult
71 {
73
74 auto option_regex = std::regex{ "^--[0-9A-z,=\\-]+" };
75 auto lmd_regex = std::regex{ "^.*\\.lmd$" };
76
77 for (auto& split_item : splits)
78 {
79 if (std::regex_match(split_item, option_regex))
80 {
81 result.options.emplace_back(std::move(split_item));
82 }
83 else if (std::regex_match(split_item, lmd_regex))
84 {
85 Append_lmds(result.lmds, split_item);
86 }
87 else if (Check_exist(split_item))
88 {
89 // it must be an executable then
90 if (not result.executable.empty())
91 {
92 R3BLOG(info, fmt::format("Ucesb Executable has been set to \"{}\" ", result.executable));
93 R3BLOG(error, fmt::format("Found another executable \"{}\" but only one is allowed!", split_item));
94 continue;
95 }
96 R3BLOG(info, fmt::format("Ucesb Executable is set to \"{}\" ", split_item));
97 result.executable = std::move(split_item);
98 }
99 else
100 {
101 // In other cases, let ucesb deal with this
102 result.others.emplace_back(std::move(split_item));
103 }
104 }
105 return result;
106 }
107
108 void lmd_filenames_sorting(std::vector<std::string>& filenames)
109 {
110 // simple lexicographically sorting
111 std::sort(filenames.begin(), filenames.end());
112 }
113
114 auto resolve_exe_options_lmd(std::string cmd) -> R3B::UcesbServerLauncher::ResolveResult
115 {
116 if (cmd.empty())
117 {
118 throw R3B::logic_error("Ucesb command string is empty!");
119 }
120 R3BLOG(debug, fmt::format("Resolving string command: {}", cmd));
121 boost::trim(cmd);
122 auto splits = std::vector<std::string>{};
123 boost::split(splits, cmd, boost::is_any_of(" "), boost::token_compress_on);
124 if (splits.empty())
125 {
126 throw R3B::runtime_error(fmt::format("Get 0 element from splitting string {}", cmd));
127 }
128 auto results = parse_splits(std::move(splits));
129 lmd_filenames_sorting(results.lmds);
130
131 return results;
132 }
133} // namespace
134
135namespace R3B
136{
137 void UcesbServerLauncher::SetLaunchCmd(const std::string& command_string)
138 {
139 launch_strings_ = resolve_exe_options_lmd(command_string);
140 if (launch_strings_.executable.empty())
141 {
142 R3BLOG(error, fmt::format("An unpacker executable doesn't exist in options {:?}", command_string));
143 }
144 Append_elements(launch_args, std::move(launch_strings_.options));
145 Append_elements(launch_args, std::move(launch_strings_.lmds));
146 Append_elements(launch_args, std::move(launch_strings_.others));
147
148 R3BLOG(debug,
149 fmt::format("Ucesb command after resolving wildcard filename: \n {} {}",
150 launch_strings_.executable,
151 fmt::join(launch_args, " ")));
152 }
153
155 {
157 std::make_unique<bpv2::process>(ios_,
158 launch_strings_.executable,
160 bpv2::process_stdio{ .in = nullptr, .out = server_pipe_, .err = stderr });
161 R3BLOG(info, fmt::format("Launching an ucesb server with pid: {}", ucesb_server_->id()));
162 if (auto is_status_ok = client_->connect(server_pipe_.native_handle()); not is_status_ok)
163 {
164 R3BLOG(error, "ext_data_clnt::connect() failed");
165 const auto* msg = (client_->last_error() == nullptr) ? UCESB_NULL_STR_MSG : client_->last_error();
166 throw R3B::runtime_error(fmt::format("UCESB error: {}", msg));
167 }
168 }
169
170 // void UcesbServerLauncher::Setup(ext_data_struct_info& struct_info, size_t event_struct_size) {}
171
173 {
174 if (auto ret_val = client_->close(); ret_val != 0)
175 {
176 R3BLOG(error, "ext_data_clnt::close() failed");
177 }
178 auto err_code = std::error_code{};
179 ucesb_server_->async_wait(
180 [](const std::error_code& err, int ret)
181 {
182 if (err)
183 {
184 LOGP(error, "Error occured from ucesb server. Error message: {}", err.message());
185 }
186 LOGP(info, "Ucesb server is closed successfully with the return value: {}", ret);
187 });
189 }
190} // 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:204