LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_name.rs (source / functions) Coverage Total Hit
Test: b4ae4c4857f9ef3e144e982a35ee23bc84c71983.info Lines: 69.9 % 226 158
Test Date: 2024-10-22 22:13:45 Functions: 57.6 % 33 19

            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              :         use super::RangeDisplayDebug;
      26              : 
      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         3258 :     pub fn parse_str(fname: &str) -> Option<Self> {
      69         3258 :         let mut parts = fname.split("__");
      70         3258 :         let mut key_parts = parts.next()?.split('-');
      71         3258 :         let mut lsn_parts = parts.next()?.split('-');
      72              : 
      73         3258 :         let key_start_str = key_parts.next()?;
      74         3258 :         let key_end_str = key_parts.next()?;
      75         3258 :         let lsn_start_str = lsn_parts.next()?;
      76         3258 :         let lsn_end_str = lsn_parts.next()?;
      77              : 
      78         1638 :         if parts.next().is_some() || key_parts.next().is_some() || key_parts.next().is_some() {
      79            0 :             return None;
      80         1638 :         }
      81         1638 : 
      82         1638 :         if key_start_str.len() != 36
      83         1638 :             || key_end_str.len() != 36
      84         1638 :             || lsn_start_str.len() != 16
      85         1638 :             || lsn_end_str.len() != 16
      86              :         {
      87            0 :             return None;
      88         1638 :         }
      89              : 
      90         1638 :         let key_start = Key::from_hex(key_start_str).ok()?;
      91         1638 :         let key_end = Key::from_hex(key_end_str).ok()?;
      92              : 
      93         1638 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      94         1638 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      95              : 
      96         1638 :         if start_lsn >= end_lsn {
      97            0 :             return None;
      98              :             // or panic?
      99         1638 :         }
     100         1638 : 
     101         1638 :         if key_start >= key_end {
     102            0 :             return None;
     103              :             // or panic?
     104         1638 :         }
     105         1638 : 
     106         1638 :         Some(DeltaLayerName {
     107         1638 :             key_range: key_start..key_end,
     108         1638 :             lsn_range: start_lsn..end_lsn,
     109         1638 :         })
     110         3258 :     }
     111              : }
     112              : 
     113              : impl fmt::Display for DeltaLayerName {
     114        38110 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     115        38110 :         write!(
     116        38110 :             f,
     117        38110 :             "{}-{}__{:016X}-{:016X}",
     118        38110 :             self.key_range.start,
     119        38110 :             self.key_range.end,
     120        38110 :             u64::from(self.lsn_range.start),
     121        38110 :             u64::from(self.lsn_range.end),
     122        38110 :         )
     123        38110 :     }
     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              :         use super::RangeDisplayDebug;
     135              : 
     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         1604 :     pub fn lsn_as_range(&self) -> Range<Lsn> {
     167         1604 :         // Saves from having to copypaste this all over
     168         1604 :         PersistentLayerDesc::image_layer_lsn_range(self.lsn)
     169         1604 :     }
     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         3258 :     pub fn parse_str(fname: &str) -> Option<Self> {
     182         3258 :         let mut parts = fname.split("__");
     183         3258 :         let mut key_parts = parts.next()?.split('-');
     184              : 
     185         3258 :         let key_start_str = key_parts.next()?;
     186         3258 :         let key_end_str = key_parts.next()?;
     187         3258 :         let lsn_str = parts.next()?;
     188         3258 :         if parts.next().is_some() || key_parts.next().is_some() {
     189            0 :             return None;
     190         3258 :         }
     191         3258 : 
     192         3258 :         if key_start_str.len() != 36 || key_end_str.len() != 36 || lsn_str.len() != 16 {
     193         1638 :             return None;
     194         1620 :         }
     195              : 
     196         1620 :         let key_start = Key::from_hex(key_start_str).ok()?;
     197         1620 :         let key_end = Key::from_hex(key_end_str).ok()?;
     198              : 
     199         1620 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     200              : 
     201         1620 :         Some(ImageLayerName {
     202         1620 :             key_range: key_start..key_end,
     203         1620 :             lsn,
     204         1620 :         })
     205         3258 :     }
     206              : }
     207              : 
     208              : impl fmt::Display for ImageLayerName {
     209         3502 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     210         3502 :         write!(
     211         3502 :             f,
     212         3502 :             "{}-{}__{:016X}",
     213         3502 :             self.key_range.start,
     214         3502 :             self.key_range.end,
     215         3502 :             u64::from(self.lsn),
     216         3502 :         )
     217         3502 :     }
     218              : }
     219              : 
     220              : /// LayerName is the logical identity of a layer within a LayerMap at a moment in time.
     221              : ///
     222              : /// The LayerName is not a unique filename, as the same LayerName may have multiple physical incarnations
     223              : /// over time (e.g. across shard splits or compression). The physical filenames of layers in local
     224              : /// storage and object names in remote storage consist of the LayerName plus some extra qualifiers
     225              : /// that uniquely identify the physical incarnation of a layer (see [crate::tenant::remote_timeline_client::remote_layer_path])
     226              : /// and [`crate::tenant::storage_layer::layer::local_layer_path`])
     227              : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
     228              : pub enum LayerName {
     229              :     Image(ImageLayerName),
     230              :     Delta(DeltaLayerName),
     231              : }
     232              : 
     233              : impl LayerName {
     234              :     /// Determines if this layer file is considered to be in future meaning we will discard these
     235              :     /// layers during timeline initialization from the given disk_consistent_lsn.
     236        17633 :     pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
     237              :         use LayerName::*;
     238         1072 :         match self {
     239         1072 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     240        16561 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     241        17620 :             _ => false,
     242              :         }
     243        17633 :     }
     244              : 
     245            0 :     pub(crate) fn kind(&self) -> &'static str {
     246              :         use LayerName::*;
     247            0 :         match self {
     248            0 :             Delta(_) => "delta",
     249            0 :             Image(_) => "image",
     250              :         }
     251            0 :     }
     252              : 
     253              :     /// Gets the key range encoded in the layer name.
     254            8 :     pub fn key_range(&self) -> &Range<Key> {
     255            8 :         match &self {
     256            4 :             LayerName::Image(layer) => &layer.key_range,
     257            4 :             LayerName::Delta(layer) => &layer.key_range,
     258              :         }
     259            8 :     }
     260              : 
     261            8 :     pub fn is_delta(&self) -> bool {
     262            8 :         matches!(self, LayerName::Delta(_))
     263            8 :     }
     264              : }
     265              : 
     266              : impl fmt::Display for LayerName {
     267         5651 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     268         5651 :         match self {
     269          818 :             Self::Image(fname) => write!(f, "{fname}"),
     270         4833 :             Self::Delta(fname) => write!(f, "{fname}"),
     271              :         }
     272         5651 :     }
     273              : }
     274              : 
     275              : impl From<ImageLayerName> for LayerName {
     276         1150 :     fn from(fname: ImageLayerName) -> Self {
     277         1150 :         Self::Image(fname)
     278         1150 :     }
     279              : }
     280              : impl From<DeltaLayerName> for LayerName {
     281         6579 :     fn from(fname: DeltaLayerName) -> Self {
     282         6579 :         Self::Delta(fname)
     283         6579 :     }
     284              : }
     285              : 
     286              : impl FromStr for LayerName {
     287              :     type Err = String;
     288              : 
     289              :     /// Conversion from either a physical layer filename, or the string-ization of
     290              :     /// Self. When loading a physical layer filename, we drop any extra information
     291              :     /// not needed to build Self.
     292         3258 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     293         3258 :         let gen_suffix_regex = Regex::new("^(?<base>.+)(?<gen>-v1-[0-9a-f]{8})$").unwrap();
     294         3258 :         let file_name: Cow<str> = match gen_suffix_regex.captures(value) {
     295           20 :             Some(captures) => captures
     296           20 :                 .name("base")
     297           20 :                 .expect("Non-optional group")
     298           20 :                 .as_str()
     299           20 :                 .into(),
     300         3238 :             None => value.into(),
     301              :         };
     302              : 
     303         3258 :         let delta = DeltaLayerName::parse_str(&file_name);
     304         3258 :         let image = ImageLayerName::parse_str(&file_name);
     305         3258 :         let ok = match (delta, image) {
     306              :             (None, None) => {
     307            0 :                 return Err(format!(
     308            0 :                     "neither delta nor image layer file name: {value:?}"
     309            0 :                 ))
     310              :             }
     311         1638 :             (Some(delta), None) => Self::Delta(delta),
     312         1620 :             (None, Some(image)) => Self::Image(image),
     313            0 :             (Some(_), Some(_)) => unreachable!(),
     314              :         };
     315         3258 :         Ok(ok)
     316         3258 :     }
     317              : }
     318              : 
     319              : impl serde::Serialize for LayerName {
     320        35471 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     321        35471 :     where
     322        35471 :         S: serde::Serializer,
     323        35471 :     {
     324        35471 :         match self {
     325         2194 :             Self::Image(fname) => serializer.collect_str(fname),
     326        33277 :             Self::Delta(fname) => serializer.collect_str(fname),
     327              :         }
     328        35471 :     }
     329              : }
     330              : 
     331              : impl<'de> serde::Deserialize<'de> for LayerName {
     332         3188 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     333         3188 :     where
     334         3188 :         D: serde::Deserializer<'de>,
     335         3188 :     {
     336         3188 :         deserializer.deserialize_string(LayerNameVisitor)
     337         3188 :     }
     338              : }
     339              : 
     340              : struct LayerNameVisitor;
     341              : 
     342              : impl serde::de::Visitor<'_> for LayerNameVisitor {
     343              :     type Value = LayerName;
     344              : 
     345            0 :     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
     346            0 :         write!(
     347            0 :             formatter,
     348            0 :             "a string that is a valid image or delta layer file name"
     349            0 :         )
     350            0 :     }
     351         3188 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     352         3188 :     where
     353         3188 :         E: serde::de::Error,
     354         3188 :     {
     355         3188 :         v.parse().map_err(|e| E::custom(e))
     356         3188 :     }
     357              : }
     358              : 
     359              : #[cfg(test)]
     360              : mod test {
     361              :     use super::*;
     362              :     #[test]
     363            2 :     fn image_layer_parse() {
     364            2 :         let expected = LayerName::Image(ImageLayerName {
     365            2 :             key_range: Key::from_i128(0)
     366            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     367            2 :             lsn: Lsn::from_hex("00000000014FED58").unwrap(),
     368            2 :         });
     369            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-v1-00000001").unwrap();
     370            2 :         assert_eq!(parsed, expected,);
     371              : 
     372              :         // Omitting generation suffix is valid
     373            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58").unwrap();
     374            2 :         assert_eq!(parsed, expected,);
     375            2 :     }
     376              : 
     377              :     #[test]
     378            2 :     fn delta_layer_parse() {
     379            2 :         let expected = LayerName::Delta(DeltaLayerName {
     380            2 :             key_range: Key::from_i128(0)
     381            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     382            2 :             lsn_range: Lsn::from_hex("00000000014FED58").unwrap()
     383            2 :                 ..Lsn::from_hex("000000000154C481").unwrap(),
     384            2 :         });
     385            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-v1-00000001").unwrap();
     386            2 :         assert_eq!(parsed, expected);
     387              : 
     388              :         // Omitting generation suffix is valid
     389            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481").unwrap();
     390            2 :         assert_eq!(parsed, expected);
     391            2 :     }
     392              : }
        

Generated by: LCOV version 2.1-beta