LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_name.rs (source / functions) Coverage Total Hit
Test: 050dd70dd490b28fffe527eae9fb8a1222b5c59c.info Lines: 65.5 % 223 146
Test Date: 2024-06-25 21:28:46 Functions: 50.0 % 30 15

            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          114 :     pub fn parse_str(fname: &str) -> Option<Self> {
      69          114 :         let mut parts = fname.split("__");
      70          114 :         let mut key_parts = parts.next()?.split('-');
      71          114 :         let mut lsn_parts = parts.next()?.split('-');
      72              : 
      73          114 :         let key_start_str = key_parts.next()?;
      74          114 :         let key_end_str = key_parts.next()?;
      75          114 :         let lsn_start_str = lsn_parts.next()?;
      76          114 :         let lsn_end_str = lsn_parts.next()?;
      77              : 
      78           98 :         if parts.next().is_some() || key_parts.next().is_some() || key_parts.next().is_some() {
      79            0 :             return None;
      80           98 :         }
      81           98 : 
      82           98 :         if key_start_str.len() != 36
      83           98 :             || key_end_str.len() != 36
      84           98 :             || lsn_start_str.len() != 16
      85           98 :             || lsn_end_str.len() != 16
      86              :         {
      87            0 :             return None;
      88           98 :         }
      89              : 
      90           98 :         let key_start = Key::from_hex(key_start_str).ok()?;
      91           98 :         let key_end = Key::from_hex(key_end_str).ok()?;
      92              : 
      93           98 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      94           98 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      95              : 
      96           98 :         if start_lsn >= end_lsn {
      97            0 :             return None;
      98              :             // or panic?
      99           98 :         }
     100           98 : 
     101           98 :         if key_start >= key_end {
     102            0 :             return None;
     103              :             // or panic?
     104           98 :         }
     105           98 : 
     106           98 :         Some(DeltaLayerName {
     107           98 :             key_range: key_start..key_end,
     108           98 :             lsn_range: start_lsn..end_lsn,
     109           98 :         })
     110          114 :     }
     111              : }
     112              : 
     113              : impl fmt::Display for DeltaLayerName {
     114        39133 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     115        39133 :         write!(
     116        39133 :             f,
     117        39133 :             "{}-{}__{:016X}-{:016X}",
     118        39133 :             self.key_range.start,
     119        39133 :             self.key_range.end,
     120        39133 :             u64::from(self.lsn_range.start),
     121        39133 :             u64::from(self.lsn_range.end),
     122        39133 :         )
     123        39133 :     }
     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            0 :     pub fn lsn_as_range(&self) -> Range<Lsn> {
     167            0 :         // Saves from having to copypaste this all over
     168            0 :         PersistentLayerDesc::image_layer_lsn_range(self.lsn)
     169            0 :     }
     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          114 :     pub fn parse_str(fname: &str) -> Option<Self> {
     182          114 :         let mut parts = fname.split("__");
     183          114 :         let mut key_parts = parts.next()?.split('-');
     184              : 
     185          114 :         let key_start_str = key_parts.next()?;
     186          114 :         let key_end_str = key_parts.next()?;
     187          114 :         let lsn_str = parts.next()?;
     188          114 :         if parts.next().is_some() || key_parts.next().is_some() {
     189            0 :             return None;
     190          114 :         }
     191          114 : 
     192          114 :         if key_start_str.len() != 36 || key_end_str.len() != 36 || lsn_str.len() != 16 {
     193           98 :             return None;
     194           16 :         }
     195              : 
     196           16 :         let key_start = Key::from_hex(key_start_str).ok()?;
     197           16 :         let key_end = Key::from_hex(key_end_str).ok()?;
     198              : 
     199           16 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     200              : 
     201           16 :         Some(ImageLayerName {
     202           16 :             key_range: key_start..key_end,
     203           16 :             lsn,
     204           16 :         })
     205          114 :     }
     206              : }
     207              : 
     208              : impl fmt::Display for ImageLayerName {
     209         3238 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     210         3238 :         write!(
     211         3238 :             f,
     212         3238 :             "{}-{}__{:016X}",
     213         3238 :             self.key_range.start,
     214         3238 :             self.key_range.end,
     215         3238 :             u64::from(self.lsn),
     216         3238 :         )
     217         3238 :     }
     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        17327 :     pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
     236              :         use LayerName::*;
     237         1015 :         match self {
     238         1015 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     239        16312 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     240        17321 :             _ => false,
     241              :         }
     242        17327 :     }
     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              : 
     253              : impl fmt::Display for LayerName {
     254         6881 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     255         6881 :         match self {
     256          909 :             Self::Image(fname) => write!(f, "{fname}"),
     257         5972 :             Self::Delta(fname) => write!(f, "{fname}"),
     258              :         }
     259         6881 :     }
     260              : }
     261              : 
     262              : impl From<ImageLayerName> for LayerName {
     263         1077 :     fn from(fname: ImageLayerName) -> Self {
     264         1077 :         Self::Image(fname)
     265         1077 :     }
     266              : }
     267              : impl From<DeltaLayerName> for LayerName {
     268         7610 :     fn from(fname: DeltaLayerName) -> Self {
     269         7610 :         Self::Delta(fname)
     270         7610 :     }
     271              : }
     272              : 
     273              : impl FromStr for LayerName {
     274              :     type Err = String;
     275              : 
     276              :     /// Conversion from either a physical layer filename, or the string-ization of
     277              :     /// Self. When loading a physical layer filename, we drop any extra information
     278              :     /// not needed to build Self.
     279          114 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     280          114 :         let gen_suffix_regex = Regex::new("^(?<base>.+)(?<gen>-v1-[0-9a-f]{8})$").unwrap();
     281          114 :         let file_name: Cow<str> = match gen_suffix_regex.captures(value) {
     282           20 :             Some(captures) => captures
     283           20 :                 .name("base")
     284           20 :                 .expect("Non-optional group")
     285           20 :                 .as_str()
     286           20 :                 .into(),
     287           94 :             None => value.into(),
     288              :         };
     289              : 
     290          114 :         let delta = DeltaLayerName::parse_str(&file_name);
     291          114 :         let image = ImageLayerName::parse_str(&file_name);
     292          114 :         let ok = match (delta, image) {
     293              :             (None, None) => {
     294            0 :                 return Err(format!(
     295            0 :                     "neither delta nor image layer file name: {value:?}"
     296            0 :                 ))
     297              :             }
     298           98 :             (Some(delta), None) => Self::Delta(delta),
     299           16 :             (None, Some(image)) => Self::Image(image),
     300            0 :             (Some(_), Some(_)) => unreachable!(),
     301              :         };
     302          114 :         Ok(ok)
     303          114 :     }
     304              : }
     305              : 
     306              : impl serde::Serialize for LayerName {
     307        35251 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     308        35251 :     where
     309        35251 :         S: serde::Serializer,
     310        35251 :     {
     311        35251 :         match self {
     312         2090 :             Self::Image(fname) => serializer.collect_str(fname),
     313        33161 :             Self::Delta(fname) => serializer.collect_str(fname),
     314              :         }
     315        35251 :     }
     316              : }
     317              : 
     318              : impl<'de> serde::Deserialize<'de> for LayerName {
     319           52 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     320           52 :     where
     321           52 :         D: serde::Deserializer<'de>,
     322           52 :     {
     323           52 :         deserializer.deserialize_string(LayerNameVisitor)
     324           52 :     }
     325              : }
     326              : 
     327              : struct LayerNameVisitor;
     328              : 
     329              : impl<'de> serde::de::Visitor<'de> for LayerNameVisitor {
     330              :     type Value = LayerName;
     331              : 
     332            0 :     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
     333            0 :         write!(
     334            0 :             formatter,
     335            0 :             "a string that is a valid image or delta layer file name"
     336            0 :         )
     337            0 :     }
     338           52 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     339           52 :     where
     340           52 :         E: serde::de::Error,
     341           52 :     {
     342           52 :         v.parse().map_err(|e| E::custom(e))
     343           52 :     }
     344              : }
     345              : 
     346              : #[cfg(test)]
     347              : mod test {
     348              :     use super::*;
     349              :     #[test]
     350            2 :     fn image_layer_parse() {
     351            2 :         let expected = LayerName::Image(ImageLayerName {
     352            2 :             key_range: Key::from_i128(0)
     353            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     354            2 :             lsn: Lsn::from_hex("00000000014FED58").unwrap(),
     355            2 :         });
     356            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-v1-00000001").unwrap();
     357            2 :         assert_eq!(parsed, expected,);
     358              : 
     359              :         // Omitting generation suffix is valid
     360            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58").unwrap();
     361            2 :         assert_eq!(parsed, expected,);
     362            2 :     }
     363              : 
     364              :     #[test]
     365            2 :     fn delta_layer_parse() {
     366            2 :         let expected = LayerName::Delta(DeltaLayerName {
     367            2 :             key_range: Key::from_i128(0)
     368            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     369            2 :             lsn_range: Lsn::from_hex("00000000014FED58").unwrap()
     370            2 :                 ..Lsn::from_hex("000000000154C481").unwrap(),
     371            2 :         });
     372            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-v1-00000001").unwrap();
     373            2 :         assert_eq!(parsed, expected);
     374              : 
     375              :         // Omitting generation suffix is valid
     376            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481").unwrap();
     377            2 :         assert_eq!(parsed, expected);
     378            2 :     }
     379              : }
        

Generated by: LCOV version 2.1-beta