Line data Source code
1 : //!
2 : //! Helper functions for dealing with filenames of the image and delta layer files.
3 : //!
4 : use std::cmp::Ordering;
5 : use std::fmt;
6 : use std::ops::Range;
7 : use std::str::FromStr;
8 :
9 : use pageserver_api::key::Key;
10 : use utils::lsn::Lsn;
11 :
12 : use super::PersistentLayerDesc;
13 :
14 : // Note: Timeline::load_layer_map() relies on this sort order
15 : #[derive(PartialEq, Eq, Clone, Hash)]
16 : pub struct DeltaLayerName {
17 : pub key_range: Range<Key>,
18 : pub lsn_range: Range<Lsn>,
19 : }
20 :
21 : impl std::fmt::Debug for DeltaLayerName {
22 0 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 : use super::RangeDisplayDebug;
24 :
25 0 : f.debug_struct("DeltaLayerName")
26 0 : .field("key_range", &RangeDisplayDebug(&self.key_range))
27 0 : .field("lsn_range", &self.lsn_range)
28 0 : .finish()
29 0 : }
30 : }
31 :
32 : impl PartialOrd for DeltaLayerName {
33 0 : fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
34 0 : Some(self.cmp(other))
35 0 : }
36 : }
37 :
38 : impl Ord for DeltaLayerName {
39 0 : fn cmp(&self, other: &Self) -> Ordering {
40 0 : let mut cmp = self.key_range.start.cmp(&other.key_range.start);
41 0 : if cmp != Ordering::Equal {
42 0 : return cmp;
43 0 : }
44 0 : cmp = self.key_range.end.cmp(&other.key_range.end);
45 0 : if cmp != Ordering::Equal {
46 0 : return cmp;
47 0 : }
48 0 : cmp = self.lsn_range.start.cmp(&other.lsn_range.start);
49 0 : if cmp != Ordering::Equal {
50 0 : return cmp;
51 0 : }
52 0 : cmp = self.lsn_range.end.cmp(&other.lsn_range.end);
53 0 :
54 0 : cmp
55 0 : }
56 : }
57 :
58 : /// Represents the region of the LSN-Key space covered by a DeltaLayer
59 : ///
60 : /// ```text
61 : /// <key start>-<key end>__<LSN start>-<LSN end>-<generation>
62 : /// ```
63 : impl DeltaLayerName {
64 : /// Parse the part of a delta layer's file name that represents the LayerName. Returns None
65 : /// if the filename does not match the expected pattern.
66 6768 : pub fn parse_str(fname: &str) -> Option<Self> {
67 6768 : let (key_parts, lsn_generation_parts) = fname.split_once("__")?;
68 6768 : let (key_start_str, key_end_str) = key_parts.split_once('-')?;
69 6768 : let (lsn_start_str, lsn_end_generation_parts) = lsn_generation_parts.split_once('-')?;
70 3540 : let lsn_end_str = if let Some((lsn_end_str, maybe_generation)) =
71 3540 : lsn_end_generation_parts.split_once('-')
72 : {
73 44 : if maybe_generation.starts_with("v") {
74 : // vY-XXXXXXXX
75 28 : lsn_end_str
76 16 : } else if maybe_generation.len() == 8 {
77 : // XXXXXXXX
78 16 : lsn_end_str
79 : } else {
80 : // no idea what this is
81 0 : return None;
82 : }
83 : } else {
84 3496 : lsn_end_generation_parts
85 : };
86 :
87 3540 : let key_start = Key::from_hex(key_start_str).ok()?;
88 3540 : let key_end = Key::from_hex(key_end_str).ok()?;
89 :
90 3540 : let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
91 3540 : let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
92 :
93 3528 : if start_lsn >= end_lsn {
94 4 : return None;
95 : // or panic?
96 3524 : }
97 3524 :
98 3524 : if key_start >= key_end {
99 0 : return None;
100 : // or panic?
101 3524 : }
102 3524 :
103 3524 : Some(DeltaLayerName {
104 3524 : key_range: key_start..key_end,
105 3524 : lsn_range: start_lsn..end_lsn,
106 3524 : })
107 6768 : }
108 : }
109 :
110 : impl fmt::Display for DeltaLayerName {
111 78134 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 78134 : write!(
113 78134 : f,
114 78134 : "{}-{}__{:016X}-{:016X}",
115 78134 : self.key_range.start,
116 78134 : self.key_range.end,
117 78134 : u64::from(self.lsn_range.start),
118 78134 : u64::from(self.lsn_range.end),
119 78134 : )
120 78134 : }
121 : }
122 :
123 : #[derive(PartialEq, Eq, Clone, Hash)]
124 : pub struct ImageLayerName {
125 : pub key_range: Range<Key>,
126 : pub lsn: Lsn,
127 : }
128 :
129 : impl std::fmt::Debug for ImageLayerName {
130 0 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 : use super::RangeDisplayDebug;
132 :
133 0 : f.debug_struct("ImageLayerName")
134 0 : .field("key_range", &RangeDisplayDebug(&self.key_range))
135 0 : .field("lsn", &self.lsn)
136 0 : .finish()
137 0 : }
138 : }
139 :
140 : impl PartialOrd for ImageLayerName {
141 0 : fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
142 0 : Some(self.cmp(other))
143 0 : }
144 : }
145 :
146 : impl Ord for ImageLayerName {
147 0 : fn cmp(&self, other: &Self) -> Ordering {
148 0 : let mut cmp = self.key_range.start.cmp(&other.key_range.start);
149 0 : if cmp != Ordering::Equal {
150 0 : return cmp;
151 0 : }
152 0 : cmp = self.key_range.end.cmp(&other.key_range.end);
153 0 : if cmp != Ordering::Equal {
154 0 : return cmp;
155 0 : }
156 0 : cmp = self.lsn.cmp(&other.lsn);
157 0 :
158 0 : cmp
159 0 : }
160 : }
161 :
162 : impl ImageLayerName {
163 3208 : pub fn lsn_as_range(&self) -> Range<Lsn> {
164 3208 : // Saves from having to copypaste this all over
165 3208 : PersistentLayerDesc::image_layer_lsn_range(self.lsn)
166 3208 : }
167 : }
168 :
169 : ///
170 : /// Represents the part of the Key-LSN space covered by an ImageLayer
171 : ///
172 : /// ```text
173 : /// <key start>-<key end>__<LSN>-<generation>
174 : /// ```
175 : impl ImageLayerName {
176 : /// Parse a string as then LayerName part of an image layer file name. Returns None if the
177 : /// filename does not match the expected pattern.
178 6768 : pub fn parse_str(fname: &str) -> Option<Self> {
179 6768 : let (key_parts, lsn_generation_parts) = fname.split_once("__")?;
180 6768 : let (key_start_str, key_end_str) = key_parts.split_once('-')?;
181 3244 : let lsn_str =
182 6768 : if let Some((lsn_str, maybe_generation)) = lsn_generation_parts.split_once('-') {
183 3540 : if maybe_generation.starts_with("v") {
184 : // vY-XXXXXXXX
185 12 : lsn_str
186 3528 : } else if maybe_generation.len() == 8 {
187 : // XXXXXXXX
188 4 : lsn_str
189 : } else {
190 : // likely a delta layer
191 3524 : return None;
192 : }
193 : } else {
194 3228 : lsn_generation_parts
195 : };
196 :
197 3244 : let key_start = Key::from_hex(key_start_str).ok()?;
198 3244 : let key_end = Key::from_hex(key_end_str).ok()?;
199 :
200 3244 : let lsn = Lsn::from_hex(lsn_str).ok()?;
201 :
202 3244 : Some(ImageLayerName {
203 3244 : key_range: key_start..key_end,
204 3244 : lsn,
205 3244 : })
206 6768 : }
207 : }
208 :
209 : impl fmt::Display for ImageLayerName {
210 9234 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 9234 : write!(
212 9234 : f,
213 9234 : "{}-{}__{:016X}",
214 9234 : self.key_range.start,
215 9234 : self.key_range.end,
216 9234 : u64::from(self.lsn),
217 9234 : )
218 9234 : }
219 : }
220 :
221 : /// LayerName is the logical identity of a layer within a LayerMap at a moment in time.
222 : ///
223 : /// The LayerName is not a unique filename, as the same LayerName may have multiple physical incarnations
224 : /// over time (e.g. across shard splits or compression). The physical filenames of layers in local
225 : /// storage and object names in remote storage consist of the LayerName plus some extra qualifiers
226 : /// that uniquely identify the physical incarnation of a layer (see [crate::tenant::remote_timeline_client::remote_layer_path])
227 : /// and [`crate::tenant::storage_layer::layer::local_layer_path`])
228 : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
229 : pub enum LayerName {
230 : Image(ImageLayerName),
231 : Delta(DeltaLayerName),
232 : }
233 :
234 : impl LayerName {
235 : /// Determines if this layer file is considered to be in future meaning we will discard these
236 : /// layers during timeline initialization from the given disk_consistent_lsn.
237 35358 : pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
238 : use LayerName::*;
239 2288 : match self {
240 2288 : Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
241 33070 : Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
242 35232 : _ => false,
243 : }
244 35358 : }
245 :
246 0 : pub(crate) fn kind(&self) -> &'static str {
247 : use LayerName::*;
248 0 : match self {
249 0 : Delta(_) => "delta",
250 0 : Image(_) => "image",
251 : }
252 0 : }
253 :
254 : /// Gets the key range encoded in the layer name.
255 16 : pub fn key_range(&self) -> &Range<Key> {
256 16 : match &self {
257 8 : LayerName::Image(layer) => &layer.key_range,
258 8 : LayerName::Delta(layer) => &layer.key_range,
259 : }
260 16 : }
261 :
262 : /// Gets the LSN range encoded in the layer name.
263 0 : pub fn lsn_as_range(&self) -> Range<Lsn> {
264 0 : match &self {
265 0 : LayerName::Image(layer) => layer.lsn_as_range(),
266 0 : LayerName::Delta(layer) => layer.lsn_range.clone(),
267 : }
268 0 : }
269 :
270 16 : pub fn is_delta(&self) -> bool {
271 16 : matches!(self, LayerName::Delta(_))
272 16 : }
273 : }
274 :
275 : impl fmt::Display for LayerName {
276 13431 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 13431 : match self {
278 2386 : Self::Image(fname) => write!(f, "{fname}"),
279 11045 : Self::Delta(fname) => write!(f, "{fname}"),
280 : }
281 13431 : }
282 : }
283 :
284 : impl From<ImageLayerName> for LayerName {
285 7575 : fn from(fname: ImageLayerName) -> Self {
286 7575 : Self::Image(fname)
287 7575 : }
288 : }
289 : impl From<DeltaLayerName> for LayerName {
290 1959226 : fn from(fname: DeltaLayerName) -> Self {
291 1959226 : Self::Delta(fname)
292 1959226 : }
293 : }
294 :
295 : impl FromStr for LayerName {
296 : type Err = String;
297 :
298 : /// Conversion from either a physical layer filename, or the string-ization of
299 : /// Self. When loading a physical layer filename, we drop any extra information
300 : /// not needed to build Self.
301 6768 : fn from_str(value: &str) -> Result<Self, Self::Err> {
302 6768 : let delta = DeltaLayerName::parse_str(value);
303 6768 : let image = ImageLayerName::parse_str(value);
304 6768 : let ok = match (delta, image) {
305 : (None, None) => {
306 0 : return Err(format!(
307 0 : "neither delta nor image layer file name: {value:?}"
308 0 : ));
309 : }
310 3524 : (Some(delta), None) => Self::Delta(delta),
311 3244 : (None, Some(image)) => Self::Image(image),
312 0 : (Some(_), Some(_)) => unreachable!(),
313 : };
314 6768 : Ok(ok)
315 6768 : }
316 : }
317 :
318 : impl serde::Serialize for LayerName {
319 72237 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
320 72237 : where
321 72237 : S: serde::Serializer,
322 72237 : {
323 72237 : match self {
324 5148 : Self::Image(fname) => serializer.collect_str(fname),
325 67089 : Self::Delta(fname) => serializer.collect_str(fname),
326 : }
327 72237 : }
328 : }
329 :
330 : impl<'de> serde::Deserialize<'de> for LayerName {
331 6400 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
332 6400 : where
333 6400 : D: serde::Deserializer<'de>,
334 6400 : {
335 6400 : deserializer.deserialize_string(LayerNameVisitor)
336 6400 : }
337 : }
338 :
339 : struct LayerNameVisitor;
340 :
341 : impl serde::de::Visitor<'_> for LayerNameVisitor {
342 : type Value = LayerName;
343 :
344 0 : fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
345 0 : write!(
346 0 : formatter,
347 0 : "a string that is a valid image or delta layer file name"
348 0 : )
349 0 : }
350 6400 : fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
351 6400 : where
352 6400 : E: serde::de::Error,
353 6400 : {
354 6400 : v.parse().map_err(|e| E::custom(e))
355 6400 : }
356 : }
357 :
358 : #[cfg(test)]
359 : mod test {
360 : use super::*;
361 : #[test]
362 4 : fn image_layer_parse() {
363 4 : let expected = LayerName::Image(ImageLayerName {
364 4 : key_range: Key::from_i128(0)
365 4 : ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
366 4 : lsn: Lsn::from_hex("00000000014FED58").unwrap(),
367 4 : });
368 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-v1-00000001").unwrap();
369 4 : assert_eq!(parsed, expected);
370 :
371 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-00000001").unwrap();
372 4 : assert_eq!(parsed, expected);
373 :
374 : // Omitting generation suffix is valid
375 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58").unwrap();
376 4 : assert_eq!(parsed, expected);
377 4 : }
378 :
379 : #[test]
380 4 : fn delta_layer_parse() {
381 4 : let expected = LayerName::Delta(DeltaLayerName {
382 4 : key_range: Key::from_i128(0)
383 4 : ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
384 4 : lsn_range: Lsn::from_hex("00000000014FED58").unwrap()
385 4 : ..Lsn::from_hex("000000000154C481").unwrap(),
386 4 : });
387 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-v1-00000001").unwrap();
388 4 : assert_eq!(parsed, expected);
389 :
390 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-00000001").unwrap();
391 4 : assert_eq!(parsed, expected);
392 :
393 : // Omitting generation suffix is valid
394 4 : let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481").unwrap();
395 4 : assert_eq!(parsed, expected);
396 4 : }
397 : }
|