LCOV - differential code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - filename.rs (source / functions) Coverage Total Hit UBC CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 64.5 % 186 120 66 120
Current Date: 2023-10-19 02:04:12 Functions: 70.6 % 34 24 10 24
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  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::cmp::Ordering;
       6                 : use std::fmt;
       7                 : use std::ops::Range;
       8                 : use std::str::FromStr;
       9                 : 
      10                 : use utils::lsn::Lsn;
      11                 : 
      12                 : use super::PersistentLayerDesc;
      13                 : 
      14                 : // Note: Timeline::load_layer_map() relies on this sort order
      15 CBC      368294 : #[derive(PartialEq, Eq, Clone, Hash)]
      16                 : pub struct DeltaFileName {
      17                 :     pub key_range: Range<Key>,
      18                 :     pub lsn_range: Range<Lsn>,
      19                 : }
      20                 : 
      21                 : impl std::fmt::Debug for DeltaFileName {
      22 UBC           0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      23               0 :         use super::RangeDisplayDebug;
      24               0 : 
      25               0 :         f.debug_struct("DeltaFileName")
      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 DeltaFileName {
      33               0 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
      34               0 :         Some(self.cmp(other))
      35               0 :     }
      36                 : }
      37                 : 
      38                 : impl Ord for DeltaFileName {
      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 filename of a DeltaLayer
      59                 : ///
      60                 : /// ```text
      61                 : ///    <key start>-<key end>__<LSN start>-<LSN end>
      62                 : /// ```
      63                 : impl DeltaFileName {
      64                 :     ///
      65                 :     /// Parse a string as a delta file name. Returns None if the filename does not
      66                 :     /// match the expected pattern.
      67                 :     ///
      68 CBC       13822 :     pub fn parse_str(fname: &str) -> Option<Self> {
      69           13822 :         let mut parts = fname.split("__");
      70           13822 :         let mut key_parts = parts.next()?.split('-');
      71           13822 :         let mut lsn_parts = parts.next()?.split('-');
      72                 : 
      73           13431 :         let key_start_str = key_parts.next()?;
      74           13431 :         let key_end_str = key_parts.next()?;
      75           13431 :         let lsn_start_str = lsn_parts.next()?;
      76           13431 :         let lsn_end_str = lsn_parts.next()?;
      77            8175 :         if parts.next().is_some() || key_parts.next().is_some() || key_parts.next().is_some() {
      78               5 :             return None;
      79            8170 :         }
      80                 : 
      81            8170 :         let key_start = Key::from_hex(key_start_str).ok()?;
      82            8170 :         let key_end = Key::from_hex(key_end_str).ok()?;
      83                 : 
      84            8170 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      85            8170 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      86                 : 
      87            8170 :         if start_lsn >= end_lsn {
      88 UBC           0 :             return None;
      89                 :             // or panic?
      90 CBC        8170 :         }
      91            8170 : 
      92            8170 :         if key_start >= key_end {
      93 UBC           0 :             return None;
      94                 :             // or panic?
      95 CBC        8170 :         }
      96            8170 : 
      97            8170 :         Some(DeltaFileName {
      98            8170 :             key_range: key_start..key_end,
      99            8170 :             lsn_range: start_lsn..end_lsn,
     100            8170 :         })
     101           13822 :     }
     102                 : }
     103                 : 
     104                 : impl fmt::Display for DeltaFileName {
     105          413868 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     106          413868 :         write!(
     107          413868 :             f,
     108          413868 :             "{}-{}__{:016X}-{:016X}",
     109          413868 :             self.key_range.start,
     110          413868 :             self.key_range.end,
     111          413868 :             u64::from(self.lsn_range.start),
     112          413868 :             u64::from(self.lsn_range.end),
     113          413868 :         )
     114          413868 :     }
     115                 : }
     116                 : 
     117          160398 : #[derive(PartialEq, Eq, Clone, Hash)]
     118                 : pub struct ImageFileName {
     119                 :     pub key_range: Range<Key>,
     120                 :     pub lsn: Lsn,
     121                 : }
     122                 : 
     123                 : impl std::fmt::Debug for ImageFileName {
     124 UBC           0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     125               0 :         use super::RangeDisplayDebug;
     126               0 : 
     127               0 :         f.debug_struct("ImageFileName")
     128               0 :             .field("key_range", &RangeDisplayDebug(&self.key_range))
     129               0 :             .field("lsn", &self.lsn)
     130               0 :             .finish()
     131               0 :     }
     132                 : }
     133                 : 
     134                 : impl PartialOrd for ImageFileName {
     135               0 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
     136               0 :         Some(self.cmp(other))
     137               0 :     }
     138                 : }
     139                 : 
     140                 : impl Ord for ImageFileName {
     141               0 :     fn cmp(&self, other: &Self) -> Ordering {
     142               0 :         let mut cmp = self.key_range.start.cmp(&other.key_range.start);
     143               0 :         if cmp != Ordering::Equal {
     144               0 :             return cmp;
     145               0 :         }
     146               0 :         cmp = self.key_range.end.cmp(&other.key_range.end);
     147               0 :         if cmp != Ordering::Equal {
     148               0 :             return cmp;
     149               0 :         }
     150               0 :         cmp = self.lsn.cmp(&other.lsn);
     151               0 : 
     152               0 :         cmp
     153               0 :     }
     154                 : }
     155                 : 
     156                 : impl ImageFileName {
     157               0 :     pub fn lsn_as_range(&self) -> Range<Lsn> {
     158               0 :         // Saves from having to copypaste this all over
     159               0 :         PersistentLayerDesc::image_layer_lsn_range(self.lsn)
     160               0 :     }
     161                 : }
     162                 : 
     163                 : ///
     164                 : /// Represents the filename of an ImageLayer
     165                 : ///
     166                 : /// ```text
     167                 : ///    <key start>-<key end>__<LSN>
     168                 : /// ```
     169                 : impl ImageFileName {
     170                 :     ///
     171                 :     /// Parse a string as an image file name. Returns None if the filename does not
     172                 :     /// match the expected pattern.
     173                 :     ///
     174 CBC       13822 :     pub fn parse_str(fname: &str) -> Option<Self> {
     175           13822 :         let mut parts = fname.split("__");
     176           13822 :         let mut key_parts = parts.next()?.split('-');
     177                 : 
     178           13822 :         let key_start_str = key_parts.next()?;
     179           13822 :         let key_end_str = key_parts.next()?;
     180           13508 :         let lsn_str = parts.next()?;
     181           13431 :         if parts.next().is_some() || key_parts.next().is_some() {
     182               8 :             return None;
     183           13423 :         }
     184                 : 
     185           13423 :         let key_start = Key::from_hex(key_start_str).ok()?;
     186           13423 :         let key_end = Key::from_hex(key_end_str).ok()?;
     187                 : 
     188           13423 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     189                 : 
     190            5253 :         Some(ImageFileName {
     191            5253 :             key_range: key_start..key_end,
     192            5253 :             lsn,
     193            5253 :         })
     194           13822 :     }
     195                 : }
     196                 : 
     197                 : impl fmt::Display for ImageFileName {
     198          214378 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     199          214378 :         write!(
     200          214378 :             f,
     201          214378 :             "{}-{}__{:016X}",
     202          214378 :             self.key_range.start,
     203          214378 :             self.key_range.end,
     204          214378 :             u64::from(self.lsn),
     205          214378 :         )
     206          214378 :     }
     207                 : }
     208          528692 : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
     209                 : pub enum LayerFileName {
     210                 :     Image(ImageFileName),
     211                 :     Delta(DeltaFileName),
     212                 : }
     213                 : 
     214                 : impl LayerFileName {
     215           96858 :     pub fn file_name(&self) -> String {
     216           96858 :         self.to_string()
     217           96858 :     }
     218                 : 
     219                 :     /// Determines if this layer file is considered to be in future meaning we will discard these
     220                 :     /// layers during timeline initialization from the given disk_consistent_lsn.
     221                 :     pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
     222                 :         use LayerFileName::*;
     223          290877 :         match self {
     224          133429 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     225          290877 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     226          424287 :             _ => false,
     227                 :         }
     228          424306 :     }
     229                 : 
     230             268 :     pub(crate) fn kind(&self) -> &'static str {
     231             268 :         use LayerFileName::*;
     232             268 :         match self {
     233             268 :             Delta(_) => "delta",
     234 UBC           0 :             Image(_) => "image",
     235                 :         }
     236 CBC         268 :     }
     237                 : }
     238                 : 
     239                 : impl fmt::Display for LayerFileName {
     240          131581 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     241          131581 :         match self {
     242           68983 :             Self::Image(fname) => write!(f, "{fname}"),
     243           62598 :             Self::Delta(fname) => write!(f, "{fname}"),
     244                 :         }
     245          131581 :     }
     246                 : }
     247                 : 
     248                 : impl From<ImageFileName> for LayerFileName {
     249           61837 :     fn from(fname: ImageFileName) -> Self {
     250           61837 :         Self::Image(fname)
     251           61837 :     }
     252                 : }
     253                 : impl From<DeltaFileName> for LayerFileName {
     254           32233 :     fn from(fname: DeltaFileName) -> Self {
     255           32233 :         Self::Delta(fname)
     256           32233 :     }
     257                 : }
     258                 : 
     259                 : impl FromStr for LayerFileName {
     260                 :     type Err = String;
     261                 : 
     262           13822 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     263           13822 :         let delta = DeltaFileName::parse_str(value);
     264           13822 :         let image = ImageFileName::parse_str(value);
     265           13822 :         let ok = match (delta, image) {
     266                 :             (None, None) => {
     267             399 :                 return Err(format!(
     268             399 :                     "neither delta nor image layer file name: {value:?}"
     269             399 :                 ))
     270                 :             }
     271            8170 :             (Some(delta), None) => Self::Delta(delta),
     272            5253 :             (None, Some(image)) => Self::Image(image),
     273 UBC           0 :             (Some(_), Some(_)) => unreachable!(),
     274                 :         };
     275 CBC       13423 :         Ok(ok)
     276           13822 :     }
     277                 : }
     278                 : 
     279                 : impl serde::Serialize for LayerFileName {
     280          422277 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     281          422277 :     where
     282          422277 :         S: serde::Serializer,
     283          422277 :     {
     284          422277 :         match self {
     285          130309 :             Self::Image(fname) => serializer.collect_str(fname),
     286          291968 :             Self::Delta(fname) => serializer.collect_str(fname),
     287                 :         }
     288          422277 :     }
     289                 : }
     290                 : 
     291                 : impl<'de> serde::Deserialize<'de> for LayerFileName {
     292            8790 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     293            8790 :     where
     294            8790 :         D: serde::Deserializer<'de>,
     295            8790 :     {
     296            8790 :         deserializer.deserialize_string(LayerFileNameVisitor)
     297            8790 :     }
     298                 : }
     299                 : 
     300                 : struct LayerFileNameVisitor;
     301                 : 
     302                 : impl<'de> serde::de::Visitor<'de> for LayerFileNameVisitor {
     303                 :     type Value = LayerFileName;
     304                 : 
     305 UBC           0 :     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
     306               0 :         write!(
     307               0 :             formatter,
     308               0 :             "a string that is a valid image or delta layer file name"
     309               0 :         )
     310               0 :     }
     311 CBC        8790 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     312            8790 :     where
     313            8790 :         E: serde::de::Error,
     314            8790 :     {
     315            8790 :         v.parse().map_err(|e| E::custom(e))
     316            8790 :     }
     317                 : }
        

Generated by: LCOV version 2.1-beta