Files
whetstone_DSL/editor/src/LeakCorruptionSignalBridge.h

155 lines
5.6 KiB
C++

#pragma once
// Step 567: Leak/Corruption Signal Bridge
#include "DebugValidationUtil.h"
#include <algorithm>
#include <cstdint>
#include <string>
#include <vector>
enum class MemorySignalType {
LeakSuspected,
LeakConfirmed,
CorruptionSuspected,
CorruptionConfirmed
};
enum class MemorySignalSeverity {
Info = 0,
Warning = 1,
Error = 2,
Critical = 3
};
struct MemorySignalRecord {
std::string signalId;
std::string sessionId;
std::string allocationId;
MemorySignalType type = MemorySignalType::LeakSuspected;
std::string message;
std::uint64_t timestamp = 0;
};
struct MemoryDiagnosticRecord {
std::string diagnosticId;
std::string sessionId;
std::string allocationId;
std::string paneKey;
std::string message;
MemorySignalSeverity severity = MemorySignalSeverity::Info;
std::uint64_t timestamp = 0;
};
class LeakCorruptionSignalBridge {
public:
bool ingestSignal(const MemorySignalRecord& signal, std::string* error) {
if (!error) return false;
error->clear();
if (!hasRequiredDebugIds(signal.signalId, signal.sessionId)) return fail(error, "signal_or_session_missing");
if (signal.allocationId.empty()) return fail(error, "allocation_id_missing");
if (signal.message.empty()) return fail(error, "signal_message_missing");
if (signal.timestamp == 0) return fail(error, "signal_timestamp_invalid");
if (containsSignal(signal.signalId)) return fail(error, "signal_duplicate");
signals_.push_back(signal);
diagnostics_.push_back(buildDiagnostic(signal));
stableSortByTimestamp(&signals_);
stableSortByTimestamp(&diagnostics_);
return true;
}
std::vector<MemoryDiagnosticRecord> diagnosticsForSession(const std::string& sessionId) const {
std::vector<MemoryDiagnosticRecord> filtered;
for (const auto& diagnostic : diagnostics_) {
if (sessionId.empty() || diagnostic.sessionId == sessionId) filtered.push_back(diagnostic);
}
return filtered;
}
std::vector<MemorySignalRecord> signalsForAllocation(const std::string& allocationId) const {
std::vector<MemorySignalRecord> filtered;
for (const auto& signal : signals_) {
if (allocationId.empty() || signal.allocationId == allocationId) filtered.push_back(signal);
}
return filtered;
}
MemorySignalSeverity highestSeverityForSession(const std::string& sessionId) const {
MemorySignalSeverity highest = MemorySignalSeverity::Info;
for (const auto& diagnostic : diagnostics_) {
if (!sessionId.empty() && diagnostic.sessionId != sessionId) continue;
if (static_cast<int>(diagnostic.severity) > static_cast<int>(highest)) highest = diagnostic.severity;
}
return highest;
}
private:
std::vector<MemorySignalRecord> signals_;
std::vector<MemoryDiagnosticRecord> diagnostics_;
static bool fail(std::string* error, const char* code) {
*error = code;
return false;
}
bool containsSignal(const std::string& signalId) const {
for (const auto& signal : signals_) {
if (signal.signalId == signalId) return true;
}
return false;
}
static MemoryDiagnosticRecord buildDiagnostic(const MemorySignalRecord& signal) {
MemoryDiagnosticRecord diagnostic;
diagnostic.diagnosticId = "diag-" + signal.signalId;
diagnostic.sessionId = signal.sessionId;
diagnostic.allocationId = signal.allocationId;
diagnostic.message = signal.message;
diagnostic.timestamp = signal.timestamp;
diagnostic.paneKey = paneForSignal(signal.type);
diagnostic.severity = severityForSignal(signal.type);
return diagnostic;
}
static std::string paneForSignal(MemorySignalType type) {
switch (type) {
case MemorySignalType::LeakSuspected:
case MemorySignalType::LeakConfirmed:
return "memory-leaks";
case MemorySignalType::CorruptionSuspected:
case MemorySignalType::CorruptionConfirmed:
return "memory-corruption";
}
return "memory-diagnostics";
}
static MemorySignalSeverity severityForSignal(MemorySignalType type) {
switch (type) {
case MemorySignalType::LeakSuspected: return MemorySignalSeverity::Warning;
case MemorySignalType::LeakConfirmed: return MemorySignalSeverity::Error;
case MemorySignalType::CorruptionSuspected: return MemorySignalSeverity::Error;
case MemorySignalType::CorruptionConfirmed: return MemorySignalSeverity::Critical;
}
return MemorySignalSeverity::Info;
}
static void stableSortByTimestamp(std::vector<MemorySignalRecord>* signals) {
std::stable_sort(signals->begin(),
signals->end(),
[](const MemorySignalRecord& a, const MemorySignalRecord& b) {
if (a.timestamp != b.timestamp) return a.timestamp < b.timestamp;
return a.signalId < b.signalId;
});
}
static void stableSortByTimestamp(std::vector<MemoryDiagnosticRecord>* diagnostics) {
std::stable_sort(diagnostics->begin(),
diagnostics->end(),
[](const MemoryDiagnosticRecord& a, const MemoryDiagnosticRecord& b) {
if (a.timestamp != b.timestamp) return a.timestamp < b.timestamp;
return a.diagnosticId < b.diagnosticId;
});
}
};