1mod disk;
4mod evict;
5mod label;
6mod memory;
7
8pub use disk::{DiskCache, IO_NANOS_PER_BYTE};
9pub use memory::MemoryCache;
10pub use sva_formula::Hash;
11
12use std::path::Path;
13use std::time::Duration;
14
15use sva_formula::SpectralSum;
16use sva_samples::{Buffer, FilterTrace, Frames, Label};
17
18#[derive(Clone, Debug, PartialEq)]
20pub enum Payload {
21 Samples(Box<Buffer>),
22 Frames(Box<Frames>),
23 Symbolic(Box<SpectralSum>),
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub enum PayloadKind {
28 Samples,
29 Frames,
30 Symbolic,
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub enum Expected {
36 Samples {
37 rate: u32,
38 width: usize,
39 samples: usize,
40 },
41 Frames,
42 Symbolic,
43}
44
45#[derive(Clone, Debug, PartialEq)]
46pub struct Entry {
47 pub payload: Payload,
48 pub traces: Vec<FilterTrace>,
49 pub label: Option<Label>,
51}
52
53impl Payload {
54 pub fn kind(&self) -> PayloadKind {
55 match self {
56 Payload::Samples(_) => PayloadKind::Samples,
57 Payload::Frames(_) => PayloadKind::Frames,
58 Payload::Symbolic(_) => PayloadKind::Symbolic,
59 }
60 }
61
62 pub fn samples(&self) -> Option<&Buffer> {
63 match self {
64 Payload::Samples(buffer) => Some(buffer),
65 _ => None,
66 }
67 }
68
69 pub fn symbolic(&self) -> Option<&SpectralSum> {
70 match self {
71 Payload::Symbolic(sum) => Some(sum),
72 _ => None,
73 }
74 }
75
76 pub fn bytes(&self) -> usize {
77 match self {
78 Payload::Samples(b) => b.len() * b.width * size_of::<f64>(),
79 Payload::Frames(f) => f.width * f.frames * f.bins * 2 * size_of::<f64>(),
80 Payload::Symbolic(n) => {
81 size_of::<SpectralSum>()
82 + n.lanes
83 .iter()
84 .map(|lane| {
85 lane.atoms.len() * size_of::<sva_formula::SpectralAtom>()
86 + (lane.series.len() + lane.modal.len()) * size_of::<SpectralSum>()
87 })
88 .sum::<usize>()
89 }
90 }
91 }
92
93 pub fn answers(&self, expected: Expected) -> bool {
94 match (self, expected) {
95 (
96 Payload::Samples(b),
97 Expected::Samples {
98 rate,
99 width,
100 samples,
101 },
102 ) => b.rate == rate && b.width == width && b.len() == samples,
103 (Payload::Frames(_), Expected::Frames) => true,
104 (Payload::Symbolic(_), Expected::Symbolic) => true,
105 _ => false,
106 }
107 }
108}
109
110#[derive(Clone, Copy)]
113pub struct Cost {
114 #[cfg(not(target_arch = "wasm32"))]
115 began: std::time::Instant,
116}
117
118impl Cost {
119 pub fn begun() -> Cost {
120 Cost {
121 #[cfg(not(target_arch = "wasm32"))]
122 began: std::time::Instant::now(),
123 }
124 }
125
126 pub fn elapsed(self) -> Duration {
127 #[cfg(not(target_arch = "wasm32"))]
128 return self.began.elapsed();
129 #[cfg(target_arch = "wasm32")]
130 return Duration::ZERO;
131 }
132}
133
134pub fn symbolic_key(src: Hash) -> Hash {
136 mixed(src, &[0x73_79_6d_62_6f_6c_69_63])
137}
138
139pub fn frames_key(buffer: Hash, window: usize, hop: usize) -> Hash {
141 mixed(
142 buffer,
143 &[window as u64, hop as u64, 0x66_72_61_6d_65_73_00_01],
144 )
145}
146
147pub fn buffer_key(
149 symbolic: Hash,
150 rate: u32,
151 origin_secs: f64,
152 width: usize,
153 score: sva_samples::AliasScore,
154) -> Hash {
155 mixed(
156 symbolic,
157 &[
158 u64::from(rate),
159 origin_secs.to_bits(),
160 width as u64,
161 u64::from(score == sva_samples::AliasScore::Asked),
162 0x62_75_66_66_65_72_00_01,
163 ],
164 )
165}
166
167const ADDRESS_ROTATE: u32 = 17;
168
169fn mixed(seed: Hash, parts: &[u64]) -> Hash {
170 let mut lanes = sva_formula::Lanes::<ADDRESS_ROTATE>::from(seed);
171 for part in parts {
172 lanes.word(*part);
173 }
174 lanes.finish()
175}
176
177pub trait Cache: Sync {
178 fn load(&self, key: Hash, node: &str, expected: Expected) -> Option<Entry>;
179
180 fn store(&self, key: Hash, payload: &Payload, traces: &[FilterTrace], label: Option<&Label>);
181
182 fn holds(&self, key: Hash) -> bool;
183
184 fn worth_storing(&self, cost: Duration, bytes: usize, kind: PayloadKind) -> bool;
185
186 fn sweep(&self);
187
188 fn held_bytes(&self) -> u64;
189
190 fn evicted_bytes(&self) -> u64;
191
192 fn faults(&self) -> u64 {
193 0
194 }
195
196 fn max_bytes(&self) -> u64;
197
198 fn dir(&self) -> Option<&Path> {
199 None
200 }
201}