Line data Source code
1 : //! Synthetic size calculation
2 : #![deny(unsafe_code)]
3 : #![deny(clippy::undocumented_unsafe_blocks)]
4 :
5 : mod calculation;
6 : pub mod svg;
7 :
8 : /// StorageModel is the input to the synthetic size calculation.
9 : ///
10 : /// It represents a tree of timelines, with just the information that's needed
11 : /// for the calculation. This doesn't track timeline names or where each timeline
12 : /// begins and ends, for example. Instead, it consists of "points of interest"
13 : /// on the timelines. A point of interest could be the timeline start or end point,
14 : /// the oldest point on a timeline that needs to be retained because of PITR
15 : /// cutoff, or snapshot points named by the user. For each such point, and the
16 : /// edge connecting the points (implicit in Segment), we store information about
17 : /// whether we need to be able to recover to the point, and if known, the logical
18 : /// size at the point.
19 : ///
20 : /// The segments must form a well-formed tree, with no loops.
21 : #[derive(serde::Serialize)]
22 : pub struct StorageModel {
23 : pub segments: Vec<Segment>,
24 : }
25 :
26 : /// Segment represents one point in the tree of branches, *and* the edge that leads
27 : /// to it (if any). We don't need separate structs for points and edges, because each
28 : /// point can have only one parent.
29 : ///
30 : /// When 'needed' is true, it means that we need to be able to reconstruct
31 : /// any version between 'parent.lsn' and 'lsn'. If you want to represent that only
32 : /// a single point is needed, create two Segments with the same lsn, and mark only
33 : /// the child as needed.
34 : ///
35 140 : #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
36 : pub struct Segment {
37 : /// Previous segment index into ['Storage::segments`], if any.
38 : pub parent: Option<usize>,
39 :
40 : /// LSN at this point
41 : pub lsn: u64,
42 :
43 : /// Logical size at this node, if known.
44 : pub size: Option<u64>,
45 :
46 : /// If true, the segment from parent to this node is needed by `retention_period`
47 : pub needed: bool,
48 : }
49 :
50 : /// Result of synthetic size calculation. Returned by StorageModel::calculate()
51 : pub struct SizeResult {
52 : pub total_size: u64,
53 :
54 : // This has same length as the StorageModel::segments vector in the input.
55 : // Each entry in this array corresponds to the entry with same index in
56 : // StorageModel::segments.
57 : pub segments: Vec<SegmentSizeResult>,
58 : }
59 :
60 0 : #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
61 : pub struct SegmentSizeResult {
62 : pub method: SegmentMethod,
63 : // calculated size of this subtree, using this method
64 : pub accum_size: u64,
65 : }
66 :
67 : /// Different methods to retain history from a particular state
68 0 : #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
69 : pub enum SegmentMethod {
70 : SnapshotHere, // A logical snapshot is needed after this segment
71 : Wal, // Keep WAL leading up to this node
72 : Skipped,
73 : }
|