1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! The on-disk dump format.
//!
//! A backbeat dump is self-describing: it carries the schema needed to decode its own records, so
//! the reader needs no compiled-in knowledge of the producing crate. The file is a small envelope
//! header pointing at a sequence of sections:
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────────┐
//! │ Envelope header │
//! │ magic[8] = b"BACKBEAT" │
//! │ format u16 = FORMAT_VERSION (governs the *envelope* only) │
//! │ flags u16 = endianness, etc. (see HeaderFlags) │
//! │ section_count u16 │
//! │ reserved u16 │
//! │ then `section_count` × SectionEntry { kind u16, _pad u16, │
//! │ offset u64, len u64 } │
//! ├─────────────────────────────────────────────────────────────────────┤
//! │ SCHEMA registry section │
//! │ for each event type compiled into the producer: │
//! │ { id u64, record_size u16, name, fields[] } │
//! │ (the serialized form of crate::schema::EventSchema) │
//! ├─────────────────────────────────────────────────────────────────────┤
//! │ INTERN table section(s) (optional) — one per instance │
//! │ { instance_id u64, (id u32 → bytes)* } — resolves Interned fields │
//! ├─────────────────────────────────────────────────────────────────────┤
//! │ SHARD section(s) — one per capture ring │
//! │ { instance_id u64, shard_id u32, head u64, capacity u64, │
//! │ region[capacity] } │
//! │ the raw ring snapshot; records are `[event_id u64][payload]` walked │
//! │ newest-first via the trailing length suffix (see crate::ring) │
//! ├─────────────────────────────────────────────────────────────────────┤
//! │ META section(s) (optional) — one per instance │
//! │ { instance_id u64, host label } — spans key on (instance_id, …) │
//! └─────────────────────────────────────────────────────────────────────┘
//! ```
//!
//! The format is inherently **multi-instance**: Meta, Intern, and Shard sections are each tagged
//! with the `instance_id` of the process that produced them, while the schema registry is unified
//! (content-addressed by [`EventId`](crate::id::EventId)). A single-process dump carries one Meta,
//! one Intern table, and its shards; `backbeat merge` splices several dumps into one by unioning the
//! registries and copying every instance's tagged sections through verbatim — so a merged dump
//! reconstructs each process's records and spans exactly as the source dumps would.
//!
//! Crucially, `FORMAT_VERSION` governs only the *envelope and section framing* — event layouts
//! evolve freely because each is described by its own schema in the registry. There is no
//! "append, never renumber" discipline to maintain by hand: add, remove, or reorder an event's
//! fields and the embedded schema simply reflects it.
/// File magic at the very front of every dump.
pub const MAGIC: = *b"BACKBEAT";
/// Version of the envelope/section framing (NOT of any event layout — those are self-described).
/// Bump only when the envelope, section table, or a section's own framing changes.
pub const FORMAT_VERSION: u16 = 1;
/// Flags in the envelope header.
/// Identifies what a section contains. Stored as the `kind` of a `SectionEntry`.
///
/// Stable on-disk values — append, never renumber (this is the *one* place that discipline
/// applies, and it governs section kinds, not event fields).