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