LCOV - differential code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - filename.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 65.2 % 187 122 65 122
Current Date: 2024-01-09 02:06:09 Functions: 68.4 % 38 26 12 26
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

           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      509311 : #[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       77442 :     pub fn parse_str(fname: &str) -> Option<Self> {
      69           77442 :         let mut parts = fname.split("__");
      70           77442 :         let mut key_parts = parts.next()?.split('-');
      71           77442 :         let mut lsn_parts = parts.next()?.split('-');
      72                 : 
      73           77034 :         let key_start_str = key_parts.next()?;
      74           77034 :         let key_end_str = key_parts.next()?;
      75           77034 :         let lsn_start_str = lsn_parts.next()?;
      76           77034 :         let lsn_end_str = lsn_parts.next()?;
      77           30543 :         if parts.next().is_some() || key_parts.next().is_some() || key_parts.next().is_some() {
      78               2 :             return None;
      79           30541 :         }
      80                 : 
      81           30541 :         let key_start = Key::from_hex(key_start_str).ok()?;
      82           30541 :         let key_end = Key::from_hex(key_end_str).ok()?;
      83                 : 
      84           30541 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      85           30541 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      86                 : 
      87           30541 :         if start_lsn >= end_lsn {
      88 UBC           0 :             return None;
      89                 :             // or panic?
      90 CBC       30541 :         }
      91           30541 : 
      92           30541 :         if key_start >= key_end {
      93 UBC           0 :             return None;
      94                 :             // or panic?
      95 CBC       30541 :         }
      96           30541 : 
      97           30541 :         Some(DeltaFileName {
      98           30541 :             key_range: key_start..key_end,
      99           30541 :             lsn_range: start_lsn..end_lsn,
     100           30541 :         })
     101           77442 :     }
     102                 : }
     103                 : 
     104                 : impl fmt::Display for DeltaFileName {
     105          833543 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     106          833543 :         write!(
     107          833543 :             f,
     108          833543 :             "{}-{}__{:016X}-{:016X}",
     109          833543 :             self.key_range.start,
     110          833543 :             self.key_range.end,
     111          833543 :             u64::from(self.lsn_range.start),
     112          833543 :             u64::from(self.lsn_range.end),
     113          833543 :         )
     114          833543 :     }
     115                 : }
     116                 : 
     117          445202 : #[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       77442 :     pub fn parse_str(fname: &str) -> Option<Self> {
     175           77442 :         let mut parts = fname.split("__");
     176           77442 :         let mut key_parts = parts.next()?.split('-');
     177                 : 
     178           77442 :         let key_start_str = key_parts.next()?;
     179           77442 :         let key_end_str = key_parts.next()?;
     180           77085 :         let lsn_str = parts.next()?;
     181           77034 :         if parts.next().is_some() || key_parts.next().is_some() {
     182               6 :             return None;
     183           77028 :         }
     184                 : 
     185           77028 :         let key_start = Key::from_hex(key_start_str).ok()?;
     186           77028 :         let key_end = Key::from_hex(key_end_str).ok()?;
     187                 : 
     188           77028 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     189                 : 
     190           46485 :         Some(ImageFileName {
     191           46485 :             key_range: key_start..key_end,
     192           46485 :             lsn,
     193           46485 :         })
     194           77442 :     }
     195                 : }
     196                 : 
     197                 : impl fmt::Display for ImageFileName {
     198          627002 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     199          627002 :         write!(
     200          627002 :             f,
     201          627002 :             "{}-{}__{:016X}",
     202          627002 :             self.key_range.start,
     203          627002 :             self.key_range.end,
     204          627002 :             u64::from(self.lsn),
     205          627002 :         )
     206          627002 :     }
     207                 : }
     208          954513 : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
     209                 : pub enum LayerFileName {
     210                 :     Image(ImageFileName),
     211                 :     Delta(DeltaFileName),
     212                 : }
     213                 : 
     214                 : impl LayerFileName {
     215          832163 :     pub fn file_name(&self) -> String {
     216          832163 :         self.to_string()
     217          832163 :     }
     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          534693 :     pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
     222                 :         use LayerFileName::*;
     223          305990 :         match self {
     224          228703 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     225          305990 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     226          534675 :             _ => false,
     227                 :         }
     228          534693 :     }
     229                 : 
     230             635 :     pub(crate) fn kind(&self) -> &'static str {
     231             635 :         use LayerFileName::*;
     232             635 :         match self {
     233             634 :             Delta(_) => "delta",
     234               1 :             Image(_) => "image",
     235                 :         }
     236             635 :     }
     237                 : }
     238                 : 
     239                 : impl fmt::Display for LayerFileName {
     240          968639 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     241          968639 :         match self {
     242          423073 :             Self::Image(fname) => write!(f, "{fname}"),
     243          545566 :             Self::Delta(fname) => write!(f, "{fname}"),
     244                 :         }
     245          968639 :     }
     246                 : }
     247                 : 
     248                 : impl From<ImageFileName> for LayerFileName {
     249          420817 :     fn from(fname: ImageFileName) -> Self {
     250          420817 :         Self::Image(fname)
     251          420817 :     }
     252                 : }
     253                 : impl From<DeltaFileName> for LayerFileName {
     254          557731 :     fn from(fname: DeltaFileName) -> Self {
     255          557731 :         Self::Delta(fname)
     256          557731 :     }
     257                 : }
     258                 : 
     259                 : impl FromStr for LayerFileName {
     260                 :     type Err = String;
     261                 : 
     262           77442 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     263           77442 :         let delta = DeltaFileName::parse_str(value);
     264           77442 :         let image = ImageFileName::parse_str(value);
     265           77442 :         let ok = match (delta, image) {
     266                 :             (None, None) => {
     267             416 :                 return Err(format!(
     268             416 :                     "neither delta nor image layer file name: {value:?}"
     269             416 :                 ))
     270                 :             }
     271           30541 :             (Some(delta), None) => Self::Delta(delta),
     272           46485 :             (None, Some(image)) => Self::Image(image),
     273 UBC           0 :             (Some(_), Some(_)) => unreachable!(),
     274                 :         };
     275 CBC       77026 :         Ok(ok)
     276           77442 :     }
     277                 : }
     278                 : 
     279                 : impl serde::Serialize for LayerFileName {
     280          486263 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     281          486263 :     where
     282          486263 :         S: serde::Serializer,
     283          486263 :     {
     284          486263 :         match self {
     285          198286 :             Self::Image(fname) => serializer.collect_str(fname),
     286          287977 :             Self::Delta(fname) => serializer.collect_str(fname),
     287                 :         }
     288          486263 :     }
     289                 : }
     290                 : 
     291                 : impl<'de> serde::Deserialize<'de> for LayerFileName {
     292           61870 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     293           61870 :     where
     294           61870 :         D: serde::Deserializer<'de>,
     295           61870 :     {
     296           61870 :         deserializer.deserialize_string(LayerFileNameVisitor)
     297           61870 :     }
     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       61870 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     312           61870 :     where
     313           61870 :         E: serde::de::Error,
     314           61870 :     {
     315           61870 :         v.parse().map_err(|e| E::custom(e))
     316           61870 :     }
     317                 : }
        

Generated by: LCOV version 2.1-beta