46 std::scoped_lock<std::mutex> lock(
_mutex);
49 _router->WriteLoadMap(map, extras);
56 const std::weak_ptr<Primary> *target,
57 std::weak_ptr<Primary> &out_session,
63 auto fut = (target !=
nullptr) ?
67 auto response = fut.get();
68 if (response.session ==
nullptr) {
69 log_error(
"multigpu: no secondary provided a token for sensor ", sensor_id);
73 const std::string_view payload(
reinterpret_cast<const char *
>(response.buffer.data()), response.buffer.size());
75 log_error(
"multigpu: secondary cannot serve sensor ", sensor_id,
" (actor ", sensor_actor_id,
")");
80 log_error(
"multigpu: malformed token reply for sensor ", sensor_id,
": ", response.buffer.size(),
" bytes");
84 out_session = response.session;
86 std::memcpy(&data, response.buffer.data(),
sizeof(data));
99 std::scoped_lock<std::mutex> lock(
_mutex);
100 std::string msg(
"Are you alive?");
101 carla::Buffer buf(
reinterpret_cast<const unsigned char *
>(msg.c_str()),
static_cast<size_t>(msg.size()));
102 log_info(
"sending is alive command");
104 auto response = fut.get();
105 if (response.session ==
nullptr) {
106 log_error(
"multigpu: is-alive command got no reply");
109 log_info(
"response from alive command: ", response.buffer.data());
120 auto response = fut.get();
121 if ((response.session ==
nullptr) || response.buffer.empty()) {
122 log_error(
"enable_for_ros for sensor ", sensor_id,
" got no reply from its secondary server");
126 log_error(
"enable_for_ros for sensor ", sensor_id,
" was refused by its secondary server");
131 log_error(
"enable_for_ros for sensor", sensor_id,
" not found on any server");
144 auto response = fut.get();
145 if ((response.session ==
nullptr) || response.buffer.empty()) {
146 log_error(
"disable_for_ros for sensor ", sensor_id,
" got no reply from its secondary server");
148 log_error(
"disable_for_ros for sensor ", sensor_id,
" was refused by its secondary server");
151 log_error(
"disable_for_ros for sensor", sensor_id,
" not found on any server");
163 auto response = fut.get();
164 if ((response.session ==
nullptr) || response.buffer.empty()) {
165 log_error(
"is_enabled_for_ros for sensor ", sensor_id,
" got no reply from its secondary server");
170 log_error(
"is_enabled_for_ros for sensor", sensor_id,
" not found on any server");
176 std::scoped_lock<std::mutex> lock(
_mutex);
178 auto it =
_tokens.find(sensor_id);
180 log_debug(
"Using token from already activated sensor: ", it->second.get_stream_id(),
", ", it->second.get_port());
184 const bool lost =
_servers.contains(sensor_id);
186 log_warning(
"multigpu: secondary of sensor ", sensor_id,
" is gone, routing it again");
191 std::weak_ptr<Primary> server;
193 auto token =
SendGetToken(sensor_id, sensor_actor_id,
nullptr, server, error);
202 _tokens.emplace(sensor_id, *token);
204 route->second.session = server;
205 route->second.actor = sensor_actor_id;
209 log_debug(
"Using token from new activated sensor: ", token->get_stream_id(),
", ", token->get_port());
215 std::scoped_lock<std::mutex> lock(
_mutex);
219 _servers[sensor_id].ros_enabled =
true;
228 if (!
GetToken(sensor_id, sensor_actor_id)) {
229 log_error(
"enable_for_ros for sensor ", sensor_id,
" failed: no secondary server accepted it");
236 std::scoped_lock<std::mutex> lock(
_mutex);
241 it->second.ros_enabled =
false;
242 if (
_router->IsConnected(it->second.session)) {
248 std::scoped_lock<std::mutex> lock(
_mutex);
256 std::scoped_lock<std::mutex> lock(
_mutex);
257 std::size_t rerouted = 0u;
258 for (
const auto &session :
_router->TakeNewSessions()) {
259 std::vector<stream_id> lost;
260 for (
const auto &[sensor_id, route] :
_servers) {
261 if (!
_router->IsConnected(route.session)) {
262 lost.push_back(sensor_id);
265 std::sort(lost.begin(), lost.end());
267 if (!
_router->IsConnected(session)) {
270 auto route =
_servers.find(sensor_id);
271 std::weak_ptr<Primary> server;
273 auto token =
SendGetToken(sensor_id, route->second.actor, &session, server, error);
276 log_warning(
"multigpu: the new secondary left while routing sensor ", sensor_id,
"; it stays lost");
279 log_warning(
"multigpu: could not route sensor ", sensor_id,
" to the new secondary; its listeners must listen() again");
284 auto old_token =
_tokens.find(sensor_id);
285 if ((old_token !=
_tokens.end()) && (old_token->second.get_port() != token->get_port())) {
286 log_warning(
"multigpu: sensor ", sensor_id,
" moved from port ", old_token->second.get_port(),
287 " to port ", token->get_port(),
"; existing listeners cannot follow it");
290 _tokens.emplace(sensor_id, *token);
291 route->second.session = server;
292 log_info(
"multigpu: routed sensor ", sensor_id,
" to the new secondary at port ", token->get_port());
301 std::scoped_lock<std::mutex> lock(
_mutex);
308 return (it !=
_servers.end()) &&
_router->IsConnected(it->second.session);
313 if ((it ==
_servers.end()) || !it->second.ros_enabled) {
317 log_warning(
"multigpu: could not enable ROS again for sensor ", sensor_id,
" on its new secondary");
323 std::memcpy(&value, buffer.
data(),
sizeof(value));
const value_type * data() const noexcept
Direct access to the allocated memory or nullptr if no memory is allocated.
std::unordered_map< stream_id, token_type > _tokens
void set_router(std::shared_ptr< Router > router)
std::optional< token_type > GetToken(stream_id sensor_id, actor_id sensor_actor_id)
Returns std::nullopt if no secondary could provide the token (e.g.
std::size_t RerouteLostSensors()
Routes every sensor whose secondary disconnected to the secondaries connected since the previous call...
void DisableForROS(stream_id sensor_id)
bool SendIsEnabledForROS(stream_id sensor_id)
void SendFrameData(carla::Buffer buffer)
bool SendEnableForROS(stream_id sensor_id)
std::optional< token_type > SendGetToken(stream_id sensor_id, actor_id sensor_actor_id, const std::weak_ptr< Primary > *target, std::weak_ptr< Primary > &out_session, TokenError &error)
bool IsRoutedToLiveSecondary(stream_id sensor_id)
Whether sensor_id is routed to a secondary that is still connected.
bool EnableForROS(stream_id sensor_id, actor_id sensor_actor_id)
Returns false if no secondary accepted this sensor or the secondary holding it did not reply; ROS ena...
std::unordered_map< stream_id, Route > _servers
void SendDisableForROS(stream_id sensor_id)
void ForgetSensor(stream_id sensor_id)
Drops the routing of a destroyed sensor so it is never routed again.
static bool ReadBoolReply(const carla::Buffer &buffer)
Reads a one-bool reply; buffer must not be empty.
void RestoreRosAfterReroute(stream_id sensor_id)
Enables ROS again on the new secondary of a re-routed sensor if it was enabled before.
bool IsEnabledForROS(stream_id sensor_id)
std::shared_ptr< Router > _router
void SendLoadMap(std::string map, const LoadMapExtras &extras={})
Serializes a stream endpoint.
const auto & get_stream_id() const
void set_stream_id(stream_id_type id)
constexpr std::string_view kTokenNotReadyMarker
GET_TOKEN reply when the secondary cannot resolve the sensor to a stream (or the request is malformed...
carla::streaming::detail::stream_id_type stream_id
This file contains definitions of common data structures used in traffic manager.
static void log_error(Args &&... args)
static void log_info(Args &&... args)
static void log_warning(Args &&... args)
static void log_debug(Args &&... args)
GET_TOKEN request payload.