Updated without Vector
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
#include "ObjectBuilder.h"
|
||||
#include "ObjectRegistryDatabase.h"
|
||||
#include "Threads.h"
|
||||
#include "Vec.h"
|
||||
|
||||
// Original broker headers
|
||||
#include "MemoryMapAsyncOutputBroker.h"
|
||||
@@ -105,10 +104,10 @@ public:
|
||||
|
||||
static void Process(DebugServiceI *service,
|
||||
DebugSignalInfo **signalInfoPointers,
|
||||
Vec<uint32> &activeIndices, Vec<uint32> &activeSizes,
|
||||
Vector<uint32> &activeIndices, Vector<uint32> &activeSizes,
|
||||
FastPollingMutexSem &activeMutex,
|
||||
volatile bool *anyBreakFlag,
|
||||
Vec<uint32> *breakIndices) {
|
||||
Vector<uint32> *breakIndices) {
|
||||
if (service == NULL_PTR(DebugServiceI *))
|
||||
return;
|
||||
|
||||
@@ -117,7 +116,7 @@ public:
|
||||
// because that prevents cross-thread EventSem posts from completing.
|
||||
|
||||
activeMutex.FastLock();
|
||||
uint32 n = activeIndices.Size();
|
||||
uint32 n = activeIndices.GetNumberOfElements();
|
||||
if (n > 0 && signalInfoPointers != NULL_PTR(DebugSignalInfo **)) {
|
||||
// Capture timestamp ONCE per broker cycle for lowest impact
|
||||
uint64 ts = (uint64)((float64)HighResolutionTimer::Counter() *
|
||||
@@ -139,13 +138,13 @@ public:
|
||||
// stall would block UpdateBrokersBreakStatus() in the Server thread and
|
||||
// cause unnecessary priority inversion on the RT path.
|
||||
bool shouldCheckBreak = (*anyBreakFlag && !service->IsPaused() &&
|
||||
breakIndices != NULL_PTR(Vec<uint32> *) &&
|
||||
breakIndices != NULL_PTR(Vector<uint32> *) &&
|
||||
signalInfoPointers != NULL_PTR(DebugSignalInfo **));
|
||||
static const uint32 MAX_BREAK_INDICES = 64u;
|
||||
uint32 localBreakIdx[MAX_BREAK_INDICES];
|
||||
uint32 nb = 0u;
|
||||
if (shouldCheckBreak) {
|
||||
nb = breakIndices->Size();
|
||||
nb = breakIndices->GetNumberOfElements();
|
||||
if (nb > MAX_BREAK_INDICES) nb = MAX_BREAK_INDICES;
|
||||
for (uint32 i = 0; i < nb; i++) {
|
||||
localBreakIdx[i] = (*breakIndices)[i];
|
||||
@@ -176,9 +175,9 @@ public:
|
||||
DebugServiceI *&service, DebugSignalInfo **&signalInfoPointers,
|
||||
uint32 numCopies, MemoryMapBrokerCopyTableEntry *copyTable,
|
||||
const char8 *functionName, SignalDirection direction,
|
||||
volatile bool *anyActiveFlag, Vec<uint32> *activeIndices,
|
||||
Vec<uint32> *activeSizes, FastPollingMutexSem *activeMutex,
|
||||
volatile bool *anyBreakFlag, Vec<uint32> *breakIndices) {
|
||||
volatile bool *anyActiveFlag, Vector<uint32> *activeIndices,
|
||||
Vector<uint32> *activeSizes, FastPollingMutexSem *activeMutex,
|
||||
volatile bool *anyBreakFlag, Vector<uint32> *breakIndices) {
|
||||
if (numCopies > 0) {
|
||||
signalInfoPointers = new DebugSignalInfo *[numCopies];
|
||||
for (uint32 i = 0; i < numCopies; i++)
|
||||
@@ -352,9 +351,9 @@ public:
|
||||
volatile bool anyBreakActive;
|
||||
bool isOutput;
|
||||
char8 gamName[256];
|
||||
Vec<uint32> activeIndices;
|
||||
Vec<uint32> activeSizes;
|
||||
Vec<uint32> breakIndices;
|
||||
Vector<uint32> activeIndices;
|
||||
Vector<uint32> activeSizes;
|
||||
Vector<uint32> breakIndices;
|
||||
FastPollingMutexSem activeMutex;
|
||||
};
|
||||
|
||||
@@ -412,9 +411,9 @@ public:
|
||||
volatile bool anyBreakActive;
|
||||
bool isOutput;
|
||||
char8 gamName[256];
|
||||
Vec<uint32> activeIndices;
|
||||
Vec<uint32> activeSizes;
|
||||
Vec<uint32> breakIndices;
|
||||
Vector<uint32> activeIndices;
|
||||
Vector<uint32> activeSizes;
|
||||
Vector<uint32> breakIndices;
|
||||
FastPollingMutexSem activeMutex;
|
||||
};
|
||||
|
||||
@@ -471,9 +470,9 @@ public:
|
||||
volatile bool anyActive;
|
||||
volatile bool anyBreakActive;
|
||||
char8 gamName[256];
|
||||
Vec<uint32> activeIndices;
|
||||
Vec<uint32> activeSizes;
|
||||
Vec<uint32> breakIndices;
|
||||
Vector<uint32> activeIndices;
|
||||
Vector<uint32> activeSizes;
|
||||
Vector<uint32> breakIndices;
|
||||
FastPollingMutexSem activeMutex;
|
||||
};
|
||||
|
||||
@@ -531,9 +530,9 @@ public:
|
||||
volatile bool anyActive;
|
||||
volatile bool anyBreakActive;
|
||||
char8 gamName[256];
|
||||
Vec<uint32> activeIndices;
|
||||
Vec<uint32> activeSizes;
|
||||
Vec<uint32> breakIndices;
|
||||
Vector<uint32> activeIndices;
|
||||
Vector<uint32> activeSizes;
|
||||
Vector<uint32> breakIndices;
|
||||
FastPollingMutexSem activeMutex;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -82,9 +82,13 @@ private:
|
||||
BasicTCPSocket *activeClient;
|
||||
|
||||
// Streamer assembly buffer
|
||||
// STREAMER_MTU: target packet size for batching small signals (network-friendly).
|
||||
// STREAMER_BUFFER_SIZE: maximum UDP datagram payload; large single-signal samples
|
||||
// can exceed STREAMER_MTU and are sent as their own datagram up to this limit.
|
||||
static const uint32 STREAMER_MTU = 1400u;
|
||||
static const uint32 STREAMER_BUFFER_SIZE = 4096u;
|
||||
uint8 streamerPacketBuffer[STREAMER_BUFFER_SIZE];
|
||||
static const uint32 STREAMER_BUFFER_SIZE = 65535u;
|
||||
uint8 streamerPacketBuffer[STREAMER_BUFFER_SIZE]; // assembled outgoing packet
|
||||
uint8 streamerSampleBuffer[STREAMER_BUFFER_SIZE]; // staging for one popped sample
|
||||
uint32 streamerPacketOffset;
|
||||
uint32 streamerSequenceNumber;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,11 +52,11 @@ public:
|
||||
uint32 numSignals,
|
||||
MemoryMapBroker *broker,
|
||||
volatile bool *anyActiveFlag,
|
||||
Vec<uint32> *activeIndices,
|
||||
Vec<uint32> *activeSizes,
|
||||
Vector<uint32> *activeIndices,
|
||||
Vector<uint32> *activeSizes,
|
||||
FastPollingMutexSem *activeMutex,
|
||||
volatile bool *anyBreakFlag,
|
||||
Vec<uint32> *breakIndices,
|
||||
Vector<uint32> *breakIndices,
|
||||
const char8 *gamName = NULL_PTR(const char8 *),
|
||||
bool isOutput = false);
|
||||
|
||||
@@ -167,10 +167,10 @@ protected:
|
||||
// Shared data members
|
||||
// =========================================================================
|
||||
|
||||
Vec<DebugSignalInfo *> signals;
|
||||
Vec<SignalAlias> aliases;
|
||||
Vec<BrokerInfo> brokers;
|
||||
Vec<MonitoredSignal> monitoredSignals;
|
||||
Vector<DebugSignalInfo *> signals;
|
||||
Vector<SignalAlias> aliases;
|
||||
Vector<BrokerInfo> brokers;
|
||||
Vector<MonitoredSignal> monitoredSignals;
|
||||
|
||||
FastPollingMutexSem mutex;
|
||||
FastPollingMutexSem tracePushMutex;
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "Object.h"
|
||||
#include "StreamString.h"
|
||||
#include "TypeDescriptor.h"
|
||||
#include "Vec.h"
|
||||
|
||||
namespace MARTe {
|
||||
|
||||
@@ -49,11 +48,11 @@ struct BrokerInfo {
|
||||
uint32 numSignals;
|
||||
MemoryMapBroker *broker;
|
||||
volatile bool *anyActiveFlag;
|
||||
Vec<uint32> *activeIndices;
|
||||
Vec<uint32> *activeSizes;
|
||||
Vector<uint32> *activeIndices;
|
||||
Vector<uint32> *activeSizes;
|
||||
FastPollingMutexSem *activeMutex;
|
||||
volatile bool *anyBreakFlag;
|
||||
Vec<uint32> *breakIndices;
|
||||
Vector<uint32> *breakIndices;
|
||||
StreamString gamName;
|
||||
bool isOutput;
|
||||
};
|
||||
@@ -124,11 +123,11 @@ public:
|
||||
uint32 numSignals,
|
||||
MemoryMapBroker *broker,
|
||||
volatile bool *anyActiveFlag,
|
||||
Vec<uint32> *activeIndices,
|
||||
Vec<uint32> *activeSizes,
|
||||
Vector<uint32> *activeIndices,
|
||||
Vector<uint32> *activeSizes,
|
||||
FastPollingMutexSem *activeMutex,
|
||||
volatile bool *anyBreakFlag,
|
||||
Vec<uint32> *breakIndices,
|
||||
Vector<uint32> *breakIndices,
|
||||
const char8 *gamName = NULL_PTR(const char8 *),
|
||||
bool isOutput = false) = 0;
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ ROOT_DIR=../../../../
|
||||
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
|
||||
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
|
||||
|
||||
INCLUDES += -I$(ROOT_DIR)/Source/Core/Types/Result
|
||||
INCLUDES += -I$(ROOT_DIR)/Source/Core/Types/Vec
|
||||
INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/TCPLogger
|
||||
INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/DebugService
|
||||
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
|
||||
|
||||
@@ -451,7 +451,7 @@ ErrorManagement::ErrorType WebDebugService::Streamer(ExecutionInfo &info) {
|
||||
// Poll monitored signals → SSE monitor events
|
||||
// -----------------------------------------------------------------
|
||||
mutex.FastLock();
|
||||
for (uint32 i = 0u; i < monitoredSignals.Size(); i++) {
|
||||
for (uint32 i = 0u; i < monitoredSignals.GetNumberOfElements(); i++) {
|
||||
if (nowMs >= (monitoredSignals[i].lastPollTime +
|
||||
monitoredSignals[i].periodMs)) {
|
||||
monitoredSignals[i].lastPollTime = nowMs;
|
||||
@@ -468,7 +468,7 @@ ErrorManagement::ErrorType WebDebugService::Streamer(ExecutionInfo &info) {
|
||||
float64 val = WDS_ToFloat64(lb, td);
|
||||
|
||||
StreamString sigName;
|
||||
for (uint32 j = 0u; j < aliases.Size(); j++) {
|
||||
for (uint32 j = 0u; j < aliases.GetNumberOfElements(); j++) {
|
||||
if (signals[aliases[j].signalIndex]->internalID ==
|
||||
monitoredSignals[i].internalID) {
|
||||
sigName = aliases[j].name;
|
||||
@@ -499,24 +499,21 @@ ErrorManagement::ErrorType WebDebugService::Streamer(ExecutionInfo &info) {
|
||||
// -----------------------------------------------------------------
|
||||
// Drain ring buffer → SSE trace events
|
||||
// -----------------------------------------------------------------
|
||||
static const uint32 SAMPLE_BUF_SIZE = 1024u;
|
||||
static const uint32 MAX_TRACE_CYCLE = 50u;
|
||||
uint32 id, size;
|
||||
uint64 sampleTs;
|
||||
uint8 sampleData[SAMPLE_BUF_SIZE];
|
||||
bool hasData = false;
|
||||
uint32 traceCount = 0u;
|
||||
|
||||
while (traceCount < MAX_TRACE_CYCLE &&
|
||||
traceBuffer.Pop(id, sampleTs, sampleData, size, SAMPLE_BUF_SIZE)) {
|
||||
traceBuffer.Pop(id, sampleTs, traceSampleBuffer, size, TRACE_SAMPLE_MAX)) {
|
||||
hasData = true;
|
||||
traceCount++;
|
||||
if (size > SAMPLE_BUF_SIZE) continue;
|
||||
|
||||
StreamString sigName;
|
||||
TypeDescriptor sigType = UnsignedInteger32Bit;
|
||||
mutex.FastLock();
|
||||
for (uint32 i = 0u; i < signals.Size(); i++) {
|
||||
for (uint32 i = 0u; i < signals.GetNumberOfElements(); i++) {
|
||||
if (signals[i]->internalID == id) {
|
||||
sigName = signals[i]->name;
|
||||
sigType = signals[i]->type;
|
||||
@@ -527,7 +524,7 @@ ErrorManagement::ErrorType WebDebugService::Streamer(ExecutionInfo &info) {
|
||||
|
||||
uint32 tsMs = (sampleTs >= streamerT0Ns)
|
||||
? (uint32)((sampleTs - streamerT0Ns) / 1000000u) : 0u;
|
||||
float64 val = WDS_ToFloat64(sampleData, sigType);
|
||||
float64 val = WDS_ToFloat64(traceSampleBuffer, sigType);
|
||||
char8 valBuf[64] = { '\0' };
|
||||
{
|
||||
AnyType vdst(CharString, 0u, valBuf); vdst.SetNumberOfElements(0u, 63u);
|
||||
|
||||
@@ -97,6 +97,10 @@ private:
|
||||
uint32 logHistoryWriteIdx;
|
||||
uint32 logHistoryFill;
|
||||
FastPollingMutexSem logHistoryMutex;
|
||||
|
||||
// Staging buffer for trace ring-buffer pops (max UDP datagram payload).
|
||||
static const uint32 TRACE_SAMPLE_MAX = 65499u;
|
||||
uint8 traceSampleBuffer[TRACE_SAMPLE_MAX];
|
||||
};
|
||||
|
||||
} // namespace MARTe
|
||||
|
||||
Reference in New Issue
Block a user