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