6cedaa10dc
tests / build-and-test (push) Failing after 32s
New TraceStore keyed by TRID; each entry is a TraceConfig with
DSPER + TOTSMP + REPGSZ + SVID list. S2F23 validates that every SVID
exists (TIAACK=4 otherwise) and registers the trace.
S6F1's body is L,4 of {TRID U4, SMPLN U4, STIME ASCII, list_of <Item>}
— the application chooses whether each value Item is a scalar SVID
value or a packed batch.
The periodic sampling timer that turns an active TraceConfig into
S6F1 emissions is intentionally left to the application (E5 doesn't
mandate a specific scheduler and vendors typically already have one).
Four new SxFy in the catalog.
COMPLIANCE.md: Trace Data Collection Additional capability flips ✅.
Tests: 82 cases / 477 assertions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
59 lines
1.6 KiB
C++
59 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
// E30 §6.12 Trace Data Collection.
|
|
//
|
|
// Host sends S2F23 with (TRID, DSPER, TOTSMP, REPGSZ, SVID list); equipment
|
|
// is supposed to sample those SVIDs every DSPER, batch them in groups of
|
|
// REPGSZ, and emit each batch as S6F1. This store keeps the *configuration*
|
|
// for each active TRID — the periodic sampling itself is intentionally left
|
|
// to the application so equipment vendors can hook into whatever clock /
|
|
// scheduler they already use.
|
|
|
|
namespace secsgem::gem {
|
|
|
|
enum class TraceAck : uint8_t { // S2F24 TIAACK
|
|
Accept = 0,
|
|
TooManySvids = 1,
|
|
NoMoreTracesAllowed = 2,
|
|
InvalidPeriod = 3,
|
|
UnknownVid = 4,
|
|
};
|
|
|
|
struct TraceConfig {
|
|
uint32_t trid;
|
|
std::string dsper; // sample period (E5: ASCII, e.g. "1000" = ms)
|
|
uint32_t totsmp; // total samples to collect
|
|
uint32_t repgsz; // samples per S6F1 batch
|
|
std::vector<uint32_t> svids;
|
|
};
|
|
|
|
class TraceStore {
|
|
public:
|
|
void add(TraceConfig c) { by_trid_.insert_or_assign(c.trid, std::move(c)); }
|
|
std::optional<TraceConfig> get(uint32_t trid) const {
|
|
auto it = by_trid_.find(trid);
|
|
if (it == by_trid_.end()) return std::nullopt;
|
|
return it->second;
|
|
}
|
|
void remove(uint32_t trid) { by_trid_.erase(trid); }
|
|
std::vector<TraceConfig> all() const {
|
|
std::vector<TraceConfig> out;
|
|
out.reserve(by_trid_.size());
|
|
for (const auto& [_, c] : by_trid_) out.push_back(c);
|
|
return out;
|
|
}
|
|
std::size_t size() const { return by_trid_.size(); }
|
|
|
|
private:
|
|
std::map<uint32_t, TraceConfig> by_trid_;
|
|
};
|
|
|
|
} // namespace secsgem::gem
|