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