Line data Source code
1 : use core::fmt::Display;
2 : use std::ops::Range;
3 :
4 : use pageserver_api::key::Key;
5 : use pageserver_api::shard::TenantShardId;
6 : use serde::{Deserialize, Serialize};
7 : #[cfg(test)]
8 : use utils::id::TenantId;
9 : use utils::id::TimelineId;
10 : use utils::lsn::Lsn;
11 :
12 : use super::{DeltaLayerName, ImageLayerName, LayerName};
13 :
14 : /// A unique identifier of a persistent layer.
15 : ///
16 : /// This is different from `LayerDescriptor`, which is only used in the benchmarks.
17 : /// This struct contains all necessary information to find the image / delta layer. It also provides
18 : /// a unified way to generate layer information like file name.
19 0 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Hash)]
20 : pub struct PersistentLayerDesc {
21 : pub tenant_shard_id: TenantShardId,
22 : pub timeline_id: TimelineId,
23 : /// Range of keys that this layer covers
24 : pub key_range: Range<Key>,
25 : /// Inclusive start, exclusive end of the LSN range that this layer holds.
26 : ///
27 : /// - For an open in-memory layer, the end bound is MAX_LSN
28 : /// - For a frozen in-memory layer or a delta layer, the end bound is a valid lsn after the
29 : /// range start
30 : /// - An image layer represents snapshot at one LSN, so end_lsn is always the snapshot LSN + 1
31 : pub lsn_range: Range<Lsn>,
32 : /// Whether this is a delta layer, and also, is this incremental.
33 : pub is_delta: bool,
34 : pub file_size: u64,
35 : }
36 :
37 : /// A unique identifier of a persistent layer within the context of one timeline.
38 : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
39 : pub struct PersistentLayerKey {
40 : pub key_range: Range<Key>,
41 : pub lsn_range: Range<Lsn>,
42 : pub is_delta: bool,
43 : }
44 :
45 : impl std::fmt::Display for PersistentLayerKey {
46 348 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 348 : write!(
48 348 : f,
49 348 : "{}..{} {}..{} is_delta={}",
50 348 : self.key_range.start,
51 348 : self.key_range.end,
52 348 : self.lsn_range.start,
53 348 : self.lsn_range.end,
54 348 : self.is_delta
55 348 : )
56 348 : }
57 : }
58 :
59 : impl From<ImageLayerName> for PersistentLayerKey {
60 0 : fn from(image_layer_name: ImageLayerName) -> Self {
61 0 : Self {
62 0 : key_range: image_layer_name.key_range,
63 0 : lsn_range: PersistentLayerDesc::image_layer_lsn_range(image_layer_name.lsn),
64 0 : is_delta: false,
65 0 : }
66 0 : }
67 : }
68 :
69 : impl From<DeltaLayerName> for PersistentLayerKey {
70 0 : fn from(delta_layer_name: DeltaLayerName) -> Self {
71 0 : Self {
72 0 : key_range: delta_layer_name.key_range,
73 0 : lsn_range: delta_layer_name.lsn_range,
74 0 : is_delta: true,
75 0 : }
76 0 : }
77 : }
78 :
79 : impl From<LayerName> for PersistentLayerKey {
80 0 : fn from(layer_name: LayerName) -> Self {
81 0 : match layer_name {
82 0 : LayerName::Image(i) => i.into(),
83 0 : LayerName::Delta(d) => d.into(),
84 : }
85 0 : }
86 : }
87 : impl PersistentLayerDesc {
88 5114169 : pub fn key(&self) -> PersistentLayerKey {
89 5114169 : PersistentLayerKey {
90 5114169 : key_range: self.key_range.clone(),
91 5114169 : lsn_range: self.lsn_range.clone(),
92 5114169 : is_delta: self.is_delta,
93 5114169 : }
94 5114169 : }
95 :
96 13392 : pub fn short_id(&self) -> impl Display {
97 13392 : self.layer_name()
98 13392 : }
99 :
100 : #[cfg(test)]
101 264 : pub fn new_test(key_range: Range<Key>, lsn_range: Range<Lsn>, is_delta: bool) -> Self {
102 264 : Self {
103 264 : tenant_shard_id: TenantShardId::unsharded(TenantId::generate()),
104 264 : timeline_id: TimelineId::generate(),
105 264 : key_range,
106 264 : lsn_range,
107 264 : is_delta,
108 264 : file_size: 0,
109 264 : }
110 264 : }
111 :
112 2520 : pub fn new_img(
113 2520 : tenant_shard_id: TenantShardId,
114 2520 : timeline_id: TimelineId,
115 2520 : key_range: Range<Key>,
116 2520 : lsn: Lsn,
117 2520 : file_size: u64,
118 2520 : ) -> Self {
119 2520 : Self {
120 2520 : tenant_shard_id,
121 2520 : timeline_id,
122 2520 : key_range,
123 2520 : lsn_range: Self::image_layer_lsn_range(lsn),
124 2520 : is_delta: false,
125 2520 : file_size,
126 2520 : }
127 2520 : }
128 :
129 9624 : pub fn new_delta(
130 9624 : tenant_shard_id: TenantShardId,
131 9624 : timeline_id: TimelineId,
132 9624 : key_range: Range<Key>,
133 9624 : lsn_range: Range<Lsn>,
134 9624 : file_size: u64,
135 9624 : ) -> Self {
136 9624 : Self {
137 9624 : tenant_shard_id,
138 9624 : timeline_id,
139 9624 : key_range,
140 9624 : lsn_range,
141 9624 : is_delta: true,
142 9624 : file_size,
143 9624 : }
144 9624 : }
145 :
146 732 : pub fn from_filename(
147 732 : tenant_shard_id: TenantShardId,
148 732 : timeline_id: TimelineId,
149 732 : filename: LayerName,
150 732 : file_size: u64,
151 732 : ) -> Self {
152 732 : match filename {
153 24 : LayerName::Image(i) => {
154 24 : Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
155 : }
156 708 : LayerName::Delta(d) => Self::new_delta(
157 708 : tenant_shard_id,
158 708 : timeline_id,
159 708 : d.key_range,
160 708 : d.lsn_range,
161 708 : file_size,
162 708 : ),
163 : }
164 732 : }
165 :
166 : /// Get the LSN that the image layer covers.
167 15244428 : pub fn image_layer_lsn(&self) -> Lsn {
168 15244428 : assert!(!self.is_delta);
169 15244428 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
170 15244428 : self.lsn_range.start
171 15244428 : }
172 :
173 : /// Get the LSN range corresponding to a single image layer LSN.
174 14616 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
175 14616 : lsn..(lsn + 1)
176 14616 : }
177 :
178 : /// Get a delta layer name for this layer.
179 : ///
180 : /// Panic: if this is not a delta layer.
181 7137460 : pub fn delta_layer_name(&self) -> DeltaLayerName {
182 7137460 : assert!(self.is_delta);
183 7137460 : DeltaLayerName {
184 7137460 : key_range: self.key_range.clone(),
185 7137460 : lsn_range: self.lsn_range.clone(),
186 7137460 : }
187 7137460 : }
188 :
189 : /// Get a image layer name for this layer.
190 : ///
191 : /// Panic: if this is not an image layer, or the lsn range is invalid
192 23380 : pub fn image_layer_name(&self) -> ImageLayerName {
193 23380 : assert!(!self.is_delta);
194 23380 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
195 23380 : ImageLayerName {
196 23380 : key_range: self.key_range.clone(),
197 23380 : lsn: self.lsn_range.start,
198 23380 : }
199 23380 : }
200 :
201 7160840 : pub fn layer_name(&self) -> LayerName {
202 7160840 : if self.is_delta {
203 7137460 : self.delta_layer_name().into()
204 : } else {
205 23380 : self.image_layer_name().into()
206 : }
207 7160840 : }
208 :
209 : // TODO: remove this in the future once we refactor timeline APIs.
210 :
211 38715728 : pub fn get_lsn_range(&self) -> Range<Lsn> {
212 38715728 : self.lsn_range.clone()
213 38715728 : }
214 :
215 569472 : pub fn get_key_range(&self) -> Range<Key> {
216 569472 : self.key_range.clone()
217 569472 : }
218 :
219 0 : pub fn get_timeline_id(&self) -> TimelineId {
220 0 : self.timeline_id
221 0 : }
222 :
223 : /// Does this layer only contain some data for the key-range (incremental),
224 : /// or does it contain a version of every page? This is important to know
225 : /// for garbage collecting old layers: an incremental layer depends on
226 : /// the previous non-incremental layer.
227 32820 : pub fn is_incremental(&self) -> bool {
228 32820 : self.is_delta
229 32820 : }
230 :
231 45755029 : pub fn is_delta(&self) -> bool {
232 45755029 : self.is_delta
233 45755029 : }
234 :
235 96 : pub fn dump(&self) {
236 96 : if self.is_delta {
237 84 : println!(
238 84 : "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
239 84 : self.tenant_shard_id,
240 84 : self.timeline_id,
241 84 : self.key_range.start,
242 84 : self.key_range.end,
243 84 : self.lsn_range.start,
244 84 : self.lsn_range.end,
245 84 : self.is_incremental(),
246 84 : self.file_size,
247 84 : );
248 84 : } else {
249 12 : println!(
250 12 : "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
251 12 : self.tenant_shard_id,
252 12 : self.timeline_id,
253 12 : self.key_range.start,
254 12 : self.key_range.end,
255 12 : self.image_layer_lsn(),
256 12 : self.is_incremental(),
257 12 : self.file_size
258 12 : );
259 12 : }
260 96 : }
261 :
262 1404 : pub fn file_size(&self) -> u64 {
263 1404 : self.file_size
264 1404 : }
265 : }
|