bb_runtime/framework/
record_buffer.rs1use std::collections::{HashMap, VecDeque};
12
13const DEFAULT_CAPACITY: usize = 1024;
15const DEFAULT_MAX_RINGS: usize = 1024;
17
18pub struct RecordBuffer {
20 rings: HashMap<String, VecDeque<Vec<u8>>>,
21 capacity: usize,
22 max_rings: usize,
23 name_drops: u64,
24}
25
26impl Default for RecordBuffer {
27 fn default() -> Self {
28 Self {
29 rings: HashMap::new(),
30 capacity: DEFAULT_CAPACITY,
31 max_rings: DEFAULT_MAX_RINGS,
32 name_drops: 0,
33 }
34 }
35}
36
37impl RecordBuffer {
38 pub fn new() -> Self {
40 Self::default()
41 }
42
43 pub fn with_caps(per_ring: usize, max_rings: usize) -> Self {
45 Self {
46 rings: HashMap::new(),
47 capacity: per_ring,
48 max_rings,
49 name_drops: 0,
50 }
51 }
52
53 pub fn record(&mut self, name: &str, bytes: Vec<u8>) {
57 if !self.rings.contains_key(name) && self.rings.len() >= self.max_rings {
58 self.name_drops += 1;
59 return;
60 }
61 let cap = self.capacity;
62 let ring = self.rings.entry(name.to_string()).or_default();
63 if ring.len() >= cap {
64 ring.pop_front();
65 }
66 ring.push_back(bytes);
67 }
68
69 pub fn snapshot(&self, name: &str) -> Vec<Vec<u8>> {
71 self.rings
72 .get(name)
73 .map(|r| r.iter().cloned().collect())
74 .unwrap_or_default()
75 }
76
77 pub fn name_drops(&self) -> u64 {
79 self.name_drops
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn record_snapshot_round_trip() {
89 let mut b = RecordBuffer::new();
90 b.record("m", b"a".to_vec());
91 b.record("m", b"b".to_vec());
92 let snap = b.snapshot("m");
93 assert_eq!(snap, vec![b"a".to_vec(), b"b".to_vec()]);
94 }
95
96 #[test]
97 fn record_overflow_drops_new_name_and_ticks_counter() {
98 let mut b = RecordBuffer::with_caps(8, 2);
99 b.record("a", b"1".to_vec());
100 b.record("b", b"2".to_vec());
101 assert_eq!(b.name_drops(), 0);
102 b.record("c", b"3".to_vec());
104 assert_eq!(b.name_drops(), 1);
105 assert_eq!(b.snapshot("c"), Vec::<Vec<u8>>::new());
106 b.record("a", b"more".to_vec());
108 assert_eq!(b.snapshot("a"), vec![b"1".to_vec(), b"more".to_vec()]);
109 }
110}