Skip to main content

sva_engine/cache/
stored.rs

1// Concern: what the tier answers of a node, and where a disk entry lays its samples | Non-concern: reading them, the bytes (codec.rs) | IO: (identity, rate) -> key; Header -> extents
2
3use sva_formula::{Codomain, Hash};
4use sva_samples::{Extent, Grid, Label};
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct Stored {
8    pub key: Hash,
9    pub label: Label,
10    pub width: u8,
11    pub codomain: Codomain,
12    pub rate: Option<u32>,
13    pub grid: Grid,
14    pub support: Extent,
15    /// Flops it and all under it cost.
16    pub priced: u128,
17    /// The most seconds a read under it moved to land on a sample.
18    pub moved: f64,
19    pub readable: bool,
20    pub sampled: bool,
21    pub cuts: Vec<(String, i64)>,
22    pub(crate) held: Vec<Extent>,
23}
24
25impl Stored {
26    pub(crate) fn extents(&self) -> &[Extent] {
27        &self.held
28    }
29
30    pub(crate) fn holds(&self, over: Extent) -> bool {
31        let mut from = over.start;
32        for part in &self.held {
33            if from >= over.end || part.start > from {
34                break;
35            }
36            from = from.max(part.end);
37        }
38        from >= over.end
39    }
40
41    pub(crate) fn holding(&self, mut held: Vec<Extent>) -> Stored {
42        held.sort_by_key(|e| e.start);
43        Stored {
44            held,
45            ..self.clone()
46        }
47    }
48}
49
50/// Only the disk tier and the memory tier read a layout. What it holds is its layout's alone.
51#[derive(Clone, Debug, PartialEq)]
52pub(crate) struct Header {
53    stored: Stored,
54    samples: Samples,
55}
56
57#[derive(Clone, Debug, Default, PartialEq)]
58pub(crate) enum Samples {
59    #[default]
60    None,
61    /// Its `n` is the file's `n - shift`.
62    Entry {
63        file: Hash,
64        runs: Vec<Laid>,
65        shift: i64,
66    },
67    Staged {
68        chunks: Vec<(String, Extent)>,
69        shift: i64,
70    },
71    /// As written: sample `n` is `key`'s sample `n + by`.
72    Of { key: Hash, by: i64 },
73}
74
75#[derive(Clone, Debug, PartialEq)]
76pub(crate) struct Laid {
77    pub(crate) rate: u32,
78    pub(crate) start: i64,
79    pub(crate) width: usize,
80    pub(crate) len: usize,
81    /// Its first byte.
82    pub(crate) at: u64,
83    pub(crate) sums: Vec<u64>,
84}
85
86impl Laid {
87    pub(crate) fn extent(&self) -> Extent {
88        Extent::new(self.start, self.start + self.len as i64)
89    }
90}
91
92impl Samples {
93    fn extents(&self) -> Vec<Extent> {
94        match self {
95            Samples::None | Samples::Of { .. } => Vec::new(),
96            Samples::Entry { runs, shift, .. } => runs
97                .iter()
98                .map(|run| run.extent().shifted(*shift))
99                .collect(),
100            Samples::Staged { chunks, shift } => {
101                chunks.iter().map(|(_, e)| e.shifted(*shift)).collect()
102            }
103        }
104    }
105}
106
107impl Header {
108    pub(crate) fn new(stored: Stored, samples: Samples) -> Header {
109        let stored = stored.holding(samples.extents());
110        Header { stored, samples }
111    }
112
113    pub(crate) fn stored(&self) -> &Stored {
114        &self.stored
115    }
116
117    pub(crate) fn samples(&self) -> &Samples {
118        &self.samples
119    }
120
121    pub(crate) fn into_parts(self) -> (Stored, Samples) {
122        (self.stored, self.samples)
123    }
124
125    pub(crate) fn refers(&self) -> bool {
126        matches!(self.samples, Samples::Of { .. })
127    }
128}
129
130/// Keyed by its source's identity, the rate and the profile.
131pub(crate) fn node_key(identity: Hash, rate: u32, profile: &sva_samples::Profile) -> Hash {
132    super::mixed(
133        identity,
134        &[
135            u64::from(rate),
136            profile.precision_bits as u64,
137            profile.ceiling_hz.to_bits(),
138            profile.prune_db.to_bits(),
139            0x6e_6f_64_65_00_00_00_01,
140        ],
141    )
142}