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