LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_name.rs (source / functions) Coverage Total Hit
Test: 2a9d99866121f170b43760bd62e1e2431e597707.info Lines: 68.4 % 231 158
Test Date: 2024-09-02 14:10:37 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            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              : }
        

Generated by: LCOV version 2.1-beta