LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - filename.rs (source / functions) Coverage Total Hit
Test: 8ac049b474321fdc72ddcb56d7165153a1a900e8.info Lines: 63.9 % 180 115
Test Date: 2023-09-06 10:18:01 Functions: 69.7 % 33 23

            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       296176 : #[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        10574 :     pub fn parse_str(fname: &str) -> Option<Self> {
      69        10574 :         let mut parts = fname.split("__");
      70        10574 :         let mut key_parts = parts.next()?.split('-');
      71        10574 :         let mut lsn_parts = parts.next()?.split('-');
      72              : 
      73        10165 :         let key_start_str = key_parts.next()?;
      74        10165 :         let key_end_str = key_parts.next()?;
      75        10165 :         let lsn_start_str = lsn_parts.next()?;
      76        10165 :         let lsn_end_str = lsn_parts.next()?;
      77         9194 :         if parts.next().is_some() || key_parts.next().is_some() || key_parts.next().is_some() {
      78            5 :             return None;
      79         9189 :         }
      80              : 
      81         9189 :         let key_start = Key::from_hex(key_start_str).ok()?;
      82         9189 :         let key_end = Key::from_hex(key_end_str).ok()?;
      83              : 
      84         9189 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      85         9189 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      86              : 
      87         9189 :         if start_lsn >= end_lsn {
      88            0 :             return None;
      89              :             // or panic?
      90         9189 :         }
      91         9189 : 
      92         9189 :         if key_start >= key_end {
      93            0 :             return None;
      94              :             // or panic?
      95         9189 :         }
      96         9189 : 
      97         9189 :         Some(DeltaFileName {
      98         9189 :             key_range: key_start..key_end,
      99         9189 :             lsn_range: start_lsn..end_lsn,
     100         9189 :         })
     101        10574 :     }
     102              : }
     103              : 
     104              : impl fmt::Display for DeltaFileName {
     105       354336 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     106       354336 :         write!(
     107       354336 :             f,
     108       354336 :             "{}-{}__{:016X}-{:016X}",
     109       354336 :             self.key_range.start,
     110       354336 :             self.key_range.end,
     111       354336 :             u64::from(self.lsn_range.start),
     112       354336 :             u64::from(self.lsn_range.end),
     113       354336 :         )
     114       354336 :     }
     115              : }
     116              : 
     117       118669 : #[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        10574 :     pub fn parse_str(fname: &str) -> Option<Self> {
     175        10574 :         let mut parts = fname.split("__");
     176        10574 :         let mut key_parts = parts.next()?.split('-');
     177              : 
     178        10574 :         let key_start_str = key_parts.next()?;
     179        10574 :         let key_end_str = key_parts.next()?;
     180        10248 :         let lsn_str = parts.next()?;
     181        10165 :         if parts.next().is_some() || key_parts.next().is_some() {
     182            5 :             return None;
     183        10160 :         }
     184              : 
     185        10160 :         let key_start = Key::from_hex(key_start_str).ok()?;
     186        10160 :         let key_end = Key::from_hex(key_end_str).ok()?;
     187              : 
     188        10160 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     189              : 
     190          971 :         Some(ImageFileName {
     191          971 :             key_range: key_start..key_end,
     192          971 :             lsn,
     193          971 :         })
     194        10574 :     }
     195              : }
     196              : 
     197              : impl fmt::Display for ImageFileName {
     198       120453 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     199       120453 :         write!(
     200       120453 :             f,
     201       120453 :             "{}-{}__{:016X}",
     202       120453 :             self.key_range.start,
     203       120453 :             self.key_range.end,
     204       120453 :             u64::from(self.lsn),
     205       120453 :         )
     206       120453 :     }
     207              : }
     208       414845 : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
     209              : pub enum LayerFileName {
     210              :     Image(ImageFileName),
     211              :     Delta(DeltaFileName),
     212              : }
     213              : 
     214              : impl LayerFileName {
     215        37396 :     pub fn file_name(&self) -> String {
     216        37396 :         self.to_string()
     217        37396 :     }
     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       236013 :         match self {
     224       109428 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     225       236013 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     226       345435 :             _ => false,
     227              :         }
     228       345441 :     }
     229              : }
     230              : 
     231              : impl fmt::Display for LayerFileName {
     232        66801 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     233        66801 :         match self {
     234         7003 :             Self::Image(fname) => write!(f, "{fname}"),
     235        59798 :             Self::Delta(fname) => write!(f, "{fname}"),
     236              :         }
     237        66801 :     }
     238              : }
     239              : 
     240              : impl From<ImageFileName> for LayerFileName {
     241         4117 :     fn from(fname: ImageFileName) -> Self {
     242         4117 :         Self::Image(fname)
     243         4117 :     }
     244              : }
     245              : impl From<DeltaFileName> for LayerFileName {
     246        27736 :     fn from(fname: DeltaFileName) -> Self {
     247        27736 :         Self::Delta(fname)
     248        27736 :     }
     249              : }
     250              : 
     251              : impl FromStr for LayerFileName {
     252              :     type Err = String;
     253              : 
     254        10574 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     255        10574 :         let delta = DeltaFileName::parse_str(value);
     256        10574 :         let image = ImageFileName::parse_str(value);
     257        10574 :         let ok = match (delta, image) {
     258              :             (None, None) => {
     259          414 :                 return Err(format!(
     260          414 :                     "neither delta nor image layer file name: {value:?}"
     261          414 :                 ))
     262              :             }
     263         9189 :             (Some(delta), None) => Self::Delta(delta),
     264          971 :             (None, Some(image)) => Self::Image(image),
     265            0 :             (Some(_), Some(_)) => unreachable!(),
     266              :         };
     267        10160 :         Ok(ok)
     268        10574 :     }
     269              : }
     270              : 
     271              : impl serde::Serialize for LayerFileName {
     272       345190 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     273       345190 :     where
     274       345190 :         S: serde::Serializer,
     275       345190 :     {
     276       345190 :         match self {
     277       108464 :             Self::Image(fname) => serializer.collect_str(fname),
     278       236726 :             Self::Delta(fname) => serializer.collect_str(fname),
     279              :         }
     280       345190 :     }
     281              : }
     282              : 
     283              : impl<'de> serde::Deserialize<'de> for LayerFileName {
     284         6294 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     285         6294 :     where
     286         6294 :         D: serde::Deserializer<'de>,
     287         6294 :     {
     288         6294 :         deserializer.deserialize_string(LayerFileNameVisitor)
     289         6294 :     }
     290              : }
     291              : 
     292              : struct LayerFileNameVisitor;
     293              : 
     294              : impl<'de> serde::de::Visitor<'de> for LayerFileNameVisitor {
     295              :     type Value = LayerFileName;
     296              : 
     297            0 :     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
     298            0 :         write!(
     299            0 :             formatter,
     300            0 :             "a string that is a valid image or delta layer file name"
     301            0 :         )
     302            0 :     }
     303         6294 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     304         6294 :     where
     305         6294 :         E: serde::de::Error,
     306         6294 :     {
     307         6294 :         v.parse().map_err(|e| E::custom(e))
     308         6294 :     }
     309              : }
        

Generated by: LCOV version 2.1-beta