skip to content
==> include/mesh/top_snap.h <==
1/* @ajax/mesh-top-snap: a parsed `snap` reply in mesh-abi's snapshot layout (crates/mesh-top
2 * src/snap.rs): a header, the mailbox header, one section per non-empty program slot (table
3 * entry, control lines, manifest extension, node records, view prefix) and the host status block.
4 * Accessors take mesh-abi offsets, never literals; reads out of range give 0. The section builder
5 * and mt_snapshot_assemble are the inverse, for the mock and the tests. */
6#ifndef MESH_TOP_SNAP_H
7#define MESH_TOP_SNAP_H
8
9#include "mesh/abi.h"
10
11#include <stdbool.h>
12#include <stddef.h>
13#include <stdint.h>
14
15/* ---- little-endian helpers on byte slices (reads out of range give 0) */
16uint32_t mt_get_u32(const uint8_t *b, size_t len, size_t at);
17uint64_t mt_get_u64(const uint8_t *b, size_t len, size_t at);
18float mt_get_f32(const uint8_t *b, size_t len, size_t at);
19/* A NUL-padded string field, repaired as String::from_utf8_lossy: out holds at least 3 * n + 1. */
20void mt_get_str(const uint8_t *b, size_t len, size_t at, size_t n, char *out);
21void mt_put_u32(uint8_t *b, size_t at, uint32_t v);
22void mt_put_u64(uint8_t *b, size_t at, uint64_t v);
23void mt_put_f32(uint8_t *b, size_t at, float v);
24/* put_str: s cut to n - 1 bytes, the rest zeroed. */
25void mt_put_str(uint8_t *b, size_t at, size_t n, const char *s);
26
27typedef struct {
28    uint32_t sm, heartbeat, tasks, last_op;
29    uint64_t busy_ns;
30} mt_node;
31
32typedef struct {
33    char name[3 * (MESH_FD_NAME_MAX + 1) + 1];
34    uint32_t ty;
35    size_t off;
36} mt_field;
37
38typedef struct {
39    uint8_t *bytes;
40    size_t len;
41} mt_section;
42
43/* ---- the section builder (owned bytes; free with mt_section_free) */
44mt_section mt_section_new(uint32_t slot, uint32_t nodes, uint32_t view);
45void mt_section_free(mt_section *s);
46mt_section mt_section_clone(const mt_section *s);
47
48uint32_t mt_section_slot(const mt_section *s);
49size_t mt_section_nodes(const mt_section *s);
50uint8_t *mt_section_entry(const mt_section *s); /* MESH_PT_BYTES */
51uint8_t *mt_section_ctl(const mt_section *s);   /* MESH_SC_CTL_BYTES */
52uint8_t *mt_section_ext(const mt_section *s);   /* MESH_PX_BYTES */
53uint8_t *mt_section_node_rec(const mt_section *s, size_t n); /* MESH_NODE_STRIDE */
54uint8_t *mt_section_view(const mt_section *s);
55size_t mt_section_view_len(const mt_section *s);
56
57/* The name (out: 3 * MESH_NAME_BYTES + 1 bytes). */
58void mt_section_name(const mt_section *s, char *out);
59bool mt_section_name_is(const mt_section *s, const char *name);
60uint32_t mt_section_state(const mt_section *s);
61const char *mt_section_state_name(const mt_section *s);
62bool mt_section_running(const mt_section *s);
63uint32_t mt_section_pt(const mt_section *s, size_t off);
64uint64_t mt_section_ptx_hash(const mt_section *s);
65uint32_t mt_section_p(const mt_section *s, size_t off);
66uint64_t mt_section_p64(const mt_section *s, size_t off);
67bool mt_section_native(const mt_section *s);
68uint32_t mt_section_counter(const mt_section *s, size_t i);
69void mt_section_counter_name(const mt_section *s, size_t i, char *out); /* 3 * MESH_NAME_BYTES + 1 */
70/* The manifest fields (at most MESH_MAX_FIELDS); returns the count. */
71size_t mt_section_fields(const mt_section *s, mt_field *out);
72/* A field's value from the view prefix, as text; "-" when snap_bytes doesn't cover it. */
73void mt_section_field_value(const mt_section *s, const mt_field *f, char *out, size_t cap);
74mt_node mt_section_node(const mt_section *s, size_t n);
75uint32_t mt_section_view_u32(const mt_section *s, size_t off);
76float mt_section_view_f32(const mt_section *s, size_t off);
77
78typedef struct {
79    uint8_t *bytes;
80    size_t len;
81    mt_section *sections;
82    size_t nsections;
83} mt_snapshot;
84
85/* Validates the framing completely (any inconsistency is refused, with *err a message to free).
86 * Copies the bytes. */
87bool mt_snapshot_parse(const uint8_t *bytes, size_t len, mt_snapshot *out, char **err);
88/* Builds a snapshot: head is the mailbox header (MESH_H_BYTES), host the host block (MESH_SNAP_HOST);
89 * sections are copied and sorted by slot. */
90mt_snapshot mt_snapshot_assemble(const uint8_t *head, const mt_section *sections, size_t n, const uint8_t *host);
91mt_snapshot mt_snapshot_clone(const mt_snapshot *s);
92void mt_snapshot_free(mt_snapshot *s);
93
94const mt_section *mt_snapshot_by_name(const mt_snapshot *s, const char *name);
95const mt_section *mt_snapshot_by_slot(const mt_snapshot *s, uint32_t slot);
96uint32_t mt_snapshot_nodes_online(const mt_snapshot *s);
97uint32_t mt_snapshot_head(const mt_snapshot *s, size_t off);
98const uint8_t *mt_snapshot_host(const mt_snapshot *s);
99uint32_t mt_snapshot_host_u32(const mt_snapshot *s, size_t off);
100uint64_t mt_snapshot_host_u64(const mt_snapshot *s, size_t off);
101float mt_snapshot_host_f32(const mt_snapshot *s, size_t off);
102void mt_snapshot_host_str(const mt_snapshot *s, size_t off, size_t n, char *out); /* 3n + 1 */
103void mt_snapshot_hostname(const mt_snapshot *s, char out[97]);
104void mt_snapshot_gpu(const mt_snapshot *s, char out[97]);
105float mt_snapshot_rate(const mt_snapshot *s, uint32_t slot);
106/* This machine's system id (false: single). */
107bool mt_snapshot_system(const mt_snapshot *s, uint32_t *k);
108uint32_t mt_snapshot_systems(const mt_snapshot *s);
109uint64_t mt_snapshot_uptime_ms(const mt_snapshot *s);
110
111typedef struct {
112    uint32_t system, state, cc, sms, sms_total, blocks_per_sm;
113    float rtt_us, wait_us;
114    uint32_t rounds;
115    uint64_t round;
116    char gpu[97], arch[49], host[97];
117    uint32_t backend;
118} mt_member;
119mt_member mt_snapshot_member(const mt_snapshot *s, uint32_t k);
120/* Every member record (none when single); returns the count (at most MESH_MAX_SYSTEMS). */
121size_t mt_snapshot_members(const mt_snapshot *s, mt_member *out);
122
123typedef struct {
124    uint32_t status, group;
125    uint64_t applied, heard_ms;
126    char reason[121];
127} mt_fleet_member;
128
129typedef struct {
130    char name[3 * MESH_NAME_BYTES + 1];
131    uint32_t epoch, cycle, mask;
132    uint8_t order[MESH_MAX_SYSTEMS];
133    bool running;
134    uint32_t local, rank;
135    bool reform;
136    uint32_t auto_ms;
137} mt_fleet_group;
138
139typedef struct {
140    bool has_leader;
141    uint32_t leader, role;
142    uint64_t term, version, applied;
143    uint32_t up, suspect, quorum, flags, dead_ms;
144    size_t nmembers;
145    mt_fleet_member members[MESH_MAX_SYSTEMS];
146    bool has_group;
147    mt_fleet_group group;
148} mt_fleet;
149bool mt_snapshot_fleet(const mt_snapshot *s, mt_fleet *out); /* false when single */
150
151typedef struct {
152    uint32_t active, total;
153    uint64_t done, failed;
154    uint32_t leased;
155    float rate;
156    uint64_t dupes;
157    uint32_t flags, held;
158} mt_jobs;
159mt_jobs mt_snapshot_jobs(const mt_snapshot *s);
160
161/* A value that may be absent (Rust's Option<f32>). */
162typedef struct {
163    bool some;
164    float v;
165} mt_opt_f32;
166
167typedef struct {
168    uint64_t at_ms, age_ms;
169    uint32_t samples, flags;
170    mt_opt_f32 share, share10;
171    float slice_us, gap_us, max_gap_us, gaps_s, observed;
172    mt_opt_f32 util_ext;
173    float queue_us;
174    mt_opt_f32 inflate;
175    float cpu, cpu_big, cpu_little, iowait;
176    float loadavg[3];
177    uint32_t cpus, cpus_big, cpus_little;
178    bool has_psi;
179    float psi[5];
180    uint32_t mem_total_mb, mem_avail_mb;
181    float mem_free;
182    uint32_t swap_total_mb, swap_used_mb;
183    float swap_out_s;
184    uint32_t compressed_mb;
185    bool has_mem_level;
186    uint32_t mem_level;
187    float meshd_cpu, meshd_rss_mb;
188    uint32_t meshd_threads, disk_free_mb, disk_total_mb;
189    bool has_thermal;
190    uint32_t thermal;
191    mt_opt_f32 temp_c;
192    size_t ncores;
193    uint8_t cores[MESH_MAX_CPUS][2]; /* (busy percent or 0xff, CORE_*) */
194} mt_load;
195bool mt_snapshot_load(const mt_snapshot *s, mt_load *out); /* false before the first sample */
196
197typedef struct {
198    uint32_t flags;
199    mt_opt_f32 share, share10;
200    float slice_us, gap_us, max_gap_us, observed;
201    uint32_t lat_n;
202    mt_opt_f32 p50_us, p90_us, p99_us, max_us, task_us;
203    float tasks_s, busy, queue_us;
204} mt_prog_load;
205bool mt_snapshot_prog_load(const mt_snapshot *s, uint32_t slot, mt_prog_load *out);
206
207typedef struct {
208    uint64_t age_ms;
209    uint32_t flags;
210    mt_opt_f32 share, share10;
211    float max_gap_us, cpu, cpu_big, cpu_little;
212    mt_opt_f32 psi_cpu, psi_mem;
213    float meshd_cpu;
214    uint32_t mem_avail_mb, mem_total_mb, disk_free_mb, cpus_big, cpus_little;
215} mt_member_load;
216bool mt_snapshot_member_load(const mt_snapshot *s, uint32_t k, mt_member_load *out);
217
218typedef struct {
219    uint32_t system;
220    uint64_t rx_bytes, tx_bytes;
221    uint64_t rx_frames[MESH_NET_KINDS], tx_frames[MESH_NET_KINDS];
222    char local[97], iface[49];
223} mt_link_stat;
224mt_link_stat mt_snapshot_link(const mt_snapshot *s, uint32_t k);
225
226/* The NI_* counters in this order: rx/tx bytes, rx/tx packets, rx/tx errors, rx/tx drops. */
227extern const size_t MT_NIC_COUNTERS[8];
228
229typedef struct {
230    char name[49];
231    uint64_t v[8];
232    uint32_t links, count;
233} mt_nic;
234/* The last NIC sample: (uptime ms when taken, samples taken). */
235void mt_snapshot_net_at(const mt_snapshot *s, uint64_t *at_ms, uint32_t *samples);
236size_t mt_snapshot_nics(const mt_snapshot *s, mt_nic *out); /* at most MESH_MAX_NICS */
237mt_nic mt_snapshot_net_total(const mt_snapshot *s);
238/* The control port's (rx, tx, requests) and the HTTP relay's (rx, tx, connections). */
239void mt_snapshot_ports(const mt_snapshot *s, uint64_t ctl[3], uint64_t http[3]);
240/* The lockstep program's consistent (name, step, view prefix). */
241void mt_snapshot_lock_pair(const mt_snapshot *s, char name[3 * MESH_NAME_BYTES + 1], uint64_t *step, uint8_t view[32]);
242
243/* The GPU column: "12.1", "apple9", "metal". out holds 32. */
244void mt_gpu_label(uint32_t cc, uint32_t backend, char *out);
245void mt_blocks_label(uint32_t blocks, uint32_t backend, char *out);
246void mt_cc_label(uint32_t cc, char *out);
247
248typedef struct {
249    uint32_t slot, node, op, ticket, start, end;
250} mt_rec;
251static inline uint32_t mt_rec_ns(const mt_rec *r) { return r->end - r->start; }
252
253typedef struct {
254    uint32_t slot, n;
255    mt_rec *recs; /* malloc'd, oldest first */
256    size_t nrecs;
257} mt_trace_prog;
258/* A `trace` reply: per non-empty slot, u32 slot, u32 P_TRACE_N, then its ring. *out is malloc'd
259 * (free with mt_trace_free). False with *err (to free) on a bad reply. */
260bool mt_parse_trace(const uint8_t *b, size_t len, mt_trace_prog **out, size_t *n, char **err);
261void mt_trace_free(mt_trace_prog *t, size_t n);
262/* The q-quantile (0..=1) of task durations in µs; false without records. */
263bool mt_quantile_us(const mt_rec *recs, size_t n, double q, double *out);
264
265#endif