diff --git a/Source/Components/Interfaces/DebugService/DebugBrokerWrapper.h b/Source/Components/Interfaces/DebugService/DebugBrokerWrapper.h index 74f39f1..a46f9bc 100644 --- a/Source/Components/Interfaces/DebugService/DebugBrokerWrapper.h +++ b/Source/Components/Interfaces/DebugService/DebugBrokerWrapper.h @@ -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 &activeIndices, Vec &activeSizes, + Vector &activeIndices, Vector &activeSizes, FastPollingMutexSem &activeMutex, volatile bool *anyBreakFlag, - Vec *breakIndices) { + Vector *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 *) && + breakIndices != NULL_PTR(Vector *) && 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 *activeIndices, - Vec *activeSizes, FastPollingMutexSem *activeMutex, - volatile bool *anyBreakFlag, Vec *breakIndices) { + volatile bool *anyActiveFlag, Vector *activeIndices, + Vector *activeSizes, FastPollingMutexSem *activeMutex, + volatile bool *anyBreakFlag, Vector *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 activeIndices; - Vec activeSizes; - Vec breakIndices; + Vector activeIndices; + Vector activeSizes; + Vector breakIndices; FastPollingMutexSem activeMutex; }; @@ -412,9 +411,9 @@ public: volatile bool anyBreakActive; bool isOutput; char8 gamName[256]; - Vec activeIndices; - Vec activeSizes; - Vec breakIndices; + Vector activeIndices; + Vector activeSizes; + Vector breakIndices; FastPollingMutexSem activeMutex; }; @@ -471,9 +470,9 @@ public: volatile bool anyActive; volatile bool anyBreakActive; char8 gamName[256]; - Vec activeIndices; - Vec activeSizes; - Vec breakIndices; + Vector activeIndices; + Vector activeSizes; + Vector breakIndices; FastPollingMutexSem activeMutex; }; @@ -531,9 +530,9 @@ public: volatile bool anyActive; volatile bool anyBreakActive; char8 gamName[256]; - Vec activeIndices; - Vec activeSizes; - Vec breakIndices; + Vector activeIndices; + Vector activeSizes; + Vector breakIndices; FastPollingMutexSem activeMutex; }; diff --git a/Source/Components/Interfaces/DebugService/DebugService.cpp b/Source/Components/Interfaces/DebugService/DebugService.cpp index 0cb2e38..8b1368a 100644 --- a/Source/Components/Interfaces/DebugService/DebugService.cpp +++ b/Source/Components/Interfaces/DebugService/DebugService.cpp @@ -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); diff --git a/Source/Components/Interfaces/DebugService/DebugService.h b/Source/Components/Interfaces/DebugService/DebugService.h index d4bfad7..11b6466 100644 --- a/Source/Components/Interfaces/DebugService/DebugService.h +++ b/Source/Components/Interfaces/DebugService/DebugService.h @@ -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; diff --git a/Source/Components/Interfaces/DebugService/DebugServiceBase.cpp b/Source/Components/Interfaces/DebugService/DebugServiceBase.cpp index 68b6206..a4e268d 100644 --- a/Source/Components/Interfaces/DebugService/DebugServiceBase.cpp +++ b/Source/Components/Interfaces/DebugService/DebugServiceBase.cpp @@ -5,10 +5,7 @@ #include "DataSourceI.h" #include "DebugBrokerWrapper.h" #include "DebugServiceBase.h" -#include "ErrorManagement.h" #include "GAM.h" -#include "GlobalObjectsDatabase.h" -#include "HighResolutionTimer.h" #include "Message.h" #include "MessageI.h" #include "ObjectRegistryDatabase.h" @@ -19,25 +16,28 @@ namespace MARTe { -// DebugServiceI static member — defined here (only once, shared by all transports). +// DebugServiceI static member — defined here (only once, shared by all +// transports). DebugServiceI *DebugServiceI::instance = NULL_PTR(DebugServiceI *); // --------------------------------------------------------------------------- // DebugServiceI::GetFullObjectName — static utility used by broker wrappers // --------------------------------------------------------------------------- -bool DebugServiceI::GetFullObjectName(const Object &obj, StreamString &fullPath) { - fullPath = ""; - // FindPathInContainer is a file-scope static below; forward-declare it here. - // The actual definition appears after this function. - extern bool DSB_FindPath(ReferenceContainer *, const Object *, StreamString &); - if (DSB_FindPath(ObjectRegistryDatabase::Instance(), &obj, fullPath)) { - return true; - } - const char8 *name = obj.GetName(); - if (name != NULL_PTR(const char8 *)) - fullPath = name; +bool DebugServiceI::GetFullObjectName(const Object &obj, + StreamString &fullPath) { + fullPath = ""; + // FindPathInContainer is a file-scope static below; forward-declare it here. + // The actual definition appears after this function. + extern bool DSB_FindPath(ReferenceContainer *, const Object *, + StreamString &); + if (DSB_FindPath(ObjectRegistryDatabase::Instance(), &obj, fullPath)) { return true; + } + const char8 *name = obj.GetName(); + if (name != NULL_PTR(const char8 *)) + fullPath = name; + return true; } // --------------------------------------------------------------------------- @@ -45,119 +45,149 @@ bool DebugServiceI::GetFullObjectName(const Object &obj, StreamString &fullPath) // --------------------------------------------------------------------------- static void EscapeJson(const char8 *src, StreamString &dst) { - if (src == NULL_PTR(const char8 *)) return; - while (*src != '\0') { - if (*src == '"') dst += "\\\""; - else if (*src == '\\') dst += "\\\\"; - else if (*src == '\n') dst += "\\n"; - else if (*src == '\r') dst += "\\r"; - else if (*src == '\t') dst += "\\t"; - else dst += *src; - src++; - } + if (src == NULL_PTR(const char8 *)) + return; + while (*src != '\0') { + if (*src == '"') + dst += "\\\""; + else if (*src == '\\') + dst += "\\\\"; + else if (*src == '\n') + dst += "\\n"; + else if (*src == '\r') + dst += "\\r"; + else if (*src == '\t') + dst += "\\t"; + else + dst += *src; + src++; + } } static bool SuffixMatch(const char8 *target, const char8 *pattern) { - uint32 tLen = StringHelper::Length(target); - uint32 pLen = StringHelper::Length(pattern); - if (pLen > tLen) return false; - const char8 *suffix = target + (tLen - pLen); - if (StringHelper::Compare(suffix, pattern) == 0) { - if (tLen == pLen || *(suffix - 1) == '.') return true; - } + uint32 tLen = StringHelper::Length(target); + uint32 pLen = StringHelper::Length(pattern); + if (pLen > tLen) return false; + const char8 *suffix = target + (tLen - pLen); + if (StringHelper::Compare(suffix, pattern) == 0) { + if (tLen == pLen || *(suffix - 1) == '.') + return true; + } + return false; } // Named with DSB_ prefix so GetFullObjectName can forward-declare it. bool DSB_FindPath(ReferenceContainer *container, const Object *target, StreamString &path) { - if (container == NULL_PTR(ReferenceContainer *)) return false; - uint32 n = container->Size(); - for (uint32 i = 0u; i < n; i++) { - Reference ref = container->Get(i); - if (!ref.IsValid()) continue; - if (ref.operator->() == target) { path = ref->GetName(); return true; } - ReferenceContainer *sub = dynamic_cast(ref.operator->()); - if (sub != NULL_PTR(ReferenceContainer *)) { - if (DSB_FindPath(sub, target, path)) { - StreamString full; - full.Printf("%s.%s", ref->GetName(), path.Buffer()); - path = full; - return true; - } - } - } + if (container == NULL_PTR(ReferenceContainer *)) return false; + uint32 n = container->Size(); + for (uint32 i = 0u; i < n; i++) { + Reference ref = container->Get(i); + if (!ref.IsValid()) + continue; + if (ref.operator->() == target) { + path = ref->GetName(); + return true; + } + ReferenceContainer *sub = + dynamic_cast(ref.operator->()); + if (sub != NULL_PTR(ReferenceContainer *)) { + if (DSB_FindPath(sub, target, path)) { + StreamString full; + full.Printf("%s.%s", ref->GetName(), path.Buffer()); + path = full; + return true; + } + } + } + return false; } static void BuildCDBFromContainer(ReferenceContainer *container, ConfigurationDatabase &cdb) { - if (container == NULL_PTR(ReferenceContainer *)) return; - uint32 n = container->Size(); - for (uint32 i = 0u; i < n; i++) { - Reference child = container->Get(i); - if (!child.IsValid()) continue; - const char8 *name = child->GetName(); - if (name == NULL_PTR(const char8 *)) continue; + if (container == NULL_PTR(ReferenceContainer *)) + return; + uint32 n = container->Size(); + for (uint32 i = 0u; i < n; i++) { + Reference child = container->Get(i); + if (!child.IsValid()) + continue; + const char8 *name = child->GetName(); + if (name == NULL_PTR(const char8 *)) + continue; - bool created = cdb.CreateRelative(name); - if (!created) { if (!cdb.MoveRelative(name)) continue; } - - const char8 *cn = child->GetClassProperties()->GetName(); - if (cn != NULL_PTR(const char8 *)) (void)cdb.Write("Class", cn); - - { - ConfigurationDatabase exp; - if (child->ExportData(exp)) { - exp.MoveToRoot(); - uint32 ne = exp.GetNumberOfChildren(); - for (uint32 j = 0u; j < ne; j++) { - const char8 *ek = exp.GetChildName(j); - if (StringHelper::Compare(ek, "Class") == 0 || - StringHelper::Compare(ek, "Name") == 0 || - StringHelper::Compare(ek, "IsContainer") == 0) continue; - if (exp.MoveRelative(ek)) { exp.MoveToAncestor(1u); continue; } - AnyType at = exp.GetType(ek); - if (at.GetDataPointer() != NULL_PTR(void *)) { - char8 buf[1024]; - AnyType st(CharString, 0u, buf); - st.SetNumberOfElements(0, 1024); - if (TypeConvert(st, at)) (void)cdb.Write(ek, buf); - } - } - } - } - - ReferenceContainer *rc = dynamic_cast(child.operator->()); - if (rc != NULL_PTR(ReferenceContainer *)) BuildCDBFromContainer(rc, cdb); - (void)cdb.MoveToAncestor(1u); + bool created = cdb.CreateRelative(name); + if (!created) { + if (!cdb.MoveRelative(name)) + continue; } + + const char8 *cn = child->GetClassProperties()->GetName(); + if (cn != NULL_PTR(const char8 *)) + (void)cdb.Write("Class", cn); + + { + ConfigurationDatabase exp; + if (child->ExportData(exp)) { + exp.MoveToRoot(); + uint32 ne = exp.GetNumberOfChildren(); + for (uint32 j = 0u; j < ne; j++) { + const char8 *ek = exp.GetChildName(j); + if (StringHelper::Compare(ek, "Class") == 0 || + StringHelper::Compare(ek, "Name") == 0 || + StringHelper::Compare(ek, "IsContainer") == 0) + continue; + if (exp.MoveRelative(ek)) { + exp.MoveToAncestor(1u); + continue; + } + AnyType at = exp.GetType(ek); + if (at.GetDataPointer() != NULL_PTR(void *)) { + char8 buf[1024]; + AnyType st(CharString, 0u, buf); + st.SetNumberOfElements(0, 1024); + if (TypeConvert(st, at)) + (void)cdb.Write(ek, buf); + } + } + } + } + + ReferenceContainer *rc = + dynamic_cast(child.operator->()); + if (rc != NULL_PTR(ReferenceContainer *)) + BuildCDBFromContainer(rc, cdb); + (void)cdb.MoveToAncestor(1u); + } } -static void PatchItemInternal(const char8 *originalName, ObjectBuilder *debugBuilder) { - ClassRegistryItem *item = ClassRegistryDatabase::Instance()->Find(originalName); - if (item != NULL_PTR(ClassRegistryItem *)) { - item->SetObjectBuilder(debugBuilder); - } +static void PatchItemInternal(const char8 *originalName, + ObjectBuilder *debugBuilder) { + ClassRegistryItem *item = + ClassRegistryDatabase::Instance()->Find(originalName); + if (item != NULL_PTR(ClassRegistryItem *)) { + item->SetObjectBuilder(debugBuilder); + } } // --------------------------------------------------------------------------- // DebugServiceBase constructor / destructor // --------------------------------------------------------------------------- -DebugServiceBase::DebugServiceBase() - : ReferenceContainer() { - isPaused = false; - stepRemaining = 0u; - manualConfigSet = false; +DebugServiceBase::DebugServiceBase() : ReferenceContainer() { + isPaused = false; + stepRemaining = 0u; + manualConfigSet = false; } DebugServiceBase::~DebugServiceBase() { - for (uint32 i = 0u; i < signals.Size(); i++) { - if (signals[i] != NULL_PTR(DebugSignalInfo *)) { - delete signals[i]; - } + for (uint32 i = 0u; i < signals.GetNumberOfElements(); i++) { + if (signals[i] != NULL_PTR(DebugSignalInfo *)) { + delete signals[i]; } + } } // --------------------------------------------------------------------------- @@ -165,28 +195,30 @@ DebugServiceBase::~DebugServiceBase() { // --------------------------------------------------------------------------- void DebugServiceBase::PatchRegistry() { - PatchItemInternal("MemoryMapInputBroker", - new DebugMemoryMapInputBrokerBuilder()); - PatchItemInternal("MemoryMapOutputBroker", - new DebugMemoryMapOutputBrokerBuilder()); - PatchItemInternal("MemoryMapSynchronisedInputBroker", - new DebugMemoryMapSynchronisedInputBrokerBuilder()); - PatchItemInternal("MemoryMapSynchronisedOutputBroker", - new DebugMemoryMapSynchronisedOutputBrokerBuilder()); - PatchItemInternal("MemoryMapInterpolatedInputBroker", - new DebugMemoryMapInterpolatedInputBrokerBuilder()); - PatchItemInternal("MemoryMapMultiBufferInputBroker", - new DebugMemoryMapMultiBufferInputBrokerBuilder()); - PatchItemInternal("MemoryMapMultiBufferOutputBroker", - new DebugMemoryMapMultiBufferOutputBrokerBuilder()); - PatchItemInternal("MemoryMapSynchronisedMultiBufferInputBroker", - new DebugMemoryMapSynchronisedMultiBufferInputBrokerBuilder()); - PatchItemInternal("MemoryMapSynchronisedMultiBufferOutputBroker", - new DebugMemoryMapSynchronisedMultiBufferOutputBrokerBuilder()); - PatchItemInternal("MemoryMapAsyncOutputBroker", - new DebugMemoryMapAsyncOutputBrokerBuilder()); - PatchItemInternal("MemoryMapAsyncTriggerOutputBroker", - new DebugMemoryMapAsyncTriggerOutputBrokerBuilder()); + PatchItemInternal("MemoryMapInputBroker", + new DebugMemoryMapInputBrokerBuilder()); + PatchItemInternal("MemoryMapOutputBroker", + new DebugMemoryMapOutputBrokerBuilder()); + PatchItemInternal("MemoryMapSynchronisedInputBroker", + new DebugMemoryMapSynchronisedInputBrokerBuilder()); + PatchItemInternal("MemoryMapSynchronisedOutputBroker", + new DebugMemoryMapSynchronisedOutputBrokerBuilder()); + PatchItemInternal("MemoryMapInterpolatedInputBroker", + new DebugMemoryMapInterpolatedInputBrokerBuilder()); + PatchItemInternal("MemoryMapMultiBufferInputBroker", + new DebugMemoryMapMultiBufferInputBrokerBuilder()); + PatchItemInternal("MemoryMapMultiBufferOutputBroker", + new DebugMemoryMapMultiBufferOutputBrokerBuilder()); + PatchItemInternal( + "MemoryMapSynchronisedMultiBufferInputBroker", + new DebugMemoryMapSynchronisedMultiBufferInputBrokerBuilder()); + PatchItemInternal( + "MemoryMapSynchronisedMultiBufferOutputBroker", + new DebugMemoryMapSynchronisedMultiBufferOutputBrokerBuilder()); + PatchItemInternal("MemoryMapAsyncOutputBroker", + new DebugMemoryMapAsyncOutputBrokerBuilder()); + PatchItemInternal("MemoryMapAsyncTriggerOutputBroker", + new DebugMemoryMapAsyncTriggerOutputBrokerBuilder()); } // --------------------------------------------------------------------------- @@ -194,116 +226,120 @@ void DebugServiceBase::PatchRegistry() { // --------------------------------------------------------------------------- DebugSignalInfo *DebugServiceBase::RegisterSignal(void *memoryAddress, - TypeDescriptor type, - const char8 *name, - uint8 numberOfDimensions, - uint32 numberOfElements) { - mutex.FastLock(); - DebugSignalInfo *res = NULL_PTR(DebugSignalInfo *); - uint32 sigIdx = 0xFFFFFFFFu; - for (uint32 i = 0u; i < signals.Size(); i++) { - if (signals[i]->memoryAddress == memoryAddress) { - res = signals[i]; sigIdx = i; break; - } + TypeDescriptor type, + const char8 *name, + uint8 numberOfDimensions, + uint32 numberOfElements) { + mutex.FastLock(); + DebugSignalInfo *res = NULL_PTR(DebugSignalInfo *); + uint32 sigIdx = 0xFFFFFFFFu; + for (uint32 i = 0u; i < signals.GetNumberOfElements(); i++) { + if (signals[i]->memoryAddress == memoryAddress) { + res = signals[i]; + sigIdx = i; + break; } - if (res == NULL_PTR(DebugSignalInfo *)) { - sigIdx = signals.Size(); - res = new DebugSignalInfo(); - res->memoryAddress = memoryAddress; - res->type = type; - res->name = name; - res->numberOfDimensions = numberOfDimensions; - res->numberOfElements = numberOfElements; - res->isTracing = false; - res->isForcing = false; - res->internalID = sigIdx; - res->decimationFactor = 1u; - res->decimationCounter = 0; - res->breakOp = BREAK_OFF; - res->breakThreshold = 0.0; - signals.Push(res); + } + if (res == NULL_PTR(DebugSignalInfo *)) { + sigIdx = signals.GetNumberOfElements(); + res = new DebugSignalInfo(); + res->memoryAddress = memoryAddress; + res->type = type; + res->name = name; + res->numberOfDimensions = numberOfDimensions; + res->numberOfElements = numberOfElements; + res->isTracing = false; + res->isForcing = false; + res->internalID = sigIdx; + res->decimationFactor = 1u; + res->decimationCounter = 0; + res->breakOp = BREAK_OFF; + res->breakThreshold = 0.0; + signals.Append(res); + } + if (sigIdx != 0xFFFFFFFFu) { + bool found = false; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name) { + found = true; + break; + } } - if (sigIdx != 0xFFFFFFFFu) { - bool found = false; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name) { found = true; break; } - } - if (!found) { - SignalAlias a; - a.name = name; - a.signalIndex = sigIdx; - aliases.Push(a); - } + if (!found) { + SignalAlias a; + a.name = name; + a.signalIndex = sigIdx; + aliases.Append(a); } - mutex.FastUnLock(); - return res; + } + mutex.FastUnLock(); + return res; } -void DebugServiceBase::ProcessSignal(DebugSignalInfo *signalInfo, - uint32 size, uint64 timestamp) { - if (signalInfo == NULL_PTR(DebugSignalInfo *)) return; - if (signalInfo->isForcing) { - memcpy(signalInfo->memoryAddress, signalInfo->forcedValue, size); - } - if (signalInfo->isTracing) { - Atomic::Add((volatile int32 *)&signalInfo->decimationCounter, 1); - if ((uint32)signalInfo->decimationCounter >= signalInfo->decimationFactor) { - int32 old = Atomic::Exchange((volatile int32 *)&signalInfo->decimationCounter, 0); - if ((uint32)old >= signalInfo->decimationFactor) { - tracePushMutex.FastLock(); - traceBuffer.Push(signalInfo->internalID, timestamp, - (uint8 *)signalInfo->memoryAddress, size); - tracePushMutex.FastUnLock(); - } - } +void DebugServiceBase::ProcessSignal(DebugSignalInfo *signalInfo, uint32 size, + uint64 timestamp) { + if (signalInfo == NULL_PTR(DebugSignalInfo *)) + return; + if (signalInfo->isForcing) { + memcpy(signalInfo->memoryAddress, signalInfo->forcedValue, size); + } + if (signalInfo->isTracing) { + Atomic::Add((volatile int32 *)&signalInfo->decimationCounter, 1); + if ((uint32)signalInfo->decimationCounter >= signalInfo->decimationFactor) { + int32 old = + Atomic::Exchange((volatile int32 *)&signalInfo->decimationCounter, 0); + if ((uint32)old >= signalInfo->decimationFactor) { + tracePushMutex.FastLock(); + traceBuffer.Push(signalInfo->internalID, timestamp, + (uint8 *)signalInfo->memoryAddress, size); + tracePushMutex.FastUnLock(); + } } + } } -void DebugServiceBase::RegisterBroker(DebugSignalInfo **signalPointers, - uint32 numSignals, - MemoryMapBroker *broker, - volatile bool *anyActiveFlag, - Vec *activeIndices, - Vec *activeSizes, - FastPollingMutexSem *activeMutex, - volatile bool *anyBreakFlag, - Vec *breakIndices, - const char8 *gamName, - bool isOutput) { - mutex.FastLock(); - BrokerInfo b; - b.signalPointers = signalPointers; - b.numSignals = numSignals; - b.broker = broker; - b.anyActiveFlag = anyActiveFlag; - b.activeIndices = activeIndices; - b.activeSizes = activeSizes; - b.activeMutex = activeMutex; - b.anyBreakFlag = anyBreakFlag; - b.breakIndices = breakIndices; - b.isOutput = isOutput; - if (gamName != NULL_PTR(const char8 *)) b.gamName = gamName; - brokers.Push(b); - mutex.FastUnLock(); +void DebugServiceBase::RegisterBroker( + DebugSignalInfo **signalPointers, uint32 numSignals, + MemoryMapBroker *broker, volatile bool *anyActiveFlag, + Vector *activeIndices, Vector *activeSizes, + FastPollingMutexSem *activeMutex, volatile bool *anyBreakFlag, + Vector *breakIndices, const char8 *gamName, bool isOutput) { + mutex.FastLock(); + BrokerInfo b; + b.signalPointers = signalPointers; + b.numSignals = numSignals; + b.broker = broker; + b.anyActiveFlag = anyActiveFlag; + b.activeIndices = activeIndices; + b.activeSizes = activeSizes; + b.activeMutex = activeMutex; + b.anyBreakFlag = anyBreakFlag; + b.breakIndices = breakIndices; + b.isOutput = isOutput; + if (gamName != NULL_PTR(const char8 *)) + b.gamName = gamName; + brokers.Append(b); + mutex.FastUnLock(); } void DebugServiceBase::ConsumeStepIfNeeded(const char8 *gamName, const char8 *threadName) { - if (stepRemaining == 0u) return; - mutex.FastLock(); - if (stepThreadFilter.Size() > 0u && - (threadName == NULL_PTR(const char8 *) || stepThreadFilter != threadName)) { - mutex.FastUnLock(); - return; - } - if (stepRemaining > 0u) { - stepRemaining--; - if (stepRemaining == 0u) { - isPaused = true; - pausedAtGam = (gamName != NULL_PTR(const char8 *)) ? gamName : ""; - } - } + if (stepRemaining == 0u) + return; + mutex.FastLock(); + if (stepThreadFilter.Size() > 0u && (threadName == NULL_PTR(const char8 *) || + stepThreadFilter != threadName)) { mutex.FastUnLock(); + return; + } + if (stepRemaining > 0u) { + stepRemaining--; + if (stepRemaining == 0u) { + isPaused = true; + pausedAtGam = (gamName != NULL_PTR(const char8 *)) ? gamName : ""; + } + } + mutex.FastUnLock(); } // --------------------------------------------------------------------------- @@ -311,183 +347,206 @@ void DebugServiceBase::ConsumeStepIfNeeded(const char8 *gamName, // --------------------------------------------------------------------------- uint32 DebugServiceBase::ForceSignal(const char8 *name, const char8 *valueStr) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || SuffixMatch(aliases[i].name.Buffer(), name)) { - DebugSignalInfo *s = signals[aliases[i].signalIndex]; - uint32 elemBytes = (uint32)(s->type.numberOfBits) / 8u; - uint32 totalBytes = elemBytes * s->numberOfElements; - if (elemBytes == 0u || totalBytes > (uint32)sizeof(s->forcedValue)) { - REPORT_ERROR_STATIC(ErrorManagement::Warning, - "ForceSignal: signal '%s' requires %u bytes but forcedValue " - "buffer is only %u bytes — force request ignored.", - s->name.Buffer(), totalBytes, (uint32)sizeof(s->forcedValue)); - continue; - } - s->isForcing = true; - AnyType dest(s->type, 0u, s->forcedValue); - AnyType source(CharString, 0u, valueStr); - (void)TypeConvert(dest, source); - count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + DebugSignalInfo *s = signals[aliases[i].signalIndex]; + uint32 elemBytes = (uint32)(s->type.numberOfBits) / 8u; + uint32 totalBytes = elemBytes * s->numberOfElements; + if (elemBytes == 0u || totalBytes > (uint32)sizeof(s->forcedValue)) { + REPORT_ERROR_STATIC( + ErrorManagement::Warning, + "ForceSignal: signal '%s' requires %u bytes but forcedValue " + "buffer is only %u bytes — force request ignored.", + s->name.Buffer(), totalBytes, (uint32)sizeof(s->forcedValue)); + continue; + } + s->isForcing = true; + AnyType dest(s->type, 0u, s->forcedValue); + AnyType source(CharString, 0u, valueStr); + (void)TypeConvert(dest, source); + count++; } - UpdateBrokersActiveStatus(); - mutex.FastUnLock(); - return count; + } + UpdateBrokersActiveStatus(); + mutex.FastUnLock(); + return count; } uint32 DebugServiceBase::UnforceSignal(const char8 *name) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || SuffixMatch(aliases[i].name.Buffer(), name)) { - signals[aliases[i].signalIndex]->isForcing = false; - count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + signals[aliases[i].signalIndex]->isForcing = false; + count++; } - UpdateBrokersActiveStatus(); - mutex.FastUnLock(); - return count; + } + UpdateBrokersActiveStatus(); + mutex.FastUnLock(); + return count; } uint32 DebugServiceBase::TraceSignal(const char8 *name, bool enable, uint32 decimation) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || SuffixMatch(aliases[i].name.Buffer(), name)) { - DebugSignalInfo *s = signals[aliases[i].signalIndex]; - s->isTracing = enable; - s->decimationFactor = decimation; - s->decimationCounter = 0; - count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + DebugSignalInfo *s = signals[aliases[i].signalIndex]; + s->isTracing = enable; + s->decimationFactor = decimation; + s->decimationCounter = 0; + count++; } - UpdateBrokersActiveStatus(); - mutex.FastUnLock(); - return count; + } + UpdateBrokersActiveStatus(); + mutex.FastUnLock(); + return count; } uint32 DebugServiceBase::SetBreak(const char8 *name, uint8 op, float64 threshold) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || SuffixMatch(aliases[i].name.Buffer(), name)) { - DebugSignalInfo *s = signals[aliases[i].signalIndex]; - s->breakThreshold = threshold; - s->breakOp = op; - count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + DebugSignalInfo *s = signals[aliases[i].signalIndex]; + s->breakThreshold = threshold; + s->breakOp = op; + count++; } - if (count > 0u) UpdateBrokersBreakStatus(); - mutex.FastUnLock(); - return count; + } + if (count > 0u) + UpdateBrokersBreakStatus(); + mutex.FastUnLock(); + return count; } uint32 DebugServiceBase::ClearBreak(const char8 *name) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || SuffixMatch(aliases[i].name.Buffer(), name)) { - signals[aliases[i].signalIndex]->breakOp = BREAK_OFF; - count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + signals[aliases[i].signalIndex]->breakOp = BREAK_OFF; + count++; } - if (count > 0u) UpdateBrokersBreakStatus(); - mutex.FastUnLock(); - return count; + } + if (count > 0u) + UpdateBrokersBreakStatus(); + mutex.FastUnLock(); + return count; } -bool DebugServiceBase::IsInstrumented(const char8 *fullPath, - bool &traceable, bool &forcable) { - mutex.FastLock(); - bool found = false; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == fullPath || - SuffixMatch(aliases[i].name.Buffer(), fullPath)) { - found = true; break; - } +bool DebugServiceBase::IsInstrumented(const char8 *fullPath, bool &traceable, + bool &forcable) { + mutex.FastLock(); + bool found = false; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == fullPath || + SuffixMatch(aliases[i].name.Buffer(), fullPath)) { + found = true; + break; } - mutex.FastUnLock(); - traceable = found; - forcable = found; - return found; + } + mutex.FastUnLock(); + traceable = found; + forcable = found; + return found; } uint32 DebugServiceBase::RegisterMonitorSignal(const char8 *path, uint32 periodMs) { - mutex.FastLock(); + mutex.FastLock(); - // If already monitored, just update period - for (uint32 j = 0u; j < monitoredSignals.Size(); j++) { - if (monitoredSignals[j].path == path) { - monitoredSignals[j].periodMs = periodMs; - mutex.FastUnLock(); - return 1u; - } + // If already monitored, just update period + for (uint32 j = 0u; j < monitoredSignals.GetNumberOfElements(); j++) { + if (monitoredSignals[j].path == path) { + monitoredSignals[j].periodMs = periodMs; + mutex.FastUnLock(); + return 1u; } + } - // Tokenise path to separate DataSource path from signal name - StreamString fullPath = path; - fullPath.Seek(0u); - char8 term; - Vec parts; - StreamString token; - while (fullPath.GetToken(token, ".", term)) { parts.Push(token); token = ""; } + // Tokenise path to separate DataSource path from signal name + StreamString fullPath = path; + fullPath.Seek(0u); + char8 term; + Vector parts; + StreamString token; + while (fullPath.GetToken(token, ".", term)) { + parts.Append(token); + token = ""; + } - uint32 count = 0u; - if (parts.Size() >= 2u) { - StreamString signalName = parts[parts.Size() - 1u]; - StreamString dsPath; - for (uint32 i = 0u; i < parts.Size() - 1u; i++) { - dsPath += parts[i]; - if (i < parts.Size() - 2u) dsPath += "."; - } - ReferenceT ds = - ObjectRegistryDatabase::Instance()->Find(dsPath.Buffer()); - if (ds.IsValid()) { - uint32 idx = 0u; - if (ds->GetSignalIndex(idx, signalName.Buffer())) { - MonitoredSignal m; - m.dataSource = ds; - m.signalIdx = idx; - m.path = path; - m.periodMs = periodMs; - m.lastPollTime = 0u; - m.size = 0u; - (void)ds->GetSignalByteSize(idx, m.size); - if (m.size == 0u) m.size = 4u; - m.internalID = 0x80000000u | monitoredSignals.Size(); - // Re-use existing brokered signal ID if available - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == path || - SuffixMatch(aliases[i].name.Buffer(), path)) { - m.internalID = signals[aliases[i].signalIndex]->internalID; - break; - } - } - monitoredSignals.Push(m); - count = 1u; - } - } + uint32 count = 0u; + if (parts.GetNumberOfElements() >= 2u) { + StreamString signalName = parts[parts.GetNumberOfElements() - 1u]; + StreamString dsPath; + for (uint32 i = 0u; i < parts.GetNumberOfElements() - 1u; i++) { + dsPath += parts[i]; + if (i < parts.GetNumberOfElements() - 2u) + dsPath += "."; } - mutex.FastUnLock(); - return count; + ReferenceT ds = + ObjectRegistryDatabase::Instance()->Find(dsPath.Buffer()); + if (ds.IsValid()) { + uint32 idx = 0u; + if (ds->GetSignalIndex(idx, signalName.Buffer())) { + MonitoredSignal m; + m.dataSource = ds; + m.signalIdx = idx; + m.path = path; + m.periodMs = periodMs; + m.lastPollTime = 0u; + m.size = 0u; + (void)ds->GetSignalByteSize(idx, m.size); + if (m.size == 0u) + m.size = 4u; + m.internalID = 0x80000000u | monitoredSignals.GetNumberOfElements(); + // Re-use existing brokered signal ID if available + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == path || + SuffixMatch(aliases[i].name.Buffer(), path)) { + m.internalID = signals[aliases[i].signalIndex]->internalID; + break; + } + } + monitoredSignals.Append(m); + count = 1u; + } + } + } + mutex.FastUnLock(); + return count; } uint32 DebugServiceBase::UnmonitorSignal(const char8 *path) { - mutex.FastLock(); - uint32 count = 0u; - for (uint32 i = 0u; i < monitoredSignals.Size(); i++) { - if (monitoredSignals[i].path == path || - SuffixMatch(monitoredSignals[i].path.Buffer(), path)) { - (void)monitoredSignals.Remove(i); i--; count++; - } + mutex.FastLock(); + uint32 count = 0u; + for (uint32 i = 0u; i < monitoredSignals.GetNumberOfElements(); ) { + if (monitoredSignals[i].path == path || + SuffixMatch(monitoredSignals[i].path.Buffer(), path)) { + // Shift elements after i one position left, then shrink by one. + uint32 n = monitoredSignals.GetNumberOfElements(); + for (uint32 k = i; k + 1u < n; k++) { + monitoredSignals[k] = monitoredSignals[k + 1u]; + } + monitoredSignals.SetSize(n - 1u); + count++; + // Do NOT increment i — re-examine the element now at position i. + } else { + i++; } - mutex.FastUnLock(); - return count; + } + mutex.FastUnLock(); + return count; } // --------------------------------------------------------------------------- @@ -495,43 +554,65 @@ uint32 DebugServiceBase::UnmonitorSignal(const char8 *path) { // --------------------------------------------------------------------------- void DebugServiceBase::UpdateBrokersActiveStatus() { - for (uint32 i = 0u; i < brokers.Size(); i++) { - if (brokers[i].signalPointers == NULL_PTR(DebugSignalInfo **)) continue; - uint32 count = 0u; - Vec tempInd, tempSizes; - for (uint32 j = 0u; j < brokers[i].numSignals; j++) { - DebugSignalInfo *s = brokers[i].signalPointers[j]; - if (s != NULL_PTR(DebugSignalInfo *) && (s->isTracing || s->isForcing)) { - tempInd.Push(j); - tempSizes.Push((brokers[i].broker != NULL_PTR(MemoryMapBroker *)) - ? brokers[i].broker->GetCopyByteSize(j) : 4u); - count++; - } - } - if (brokers[i].activeMutex) brokers[i].activeMutex->FastLock(); - if (brokers[i].activeIndices) brokers[i].activeIndices->Swap(tempInd); - if (brokers[i].activeSizes) brokers[i].activeSizes->Swap(tempSizes); - if (brokers[i].anyActiveFlag) *(brokers[i].anyActiveFlag) = (count > 0u); - if (brokers[i].activeMutex) brokers[i].activeMutex->FastUnLock(); + for (uint32 i = 0u; i < brokers.GetNumberOfElements(); i++) { + if (brokers[i].signalPointers == NULL_PTR(DebugSignalInfo **)) + continue; + uint32 count = 0u; + Vector tempInd, tempSizes; + for (uint32 j = 0u; j < brokers[i].numSignals; j++) { + DebugSignalInfo *s = brokers[i].signalPointers[j]; + if (s != NULL_PTR(DebugSignalInfo *) && (s->isTracing || s->isForcing)) { + tempInd.Append(j); + tempSizes.Append((brokers[i].broker != NULL_PTR(MemoryMapBroker *)) + ? brokers[i].broker->GetCopyByteSize(j) + : 4u); + count++; + } } + if (brokers[i].activeMutex) + brokers[i].activeMutex->FastLock(); + if (brokers[i].activeIndices) { + brokers[i].activeIndices->SetSize(0u); + for (uint32 k = 0u; k < tempInd.GetNumberOfElements(); k++) + brokers[i].activeIndices->Append(tempInd[k]); + } + if (brokers[i].activeSizes) { + brokers[i].activeSizes->SetSize(0u); + for (uint32 k = 0u; k < tempSizes.GetNumberOfElements(); k++) + brokers[i].activeSizes->Append(tempSizes[k]); + } + if (brokers[i].anyActiveFlag) + *(brokers[i].anyActiveFlag) = (count > 0u); + if (brokers[i].activeMutex) + brokers[i].activeMutex->FastUnLock(); + } } void DebugServiceBase::UpdateBrokersBreakStatus() { - for (uint32 i = 0u; i < brokers.Size(); i++) { - if (brokers[i].signalPointers == NULL_PTR(DebugSignalInfo **)) continue; - Vec tempBreak; - uint32 count = 0u; - for (uint32 j = 0u; j < brokers[i].numSignals; j++) { - DebugSignalInfo *s = brokers[i].signalPointers[j]; - if (s != NULL_PTR(DebugSignalInfo *) && s->breakOp != BREAK_OFF) { - tempBreak.Push(j); count++; - } - } - if (brokers[i].activeMutex) brokers[i].activeMutex->FastLock(); - if (brokers[i].breakIndices) brokers[i].breakIndices->Swap(tempBreak); - if (brokers[i].anyBreakFlag) *(brokers[i].anyBreakFlag) = (count > 0u); - if (brokers[i].activeMutex) brokers[i].activeMutex->FastUnLock(); + for (uint32 i = 0u; i < brokers.GetNumberOfElements(); i++) { + if (brokers[i].signalPointers == NULL_PTR(DebugSignalInfo **)) + continue; + Vector tempBreak; + uint32 count = 0u; + for (uint32 j = 0u; j < brokers[i].numSignals; j++) { + DebugSignalInfo *s = brokers[i].signalPointers[j]; + if (s != NULL_PTR(DebugSignalInfo *) && s->breakOp != BREAK_OFF) { + tempBreak.Append(j); + count++; + } } + if (brokers[i].activeMutex) + brokers[i].activeMutex->FastLock(); + if (brokers[i].breakIndices) { + brokers[i].breakIndices->SetSize(0u); + for (uint32 k = 0u; k < tempBreak.GetNumberOfElements(); k++) + brokers[i].breakIndices->Append(tempBreak[k]); + } + if (brokers[i].anyBreakFlag) + *(brokers[i].anyBreakFlag) = (count > 0u); + if (brokers[i].activeMutex) + brokers[i].activeMutex->FastUnLock(); + } } // --------------------------------------------------------------------------- @@ -539,11 +620,11 @@ void DebugServiceBase::UpdateBrokersBreakStatus() { // --------------------------------------------------------------------------- void DebugServiceBase::Step(uint32 n, const char8 *threadName) { - mutex.FastLock(); - stepRemaining = n; - isPaused = false; - stepThreadFilter = (threadName != NULL_PTR(const char8 *)) ? threadName : ""; - mutex.FastUnLock(); + mutex.FastLock(); + stepRemaining = n; + isPaused = false; + stepThreadFilter = (threadName != NULL_PTR(const char8 *)) ? threadName : ""; + mutex.FastUnLock(); } // --------------------------------------------------------------------------- @@ -551,197 +632,232 @@ void DebugServiceBase::Step(uint32 n, const char8 *threadName) { // --------------------------------------------------------------------------- void DebugServiceBase::GetStepStatus(StreamString &out) { - mutex.FastLock(); - bool paused = isPaused; - uint32 rem = stepRemaining; - StreamString gam = pausedAtGam; - StreamString thr = stepThreadFilter; - mutex.FastUnLock(); - out.Printf("{\"Paused\":%s,\"PausedAtGam\":\"%s\"," - "\"StepRemaining\":%u,\"StepThread\":\"%s\"}\nOK STEP_STATUS\n", - paused ? "true" : "false", gam.Buffer(), rem, thr.Buffer()); + mutex.FastLock(); + bool paused = isPaused; + uint32 rem = stepRemaining; + StreamString gam = pausedAtGam; + StreamString thr = stepThreadFilter; + mutex.FastUnLock(); + out.Printf("{\"Paused\":%s,\"PausedAtGam\":\"%s\"," + "\"StepRemaining\":%u,\"StepThread\":\"%s\"}\nOK STEP_STATUS\n", + paused ? "true" : "false", gam.Buffer(), rem, thr.Buffer()); } void DebugServiceBase::GetSignalValue(const char8 *name, StreamString &out) { - mutex.FastLock(); - DebugSignalInfo *sig = NULL_PTR(DebugSignalInfo *); - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == name || - SuffixMatch(aliases[i].name.Buffer(), name)) { - sig = signals[aliases[i].signalIndex]; break; - } + mutex.FastLock(); + DebugSignalInfo *sig = NULL_PTR(DebugSignalInfo *); + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == name || + SuffixMatch(aliases[i].name.Buffer(), name)) { + sig = signals[aliases[i].signalIndex]; + break; } - if (sig == NULL_PTR(DebugSignalInfo *)) { - mutex.FastUnLock(); - out.Printf("{\"Error\":\"Signal not found: %s\"}\nOK VALUE\n", name); - return; - } - TypeDescriptor td = sig->type; - uint32 nElem = sig->numberOfElements; - uint32 bySz = (td.numberOfBits > 0u) ? (td.numberOfBits / 8u) : 1u; - bool trunc = (nElem > GET_VALUE_MAX_ELEMENTS); - if (trunc) nElem = GET_VALUE_MAX_ELEMENTS; - uint32 total = bySz * nElem; - if (total > 1024u) { total = 1024u; nElem = total / bySz; } - uint8 lb[1024]; memset(lb, 0, sizeof(lb)); - if (sig->memoryAddress != NULL_PTR(void *)) memcpy(lb, sig->memoryAddress, total); + } + if (sig == NULL_PTR(DebugSignalInfo *)) { mutex.FastUnLock(); + out.Printf("{\"Error\":\"Signal not found: %s\"}\nOK VALUE\n", name); + return; + } + TypeDescriptor td = sig->type; + uint32 nElem = sig->numberOfElements; + uint32 bySz = (td.numberOfBits > 0u) ? (td.numberOfBits / 8u) : 1u; + bool trunc = (nElem > GET_VALUE_MAX_ELEMENTS); + if (trunc) + nElem = GET_VALUE_MAX_ELEMENTS; + uint32 total = bySz * nElem; + if (total > 1024u) { + total = 1024u; + nElem = total / bySz; + } + uint8 lb[1024]; + memset(lb, 0, sizeof(lb)); + if (sig->memoryAddress != NULL_PTR(void *)) + memcpy(lb, sig->memoryAddress, total); + mutex.FastUnLock(); - StreamString valueStr; - if (nElem > 1u) { - for (uint32 i = 0u; i < nElem; i++) { - char8 eb[128] = { '\0' }; - AnyType se(td, 0u, (void *)(lb + i * bySz)); - AnyType ds(CharString, 0u, eb); - ds.SetNumberOfElements(0u, 128u); - (void)TypeConvert(ds, se); - if (i > 0u) valueStr += ", "; - valueStr += eb; - } - } else { - char8 eb[256] = { '\0' }; - AnyType se(td, 0u, (void *)lb); - AnyType ds(CharString, 0u, eb); - ds.SetNumberOfElements(0u, 256u); - (void)TypeConvert(ds, se); - valueStr = eb; + StreamString valueStr; + if (nElem > 1u) { + for (uint32 i = 0u; i < nElem; i++) { + char8 eb[128] = {'\0'}; + AnyType se(td, 0u, (void *)(lb + i * bySz)); + AnyType ds(CharString, 0u, eb); + ds.SetNumberOfElements(0u, 128u); + (void)TypeConvert(ds, se); + if (i > 0u) + valueStr += ", "; + valueStr += eb; } + } else { + char8 eb[256] = {'\0'}; + AnyType se(td, 0u, (void *)lb); + AnyType ds(CharString, 0u, eb); + ds.SetNumberOfElements(0u, 256u); + (void)TypeConvert(ds, se); + valueStr = eb; + } - out += "{\"Name\":\""; - out += name; - out += "\",\"Value\":\""; - const char8 *vp = valueStr.Buffer(); - while (vp != NULL_PTR(const char8 *) && *vp != '\0') { - if (*vp == '"') out += "\\\""; - else if (*vp == '\\') out += "\\\\"; - else { char8 tmp[2] = { *vp, '\0' }; out += tmp; } - vp++; + out += "{\"Name\":\""; + out += name; + out += "\",\"Value\":\""; + const char8 *vp = valueStr.Buffer(); + while (vp != NULL_PTR(const char8 *) && *vp != '\0') { + if (*vp == '"') + out += "\\\""; + else if (*vp == '\\') + out += "\\\\"; + else { + char8 tmp[2] = {*vp, '\0'}; + out += tmp; } - out.Printf("\",\"Elements\":%u,\"Truncated\":%s}\nOK VALUE\n", - nElem, trunc ? "true" : "false"); + vp++; + } + out.Printf("\",\"Elements\":%u,\"Truncated\":%s}\nOK VALUE\n", nElem, + trunc ? "true" : "false"); } void DebugServiceBase::Discover(StreamString &out) { - out += "{\"Signals\":[\n"; - mutex.FastLock(); - uint32 total = 0u; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (total > 0u) out += ",\n"; - DebugSignalInfo *sig = signals[aliases[i].signalIndex]; - const char8 *tn = TypeDescriptor::GetTypeNameFromTypeDescriptor(sig->type); - out.Printf(" {\"name\":\"%s\",\"id\":%u,\"type\":\"%s\"," - "\"dimensions\":%u,\"elements\":%u", - aliases[i].name.Buffer(), sig->internalID, - tn ? tn : "Unknown", sig->numberOfDimensions, sig->numberOfElements); - EnrichWithConfig(aliases[i].name.Buffer(), out); - out += "}"; - total++; + out += "{\"Signals\":[\n"; + mutex.FastLock(); + uint32 total = 0u; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (total > 0u) + out += ",\n"; + DebugSignalInfo *sig = signals[aliases[i].signalIndex]; + const char8 *tn = TypeDescriptor::GetTypeNameFromTypeDescriptor(sig->type); + out.Printf(" {\"name\":\"%s\",\"id\":%u,\"type\":\"%s\"," + "\"dimensions\":%u,\"elements\":%u", + aliases[i].name.Buffer(), sig->internalID, tn ? tn : "Unknown", + sig->numberOfDimensions, sig->numberOfElements); + EnrichWithConfig(aliases[i].name.Buffer(), out); + out += "}"; + total++; + } + for (uint32 i = 0u; i < monitoredSignals.GetNumberOfElements(); i++) { + bool found = false; + for (uint32 j = 0u; j < aliases.GetNumberOfElements(); j++) { + if (aliases[j].name == monitoredSignals[i].path) { + found = true; + break; + } } - for (uint32 i = 0u; i < monitoredSignals.Size(); i++) { - bool found = false; - for (uint32 j = 0u; j < aliases.Size(); j++) { - if (aliases[j].name == monitoredSignals[i].path) { found = true; break; } - } - if (!found) { - if (total > 0u) out += ",\n"; - const char8 *tn = TypeDescriptor::GetTypeNameFromTypeDescriptor( - monitoredSignals[i].dataSource->GetSignalType(monitoredSignals[i].signalIdx)); - uint8 dims = 0u; uint32 elems = 1u; - (void)monitoredSignals[i].dataSource->GetSignalNumberOfDimensions( - monitoredSignals[i].signalIdx, dims); - (void)monitoredSignals[i].dataSource->GetSignalNumberOfElements( - monitoredSignals[i].signalIdx, elems); - out.Printf(" {\"name\":\"%s\",\"id\":%u,\"type\":\"%s\"," - "\"dimensions\":%u,\"elements\":%u", - monitoredSignals[i].path.Buffer(), monitoredSignals[i].internalID, - tn ? tn : "Unknown", dims, elems); - EnrichWithConfig(monitoredSignals[i].path.Buffer(), out); - out += "}"; - total++; - } + if (!found) { + if (total > 0u) + out += ",\n"; + const char8 *tn = TypeDescriptor::GetTypeNameFromTypeDescriptor( + monitoredSignals[i].dataSource->GetSignalType( + monitoredSignals[i].signalIdx)); + uint8 dims = 0u; + uint32 elems = 1u; + (void)monitoredSignals[i].dataSource->GetSignalNumberOfDimensions( + monitoredSignals[i].signalIdx, dims); + (void)monitoredSignals[i].dataSource->GetSignalNumberOfElements( + monitoredSignals[i].signalIdx, elems); + out.Printf(" {\"name\":\"%s\",\"id\":%u,\"type\":\"%s\"," + "\"dimensions\":%u,\"elements\":%u", + monitoredSignals[i].path.Buffer(), + monitoredSignals[i].internalID, tn ? tn : "Unknown", dims, + elems); + EnrichWithConfig(monitoredSignals[i].path.Buffer(), out); + out += "}"; + total++; } - mutex.FastUnLock(); - out += "\n]}\nOK DISCOVER\n"; + } + mutex.FastUnLock(); + out += "\n]}\nOK DISCOVER\n"; } void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) { - Reference ref = ObjectRegistryDatabase::Instance()->Find(path); - out += "{"; - if (ref.IsValid()) { - out += "\"Name\":\""; EscapeJson(ref->GetName(), out); - out += "\",\"Class\":\""; EscapeJson(ref->GetClassProperties()->GetName(), out); - out += "\""; - ConfigurationDatabase db; - if (ref->ExportData(db)) { - out += ",\"Config\":{"; - db.MoveToRoot(); - uint32 nc = db.GetNumberOfChildren(); - for (uint32 i = 0u; i < nc; i++) { - const char8 *cn = db.GetChildName(i); - AnyType at = db.GetType(cn); - char8 buf[1024]; AnyType st(CharString, 0u, buf); st.SetNumberOfElements(0, 1024); - if (TypeConvert(st, at)) { - out += "\""; EscapeJson(cn, out); out += "\":\""; - EscapeJson(buf, out); out += "\""; - if (i < nc - 1u) out += ","; - } - } - out += "}"; + Reference ref = ObjectRegistryDatabase::Instance()->Find(path); + out += "{"; + if (ref.IsValid()) { + out += "\"Name\":\""; + EscapeJson(ref->GetName(), out); + out += "\",\"Class\":\""; + EscapeJson(ref->GetClassProperties()->GetName(), out); + out += "\""; + ConfigurationDatabase db; + if (ref->ExportData(db)) { + out += ",\"Config\":{"; + db.MoveToRoot(); + uint32 nc = db.GetNumberOfChildren(); + for (uint32 i = 0u; i < nc; i++) { + const char8 *cn = db.GetChildName(i); + AnyType at = db.GetType(cn); + char8 buf[1024]; + AnyType st(CharString, 0u, buf); + st.SetNumberOfElements(0, 1024); + if (TypeConvert(st, at)) { + out += "\""; + EscapeJson(cn, out); + out += "\":\""; + EscapeJson(buf, out); + out += "\""; + if (i < nc - 1u) + out += ","; } - EnrichWithConfig(path, out); - } else { - StreamString enrichAlias; - mutex.FastLock(); - bool found = false; - for (uint32 i = 0u; i < aliases.Size(); i++) { - if (aliases[i].name == path || - SuffixMatch(aliases[i].name.Buffer(), path)) { - DebugSignalInfo *s = signals[aliases[i].signalIndex]; - const char8 *tn = TypeDescriptor::GetTypeNameFromTypeDescriptor(s->type); - out.Printf("\"Name\":\"%s\",\"Class\":\"Signal\",\"Type\":\"%s\"," - "\"ID\":%u", - s->name.Buffer(), tn ? tn : "Unknown", s->internalID); - enrichAlias = aliases[i].name; - found = true; break; - } - } - mutex.FastUnLock(); - if (found) EnrichWithConfig(enrichAlias.Buffer(), out); - else out += "\"Error\":\"Object not found\""; + } + out += "}"; } - out += "}\nOK INFO\n"; + EnrichWithConfig(path, out); + } else { + StreamString enrichAlias; + mutex.FastLock(); + bool found = false; + for (uint32 i = 0u; i < aliases.GetNumberOfElements(); i++) { + if (aliases[i].name == path || + SuffixMatch(aliases[i].name.Buffer(), path)) { + DebugSignalInfo *s = signals[aliases[i].signalIndex]; + const char8 *tn = + TypeDescriptor::GetTypeNameFromTypeDescriptor(s->type); + out.Printf("\"Name\":\"%s\",\"Class\":\"Signal\",\"Type\":\"%s\"," + "\"ID\":%u", + s->name.Buffer(), tn ? tn : "Unknown", s->internalID); + enrichAlias = aliases[i].name; + found = true; + break; + } + } + mutex.FastUnLock(); + if (found) + EnrichWithConfig(enrichAlias.Buffer(), out); + else + out += "\"Error\":\"Object not found\""; + } + out += "}\nOK INFO\n"; } void DebugServiceBase::ListNodes(const char8 *path, StreamString &out) { - Reference ref = - (path == NULL_PTR(const char8 *) || StringHelper::Length(path) == 0 || - StringHelper::Compare(path, "/") == 0) - ? ObjectRegistryDatabase::Instance() - : ObjectRegistryDatabase::Instance()->Find(path); - out.Printf("Nodes under %s:\n", path ? path : "/"); - if (ref.IsValid()) { - ReferenceContainer *rc = dynamic_cast(ref.operator->()); - if (rc != NULL_PTR(ReferenceContainer *)) { - uint32 n = rc->Size(); - for (uint32 i = 0u; i < n; i++) { - Reference c = rc->Get(i); - if (c.IsValid()) { - out.Printf(" %s [%s]\n", c->GetName(), - c->GetClassProperties()->GetName()); - } - } + Reference ref = + (path == NULL_PTR(const char8 *) || StringHelper::Length(path) == 0 || + StringHelper::Compare(path, "/") == 0) + ? ObjectRegistryDatabase::Instance() + : ObjectRegistryDatabase::Instance()->Find(path); + out.Printf("Nodes under %s:\n", path ? path : "/"); + if (ref.IsValid()) { + ReferenceContainer *rc = + dynamic_cast(ref.operator->()); + if (rc != NULL_PTR(ReferenceContainer *)) { + uint32 n = rc->Size(); + for (uint32 i = 0u; i < n; i++) { + Reference c = rc->Get(i); + if (c.IsValid()) { + out.Printf(" %s [%s]\n", c->GetName(), + c->GetClassProperties()->GetName()); } - } else { - out += " (not found)\n"; + } } - out += "OK LS\n"; + } else { + out += " (not found)\n"; + } + out += "OK LS\n"; } void DebugServiceBase::ServeConfig(StreamString &out) { - if (!manualConfigSet) RebuildConfigFromRegistry(); - fullConfig.MoveToRoot(); - JsonifyDatabase(fullConfig, out); - out += "\nOK CONFIG\n"; + if (!manualConfigSet) + RebuildConfigFromRegistry(); + fullConfig.MoveToRoot(); + JsonifyDatabase(fullConfig, out); + out += "\nOK CONFIG\n"; } // --------------------------------------------------------------------------- @@ -749,16 +865,16 @@ void DebugServiceBase::ServeConfig(StreamString &out) { // --------------------------------------------------------------------------- void DebugServiceBase::SetFullConfig(ConfigurationDatabase &config) { - config.MoveToRoot(); - config.Copy(fullConfig); - manualConfigSet = true; + config.MoveToRoot(); + config.Copy(fullConfig); + manualConfigSet = true; } void DebugServiceBase::RebuildConfigFromRegistry() { - fullConfig = ConfigurationDatabase(); - BuildCDBFromContainer(ObjectRegistryDatabase::Instance(), fullConfig); - // Let the transport subclass write back its specific port numbers etc. - RebuildTransportConfig(); + fullConfig = ConfigurationDatabase(); + BuildCDBFromContainer(ObjectRegistryDatabase::Instance(), fullConfig); + // Let the transport subclass write back its specific port numbers etc. + RebuildTransportConfig(); } // --------------------------------------------------------------------------- @@ -768,95 +884,132 @@ void DebugServiceBase::RebuildConfigFromRegistry() { uint32 DebugServiceBase::ExportTree(ReferenceContainer *container, StreamString &json, const char8 *pathPrefix) { - if (container == NULL_PTR(ReferenceContainer *)) return 0u; - uint32 size = container->Size(); - uint32 valid = 0u; - for (uint32 i = 0u; i < size; i++) { - Reference child = container->Get(i); - if (!child.IsValid()) continue; - if (valid > 0u) json += ",\n"; - const char8 *cname = child->GetName(); - if (cname == NULL_PTR(const char8 *)) cname = "unnamed"; - StreamString cp; - if (pathPrefix != NULL_PTR(const char8 *)) cp.Printf("%s.%s", pathPrefix, cname); - else cp = cname; + if (container == NULL_PTR(ReferenceContainer *)) + return 0u; + uint32 size = container->Size(); + uint32 valid = 0u; + for (uint32 i = 0u; i < size; i++) { + Reference child = container->Get(i); + if (!child.IsValid()) + continue; + if (valid > 0u) + json += ",\n"; + const char8 *cname = child->GetName(); + if (cname == NULL_PTR(const char8 *)) + cname = "unnamed"; + StreamString cp; + if (pathPrefix != NULL_PTR(const char8 *)) + cp.Printf("%s.%s", pathPrefix, cname); + else + cp = cname; - StreamString nj; - nj += "{\"Name\":\""; EscapeJson(cname, nj); - nj += "\",\"Class\":\""; EscapeJson(child->GetClassProperties()->GetName(), nj); - nj += "\""; + StreamString nj; + nj += "{\"Name\":\""; + EscapeJson(cname, nj); + nj += "\",\"Class\":\""; + EscapeJson(child->GetClassProperties()->GetName(), nj); + nj += "\""; - ReferenceContainer *inner = dynamic_cast(child.operator->()); - DataSourceI *ds = dynamic_cast(child.operator->()); - GAM *gam = dynamic_cast(child.operator->()); + ReferenceContainer *inner = + dynamic_cast(child.operator->()); + DataSourceI *ds = dynamic_cast(child.operator->()); + GAM *gam = dynamic_cast(child.operator->()); - if (inner != NULL_PTR(ReferenceContainer *) || - ds != NULL_PTR(DataSourceI *) || - gam != NULL_PTR(GAM *)) { - nj += ",\"Children\":[\n"; - uint32 sc = 0u; - if (inner != NULL_PTR(ReferenceContainer *)) - sc += ExportTree(inner, nj, cp.Buffer()); - if (ds != NULL_PTR(DataSourceI *)) { - uint32 ns = ds->GetNumberOfSignals(); - for (uint32 j = 0u; j < ns; j++) { - if (sc > 0u) { nj += ",\n"; } sc++; - StreamString sn; (void)ds->GetSignalName(j, sn); - const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor(ds->GetSignalType(j)); - uint8 d = 0u; (void)ds->GetSignalNumberOfDimensions(j, d); - uint32 el = 0u; (void)ds->GetSignalNumberOfElements(j, el); - StreamString sfp; sfp.Printf("%s.%s", cp.Buffer(), sn.Buffer()); - bool tr = false, fo = false; (void)IsInstrumented(sfp.Buffer(), tr, fo); - nj += "{\"Name\":\""; EscapeJson(sn.Buffer(), nj); - nj += "\",\"Class\":\"Signal\",\"Type\":\""; EscapeJson(st ? st : "Unknown", nj); - nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," - "\"IsTraceable\":%s,\"IsForcable\":%s}", - d, el, tr ? "true" : "false", fo ? "true" : "false"); - } - } - if (gam != NULL_PTR(GAM *)) { - uint32 nIn = gam->GetNumberOfInputSignals(); - for (uint32 j = 0u; j < nIn; j++) { - if (sc > 0u) { nj += ",\n"; } sc++; - StreamString sn; (void)gam->GetSignalName(InputSignals, j, sn); - const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor( - gam->GetSignalType(InputSignals, j)); - uint32 d = 0u; (void)gam->GetSignalNumberOfDimensions(InputSignals, j, d); - uint32 el = 0u; (void)gam->GetSignalNumberOfElements(InputSignals, j, el); - StreamString sfp; sfp.Printf("%s.In.%s", cp.Buffer(), sn.Buffer()); - bool tr = false, fo = false; (void)IsInstrumented(sfp.Buffer(), tr, fo); - nj += "{\"Name\":\"In."; EscapeJson(sn.Buffer(), nj); - nj += "\",\"Class\":\"InputSignal\",\"Type\":\""; - EscapeJson(st ? st : "Unknown", nj); - nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," - "\"IsTraceable\":%s,\"IsForcable\":%s}", - d, el, tr ? "true" : "false", fo ? "true" : "false"); - } - uint32 nOut = gam->GetNumberOfOutputSignals(); - for (uint32 j = 0u; j < nOut; j++) { - if (sc > 0u) { nj += ",\n"; } sc++; - StreamString sn; (void)gam->GetSignalName(OutputSignals, j, sn); - const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor( - gam->GetSignalType(OutputSignals, j)); - uint32 d = 0u; (void)gam->GetSignalNumberOfDimensions(OutputSignals, j, d); - uint32 el = 0u; (void)gam->GetSignalNumberOfElements(OutputSignals, j, el); - StreamString sfp; sfp.Printf("%s.Out.%s", cp.Buffer(), sn.Buffer()); - bool tr = false, fo = false; (void)IsInstrumented(sfp.Buffer(), tr, fo); - nj += "{\"Name\":\"Out."; EscapeJson(sn.Buffer(), nj); - nj += "\",\"Class\":\"OutputSignal\",\"Type\":\""; - EscapeJson(st ? st : "Unknown", nj); - nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," - "\"IsTraceable\":%s,\"IsForcable\":%s}", - d, el, tr ? "true" : "false", fo ? "true" : "false"); - } - } - nj += "\n]"; + if (inner != NULL_PTR(ReferenceContainer *) || + ds != NULL_PTR(DataSourceI *) || gam != NULL_PTR(GAM *)) { + nj += ",\"Children\":[\n"; + uint32 sc = 0u; + if (inner != NULL_PTR(ReferenceContainer *)) + sc += ExportTree(inner, nj, cp.Buffer()); + if (ds != NULL_PTR(DataSourceI *)) { + uint32 ns = ds->GetNumberOfSignals(); + for (uint32 j = 0u; j < ns; j++) { + if (sc > 0u) { + nj += ",\n"; + } + sc++; + StreamString sn; + (void)ds->GetSignalName(j, sn); + const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor( + ds->GetSignalType(j)); + uint8 d = 0u; + (void)ds->GetSignalNumberOfDimensions(j, d); + uint32 el = 0u; + (void)ds->GetSignalNumberOfElements(j, el); + StreamString sfp; + sfp.Printf("%s.%s", cp.Buffer(), sn.Buffer()); + bool tr = false, fo = false; + (void)IsInstrumented(sfp.Buffer(), tr, fo); + nj += "{\"Name\":\""; + EscapeJson(sn.Buffer(), nj); + nj += "\",\"Class\":\"Signal\",\"Type\":\""; + EscapeJson(st ? st : "Unknown", nj); + nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," + "\"IsTraceable\":%s,\"IsForcable\":%s}", + d, el, tr ? "true" : "false", fo ? "true" : "false"); } - nj += "}"; - json += nj; - valid++; + } + if (gam != NULL_PTR(GAM *)) { + uint32 nIn = gam->GetNumberOfInputSignals(); + for (uint32 j = 0u; j < nIn; j++) { + if (sc > 0u) { + nj += ",\n"; + } + sc++; + StreamString sn; + (void)gam->GetSignalName(InputSignals, j, sn); + const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor( + gam->GetSignalType(InputSignals, j)); + uint32 d = 0u; + (void)gam->GetSignalNumberOfDimensions(InputSignals, j, d); + uint32 el = 0u; + (void)gam->GetSignalNumberOfElements(InputSignals, j, el); + StreamString sfp; + sfp.Printf("%s.In.%s", cp.Buffer(), sn.Buffer()); + bool tr = false, fo = false; + (void)IsInstrumented(sfp.Buffer(), tr, fo); + nj += "{\"Name\":\"In."; + EscapeJson(sn.Buffer(), nj); + nj += "\",\"Class\":\"InputSignal\",\"Type\":\""; + EscapeJson(st ? st : "Unknown", nj); + nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," + "\"IsTraceable\":%s,\"IsForcable\":%s}", + d, el, tr ? "true" : "false", fo ? "true" : "false"); + } + uint32 nOut = gam->GetNumberOfOutputSignals(); + for (uint32 j = 0u; j < nOut; j++) { + if (sc > 0u) { + nj += ",\n"; + } + sc++; + StreamString sn; + (void)gam->GetSignalName(OutputSignals, j, sn); + const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor( + gam->GetSignalType(OutputSignals, j)); + uint32 d = 0u; + (void)gam->GetSignalNumberOfDimensions(OutputSignals, j, d); + uint32 el = 0u; + (void)gam->GetSignalNumberOfElements(OutputSignals, j, el); + StreamString sfp; + sfp.Printf("%s.Out.%s", cp.Buffer(), sn.Buffer()); + bool tr = false, fo = false; + (void)IsInstrumented(sfp.Buffer(), tr, fo); + nj += "{\"Name\":\"Out."; + EscapeJson(sn.Buffer(), nj); + nj += "\",\"Class\":\"OutputSignal\",\"Type\":\""; + EscapeJson(st ? st : "Unknown", nj); + nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u," + "\"IsTraceable\":%s,\"IsForcable\":%s}", + d, el, tr ? "true" : "false", fo ? "true" : "false"); + } + } + nj += "\n]"; } - return valid; + nj += "}"; + json += nj; + valid++; + } + return valid; } // --------------------------------------------------------------------------- @@ -864,59 +1017,74 @@ uint32 DebugServiceBase::ExportTree(ReferenceContainer *container, // --------------------------------------------------------------------------- void DebugServiceBase::EnrichWithConfig(const char8 *path, StreamString &json) { - if (path == NULL_PTR(const char8 *)) return; - if (!manualConfigSet) RebuildConfigFromRegistry(); - fullConfig.MoveToRoot(); + if (path == NULL_PTR(const char8 *)) + return; + if (!manualConfigSet) + RebuildConfigFromRegistry(); + fullConfig.MoveToRoot(); - const char8 *current = path; - bool ok = true; - while (ok) { - const char8 *nextDot = StringHelper::SearchString(current, "."); - StreamString part; - if (nextDot != NULL_PTR(const char8 *)) { - uint32 len = (uint32)(nextDot - current); - (void)part.Write(current, len); - current = nextDot + 1; - } else { - part = current; ok = false; - } - bool found = false; - if (fullConfig.MoveRelative(part.Buffer())) { found = true; } - if (!found) { - StreamString pref; pref.Printf("+%s", part.Buffer()); - if (fullConfig.MoveRelative(pref.Buffer())) found = true; - } - if (!found) { - if (part == "In") { - if (fullConfig.MoveRelative("InputSignals")) found = true; - else if (fullConfig.MoveRelative("+InputSignals")) found = true; - } else if (part == "Out") { - if (fullConfig.MoveRelative("OutputSignals")) found = true; - else if (fullConfig.MoveRelative("+OutputSignals")) found = true; - } - } - if (!found) { fullConfig.MoveToRoot(); return; } + const char8 *current = path; + bool ok = true; + while (ok) { + const char8 *nextDot = StringHelper::SearchString(current, "."); + StreamString part; + if (nextDot != NULL_PTR(const char8 *)) { + uint32 len = (uint32)(nextDot - current); + (void)part.Write(current, len); + current = nextDot + 1; + } else { + part = current; + ok = false; } + bool found = false; + if (fullConfig.MoveRelative(part.Buffer())) { + found = true; + } + if (!found) { + StreamString pref; + pref.Printf("+%s", part.Buffer()); + if (fullConfig.MoveRelative(pref.Buffer())) + found = true; + } + if (!found) { + if (part == "In") { + if (fullConfig.MoveRelative("InputSignals")) + found = true; + else if (fullConfig.MoveRelative("+InputSignals")) + found = true; + } else if (part == "Out") { + if (fullConfig.MoveRelative("OutputSignals")) + found = true; + else if (fullConfig.MoveRelative("+OutputSignals")) + found = true; + } + } + if (!found) { + fullConfig.MoveToRoot(); + return; + } + } - ConfigurationDatabase db; - fullConfig.Copy(db); - fullConfig.MoveToRoot(); - db.MoveToRoot(); - uint32 n = db.GetNumberOfChildren(); - for (uint32 i = 0u; i < n; i++) { - const char8 *name = db.GetChildName(i); - AnyType at = db.GetType(name); - if (!at.GetTypeDescriptor().isStructuredData) { - json += ", \""; - EscapeJson(name, json); - json += "\": \""; - char8 buf[1024]; - AnyType st(CharString, 0u, buf); - st.SetNumberOfElements(0, 1024); - if (TypeConvert(st, at)) EscapeJson(buf, json); - json += "\""; - } + ConfigurationDatabase db; + fullConfig.Copy(db); + fullConfig.MoveToRoot(); + db.MoveToRoot(); + uint32 n = db.GetNumberOfChildren(); + for (uint32 i = 0u; i < n; i++) { + const char8 *name = db.GetChildName(i); + AnyType at = db.GetType(name); + if (!at.GetTypeDescriptor().isStructuredData) { + json += ", \""; + EscapeJson(name, json); + json += "\": \""; + char8 buf[1024]; + AnyType st(CharString, 0u, buf); + st.SetNumberOfElements(0, 1024); + if (TypeConvert(st, at)) + EscapeJson(buf, json); + json += "\""; } + } } // --------------------------------------------------------------------------- @@ -925,290 +1093,322 @@ void DebugServiceBase::EnrichWithConfig(const char8 *path, StreamString &json) { void DebugServiceBase::JsonifyDatabase(ConfigurationDatabase &db, StreamString &json) { - json += "{"; - uint32 n = db.GetNumberOfChildren(); - bool first = true; - for (uint32 i = 0u; i < n; i++) { - const char8 *key = db.GetChildName(i); - if (key == NULL_PTR(const char8 *)) continue; - if (!first) json += ", "; - first = false; - json += "\""; EscapeJson(key, json); json += "\": "; - if (db.MoveRelative(key)) { - JsonifyDatabase(db, json); - (void)db.MoveToAncestor(1u); + json += "{"; + uint32 n = db.GetNumberOfChildren(); + bool first = true; + for (uint32 i = 0u; i < n; i++) { + const char8 *key = db.GetChildName(i); + if (key == NULL_PTR(const char8 *)) + continue; + if (!first) + json += ", "; + first = false; + json += "\""; + EscapeJson(key, json); + json += "\": "; + if (db.MoveRelative(key)) { + JsonifyDatabase(db, json); + (void)db.MoveToAncestor(1u); + } else { + AnyType at = db.GetType(key); + if (at.GetDataPointer() != NULL_PTR(void *)) { + char8 buf[512] = {'\0'}; + AnyType dst(CharString, 0u, buf); + dst.SetNumberOfElements(0u, 512u); + if (TypeConvert(dst, at)) { + json += "\""; + EscapeJson(buf, json); + json += "\""; } else { - AnyType at = db.GetType(key); - if (at.GetDataPointer() != NULL_PTR(void *)) { - char8 buf[512] = { '\0' }; - AnyType dst(CharString, 0u, buf); - dst.SetNumberOfElements(0u, 512u); - if (TypeConvert(dst, at)) { - json += "\""; EscapeJson(buf, json); json += "\""; - } else { - json += "null"; - } - } else { - json += "null"; - } + json += "null"; } + } else { + json += "null"; + } } - json += "}"; + } + json += "}"; } // --------------------------------------------------------------------------- // HandleCommand — unified command dispatcher // --------------------------------------------------------------------------- -void DebugServiceBase::HandleCommand(const StreamString &cmdIn, StreamString &out) { - StreamString cmd = cmdIn; - StreamString token; - cmd.Seek(0u); - char8 term; - const char8 *delims = " \r\n"; - if (!cmd.GetToken(token, delims, term)) return; +void DebugServiceBase::HandleCommand(const StreamString &cmdIn, + StreamString &out) { + StreamString cmd = cmdIn; + StreamString token; + cmd.Seek(0u); + char8 term; + const char8 *delims = " \r\n"; + if (!cmd.GetToken(token, delims, term)) + return; - if (token == "FORCE") { - StreamString name, val; - if (cmd.GetToken(name, delims, term) && cmd.GetToken(val, delims, term)) { - uint32 c = ForceSignal(name.Buffer(), val.Buffer()); - out.Printf("OK FORCE %u\n", c); - } - } else if (token == "UNFORCE") { - StreamString name; - if (cmd.GetToken(name, delims, term)) { - uint32 c = UnforceSignal(name.Buffer()); - out.Printf("OK UNFORCE %u\n", c); - } - } else if (token == "TRACE") { - StreamString name, state, decim; - if (cmd.GetToken(name, delims, term) && cmd.GetToken(state, delims, term)) { - bool en = (state == "1"); - uint32 d = 1u; - if (cmd.GetToken(decim, delims, term)) { - AnyType dv(UnsignedInteger32Bit, 0u, &d); - AnyType ds(CharString, 0u, decim.Buffer()); - (void)TypeConvert(dv, ds); - } - uint32 c = TraceSignal(name.Buffer(), en, d); - out.Printf("OK TRACE %u\n", c); - } - } else if (token == "BREAK") { - StreamString name, opStr; - if (cmd.GetToken(name, delims, term) && cmd.GetToken(opStr, delims, term)) { - uint32 c = 0u; - if (opStr == "OFF") { - c = ClearBreak(name.Buffer()); - } else { - StreamString thrStr; - if (cmd.GetToken(thrStr, delims, term)) { - uint8 op = BREAK_OFF; - if (opStr == ">") op = BREAK_GT; - else if (opStr == "<") op = BREAK_LT; - else if (opStr == "==") op = BREAK_EQ; - else if (opStr == ">=") op = BREAK_GEQ; - else if (opStr == "<=") op = BREAK_LEQ; - else if (opStr == "!=") op = BREAK_NEQ; - if (op != BREAK_OFF) { - float64 thr = 0.0; - AnyType tv(Float64Bit, 0u, &thr); - AnyType ts(CharString, 0u, thrStr.Buffer()); - (void)TypeConvert(tv, ts); - c = SetBreak(name.Buffer(), op, thr); - } - } - } - out.Printf("OK BREAK %u\n", c); - } - } else if (token == "PAUSE") { - SetPaused(true); - out += "OK\n"; - } else if (token == "RESUME") { - SetPaused(false); - out += "OK\n"; - } else if (token == "STEP") { - StreamString nStr; - uint32 n = 1u; - if (cmd.GetToken(nStr, delims, term)) { - AnyType nv(UnsignedInteger32Bit, 0u, &n); - AnyType ns(CharString, 0u, nStr.Buffer()); - (void)TypeConvert(nv, ns); - } - StreamString thr; - const char8 *ta = NULL_PTR(const char8 *); - if (cmd.GetToken(thr, delims, term) && thr.Size() > 0u) ta = thr.Buffer(); - Step(n, ta); - out.Printf("OK STEP %u\n", n); - } else if (token == "STEP_STATUS") { - GetStepStatus(out); - } else if (token == "VALUE") { - StreamString sn; - if (cmd.GetToken(sn, delims, term)) { - GetSignalValue(sn.Buffer(), out); - } else { - out += "{\"Error\":\"Missing signal name\"}\nOK VALUE\n"; - } - } else if (token == "DISCOVER") { - Discover(out); - } else if (token == "TREE") { - out += "{\"Name\":\"Root\",\"Class\":\"ObjectRegistryDatabase\"," - "\"Children\":[\n"; - (void)ExportTree(ObjectRegistryDatabase::Instance(), out, - NULL_PTR(const char8 *)); - out += "\n]}\nOK TREE\n"; - } else if (token == "INFO") { - StreamString path; - if (cmd.GetToken(path, delims, term)) InfoNode(path.Buffer(), out); - } else if (token == "LS") { - StreamString path; - if (cmd.GetToken(path, delims, term)) ListNodes(path.Buffer(), out); - else ListNodes(NULL_PTR(const char8 *), out); - } else if (token == "CONFIG") { - ServeConfig(out); - } else if (token == "MONITOR") { - StreamString sub, name, period; - if (cmd.GetToken(sub, delims, term) && sub == "SIGNAL" && - cmd.GetToken(name, delims, term) && - cmd.GetToken(period, delims, term)) { - uint32 p = 100u; - AnyType pv(UnsignedInteger32Bit, 0u, &p); - AnyType ps(CharString, 0u, period.Buffer()); - (void)TypeConvert(pv, ps); - uint32 c = RegisterMonitorSignal(name.Buffer(), p); - out.Printf("OK MONITOR %u\n", c); - } - } else if (token == "UNMONITOR") { - StreamString sub, name; - if (cmd.GetToken(sub, delims, term) && sub == "SIGNAL" && - cmd.GetToken(name, delims, term)) { - uint32 c = UnmonitorSignal(name.Buffer()); - out.Printf("OK UNMONITOR %u\n", c); - } - } else if (token == "SERVICE_INFO") { - GetServiceInfo(out); - } else if (token == "MSG") { - // MSG [key=value\nkey=value...] - StreamString dest, func, waitStr; - if (cmd.GetToken(dest, delims, term) && - cmd.GetToken(func, delims, term) && - cmd.GetToken(waitStr, delims, term)) { - bool wait = (waitStr == "1"); - - const char8 *pStart = cmd.Buffer() + cmd.Position(); - StreamString rawPayload = pStart; - - // Decode escaped newlines (\n → real newline) - StreamString payload; - rawPayload.Seek(0u); - char8 c; - while (rawPayload.Size() > rawPayload.Position()) { - uint32 rs = 1u; - if (rawPayload.Read(&c, rs)) { - if (c == '\\') { - char8 next; - if (rawPayload.Read(&next, rs)) { - if (next == 'n') payload += '\n'; - else { payload += c; payload += next; } - } else { - payload += c; - } - } else { - payload += c; - } - } - } - - ReferenceT msg( - "Message", GlobalObjectsDatabase::Instance()->GetStandardHeap()); - ConfigurationDatabase msgConfig; - msgConfig.Write("Destination", dest.Buffer()); - msgConfig.Write("Function", func.Buffer()); - if (wait) msgConfig.Write("Mode", "ExpectsReply"); - - ReferenceT paramCdb( - "ConfigurationDatabase", - GlobalObjectsDatabase::Instance()->GetStandardHeap()); - - if (payload.Size() > 0u && paramCdb.IsValid()) { - payload.Seek(0u); - StreamString line; - while (payload.GetToken(line, "\n", term)) { - if (line.Size() > 0u) { - const char8 *eq = StringHelper::SearchChar(line.Buffer(), '='); - if (eq != NULL_PTR(const char8 *)) { - uint32 eqPos = (uint32)(eq - line.Buffer()); - static const uint32 KEY_BUF_SIZE = 256u; - static const uint32 VAL_BUF_SIZE = 1024u; - if (eqPos >= KEY_BUF_SIZE) { - REPORT_ERROR_STATIC(ErrorManagement::Warning, - "MSG: key length %u exceeds buffer (%u) — line skipped.", - eqPos, KEY_BUF_SIZE); - line = ""; continue; - } - (void)line.Seek(0u); - char8 keyBuf[KEY_BUF_SIZE]; - MemoryOperationsHelper::Set(keyBuf, '\0', KEY_BUF_SIZE); - uint32 keyReadSize = eqPos; - (void)line.Read(keyBuf, keyReadSize); - (void)line.Seek(eqPos + 1u); - uint32 valLen = (uint32)(line.Size() - eqPos - 1u); - if (valLen >= VAL_BUF_SIZE) { - REPORT_ERROR_STATIC(ErrorManagement::Warning, - "MSG: value length %u truncated to %u for key '%s'.", - valLen, VAL_BUF_SIZE - 1u, keyBuf); - valLen = VAL_BUF_SIZE - 1u; - } - char8 valBuf[VAL_BUF_SIZE]; - MemoryOperationsHelper::Set(valBuf, '\0', VAL_BUF_SIZE); - (void)line.Read(valBuf, valLen); - // Trim trailing whitespace from value - for (int32 ti = (int32)valLen - 1; ti >= 0; ti--) { - if (valBuf[ti] == ' ' || valBuf[ti] == '\r' || - valBuf[ti] == '\t') - valBuf[ti] = '\0'; - else break; - } - // Trim leading whitespace from key - const char8 *kp = keyBuf; - while (*kp == ' ' || *kp == '\t') kp++; - if (*kp != '\0') (void)paramCdb->Write(kp, valBuf); - } - line = ""; - } - } - } - - ErrorManagement::ErrorType err = ErrorManagement::ParametersError; - if (msg->Initialise(msgConfig)) { - if (paramCdb.IsValid() && payload.Size() > 0u) { - (void)msg->Insert(paramCdb); - } - Reference destObj = ObjectRegistryDatabase::Instance()->Find(dest.Buffer()); - if (destObj.IsValid()) { - StreamString myPath; - Object *sender = this; - if (!GetFullObjectName(*this, myPath)) { - sender = NULL_PTR(Object *); - } - if (wait) { - err = MessageI::WaitForReply(msg, TTInfiniteWait); - } else { - (void)MessageI::SendMessage(msg, sender); - err = ErrorManagement::NoError; - } - } else { - REPORT_ERROR_STATIC(ErrorManagement::Warning, - "MSG: destination '%s' not found in ORD.", dest.Buffer()); - } - } else { - REPORT_ERROR_STATIC(ErrorManagement::Warning, - "MSG: Message initialisation failed."); - } - - if (err == ErrorManagement::NoError) out += "OK MSG\n"; - else out += "ERROR MSG\n"; - } + if (token == "FORCE") { + StreamString name, val; + if (cmd.GetToken(name, delims, term) && cmd.GetToken(val, delims, term)) { + uint32 c = ForceSignal(name.Buffer(), val.Buffer()); + out.Printf("OK FORCE %u\n", c); } + } else if (token == "UNFORCE") { + StreamString name; + if (cmd.GetToken(name, delims, term)) { + uint32 c = UnforceSignal(name.Buffer()); + out.Printf("OK UNFORCE %u\n", c); + } + } else if (token == "TRACE") { + StreamString name, state, decim; + if (cmd.GetToken(name, delims, term) && cmd.GetToken(state, delims, term)) { + bool en = (state == "1"); + uint32 d = 1u; + if (cmd.GetToken(decim, delims, term)) { + AnyType dv(UnsignedInteger32Bit, 0u, &d); + AnyType ds(CharString, 0u, decim.Buffer()); + (void)TypeConvert(dv, ds); + } + uint32 c = TraceSignal(name.Buffer(), en, d); + out.Printf("OK TRACE %u\n", c); + } + } else if (token == "BREAK") { + StreamString name, opStr; + if (cmd.GetToken(name, delims, term) && cmd.GetToken(opStr, delims, term)) { + uint32 c = 0u; + if (opStr == "OFF") { + c = ClearBreak(name.Buffer()); + } else { + StreamString thrStr; + if (cmd.GetToken(thrStr, delims, term)) { + uint8 op = BREAK_OFF; + if (opStr == ">") + op = BREAK_GT; + else if (opStr == "<") + op = BREAK_LT; + else if (opStr == "==") + op = BREAK_EQ; + else if (opStr == ">=") + op = BREAK_GEQ; + else if (opStr == "<=") + op = BREAK_LEQ; + else if (opStr == "!=") + op = BREAK_NEQ; + if (op != BREAK_OFF) { + float64 thr = 0.0; + AnyType tv(Float64Bit, 0u, &thr); + AnyType ts(CharString, 0u, thrStr.Buffer()); + (void)TypeConvert(tv, ts); + c = SetBreak(name.Buffer(), op, thr); + } + } + } + out.Printf("OK BREAK %u\n", c); + } + } else if (token == "PAUSE") { + SetPaused(true); + out += "OK\n"; + } else if (token == "RESUME") { + SetPaused(false); + out += "OK\n"; + } else if (token == "STEP") { + StreamString nStr; + uint32 n = 1u; + if (cmd.GetToken(nStr, delims, term)) { + AnyType nv(UnsignedInteger32Bit, 0u, &n); + AnyType ns(CharString, 0u, nStr.Buffer()); + (void)TypeConvert(nv, ns); + } + StreamString thr; + const char8 *ta = NULL_PTR(const char8 *); + if (cmd.GetToken(thr, delims, term) && thr.Size() > 0u) + ta = thr.Buffer(); + Step(n, ta); + out.Printf("OK STEP %u\n", n); + } else if (token == "STEP_STATUS") { + GetStepStatus(out); + } else if (token == "VALUE") { + StreamString sn; + if (cmd.GetToken(sn, delims, term)) { + GetSignalValue(sn.Buffer(), out); + } else { + out += "{\"Error\":\"Missing signal name\"}\nOK VALUE\n"; + } + } else if (token == "DISCOVER") { + Discover(out); + } else if (token == "TREE") { + out += "{\"Name\":\"Root\",\"Class\":\"ObjectRegistryDatabase\"," + "\"Children\":[\n"; + (void)ExportTree(ObjectRegistryDatabase::Instance(), out, + NULL_PTR(const char8 *)); + out += "\n]}\nOK TREE\n"; + } else if (token == "INFO") { + StreamString path; + if (cmd.GetToken(path, delims, term)) + InfoNode(path.Buffer(), out); + } else if (token == "LS") { + StreamString path; + if (cmd.GetToken(path, delims, term)) + ListNodes(path.Buffer(), out); + else + ListNodes(NULL_PTR(const char8 *), out); + } else if (token == "CONFIG") { + ServeConfig(out); + } else if (token == "MONITOR") { + StreamString sub, name, period; + if (cmd.GetToken(sub, delims, term) && sub == "SIGNAL" && + cmd.GetToken(name, delims, term) && + cmd.GetToken(period, delims, term)) { + uint32 p = 100u; + AnyType pv(UnsignedInteger32Bit, 0u, &p); + AnyType ps(CharString, 0u, period.Buffer()); + (void)TypeConvert(pv, ps); + uint32 c = RegisterMonitorSignal(name.Buffer(), p); + out.Printf("OK MONITOR %u\n", c); + } + } else if (token == "UNMONITOR") { + StreamString sub, name; + if (cmd.GetToken(sub, delims, term) && sub == "SIGNAL" && + cmd.GetToken(name, delims, term)) { + uint32 c = UnmonitorSignal(name.Buffer()); + out.Printf("OK UNMONITOR %u\n", c); + } + } else if (token == "SERVICE_INFO") { + GetServiceInfo(out); + } else if (token == "MSG") { + // MSG [key=value\nkey=value...] + StreamString dest, func, waitStr; + if (cmd.GetToken(dest, delims, term) && cmd.GetToken(func, delims, term) && + cmd.GetToken(waitStr, delims, term)) { + bool wait = (waitStr == "1"); + + const char8 *pStart = cmd.Buffer() + cmd.Position(); + StreamString rawPayload = pStart; + + // Decode escaped newlines (\n → real newline) + StreamString payload; + rawPayload.Seek(0u); + char8 c; + while (rawPayload.Size() > rawPayload.Position()) { + uint32 rs = 1u; + if (rawPayload.Read(&c, rs)) { + if (c == '\\') { + char8 next; + if (rawPayload.Read(&next, rs)) { + if (next == 'n') + payload += '\n'; + else { + payload += c; + payload += next; + } + } else { + payload += c; + } + } else { + payload += c; + } + } + } + + ReferenceT msg( + "Message", GlobalObjectsDatabase::Instance()->GetStandardHeap()); + ConfigurationDatabase msgConfig; + msgConfig.Write("Destination", dest.Buffer()); + msgConfig.Write("Function", func.Buffer()); + if (wait) + msgConfig.Write("Mode", "ExpectsReply"); + + ReferenceT paramCdb( + "ConfigurationDatabase", + GlobalObjectsDatabase::Instance()->GetStandardHeap()); + + if (payload.Size() > 0u && paramCdb.IsValid()) { + payload.Seek(0u); + StreamString line; + while (payload.GetToken(line, "\n", term)) { + if (line.Size() > 0u) { + const char8 *eq = StringHelper::SearchChar(line.Buffer(), '='); + if (eq != NULL_PTR(const char8 *)) { + uint32 eqPos = (uint32)(eq - line.Buffer()); + static const uint32 KEY_BUF_SIZE = 256u; + static const uint32 VAL_BUF_SIZE = 1024u; + if (eqPos >= KEY_BUF_SIZE) { + REPORT_ERROR_STATIC( + ErrorManagement::Warning, + "MSG: key length %u exceeds buffer (%u) — line skipped.", + eqPos, KEY_BUF_SIZE); + line = ""; + continue; + } + (void)line.Seek(0u); + char8 keyBuf[KEY_BUF_SIZE]; + MemoryOperationsHelper::Set(keyBuf, '\0', KEY_BUF_SIZE); + uint32 keyReadSize = eqPos; + (void)line.Read(keyBuf, keyReadSize); + (void)line.Seek(eqPos + 1u); + uint32 valLen = (uint32)(line.Size() - eqPos - 1u); + if (valLen >= VAL_BUF_SIZE) { + REPORT_ERROR_STATIC( + ErrorManagement::Warning, + "MSG: value length %u truncated to %u for key '%s'.", + valLen, VAL_BUF_SIZE - 1u, keyBuf); + valLen = VAL_BUF_SIZE - 1u; + } + char8 valBuf[VAL_BUF_SIZE]; + MemoryOperationsHelper::Set(valBuf, '\0', VAL_BUF_SIZE); + (void)line.Read(valBuf, valLen); + // Trim trailing whitespace from value + for (int32 ti = (int32)valLen - 1; ti >= 0; ti--) { + if (valBuf[ti] == ' ' || valBuf[ti] == '\r' || + valBuf[ti] == '\t') + valBuf[ti] = '\0'; + else + break; + } + // Trim leading whitespace from key + const char8 *kp = keyBuf; + while (*kp == ' ' || *kp == '\t') + kp++; + if (*kp != '\0') + (void)paramCdb->Write(kp, valBuf); + } + line = ""; + } + } + } + + ErrorManagement::ErrorType err = ErrorManagement::ParametersError; + if (msg->Initialise(msgConfig)) { + if (paramCdb.IsValid() && payload.Size() > 0u) { + (void)msg->Insert(paramCdb); + } + Reference destObj = + ObjectRegistryDatabase::Instance()->Find(dest.Buffer()); + if (destObj.IsValid()) { + StreamString myPath; + Object *sender = this; + if (!GetFullObjectName(*this, myPath)) { + sender = NULL_PTR(Object *); + } + if (wait) { + err = MessageI::WaitForReply(msg, TTInfiniteWait); + } else { + (void)MessageI::SendMessage(msg, sender); + err = ErrorManagement::NoError; + } + } else { + REPORT_ERROR_STATIC(ErrorManagement::Warning, + "MSG: destination '%s' not found in ORD.", + dest.Buffer()); + } + } else { + REPORT_ERROR_STATIC(ErrorManagement::Warning, + "MSG: Message initialisation failed."); + } + + if (err == ErrorManagement::NoError) + out += "OK MSG\n"; + else + out += "ERROR MSG\n"; + } + } } // --------------------------------------------------------------------------- diff --git a/Source/Components/Interfaces/DebugService/DebugServiceBase.h b/Source/Components/Interfaces/DebugService/DebugServiceBase.h index 8c1c262..a7529aa 100644 --- a/Source/Components/Interfaces/DebugService/DebugServiceBase.h +++ b/Source/Components/Interfaces/DebugService/DebugServiceBase.h @@ -52,11 +52,11 @@ public: uint32 numSignals, MemoryMapBroker *broker, volatile bool *anyActiveFlag, - Vec *activeIndices, - Vec *activeSizes, + Vector *activeIndices, + Vector *activeSizes, FastPollingMutexSem *activeMutex, volatile bool *anyBreakFlag, - Vec *breakIndices, + Vector *breakIndices, const char8 *gamName = NULL_PTR(const char8 *), bool isOutput = false); @@ -167,10 +167,10 @@ protected: // Shared data members // ========================================================================= - Vec signals; - Vec aliases; - Vec brokers; - Vec monitoredSignals; + Vector signals; + Vector aliases; + Vector brokers; + Vector monitoredSignals; FastPollingMutexSem mutex; FastPollingMutexSem tracePushMutex; diff --git a/Source/Components/Interfaces/DebugService/DebugServiceI.h b/Source/Components/Interfaces/DebugService/DebugServiceI.h index bc28c41..846713e 100644 --- a/Source/Components/Interfaces/DebugService/DebugServiceI.h +++ b/Source/Components/Interfaces/DebugService/DebugServiceI.h @@ -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 *activeIndices; - Vec *activeSizes; + Vector *activeIndices; + Vector *activeSizes; FastPollingMutexSem *activeMutex; volatile bool *anyBreakFlag; - Vec *breakIndices; + Vector *breakIndices; StreamString gamName; bool isOutput; }; @@ -124,11 +123,11 @@ public: uint32 numSignals, MemoryMapBroker *broker, volatile bool *anyActiveFlag, - Vec *activeIndices, - Vec *activeSizes, + Vector *activeIndices, + Vector *activeSizes, FastPollingMutexSem *activeMutex, volatile bool *anyBreakFlag, - Vec *breakIndices, + Vector *breakIndices, const char8 *gamName = NULL_PTR(const char8 *), bool isOutput = false) = 0; diff --git a/Source/Components/Interfaces/WebDebugService/Makefile.inc b/Source/Components/Interfaces/WebDebugService/Makefile.inc index b19a8e9..7ed2f8a 100644 --- a/Source/Components/Interfaces/WebDebugService/Makefile.inc +++ b/Source/Components/Interfaces/WebDebugService/Makefile.inc @@ -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 diff --git a/Source/Components/Interfaces/WebDebugService/WebDebugService.cpp b/Source/Components/Interfaces/WebDebugService/WebDebugService.cpp index dcd5953..2ddf672 100644 --- a/Source/Components/Interfaces/WebDebugService/WebDebugService.cpp +++ b/Source/Components/Interfaces/WebDebugService/WebDebugService.cpp @@ -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); diff --git a/Source/Components/Interfaces/WebDebugService/WebDebugService.h b/Source/Components/Interfaces/WebDebugService/WebDebugService.h index 7d88141..fd0c57a 100644 --- a/Source/Components/Interfaces/WebDebugService/WebDebugService.h +++ b/Source/Components/Interfaces/WebDebugService/WebDebugService.h @@ -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 diff --git a/Source/Core/Types/Makefile.gcc b/Source/Core/Types/Makefile.gcc deleted file mode 100644 index ab19097..0000000 --- a/Source/Core/Types/Makefile.gcc +++ /dev/null @@ -1 +0,0 @@ -include Makefile.inc diff --git a/Source/Core/Types/Makefile.inc b/Source/Core/Types/Makefile.inc deleted file mode 100644 index edef047..0000000 --- a/Source/Core/Types/Makefile.inc +++ /dev/null @@ -1,46 +0,0 @@ -############################################################# -# -# Copyright 2015 F4E | European Joint Undertaking for ITER -# and the Development of Fusion Energy ('Fusion for Energy') -# -# Licensed under the EUPL, Version 1.1 or - as soon they -# will be approved by the European Commission - subsequent -# versions of the EUPL (the "Licence"); -# You may not use this work except in compliance with the -# Licence. -# You may obtain a copy of the Licence at: -# -# http://ec.europa.eu/idabc/eupl -# -# Unless required by applicable law or agreed to in -# writing, software distributed under the Licence is -# distributed on an "AS IS" basis, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. -# See the Licence for the specific language governing -# permissions and limitations under the Licence. -# -# $Id: Makefile.inc 3 2012-01-15 16:26:07Z aneto $ -# -############################################################# - -SPB = - - -ROOT_DIR=../../.. - - -PACKAGE=Core -ROOT_DIR=../../.. -ABS_ROOT_DIR=$(abspath $(ROOT_DIR)) -MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults - -include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET) - -all: $(OBJS) $(SUBPROJ) - echo $(OBJS) - -include depends.$(TARGET) - -include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET) - diff --git a/Source/Core/Types/Result/Result.h b/Source/Core/Types/Result/Result.h deleted file mode 100644 index c23374c..0000000 --- a/Source/Core/Types/Result/Result.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __RESULT_H -#define __RESULT_H - -#include - -namespace MARTe { - -/** - * @brief Namespace for result error codes. - */ -namespace Errors { -enum ErrorT { - None = 0, - Generic = 1, - OutOfMemory = 2, - IndexOutOfBounds = 3, - ValueOutOfRange = 4, - WrongType = 5, - Empty = 6, -}; -} - -/** - * @brief A simple Result type for error handling. - * @details This implementation is header-only to ensure template linkage. - * Requirement: T and E must have default constructors and be copyable. - */ -template -class Result { -public: - static Result Success(const T &t) { - return Result(t, true); - } - - static Result Fail(const E &e) { - return Result(e, false); - } - - Result() : state(false), val(T()), err(E()) {} - Result(const Result &r) : state(r.state), val(r.val), err(r.err) {} - - Result& operator=(const Result &r) { - if (this != &r) { - state = r.state; - val = r.val; - err = r.err; - } - return *this; - } - - bool Ok() const { return state; } - bool IsOk() const { return state; } - - // Const accessors - const T &Val() const { assert(state); return val; } - const E &Err() const { assert(!state); return err; } - - // Non-const accessors - T &Val() { assert(state); return val; } - E &Err() { assert(!state); return err; } - - operator bool() const { return state; } - -private: - Result(const T &v, bool s) : state(s), val(v), err(E()) {} - Result(const E &e, bool s) : state(s), val(T()), err(e) {} - - bool state; - T val; - E err; -}; - -} // namespace MARTe - -#endif diff --git a/Source/Core/Types/Result/dependsRaw.x86-linux b/Source/Core/Types/Result/dependsRaw.x86-linux deleted file mode 100644 index 7ee6bd6..0000000 --- a/Source/Core/Types/Result/dependsRaw.x86-linux +++ /dev/null @@ -1 +0,0 @@ -Result.o: Result.cpp Result.h diff --git a/Source/Core/Types/Vec/Vec.h b/Source/Core/Types/Vec/Vec.h deleted file mode 100644 index bcab1ea..0000000 --- a/Source/Core/Types/Vec/Vec.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef __VEC_H -#define __VEC_H - -#include "Result.h" -#include -#include -#include -#include - -namespace MARTe { - -/** - * @brief Simple dynamic array (vector) implementation with fixed growth. - * @tparam T The type of elements. - * @tparam GROWTH The number of elements to add when the buffer is full. - */ -template -class Vec { -public: - Vec() : size(0), mem_size(GROWTH), arr(NULL) { - arr = new T[mem_size]; - } - - Vec(const Vec &other) : size(other.size), mem_size(other.mem_size), arr(NULL) { - arr = new T[mem_size]; - for (size_t i = 0; i < size; ++i) { - arr[i] = other.arr[i]; - } - } - - Vec(const T *data, const size_t count) : size(count), mem_size(count + GROWTH), arr(NULL) { - arr = new T[mem_size]; - for (size_t i = 0; i < size; ++i) { - arr[i] = data[i]; - } - } - - ~Vec() { - if (arr != NULL) { - delete[] arr; - arr = NULL; - } - } - - Vec& operator=(const Vec &other) { - if (this != &other) { - T* new_arr = new T[other.mem_size]; - for (size_t i = 0; i < other.size; ++i) { - new_arr[i] = other.arr[i]; - } - if (arr != NULL) { - delete[] arr; - } - arr = new_arr; - size = other.size; - mem_size = other.mem_size; - } - return *this; - } - - void Clear() { - size = 0; - } - - /** - * @brief Exchange contents with another Vec in O(1) — no allocation, no element copies. - * - * Used by UpdateBrokersActiveStatus / UpdateBrokersBreakStatus to publish a - * freshly built index list to the RT thread with the shortest possible lock - * hold time: only three pointer/size swaps happen inside the mutex. - * The old arrays end up in @p other and are freed when it leaves scope - * AFTER the lock is released. - */ - void Swap(Vec &other) { - T *tmpArr = arr; arr = other.arr; other.arr = tmpArr; - size_t tmpSz = size; size = other.size; other.size = tmpSz; - size_t tmpMem = mem_size; mem_size = other.mem_size; other.mem_size = tmpMem; - } - - size_t Size() const { - return size; - } - - T* GetInternalBuffer() { return arr; } - - bool Remove(size_t index) { - if (index >= size) return false; - for (size_t i = index; i < size - 1; ++i) { - arr[i] = arr[i + 1]; - } - size--; - return true; - } - - bool Insert(size_t index, const T& val) { - if (index > size) return false; - if (size == mem_size) extend(); - - for (size_t i = size; i > index; --i) { - arr[i] = arr[i - 1]; - } - arr[index] = val; - size++; - return true; - } - - Result Get(size_t index) const { - if (index >= size) return Result::Fail(Errors::IndexOutOfBounds); - return Result::Success(arr[index]); - } - - void Push(const T &val) { - if (size == mem_size) extend(); - arr[size++] = val; - } - - Result Pop() { - if (size == 0) return Result::Fail(Errors::Empty); - T last = arr[--size]; - return Result::Success(last); - } - - const T &operator[](const size_t index) const { - assert(index < size); - return arr[index]; - } - - T &operator[](const size_t index) { - assert(index < size); - return arr[index]; - } - -protected: - const T *mem() const { return arr; } - size_t memSize() const { return mem_size; } - -private: - size_t size; - size_t mem_size; - T *arr; - - void extend() { - size_t new_mem_size = mem_size + GROWTH; - T *new_arr = new T[new_mem_size]; - for (size_t i = 0; i < size; ++i) { - new_arr[i] = arr[i]; - } - if (arr != NULL) { - delete[] arr; - } - arr = new_arr; - mem_size = new_mem_size; - } -}; - -} // namespace MARTe - -#endif diff --git a/Source/Core/Types/Vec/depends.x86-linux b/Source/Core/Types/Vec/depends.x86-linux deleted file mode 100644 index e89ee79..0000000 --- a/Source/Core/Types/Vec/depends.x86-linux +++ /dev/null @@ -1 +0,0 @@ -../../../..//Build/x86-linux/Core/Types/Vec/Vec.o: Vec.cpp diff --git a/Source/Core/Types/Vec/dependsRaw.x86-linux b/Source/Core/Types/Vec/dependsRaw.x86-linux deleted file mode 100644 index f009802..0000000 --- a/Source/Core/Types/Vec/dependsRaw.x86-linux +++ /dev/null @@ -1 +0,0 @@ -Vec.o: Vec.cpp diff --git a/Source/Core/Types/dependsRaw.x86-linux b/Source/Core/Types/dependsRaw.x86-linux deleted file mode 100644 index e69de29..0000000 diff --git a/Tools/go_web_client/marte2-web-client b/Tools/go_web_client/marte2-web-client index 65fa405..a905101 100755 Binary files a/Tools/go_web_client/marte2-web-client and b/Tools/go_web_client/marte2-web-client differ diff --git a/Tools/go_web_client/marte2.go b/Tools/go_web_client/marte2.go index 9ecf220..8e34743 100644 --- a/Tools/go_web_client/marte2.go +++ b/Tools/go_web_client/marte2.go @@ -297,6 +297,12 @@ func (m *MarteClient) handleTextLine(line string) { fmt.Sscanf(p[8:], "%d", &newLog) } } + // Always forward as a response so the browser can display it. + broadcast(m.hub, map[string]any{ + "type": "response", + "tag": "SERVICE_INFO", + "data": line[len("OK SERVICE_INFO "):], + }) if newUDP > 0 || newLog > 0 { broadcast(m.hub, map[string]any{ "type": "service_config", diff --git a/Tools/go_web_client/static/app.js b/Tools/go_web_client/static/app.js index b001c74..d4788d3 100644 --- a/Tools/go_web_client/static/app.js +++ b/Tools/go_web_client/static/app.js @@ -116,12 +116,13 @@ function onResponse(msg) { try { const data = msg.data ? JSON.parse(msg.data) : null; switch (msg.tag) { - case 'DISCOVER': if (data) processDiscovery(data.Signals || []); break; - case 'TREE': if (data) processTree(data); break; - case 'INFO': showInfo(msg.tag, msg.data); break; - case 'CONFIG': showInfo('CONFIG', msg.data); break; - case 'STEP_STATUS': processStepStatus(data); break; - case 'VALUE': processValue(data); break; + case 'DISCOVER': if (data) processDiscovery(data.Signals || []); break; + case 'TREE': if (data) processTree(data); break; + case 'INFO': showInfo(msg.tag, msg.data); break; + case 'CONFIG': showInfo('CONFIG', msg.data); break; + case 'SERVICE_INFO': showInfo('Service Info', msg.data); break; + case 'STEP_STATUS': processStepStatus(data); break; + case 'VALUE': processValue(data); break; } } catch(e) { // non-JSON responses (TRACE, FORCE, etc.) — silently ignore @@ -144,7 +145,12 @@ function onLog(msg) { } function onServiceConfig(msg) { - appendLog('sys','INFO',`ServiceConfig: UDP=${msg.udp_port} LOG=${msg.log_port}`); + const auto = document.getElementById('auto-ports')?.checked ?? true; + if (auto) { + if (msg.udp_port) document.getElementById('udp-port').value = msg.udp_port; + if (msg.log_port) document.getElementById('log-port').value = msg.log_port; + } + appendLog('sys','INFO',`ServiceConfig: UDP=${msg.udp_port} LOG=${msg.log_port}${auto ? '' : ' (ignored — manual ports)'}`); } function onUdpStats(msg) { @@ -684,13 +690,33 @@ function showInfo(title, data) { // Connect / Disconnect // ════════════════════════════════════════════════════════════════════ +function requireConnected() { + if (!marteConnected) { + appendLog('sys', 'WARNING', 'Not connected to MARTe2'); + return false; + } + return true; +} + +function discoverCmd() { if (requireConnected()) { sendCmd('DISCOVER'); closeAllMenus(); } } +function treeCmd() { if (requireConnected()) { sendCmd('TREE'); closeAllMenus(); } } +function serviceInfoCmd() { if (requireConnected()) { sendCmd('SERVICE_INFO'); closeAllMenus(); } } + +function toggleAutoPorts(auto) { + const row = document.getElementById('port-manual-row'); + if (row) row.style.display = auto ? 'none' : 'flex'; +} + function toggleConnect() { if (marteConnected) { sendWS({type:'disconnect'}); } else { - const host = document.getElementById('host').value.trim() || '127.0.0.1'; - const port = parseInt(document.getElementById('port').value) || 8080; - sendWS({type:'connect', data:{host, port, udp_port:port+1, log_port:port+2}}); + const host = document.getElementById('host').value.trim() || '127.0.0.1'; + const port = parseInt(document.getElementById('port').value) || 8080; + const auto = document.getElementById('auto-ports').checked; + const udpPort = auto ? port + 1 : (parseInt(document.getElementById('udp-port').value) || port + 1); + const logPort = auto ? port + 2 : (parseInt(document.getElementById('log-port').value) || port + 2); + sendWS({type:'connect', data:{host, port, udp_port:udpPort, log_port:logPort}}); } closeAllMenus(); } diff --git a/Tools/go_web_client/static/index.html b/Tools/go_web_client/static/index.html index 9761698..d8ba8f9 100644 --- a/Tools/go_web_client/static/index.html +++ b/Tools/go_web_client/static/index.html @@ -176,15 +176,27 @@ select{background:#313244;border:1px solid #45475a;color:#cdd6f4;padding:2px 4px diff --git a/Tools/gui_client/src/main.rs b/Tools/gui_client/src/main.rs index 9a44c15..3d1d388 100644 --- a/Tools/gui_client/src/main.rs +++ b/Tools/gui_client/src/main.rs @@ -91,6 +91,7 @@ struct ConnectionConfig { tcp_port: String, udp_port: String, log_port: String, + auto_ports: bool, // when true, SERVICE_INFO may override udp_port / log_port version: u64, } @@ -314,6 +315,7 @@ impl MarteDebugApp { tcp_port: "8080".to_string(), udp_port: "8081".to_string(), log_port: "8082".to_string(), + auto_ports: true, version: 0, }; let shared_config = Arc::new(Mutex::new(config.clone())); @@ -1102,7 +1104,7 @@ fn udp_worker( thread::sleep(std::time::Duration::from_secs(1)); continue; }; - let mut buf = [0u8; 4096]; + let mut buf = [0u8; 65535]; let mut total_packets = 0u64; loop { if shared_config.lock().unwrap().version != current_version { @@ -1360,23 +1362,25 @@ impl eframe::App for MarteDebugApp { let _ = self.tx_cmd.send("DISCOVER".to_string()); } InternalEvent::ServiceConfig { udp_port, log_port } => { - let mut changed = false; - if !udp_port.is_empty() && self.config.udp_port != udp_port { - self.config.udp_port = udp_port; - changed = true; - } - if !log_port.is_empty() && self.config.log_port != log_port { - self.config.log_port = log_port; - changed = true; - } - if changed { - self.config.version += 1; - *self.shared_config.lock().unwrap() = self.config.clone(); - self.logs.push_back(LogEntry { - time: Local::now().format("%H:%M:%S").to_string(), - level: "GUI_INFO".to_string(), - message: format!("Config updated from server: UDP={}, LOG={}", self.config.udp_port, self.config.log_port), - }); + if self.config.auto_ports { + let mut changed = false; + if !udp_port.is_empty() && self.config.udp_port != udp_port { + self.config.udp_port = udp_port; + changed = true; + } + if !log_port.is_empty() && self.config.log_port != log_port { + self.config.log_port = log_port; + changed = true; + } + if changed { + self.config.version += 1; + *self.shared_config.lock().unwrap() = self.config.clone(); + self.logs.push_back(LogEntry { + time: Local::now().format("%H:%M:%S").to_string(), + level: "GUI_INFO".to_string(), + message: format!("Ports auto-configured: UDP={}, LOG={}", self.config.udp_port, self.config.log_port), + }); + } } } InternalEvent::Disconnected => { @@ -1942,14 +1946,17 @@ impl eframe::App for MarteDebugApp { ui.label("IP:"); ui.text_edit_singleline(&mut self.config.ip); ui.end_row(); - ui.label("Control:"); + ui.label("Control TCP:"); ui.text_edit_singleline(&mut self.config.tcp_port); ui.end_row(); - ui.label("Telemetry (Auto):"); - ui.label(&self.config.udp_port); + ui.label("Telemetry UDP:"); + ui.add_enabled(!self.config.auto_ports, egui::TextEdit::singleline(&mut self.config.udp_port)); ui.end_row(); - ui.label("Logs (Auto):"); - ui.label(&self.config.log_port); + ui.label("Log TCP:"); + ui.add_enabled(!self.config.auto_ports, egui::TextEdit::singleline(&mut self.config.log_port)); + ui.end_row(); + ui.label("Auto ports:"); + ui.checkbox(&mut self.config.auto_ports, "from SERVICE_INFO"); ui.end_row(); }); if ui.button("🔄 Apply").clicked() { diff --git a/compile_commands.json b/compile_commands.json index c8aabcd..fec99cf 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -2,24 +2,24 @@ { "file": "TcpLogger.cpp", "arguments": [ - "g++", + "/usr/bin/g++", "-c", "-I.", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Logger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4LoggerService", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L3Streams", "-fPIC", "-Wall", "-std=c++98", @@ -47,25 +47,26 @@ { "file": "DebugService.cpp", "arguments": [ - "g++", + "/usr/bin/g++", "-c", "-I../../../..//Source/Core/Types/Result", "-I../../../..//Source/Core/Types/Vec", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", + "-I../../../..//Source/Components/Interfaces/TCPLogger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Logger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4LoggerService", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L3Streams", "-fPIC", "-Wall", "-std=c++98", @@ -91,29 +92,28 @@ "output": "../../../..//Build/x86-linux/Components/Interfaces/DebugService/DebugService.o" }, { - "file": "UnitTests.cpp", + "file": "DebugServiceBase.cpp", "arguments": [ - "g++", + "/usr/bin/g++", "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", + "-I../../../..//Source/Core/Types/Result", + "-I../../../..//Source/Core/Types/Vec", + "-I../../../..//Source/Components/Interfaces/TCPLogger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Logger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4LoggerService", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L3Streams", "-fPIC", "-Wall", "-std=c++98", @@ -131,38 +131,35 @@ "-Wno-unused-value", "-g", "-ggdb", - "UnitTests.cpp", + "DebugServiceBase.cpp", "-o", - "../../Build/x86-linux/Test/UnitTests/UnitTests/UnitTests.o" + "../../../..//Build/x86-linux/Components/Interfaces/DebugService/DebugServiceBase.o" ], - "directory": "/home/martino/Projects/marte_debug/Test/UnitTests", - "output": "../../Build/x86-linux/Test/UnitTests/UnitTests/UnitTests.o" + "directory": "/home/martino/Projects/marte_debug/Source/Components/Interfaces/DebugService", + "output": "../../../..//Build/x86-linux/Components/Interfaces/DebugService/DebugServiceBase.o" }, { - "file": "SchedulerTest.cpp", + "file": "WebDebugService.cpp", "arguments": [ - "g++", + "/usr/bin/g++", "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L6App", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", + "-I../../../..//Source/Components/Interfaces/TCPLogger", + "-I../../../..//Source/Components/Interfaces/DebugService", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Logger", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration", + "-I/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4Messages", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L4LoggerService", + "-I/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability", + "-I/home/martino/workspace/MARTe2/Source/Core/FileSystem/L3Streams", "-fPIC", "-Wall", "-std=c++98", @@ -180,207 +177,11 @@ "-Wno-unused-value", "-g", "-ggdb", - "SchedulerTest.cpp", + "WebDebugService.cpp", "-o", - "../../Build/x86-linux/Test/Integration/Integration/SchedulerTest.o" + "../../../..//Build/x86-linux/Components/Interfaces/WebDebugService/WebDebugService.o" ], - "directory": "/home/martino/Projects/marte_debug/Test/Integration", - "output": "../../Build/x86-linux/Test/Integration/Integration/SchedulerTest.o" - }, - { - "file": "TraceTest.cpp", - "arguments": [ - "g++", - "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L6App", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", - "-fPIC", - "-Wall", - "-std=c++98", - "-Werror", - "-Wno-invalid-offsetof", - "-Wno-unused-variable", - "-fno-strict-aliasing", - "-frtti", - "-DMARTe2_TEST_ENVIRONMENT=GTest", - "-DARCHITECTURE=x86_gcc", - "-DENVIRONMENT=Linux", - "-DUSE_PTHREAD", - "-pthread", - "-Wno-deprecated-declarations", - "-Wno-unused-value", - "-g", - "-ggdb", - "TraceTest.cpp", - "-o", - "../../Build/x86-linux/Test/Integration/Integration/TraceTest.o" - ], - "directory": "/home/martino/Projects/marte_debug/Test/Integration", - "output": "../../Build/x86-linux/Test/Integration/Integration/TraceTest.o" - }, - { - "file": "ValidationTest.cpp", - "arguments": [ - "g++", - "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L6App", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", - "-fPIC", - "-Wall", - "-std=c++98", - "-Werror", - "-Wno-invalid-offsetof", - "-Wno-unused-variable", - "-fno-strict-aliasing", - "-frtti", - "-DMARTe2_TEST_ENVIRONMENT=GTest", - "-DARCHITECTURE=x86_gcc", - "-DENVIRONMENT=Linux", - "-DUSE_PTHREAD", - "-pthread", - "-Wno-deprecated-declarations", - "-Wno-unused-value", - "-g", - "-ggdb", - "ValidationTest.cpp", - "-o", - "../../Build/x86-linux/Test/Integration/Integration/ValidationTest.o" - ], - "directory": "/home/martino/Projects/marte_debug/Test/Integration", - "output": "../../Build/x86-linux/Test/Integration/Integration/ValidationTest.o" - }, - { - "file": "ConfigCommandTest.cpp", - "arguments": [ - "g++", - "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L6App", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", - "-fPIC", - "-Wall", - "-std=c++98", - "-Werror", - "-Wno-invalid-offsetof", - "-Wno-unused-variable", - "-fno-strict-aliasing", - "-frtti", - "-DMARTe2_TEST_ENVIRONMENT=GTest", - "-DARCHITECTURE=x86_gcc", - "-DENVIRONMENT=Linux", - "-DUSE_PTHREAD", - "-pthread", - "-Wno-deprecated-declarations", - "-Wno-unused-value", - "-g", - "-ggdb", - "ConfigCommandTest.cpp", - "-o", - "../../Build/x86-linux/Test/Integration/Integration/ConfigCommandTest.o" - ], - "directory": "/home/martino/Projects/marte_debug/Test/Integration", - "output": "../../Build/x86-linux/Test/Integration/Integration/ConfigCommandTest.o" - }, - { - "file": "IntegrationTests.cpp", - "arguments": [ - "g++", - "-c", - "-I../../Source/Core/Types/Result", - "-I../../Source/Core/Types/Vec", - "-I../../Source/Components/Interfaces/DebugService", - "-I../../Source/Components/Interfaces/TCPLogger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L0Types", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L2Objects", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L3Streams", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Logger", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L4Configuration", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/BareMetal/L6App", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L3Services", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4Messages", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L4LoggerService", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/Scheduler/L5GAMs", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L1Portability", - "-I/home/martino/Projects/marte_debug/dependency/MARTe2/Source/Core/FileSystem/L3Streams", - "-fPIC", - "-Wall", - "-std=c++98", - "-Werror", - "-Wno-invalid-offsetof", - "-Wno-unused-variable", - "-fno-strict-aliasing", - "-frtti", - "-DMARTe2_TEST_ENVIRONMENT=GTest", - "-DARCHITECTURE=x86_gcc", - "-DENVIRONMENT=Linux", - "-DUSE_PTHREAD", - "-pthread", - "-Wno-deprecated-declarations", - "-Wno-unused-value", - "-g", - "-ggdb", - "IntegrationTests.cpp", - "-o", - "../../Build/x86-linux/Test/Integration/Integration/IntegrationTests.o" - ], - "directory": "/home/martino/Projects/marte_debug/Test/Integration", - "output": "../../Build/x86-linux/Test/Integration/Integration/IntegrationTests.o" + "directory": "/home/martino/Projects/marte_debug/Source/Components/Interfaces/WebDebugService", + "output": "../../../..//Build/x86-linux/Components/Interfaces/WebDebugService/WebDebugService.o" } ] \ No newline at end of file diff --git a/env.sh b/env.sh index e5a09dc..60a76e5 100644 --- a/env.sh +++ b/env.sh @@ -2,8 +2,8 @@ # Get the directory of this script DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -export MARTe2_DIR=$DIR/dependency/MARTe2 -export MARTe2_Components_DIR=$DIR/dependency/MARTe2-components +export MARTe2_DIR=$HOME/workspace/MARTe2 +export MARTe2_Components_DIR=$HOME/workspace/MARTe2-components export TARGET=x86-linux export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_DIR/Build/$TARGET/Core export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/$TARGET/Components