jfjoch_writer: Repub ZeroMQ from TCP image stream
All checks were successful
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m36s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 18m8s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 18m22s
Build Packages / Generate python client (push) Successful in 34s
Build Packages / build:rpm (rocky9) (push) Successful in 19m16s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 19m28s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 19m37s
Build Packages / build:rpm (rocky8) (push) Successful in 19m56s
Build Packages / Build documentation (push) Successful in 1m10s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 20m36s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m11s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m36s
Build Packages / Unit tests (push) Successful in 53m29s

This commit is contained in:
2026-03-05 17:22:47 +01:00
parent 8bfe145afa
commit ad1e724bcf
4 changed files with 227 additions and 15 deletions

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
#include "TCPImagePuller.h"
#include "../frame_serialize/CBORStream2Serializer.h"
#include <sys/socket.h>
#include <arpa/inet.h>
@@ -10,7 +11,7 @@
#include <limits>
#include <netdb.h>
static std::pair<std::string, uint16_t> ParseTcpAddressPull(const std::string& addr) {
static std::pair<std::string, uint16_t> ParseTcpAddressPull(const std::string &addr) {
const std::string prefix = "tcp://";
if (addr.rfind(prefix, 0) != 0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Invalid TCP address: " + addr);
@@ -28,27 +29,39 @@ static std::pair<std::string, uint16_t> ParseTcpAddressPull(const std::string& a
size_t parsed = 0;
port_i = std::stoi(port_str, &parsed);
if (parsed != port_str.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Invalid TCP port in address: " + addr);
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Invalid TCP port in address: " + addr);
} catch (...) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Invalid TCP port in address: " + addr);
}
if (port_i < 1 || port_i > static_cast<int>(std::numeric_limits<uint16_t>::max()))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "TCP port out of range in address: " + addr);
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"TCP port out of range in address: " + addr);
return {host, static_cast<uint16_t>(port_i)};
}
TCPImagePuller::TCPImagePuller(const std::string &tcp_addr,
std::optional<int32_t> rcv_buffer_size)
: addr(tcp_addr),
receive_buffer_size(rcv_buffer_size) {
std::optional<int32_t> rcv_buffer_size,
const std::string &repub_address,
const std::optional<int32_t> &repub_watermark)
: addr(tcp_addr),
receive_buffer_size(rcv_buffer_size) {
auto parsed = ParseTcpAddressPull(tcp_addr);
host = parsed.first;
port = parsed.second;
receiver_thread = std::thread(&TCPImagePuller::ReceiverThread, this);
cbor_thread = std::thread(&TCPImagePuller::CBORThread, this);
if (!repub_address.empty()) {
repub_socket = std::make_unique<ZMQSocket>(ZMQSocketType::Push);
repub_socket->SendWaterMark(repub_watermark.value_or(default_repub_watermark));
repub_socket->SendTimeout(RepubTimeout);
repub_socket->Bind(repub_address);
repub_thread = std::thread(&TCPImagePuller::RepubThread, this);
}
}
bool TCPImagePuller::SendAll(const void *buf, size_t len) {
@@ -113,15 +126,53 @@ void TCPImagePuller::CBORThread() {
} else {
ret.cbor = CBORStream2Deserialize(ret.tcp_msg->payload.data(), ret.tcp_msg->payload.size());
outside_fifo.PutBlocking(ret);
if (repub_socket) {
if ((ret.cbor->msg_type == CBORImageType::START)
|| (ret.cbor->msg_type == CBORImageType::END))
repub_fifo.PutBlocking(ret);
else
repub_fifo.Put(ret);
}
}
} catch (const JFJochException &e) {
logger.ErrorException(e);
}
ret = cbor_fifo.GetBlocking();
}
if (repub_socket)
repub_fifo.PutBlocking(ret);
outside_fifo.PutBlocking(ret);
}
void TCPImagePuller::RepubThread() {
auto ret = repub_fifo.GetBlocking();
bool repub_active = false;
while (ret.tcp_msg) {
try {
if (ret.cbor->msg_type == CBORImageType::START) {
// Start message needs to be cleaned when running republish
StartMessage msg = ret.cbor->start_message.value();
msg.writer_notification_zmq_addr = "";
std::vector<uint8_t> serialization_buffer(256 * 1024 * 1024);
CBORStream2Serializer serializer(serialization_buffer.data(), serialization_buffer.size());
serializer.SerializeSequenceStart(msg);
repub_active = repub_socket->Send(serialization_buffer.data(), serializer.GetBufferSize(), true);
if (repub_active)
logger.Info("Republish active");
} else {
if (repub_active)
repub_socket->Send(ret.tcp_msg->payload.data(), ret.tcp_msg->payload.size(), true);
}
} catch (const JFJochException &e) {
logger.ErrorException(e);
}
ret = repub_fifo.GetBlocking();
}
if (repub_active)
logger.Info("Republish finished");
}
TCPImagePuller::~TCPImagePuller() {
TCPImagePuller::Disconnect();
}
@@ -150,7 +201,7 @@ bool TCPImagePuller::EnsureConnected() {
}
addrinfo hints{};
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
@@ -322,4 +373,6 @@ void TCPImagePuller::Disconnect() {
receiver_thread.join();
if (cbor_thread.joinable())
cbor_thread.join();
}
if (repub_thread.joinable())
repub_thread.join();
}