Updated without Vector

This commit is contained in:
Martino Ferrari
2026-05-20 11:30:05 +02:00
parent d967098ead
commit f6eb0a7056
24 changed files with 1457 additions and 1666 deletions
@@ -24,6 +24,10 @@ const uint32 DebugService::CMD_RATE_LIMIT;
const uint32 DebugService::CLIENT_IDLE_TIMEOUT_MS;
const uint32 DebugService::INPUT_BUFFER_MAX;
// Maximum data bytes that fit in one sample entry inside a datagram:
// STREAMER_BUFFER_SIZE(65535) - TraceHeader(20) - entry_header(16) = 65499
static const uint32 MAX_SAMPLE_DATA_SIZE = 65499u;
// ---------------------------------------------------------------------------
// Constructor / Destructor
// ---------------------------------------------------------------------------
@@ -313,12 +317,21 @@ ErrorManagement::ErrorType DebugService::Server(ExecutionInfo &info) {
uint32 cmdLen = len;
command.Write(raw + lineStart, cmdLen);
// Dispatch via base HandleCommand, write response to socket
// Dispatch via base HandleCommand, write response to socket.
// Loop to handle partial writes for large responses.
StreamString out;
HandleCommand(command, out);
if (out.Size() > 0u) {
uint32 outSz = out.Size();
(void)activeClient->Write(out.Buffer(), outSz);
const char8 *wPtr = out.Buffer();
uint32 remaining = (uint32)out.Size();
while (remaining > 0u) {
uint32 wrote = remaining;
if (!activeClient->Write(wPtr, wrote) || wrote == 0u) {
break;
}
wPtr += wrote;
remaining -= wrote;
}
}
}
lineStart = pos + 1u;
@@ -374,7 +387,7 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
uint64 currentTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
HighResolutionTimer::Period() * 1000.0);
mutex.FastLock();
for (uint32 i = 0u; i < monitoredSignals.Size(); i++) {
for (uint32 i = 0u; i < monitoredSignals.GetNumberOfElements(); i++) {
if (currentTimeMs >= (monitoredSignals[i].lastPollTime +
monitoredSignals[i].periodMs)) {
monitoredSignals[i].lastPollTime = currentTimeMs;
@@ -392,54 +405,62 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
}
mutex.FastUnLock();
// Drain ring buffer into UDP packet(s)
static const uint32 SAMPLE_BUF_SIZE = 1024u;
typedef char StaticAssert_StreamerBufferTooSmall[
(sizeof(TraceHeader) + 16u + SAMPLE_BUF_SIZE <= STREAMER_BUFFER_SIZE) ? 1 : -1];
(void)sizeof(StaticAssert_StreamerBufferTooSmall);
// Drain ring buffer into UDP packet(s).
//
// Batching strategy:
// - Normal samples (entry ≤ STREAMER_MTU): accumulate into a packet and
// flush when the next sample would push it past STREAMER_MTU.
// - Oversized samples (entry > STREAMER_MTU): flush any pending packet
// first, then send the oversized sample as its own datagram (up to
// STREAMER_BUFFER_SIZE bytes; handled transparently by IP fragmentation
// on loopback / internal networks).
// - MAX_SAMPLE_DATA_SIZE (65499 bytes) is the hard cap; larger entries
// in the ring buffer are skipped by Pop() and discarded.
bool hasData = false;
uint32 id, size;
uint64 ts;
uint8 sampleData[SAMPLE_BUF_SIZE];
bool hasData = false;
while (traceBuffer.Pop(id, ts, sampleData, size, SAMPLE_BUF_SIZE)) {
while (traceBuffer.Pop(id, ts, streamerSampleBuffer, size, MAX_SAMPLE_DATA_SIZE)) {
hasData = true;
if (size > SAMPLE_BUF_SIZE ||
streamerPacketOffset + 16u + size > STREAMER_BUFFER_SIZE) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"Streamer: sample size %u would overflow assembly buffer "
"(%u bytes used of %u) — sample dropped.",
size, streamerPacketOffset, STREAMER_BUFFER_SIZE);
continue;
}
if (streamerPacketOffset == 0u) {
TraceHeader header;
header.magic = 0xDA7A57ADu;
header.seq = streamerSequenceNumber++;
header.timestamp = HighResolutionTimer::Counter();
header.count = 0u;
memcpy(streamerPacketBuffer, &header, sizeof(TraceHeader));
streamerPacketOffset = sizeof(TraceHeader);
}
if (streamerPacketOffset + 16u + size > STREAMER_MTU) {
const uint32 entryBytes = 16u + size; // [id:4][ts:8][size:4][data:size]
// If this entry would push the current packet past the MTU target,
// flush what we have before appending (unless the buffer is empty).
if (streamerPacketOffset > 0u &&
streamerPacketOffset + entryBytes > STREAMER_MTU) {
uint32 toWrite = streamerPacketOffset;
(void)udpSocket.Write((char8 *)streamerPacketBuffer, toWrite);
TraceHeader header;
header.magic = 0xDA7A57ADu;
header.seq = streamerSequenceNumber++;
header.timestamp = HighResolutionTimer::Counter();
header.count = 0u;
memcpy(streamerPacketBuffer, &header, sizeof(TraceHeader));
streamerPacketOffset = sizeof(TraceHeader);
streamerPacketOffset = 0u;
}
memcpy(&streamerPacketBuffer[streamerPacketOffset], &id, 4u);
memcpy(&streamerPacketBuffer[streamerPacketOffset + 4u], &ts, 8u);
// Open a new packet header if the buffer is empty.
if (streamerPacketOffset == 0u) {
TraceHeader hdr;
hdr.magic = 0xDA7A57ADu;
hdr.seq = streamerSequenceNumber++;
hdr.timestamp = HighResolutionTimer::Counter();
hdr.count = 0u;
memcpy(streamerPacketBuffer, &hdr, sizeof(TraceHeader));
streamerPacketOffset = (uint32)sizeof(TraceHeader);
}
// Append the sample entry.
memcpy(&streamerPacketBuffer[streamerPacketOffset], &id, 4u);
memcpy(&streamerPacketBuffer[streamerPacketOffset + 4u], &ts, 8u);
memcpy(&streamerPacketBuffer[streamerPacketOffset + 12u], &size, 4u);
memcpy(&streamerPacketBuffer[streamerPacketOffset + 16u], sampleData, size);
streamerPacketOffset += (16u + size);
memcpy(&streamerPacketBuffer[streamerPacketOffset + 16u], streamerSampleBuffer, size);
streamerPacketOffset += entryBytes;
((TraceHeader *)streamerPacketBuffer)->count++;
// Oversized single sample: send immediately rather than accumulating.
if (streamerPacketOffset > STREAMER_MTU) {
uint32 toWrite = streamerPacketOffset;
(void)udpSocket.Write((char8 *)streamerPacketBuffer, toWrite);
streamerPacketOffset = 0u;
}
}
// Flush any remaining partial packet.
if (streamerPacketOffset > 0u) {
uint32 toWrite = streamerPacketOffset;
(void)udpSocket.Write((char8 *)streamerPacketBuffer, toWrite);