TLA Line data Source code
1 : use core::fmt::Display;
2 : use pageserver_api::shard::TenantShardId;
3 : use std::ops::Range;
4 : use utils::{id::TimelineId, lsn::Lsn};
5 :
6 : use crate::repository::Key;
7 :
8 : use super::{DeltaFileName, ImageFileName, LayerFileName};
9 :
10 : use serde::{Deserialize, Serialize};
11 :
12 : #[cfg(test)]
13 : use utils::id::TenantId;
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 83646 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
19 : pub struct PersistentLayerDesc {
20 : pub tenant_shard_id: TenantShardId,
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 15681652 : #[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 15623577 : pub fn key(&self) -> PersistentLayerKey {
46 15623577 : PersistentLayerKey {
47 15623577 : key_range: self.key_range.clone(),
48 15623577 : lsn_range: self.lsn_range.clone(),
49 15623577 : is_delta: self.is_delta,
50 15623577 : }
51 15623577 : }
52 :
53 53275 : pub fn short_id(&self) -> impl Display {
54 53275 : self.filename()
55 53275 : }
56 :
57 : #[cfg(test)]
58 UBC 0 : pub fn new_test(key_range: Range<Key>) -> Self {
59 0 : Self {
60 0 : tenant_shard_id: TenantShardId::unsharded(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 39000 : pub fn new_img(
70 39000 : tenant_shard_id: TenantShardId,
71 39000 : timeline_id: TimelineId,
72 39000 : key_range: Range<Key>,
73 39000 : lsn: Lsn,
74 39000 : file_size: u64,
75 39000 : ) -> Self {
76 39000 : Self {
77 39000 : tenant_shard_id,
78 39000 : timeline_id,
79 39000 : key_range,
80 39000 : lsn_range: Self::image_layer_lsn_range(lsn),
81 39000 : is_delta: false,
82 39000 : file_size,
83 39000 : }
84 39000 : }
85 :
86 39253 : pub fn new_delta(
87 39253 : tenant_shard_id: TenantShardId,
88 39253 : timeline_id: TimelineId,
89 39253 : key_range: Range<Key>,
90 39253 : lsn_range: Range<Lsn>,
91 39253 : file_size: u64,
92 39253 : ) -> Self {
93 39253 : Self {
94 39253 : tenant_shard_id,
95 39253 : timeline_id,
96 39253 : key_range,
97 39253 : lsn_range,
98 39253 : is_delta: true,
99 39253 : file_size,
100 39253 : }
101 39253 : }
102 :
103 57805 : pub fn from_filename(
104 57805 : tenant_shard_id: TenantShardId,
105 57805 : timeline_id: TimelineId,
106 57805 : filename: LayerFileName,
107 57805 : file_size: u64,
108 57805 : ) -> Self {
109 57805 : match filename {
110 33361 : LayerFileName::Image(i) => {
111 33361 : Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
112 : }
113 24444 : LayerFileName::Delta(d) => Self::new_delta(
114 24444 : tenant_shard_id,
115 24444 : timeline_id,
116 24444 : d.key_range,
117 24444 : d.lsn_range,
118 24444 : file_size,
119 24444 : ),
120 : }
121 57805 : }
122 :
123 : /// Get the LSN that the image layer covers.
124 927012 : pub fn image_layer_lsn(&self) -> Lsn {
125 927012 : assert!(!self.is_delta);
126 927012 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
127 927012 : self.lsn_range.start
128 927012 : }
129 :
130 : /// Get the LSN range corresponding to a single image layer LSN.
131 39000 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
132 39000 : lsn..(lsn + 1)
133 39000 : }
134 :
135 : /// Get a delta file name for this layer.
136 : ///
137 : /// Panic: if this is not a delta layer.
138 557731 : pub fn delta_file_name(&self) -> DeltaFileName {
139 557731 : assert!(self.is_delta);
140 557731 : DeltaFileName {
141 557731 : key_range: self.key_range.clone(),
142 557731 : lsn_range: self.lsn_range.clone(),
143 557731 : }
144 557731 : }
145 :
146 : /// Get a delta file name for this layer.
147 : ///
148 : /// Panic: if this is not an image layer, or the lsn range is invalid
149 420817 : pub fn image_file_name(&self) -> ImageFileName {
150 420817 : assert!(!self.is_delta);
151 420817 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
152 420817 : ImageFileName {
153 420817 : key_range: self.key_range.clone(),
154 420817 : lsn: self.lsn_range.start,
155 420817 : }
156 420817 : }
157 :
158 978548 : pub fn filename(&self) -> LayerFileName {
159 978548 : if self.is_delta {
160 557731 : self.delta_file_name().into()
161 : } else {
162 420817 : self.image_file_name().into()
163 : }
164 978548 : }
165 :
166 : // TODO: remove this in the future once we refactor timeline APIs.
167 :
168 29074365 : pub fn get_lsn_range(&self) -> Range<Lsn> {
169 29074365 : self.lsn_range.clone()
170 29074365 : }
171 :
172 2216596 : pub fn get_key_range(&self) -> Range<Key> {
173 2216596 : self.key_range.clone()
174 2216596 : }
175 :
176 UBC 0 : pub fn get_timeline_id(&self) -> TimelineId {
177 0 : self.timeline_id
178 0 : }
179 :
180 : /// Does this layer only contain some data for the key-range (incremental),
181 : /// or does it contain a version of every page? This is important to know
182 : /// for garbage collecting old layers: an incremental layer depends on
183 : /// the previous non-incremental layer.
184 CBC 83227 : pub fn is_incremental(&self) -> bool {
185 83227 : self.is_delta
186 83227 : }
187 :
188 UBC 0 : pub fn is_delta(&self) -> bool {
189 0 : self.is_delta
190 0 : }
191 :
192 CBC 2 : pub fn dump(&self) {
193 2 : if self.is_delta {
194 2 : println!(
195 2 : "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
196 2 : self.tenant_shard_id,
197 2 : self.timeline_id,
198 2 : self.key_range.start,
199 2 : self.key_range.end,
200 2 : self.lsn_range.start,
201 2 : self.lsn_range.end,
202 2 : self.is_incremental(),
203 2 : self.file_size,
204 2 : );
205 2 : } else {
206 UBC 0 : println!(
207 0 : "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
208 0 : self.tenant_shard_id,
209 0 : self.timeline_id,
210 0 : self.key_range.start,
211 0 : self.key_range.end,
212 0 : self.image_layer_lsn(),
213 0 : self.is_incremental(),
214 0 : self.file_size
215 0 : );
216 0 : }
217 CBC 2 : }
218 :
219 366239 : pub fn file_size(&self) -> u64 {
220 366239 : self.file_size
221 366239 : }
222 : }
|