LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - filename.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 64.7 % 187 121
Test Date: 2024-02-07 07:37:29 Functions: 68.4 % 38 26

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

Generated by: LCOV version 2.1-beta