An event was a tree of values encoded into a new string, a dropped line was never given back, and every batch and save joined the queue into another. Now: telemetry_props / telemetry_str / _int / _bool write the properties as JSON into a buffer the state keeps; the line is written beside it, its time worked out from the clock's seconds (TelemetryWorld.clock_s, was stamp); its bytes go into one ring (ring_bytes, at most queue_max lines), the oldest overwritten past either; a batch and the file are written into a third kept buffer and go as bytes (TelemetryTransport.send takes the bytes and their length; Http.body_bytes, Fs.write_bytes). The facts are pooled. tests/ring_test: ten thousand events past the cap in lines and in bytes, 0 bytes of heap; the line exact JSON, escaped, 2000-02-29 right; the batch puts the id in; the file round-trips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.2 KiB
Text
76 lines
3.2 KiB
Text
# ring.ludic - the queued lines in one byte ring made at the start: a line's bytes, its length and where
|
|
# its player mark is, oldest first. Full (lines or bytes), the oldest are overwritten; nothing is made
|
|
# per event, per drop or per send
|
|
|
|
# the ring for this start, made once at its size and kept across starts of the same size
|
|
function tr_init(telemetry_st: mut TelemetryState) -> void {
|
|
let c = telemetry__conf(telemetry_st)
|
|
if telemetry_st.telemetry__ring == null or len(telemetry_st.telemetry__ring) != c.ring_bytes {
|
|
telemetry_st.telemetry__ring = buffer(c.ring_bytes)
|
|
telemetry_st.telemetry__out = sb_new(c.ring_bytes + c.batch * 128 + 1024)
|
|
}
|
|
if telemetry_st.telemetry__off == null or len(telemetry_st.telemetry__off) != c.queue_max {
|
|
telemetry_st.telemetry__off = words(c.queue_max)
|
|
telemetry_st.telemetry__len = words(c.queue_max)
|
|
telemetry_st.telemetry__mk = words(c.queue_max)
|
|
}
|
|
tr_clear(telemetry_st)
|
|
}
|
|
function tr_clear(telemetry_st: mut TelemetryState) -> void {
|
|
telemetry_st.telemetry__head = 0
|
|
telemetry_st.telemetry__n = 0
|
|
telemetry_st.telemetry__wr = 0
|
|
}
|
|
function tr_slot(telemetry_st: TelemetryState, i: int) -> int { return (telemetry_st.telemetry__head + i) % len(telemetry_st.telemetry__off) }
|
|
|
|
# the oldest k lines gone (sent, or overwritten)
|
|
function tr_drop(telemetry_st: mut TelemetryState, k: int) -> void {
|
|
let n = Math.min(k, telemetry_st.telemetry__n)
|
|
telemetry_st.telemetry__head = tr_slot(telemetry_st, n)
|
|
telemetry_st.telemetry__n -= n
|
|
if telemetry_st.telemetry__n == 0 { tr_clear(telemetry_st) }
|
|
telemetry_st.telemetry__dirty = true
|
|
}
|
|
|
|
# a line (the first `n` bytes of b) put at the ring's end, its mark `mk` bytes in (-1 none)
|
|
function tr_add(telemetry_st: mut TelemetryState, b: []byte, n: int, mk: int) -> void {
|
|
let ring = telemetry_st.telemetry__ring
|
|
if n <= 0 or n > len(ring) { return }
|
|
if telemetry_st.telemetry__n == len(telemetry_st.telemetry__off) { tr_drop(telemetry_st, 1) }
|
|
var at = telemetry_st.telemetry__wr
|
|
if at + n > len(ring) { at = 0 }
|
|
while telemetry_st.telemetry__n > 0 and tr_over(telemetry_st, at, n) { tr_drop(telemetry_st, 1) }
|
|
for i in 0 .. n { ring[at + i] = b[i] }
|
|
let s = tr_slot(telemetry_st, telemetry_st.telemetry__n)
|
|
telemetry_st.telemetry__off[s] = at
|
|
telemetry_st.telemetry__len[s] = n
|
|
telemetry_st.telemetry__mk[s] = mk
|
|
telemetry_st.telemetry__n += 1
|
|
telemetry_st.telemetry__wr = at + n
|
|
telemetry_st.telemetry__dirty = true
|
|
}
|
|
# would bytes at .. at + n overwrite the oldest line
|
|
function tr_over(telemetry_st: TelemetryState, at: int, n: int) -> bool {
|
|
let s = telemetry_st.telemetry__head
|
|
let o = telemetry_st.telemetry__off[s]
|
|
return o < at + n and at < o + telemetry_st.telemetry__len[s]
|
|
}
|
|
|
|
# line i (0 the oldest) onto sb, its mark written as `id` when id is not null
|
|
function tr_line_to(telemetry_st: TelemetryState, i: int, sb: StrBuf, id: string) -> void {
|
|
let s = tr_slot(telemetry_st, i)
|
|
let o = telemetry_st.telemetry__off[s]
|
|
let n = telemetry_st.telemetry__len[s]
|
|
let mk = telemetry_st.telemetry__mk[s]
|
|
let ring = telemetry_st.telemetry__ring
|
|
var k = 0
|
|
while k < n {
|
|
if id != null and k == mk {
|
|
sb_add(sb, id)
|
|
k += len(TELEMETRY_MARK)
|
|
} else {
|
|
sb_byte(sb, ring[o + k])
|
|
k += 1
|
|
}
|
|
}
|
|
}
|