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