1mod codec;
4mod index;
5pub(crate) mod log;
6mod memory;
7mod persist;
8mod stats;
9mod stored;
10mod tier;
11mod watch;
12
13pub use codec::STORE_FORMAT;
14pub use memory::{Counters, DEFAULT_CACHE_BYTES, DEFAULT_MARK_EVERY};
15pub(crate) use memory::{Facts, Keep, Known, Memory, Offered};
16pub use persist::{Backend, DEFAULT_STORE_BYTES, INDEX_NAME, Opening, Persisted, Store};
17pub(crate) use stats::Recording;
18pub use stats::{CacheStats, Lookup, Outcome, Tally};
19pub use stored::{Cut, Stored};
20pub use sva_formula::Hash;
21pub(crate) use tier::now;
22pub use tier::{FETCH_READS, Nothing, Tier};
23pub use watch::{
24 Boot, BootPhase, Call, CallStats, EngineStats, Gauge, Kind, Phase, Progress, StoreBoot, Typed,
25 Worked,
26};
27
28use std::collections::BTreeMap;
29use std::sync::Arc;
30
31use sva_samples::{Buffer, Frames, Grid, Label, MachineState, Profile};
32
33#[derive(Clone, Debug, PartialEq)]
36pub enum Payload {
37 Segments(Vec<Arc<Buffer>>),
38 Frames(Arc<Frames>),
39 Run(Arc<Run>),
40}
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum PayloadKind {
44 Segments,
45 Frames,
46 Run,
47}
48
49#[derive(Clone)]
51pub struct Run {
52 pub samples: Arc<Buffer>,
53 pub marks: BTreeMap<i64, MachineState>,
54 pub parent: Option<Hash>,
55}
56
57impl Run {
58 pub fn end(&self) -> i64 {
59 self.samples.extent().end
60 }
61
62 pub fn bytes(&self) -> usize {
63 let marks: usize = self.marks.values().map(MachineState::bytes).sum();
64 self.samples.len() * self.samples.width() * size_of::<f64>() + marks
65 }
66}
67
68impl PartialEq for Run {
70 fn eq(&self, other: &Run) -> bool {
71 self.samples == other.samples
72 }
73}
74
75impl std::fmt::Debug for Run {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 f.debug_struct("Run")
78 .field("samples", &self.samples.extent())
79 .finish()
80 }
81}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub enum Expected {
86 Segments { rate: u32, width: usize },
87 Frames,
88 Run { rate: u32, width: usize },
89}
90
91impl Expected {
92 pub(crate) fn kind(self) -> PayloadKind {
93 match self {
94 Expected::Segments { .. } => PayloadKind::Segments,
95 Expected::Frames => PayloadKind::Frames,
96 Expected::Run { .. } => PayloadKind::Run,
97 }
98 }
99}
100
101#[derive(Clone, Debug, PartialEq)]
102pub struct Entry {
103 pub payload: Payload,
104 pub label: Option<Label>,
106}
107
108impl Payload {
109 pub fn run(self) -> Option<Arc<Run>> {
110 match self {
111 Payload::Run(run) => Some(run),
112 _ => None,
113 }
114 }
115
116 pub fn kind(&self) -> PayloadKind {
117 match self {
118 Payload::Segments(_) => PayloadKind::Segments,
119 Payload::Frames(_) => PayloadKind::Frames,
120 Payload::Run(_) => PayloadKind::Run,
121 }
122 }
123
124 pub fn bytes(&self) -> usize {
125 match self {
126 Payload::Segments(parts) => parts
127 .iter()
128 .map(|b| b.len() * b.width() * size_of::<f64>())
129 .sum(),
130 Payload::Frames(f) => f.width * f.frames * f.bins * 2 * size_of::<f64>(),
131 Payload::Run(run) => run.bytes(),
132 }
133 }
134
135 pub fn answers(&self, expected: Expected) -> bool {
136 match (self, expected) {
137 (Payload::Segments(parts), Expected::Segments { rate, width }) => {
138 parts.iter().all(|b| b.rate == rate && b.width() == width)
139 }
140 (Payload::Frames(_), Expected::Frames) => true,
141 (Payload::Run(run), Expected::Run { rate, width }) => {
142 run.samples.rate == rate && run.samples.width() == width
143 }
144 _ => false,
145 }
146 }
147}
148
149#[derive(Clone, Copy, Debug)]
150pub(crate) struct Question<'p> {
151 pub(crate) grid: Grid,
152 pub(crate) width: usize,
153 pub(crate) profile: &'p Profile,
154 pub(crate) shape: Shape,
155}
156
157#[derive(Clone, Copy, Debug, PartialEq, Eq)]
158pub(crate) enum Shape {
159 Samples,
160 Frames { window: usize, hop: usize },
161}
162
163pub(crate) fn key(identity: Hash, question: &Question) -> Hash {
165 let Question {
166 grid,
167 width,
168 profile,
169 shape,
170 } = *question;
171 let asked = [
172 grid.a as u64,
173 grid.d as u64,
174 u64::from(grid.rate),
175 width as u64,
176 ];
177 let shape = match shape {
178 Shape::Samples => [0, 0, 0],
179 Shape::Frames { window, hop } => [1, window as u64, hop as u64],
180 };
181 let tag = [0x6b_65_79_00_00_00_00_01];
182 mixed(
183 identity,
184 &[&asked[..], &profile.deciding(), &shape, &tag].concat(),
185 )
186}
187
188pub(crate) fn mixed(seed: Hash, parts: &[u64]) -> Hash {
189 let mut hasher = sva_formula::ContentHasher::new(sva_formula::HashDomain::CacheAddress);
190 hasher.hash(seed);
191 for part in parts {
192 hasher.word(*part);
193 }
194 hasher.finish()
195}
196
197pub(crate) fn joined(parts: &mut Vec<Arc<Buffer>>, more: Vec<Arc<Buffer>>) {
200 for part in more {
201 parts.push(part);
202 }
203 parts.sort_by_key(|b| b.start);
204 let mut out: Vec<Arc<Buffer>> = Vec::with_capacity(parts.len());
205 for part in parts.drain(..) {
206 match out.last_mut() {
207 Some(last) if last.extent().end >= part.start => {
208 let from = (last.extent().end - part.start) as usize;
209 if from < part.len() {
210 let last = Arc::make_mut(last);
211 for (held, more) in last.planes.iter_mut().zip(&part.planes) {
212 held.extend_from_slice(&more[from.min(more.len())..]);
213 }
214 }
215 }
216 _ => out.push(part),
217 }
218 }
219 *parts = out;
220}