TLA Line data Source code
1 : use anyhow::Result;
2 : use core::fmt::Display;
3 : use std::ops::Range;
4 : use utils::{
5 : id::{TenantId, TimelineId},
6 : lsn::Lsn,
7 : };
8 :
9 : use crate::{context::RequestContext, repository::Key};
10 :
11 : use super::{DeltaFileName, ImageFileName, LayerFileName};
12 :
13 : use serde::{Deserialize, Serialize};
14 :
15 : /// A unique identifier of a persistent layer. This is different from `LayerDescriptor`, which is only used in the
16 : /// benchmarks. This struct contains all necessary information to find the image / delta layer. It also provides
17 : /// a unified way to generate layer information like file name.
18 CBC 37174 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
19 : pub struct PersistentLayerDesc {
20 : pub tenant_id: TenantId,
21 : pub timeline_id: TimelineId,
22 : /// Range of keys that this layer covers
23 : pub key_range: Range<Key>,
24 : /// Inclusive start, exclusive end of the LSN range that this layer holds.
25 : ///
26 : /// - For an open in-memory layer, the end bound is MAX_LSN
27 : /// - For a frozen in-memory layer or a delta layer, the end bound is a valid lsn after the
28 : /// range start
29 : /// - An image layer represents snapshot at one LSN, so end_lsn is always the snapshot LSN + 1
30 : pub lsn_range: Range<Lsn>,
31 : /// Whether this is a delta layer, and also, is this incremental.
32 : pub is_delta: bool,
33 : pub file_size: u64,
34 : }
35 :
36 : /// A unique identifier of a persistent layer within the context of one timeline.
37 24179132 : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
38 : pub struct PersistentLayerKey {
39 : pub key_range: Range<Key>,
40 : pub lsn_range: Range<Lsn>,
41 : pub is_delta: bool,
42 : }
43 :
44 : impl PersistentLayerDesc {
45 23992150 : pub fn key(&self) -> PersistentLayerKey {
46 23992150 : PersistentLayerKey {
47 23992150 : key_range: self.key_range.clone(),
48 23992150 : lsn_range: self.lsn_range.clone(),
49 23992150 : is_delta: self.is_delta,
50 23992150 : }
51 23992150 : }
52 :
53 9199 : pub fn short_id(&self) -> impl Display {
54 9199 : self.filename()
55 9199 : }
56 :
57 : #[cfg(test)]
58 UBC 0 : pub fn new_test(key_range: Range<Key>) -> Self {
59 0 : Self {
60 0 : tenant_id: TenantId::generate(),
61 0 : timeline_id: TimelineId::generate(),
62 0 : key_range,
63 0 : lsn_range: Lsn(0)..Lsn(1),
64 0 : is_delta: false,
65 0 : file_size: 0,
66 0 : }
67 0 : }
68 :
69 CBC 8010 : pub fn new_img(
70 8010 : tenant_id: TenantId,
71 8010 : timeline_id: TimelineId,
72 8010 : key_range: Range<Key>,
73 8010 : lsn: Lsn,
74 8010 : file_size: u64,
75 8010 : ) -> Self {
76 8010 : Self {
77 8010 : tenant_id,
78 8010 : timeline_id,
79 8010 : key_range,
80 8010 : lsn_range: Self::image_layer_lsn_range(lsn),
81 8010 : is_delta: false,
82 8010 : file_size,
83 8010 : }
84 8010 : }
85 :
86 21156 : pub fn new_delta(
87 21156 : tenant_id: TenantId,
88 21156 : timeline_id: TimelineId,
89 21156 : key_range: Range<Key>,
90 21156 : lsn_range: Range<Lsn>,
91 21156 : file_size: u64,
92 21156 : ) -> Self {
93 21156 : Self {
94 21156 : tenant_id,
95 21156 : timeline_id,
96 21156 : key_range,
97 21156 : lsn_range,
98 21156 : is_delta: true,
99 21156 : file_size,
100 21156 : }
101 21156 : }
102 :
103 : /// Get the LSN that the image layer covers.
104 4010 : pub fn image_layer_lsn(&self) -> Lsn {
105 4010 : assert!(!self.is_delta);
106 4010 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
107 4010 : self.lsn_range.start
108 4010 : }
109 :
110 : /// Get the LSN range corresponding to a single image layer LSN.
111 8010 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
112 8010 : lsn..(lsn + 1)
113 8010 : }
114 :
115 : /// Get a delta file name for this layer.
116 : ///
117 : /// Panic: if this is not a delta layer.
118 76183 : pub fn delta_file_name(&self) -> DeltaFileName {
119 76183 : assert!(self.is_delta);
120 76183 : DeltaFileName {
121 76183 : key_range: self.key_range.clone(),
122 76183 : lsn_range: self.lsn_range.clone(),
123 76183 : }
124 76183 : }
125 :
126 : /// Get a delta file name for this layer.
127 : ///
128 : /// Panic: if this is not an image layer, or the lsn range is invalid
129 71116 : pub fn image_file_name(&self) -> ImageFileName {
130 71116 : assert!(!self.is_delta);
131 71116 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
132 71116 : ImageFileName {
133 71116 : key_range: self.key_range.clone(),
134 71116 : lsn: self.lsn_range.start,
135 71116 : }
136 71116 : }
137 :
138 94070 : pub fn filename(&self) -> LayerFileName {
139 94070 : if self.is_delta {
140 32233 : self.delta_file_name().into()
141 : } else {
142 61837 : self.image_file_name().into()
143 : }
144 94070 : }
145 :
146 : // TODO: remove this in the future once we refactor timeline APIs.
147 :
148 51786066 : pub fn get_lsn_range(&self) -> Range<Lsn> {
149 51786066 : self.lsn_range.clone()
150 51786066 : }
151 :
152 7243122 : pub fn get_key_range(&self) -> Range<Key> {
153 7243122 : self.key_range.clone()
154 7243122 : }
155 :
156 UBC 0 : pub fn get_timeline_id(&self) -> TimelineId {
157 0 : self.timeline_id
158 0 : }
159 :
160 0 : pub fn get_tenant_id(&self) -> TenantId {
161 0 : self.tenant_id
162 0 : }
163 :
164 : /// Does this layer only contain some data for the key-range (incremental),
165 : /// or does it contain a version of every page? This is important to know
166 : /// for garbage collecting old layers: an incremental layer depends on
167 : /// the previous non-incremental layer.
168 CBC 34205 : pub fn is_incremental(&self) -> bool {
169 34205 : self.is_delta
170 34205 : }
171 :
172 UBC 0 : pub fn is_delta(&self) -> bool {
173 0 : self.is_delta
174 0 : }
175 :
176 0 : pub fn dump(&self, _verbose: bool, _ctx: &RequestContext) -> Result<()> {
177 0 : println!(
178 0 : "----- layer for ten {} tli {} keys {}-{} lsn {}-{} is_delta {} is_incremental {} size {} ----",
179 0 : self.tenant_id,
180 0 : self.timeline_id,
181 0 : self.key_range.start,
182 0 : self.key_range.end,
183 0 : self.lsn_range.start,
184 0 : self.lsn_range.end,
185 0 : self.is_delta,
186 0 : self.is_incremental(),
187 0 : self.file_size,
188 0 : );
189 0 :
190 0 : Ok(())
191 0 : }
192 :
193 CBC 94899 : pub fn file_size(&self) -> u64 {
194 94899 : self.file_size
195 94899 : }
196 : }
|