Fixed issues with config and tracing
This commit is contained in:
@@ -26,6 +26,30 @@
|
||||
|
||||
namespace MARTe {
|
||||
|
||||
// Recursive search for any object with a given name anywhere in the registry.
|
||||
// Used to find GAMs regardless of nesting level.
|
||||
static Reference FindByNameRecursive(ReferenceContainer *container,
|
||||
const char8 *name) {
|
||||
if (container == NULL_PTR(ReferenceContainer *))
|
||||
return Reference();
|
||||
uint32 n = container->Size();
|
||||
for (uint32 i = 0; i < n; i++) {
|
||||
Reference child = container->Get(i);
|
||||
if (!child.IsValid())
|
||||
continue;
|
||||
if (StringHelper::Compare(child->GetName(), name) == 0)
|
||||
return child;
|
||||
ReferenceContainer *sub =
|
||||
dynamic_cast<ReferenceContainer *>(child.operator->());
|
||||
if (sub != NULL_PTR(ReferenceContainer *)) {
|
||||
Reference found = FindByNameRecursive(sub, name);
|
||||
if (found.IsValid())
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return Reference();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper for optimized signal processing within brokers.
|
||||
*/
|
||||
@@ -126,21 +150,14 @@ public:
|
||||
(direction == InputSignals) ? "InputSignals" : "OutputSignals";
|
||||
const char8 *dirStrShort = (direction == InputSignals) ? "In" : "Out";
|
||||
|
||||
// Try to find the GAM with different path variations
|
||||
// Search recursively through the entire registry for the GAM by name.
|
||||
// Direct Find("GAM1") only checks top-level; the GAM may be nested
|
||||
// several levels deep inside a RealTimeApplication container.
|
||||
Reference gamRef =
|
||||
ObjectRegistryDatabase::Instance()->Find(functionName);
|
||||
if (!gamRef.IsValid()) {
|
||||
// Try with "App.Functions." prefix
|
||||
StreamString tryPath;
|
||||
tryPath.Printf("App.Functions.%s", functionName);
|
||||
gamRef = ObjectRegistryDatabase::Instance()->Find(tryPath.Buffer());
|
||||
}
|
||||
if (!gamRef.IsValid()) {
|
||||
// Try with "Functions." prefix
|
||||
StreamString tryPath;
|
||||
tryPath.Printf("Functions.%s", functionName);
|
||||
gamRef = ObjectRegistryDatabase::Instance()->Find(tryPath.Buffer());
|
||||
}
|
||||
FindByNameRecursive(ObjectRegistryDatabase::Instance(),
|
||||
functionName);
|
||||
fprintf(stderr, ">> GAM lookup '%s': %s\n", functionName,
|
||||
gamRef.IsValid() ? "FOUND" : "NOT FOUND");
|
||||
|
||||
if (gamRef.IsValid()) {
|
||||
StreamString absGamPath;
|
||||
|
||||
@@ -93,6 +93,7 @@ DebugService::DebugService()
|
||||
isServer = false;
|
||||
suppressTimeoutLogs = true;
|
||||
isPaused = false;
|
||||
manualConfigSet = false;
|
||||
activeClient = NULL_PTR(BasicTCPSocket *);
|
||||
}
|
||||
|
||||
@@ -157,18 +158,10 @@ bool DebugService::Initialise(StructuredDataI &data) {
|
||||
suppressTimeoutLogs = (suppress == 1);
|
||||
}
|
||||
|
||||
// Try to capture full configuration autonomously if data is a
|
||||
// ConfigurationDatabase
|
||||
ConfigurationDatabase *cdb = dynamic_cast<ConfigurationDatabase *>(&data);
|
||||
if (cdb != NULL_PTR(ConfigurationDatabase *)) {
|
||||
// Save current position
|
||||
StreamString currentPath;
|
||||
// In MARTe2 ConfigurationDatabase there isn't a direct GetCurrentPath,
|
||||
// but we can at least try to copy from root if we are at root.
|
||||
// For now, we rely on explicit SetFullConfig or documentary injection.
|
||||
}
|
||||
|
||||
// Copy local branch as fallback
|
||||
// Do NOT call MoveToRoot() on the shared CDB here — that corrupts the
|
||||
// ReferenceContainer::Initialise() traversal cursor for sibling objects.
|
||||
// Just capture the local subtree; full config is rebuilt lazily from the
|
||||
// live ObjectRegistryDatabase when ServeConfig/EnrichWithConfig is called.
|
||||
(void)data.Copy(fullConfig);
|
||||
|
||||
if (isServer) {
|
||||
@@ -196,6 +189,50 @@ bool DebugService::Initialise(StructuredDataI &data) {
|
||||
void DebugService::SetFullConfig(ConfigurationDatabase &config) {
|
||||
config.MoveToRoot();
|
||||
config.Copy(fullConfig);
|
||||
manualConfigSet = true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool created = cdb.CreateRelative(name);
|
||||
if (!created) {
|
||||
if (!cdb.MoveRelative(name))
|
||||
continue;
|
||||
}
|
||||
|
||||
const char8 *className = child->GetClassProperties()->GetName();
|
||||
if (className != NULL_PTR(const char8 *))
|
||||
(void)cdb.Write("Class", className);
|
||||
|
||||
// Export the object's own properties (standard fields, parameters).
|
||||
// Custom config-file-only fields (PVName etc.) are not available here.
|
||||
(void)child->ExportData(cdb);
|
||||
|
||||
ReferenceContainer *sub =
|
||||
dynamic_cast<ReferenceContainer *>(child.operator->());
|
||||
if (sub != NULL_PTR(ReferenceContainer *))
|
||||
BuildCDBFromContainer(sub, cdb);
|
||||
|
||||
(void)cdb.MoveToAncestor(1u);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugService::RebuildConfigFromRegistry() {
|
||||
ConfigurationDatabase newConfig;
|
||||
BuildCDBFromContainer(ObjectRegistryDatabase::Instance(), newConfig);
|
||||
newConfig.MoveToRoot();
|
||||
newConfig.Copy(fullConfig);
|
||||
}
|
||||
|
||||
static void PatchItemInternal(const char8 *originalName,
|
||||
@@ -247,7 +284,7 @@ DebugSignalInfo *DebugService::RegisterSignal(void *memoryAddress,
|
||||
const char8 *name,
|
||||
uint8 numberOfDimensions,
|
||||
uint32 numberOfElements) {
|
||||
printf("<debug> registering: %s\n", name);
|
||||
fprintf(stderr, "<debug> RegisterSignal[%p]: %s\n", (void*)this, name);
|
||||
mutex.FastLock();
|
||||
DebugSignalInfo *res = NULL_PTR(DebugSignalInfo *);
|
||||
uint32 sigIdx = 0xFFFFFFFF;
|
||||
@@ -785,8 +822,13 @@ void DebugService::HandleCommand(StreamString cmd, BasicTCPSocket *client) {
|
||||
void DebugService::EnrichWithConfig(const char8 *path, StreamString &json) {
|
||||
if (path == NULL_PTR(const char8 *))
|
||||
return;
|
||||
if (!manualConfigSet) {
|
||||
RebuildConfigFromRegistry();
|
||||
}
|
||||
fullConfig.MoveToRoot();
|
||||
|
||||
fprintf(stderr, "[EnrichWithConfig] path=%s\n", path);
|
||||
|
||||
const char8 *current = path;
|
||||
bool ok = true;
|
||||
while (ok) {
|
||||
@@ -801,29 +843,49 @@ void DebugService::EnrichWithConfig(const char8 *path, StreamString &json) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// Normalise short direction names to both forms so we search consistently.
|
||||
// Paths use "In"/"Out" (alias convention); CDBs may store either form.
|
||||
bool found = false;
|
||||
|
||||
// 1. Try exact match (bare name - rebuilt-from-registry CDBs use this)
|
||||
if (fullConfig.MoveRelative(part.Buffer())) {
|
||||
// Found exact
|
||||
} else {
|
||||
bool found = false;
|
||||
fprintf(stderr, "[EnrichWithConfig] nav exact '%s' OK\n", part.Buffer());
|
||||
found = true;
|
||||
}
|
||||
|
||||
// 2. Try +name (raw config-file CDBs prefix nodes with '+')
|
||||
if (!found) {
|
||||
StreamString prefixed;
|
||||
prefixed.Printf("+%s", part.Buffer());
|
||||
if (fullConfig.MoveRelative(prefixed.Buffer())) {
|
||||
fprintf(stderr, "[EnrichWithConfig] nav prefixed '%s' OK\n", prefixed.Buffer());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Expand short direction aliases: In -> InputSignals / Out -> OutputSignals
|
||||
if (!found) {
|
||||
if (part == "In") {
|
||||
if (fullConfig.MoveRelative("InputSignals")) {
|
||||
fprintf(stderr, "[EnrichWithConfig] nav 'In'->InputSignals OK\n");
|
||||
found = true;
|
||||
} else if (fullConfig.MoveRelative("+InputSignals")) {
|
||||
fprintf(stderr, "[EnrichWithConfig] nav 'In'->+InputSignals OK\n");
|
||||
found = true;
|
||||
}
|
||||
} else if (part == "Out") {
|
||||
if (fullConfig.MoveRelative("OutputSignals")) {
|
||||
found = true;
|
||||
} else if (fullConfig.MoveRelative("+OutputSignals")) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
StreamString prefixed;
|
||||
prefixed.Printf("+%s", part.Buffer());
|
||||
if (fullConfig.MoveRelative(prefixed.Buffer())) {
|
||||
// Found prefixed
|
||||
} else {
|
||||
return; // Not found
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr, "[EnrichWithConfig] FAILED at part '%s'\n", part.Buffer());
|
||||
fullConfig.MoveToRoot();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,6 +948,14 @@ void DebugService::JsonifyDatabase(ConfigurationDatabase &db,
|
||||
void DebugService::ServeConfig(BasicTCPSocket *client) {
|
||||
if (client == NULL_PTR(BasicTCPSocket *))
|
||||
return;
|
||||
|
||||
// If no manual config was injected (test case), rebuild from the live registry.
|
||||
// In production, Initialise() only captures the DebugService subtree (to avoid
|
||||
// corrupting the shared CDB cursor), so we always need to rebuild here.
|
||||
if (!manualConfigSet) {
|
||||
RebuildConfigFromRegistry();
|
||||
}
|
||||
|
||||
StreamString json;
|
||||
fullConfig.MoveToRoot();
|
||||
JsonifyDatabase(fullConfig, json);
|
||||
@@ -930,6 +1000,7 @@ void DebugService::InfoNode(const char8 *path, BasicTCPSocket *client) {
|
||||
}
|
||||
EnrichWithConfig(path, json);
|
||||
} else {
|
||||
StreamString enrichAlias;
|
||||
mutex.FastLock();
|
||||
bool found = false;
|
||||
for (uint32 i = 0; i < aliases.Size(); i++) {
|
||||
@@ -941,13 +1012,21 @@ void DebugService::InfoNode(const char8 *path, BasicTCPSocket *client) {
|
||||
json.Printf("\"Name\": \"%s\", \"Class\": \"Signal\", \"Type\": "
|
||||
"\"%s\", \"ID\": %d",
|
||||
s->name.Buffer(), tname ? tname : "Unknown", s->internalID);
|
||||
EnrichWithConfig(aliases[i].name.Buffer(), json);
|
||||
enrichAlias = aliases[i].name;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr, "[InfoNode][%p] signal '%s' NOT found in %u aliases:\n", (void*)this, path, (uint32)aliases.Size());
|
||||
for (uint32 i = 0; i < aliases.Size(); i++) {
|
||||
fprintf(stderr, " alias[%u] = '%s'\n", i, aliases[i].name.Buffer());
|
||||
}
|
||||
}
|
||||
mutex.FastUnLock();
|
||||
if (!found)
|
||||
if (found)
|
||||
EnrichWithConfig(enrichAlias.Buffer(), json);
|
||||
else
|
||||
json += "\"Error\": \"Object not found\"";
|
||||
}
|
||||
json += "}\nOK INFO\n";
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
void ListNodes(const char8 *path, BasicTCPSocket *client);
|
||||
void ServeConfig(BasicTCPSocket *client);
|
||||
void SetFullConfig(ConfigurationDatabase &config);
|
||||
void RebuildConfigFromRegistry();
|
||||
|
||||
struct MonitoredSignal {
|
||||
ReferenceT<DataSourceI> dataSource;
|
||||
@@ -150,6 +151,7 @@ private:
|
||||
BasicTCPSocket *activeClient;
|
||||
|
||||
ConfigurationDatabase fullConfig;
|
||||
bool manualConfigSet;
|
||||
|
||||
static DebugService *instance;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user