LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_name.rs (source / functions) Coverage Total Hit
Test: 09e7485004805bd42b53a0c369170b3228136512.info Lines: 68.0 % 219 149
Test Date: 2024-11-21 18:36:18 Functions: 55.9 % 34 19

            Line data    Source code
       1              : //!
       2              : //! Helper functions for dealing with filenames of the image and delta layer files.
       3              : //!
       4              : use pageserver_api::key::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              : #[derive(PartialEq, Eq, Clone, Hash)]
      16              : pub struct DeltaLayerName {
      17              :     pub key_range: Range<Key>,
      18              :     pub lsn_range: Range<Lsn>,
      19              : }
      20              : 
      21              : impl std::fmt::Debug for DeltaLayerName {
      22            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      23              :         use super::RangeDisplayDebug;
      24              : 
      25            0 :         f.debug_struct("DeltaLayerName")
      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 DeltaLayerName {
      33            0 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
      34            0 :         Some(self.cmp(other))
      35            0 :     }
      36              : }
      37              : 
      38              : impl Ord for DeltaLayerName {
      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 region of the LSN-Key space covered by a DeltaLayer
      59              : ///
      60              : /// ```text
      61              : ///    <key start>-<key end>__<LSN start>-<LSN end>-<generation>
      62              : /// ```
      63              : impl DeltaLayerName {
      64              :     /// Parse the part of a delta layer's file name that represents the LayerName. Returns None
      65              :     /// if the filename does not match the expected pattern.
      66         3262 :     pub fn parse_str(fname: &str) -> Option<Self> {
      67         3262 :         let (key_parts, lsn_generation_parts) = fname.split_once("__")?;
      68         3262 :         let (key_start_str, key_end_str) = key_parts.split_once('-')?;
      69         3262 :         let (lsn_start_str, lsn_end_generation_parts) = lsn_generation_parts.split_once('-')?;
      70         1648 :         let lsn_end_str = if let Some((lsn_end_str, maybe_generation)) =
      71         1648 :             lsn_end_generation_parts.split_once('-')
      72              :         {
      73           22 :             if maybe_generation.starts_with("v") {
      74              :                 // vY-XXXXXXXX
      75           14 :                 lsn_end_str
      76            8 :             } else if maybe_generation.len() == 8 {
      77              :                 // XXXXXXXX
      78            8 :                 lsn_end_str
      79              :             } else {
      80              :                 // no idea what this is
      81            0 :                 return None;
      82              :             }
      83              :         } else {
      84         1626 :             lsn_end_generation_parts
      85              :         };
      86              : 
      87         1648 :         let key_start = Key::from_hex(key_start_str).ok()?;
      88         1648 :         let key_end = Key::from_hex(key_end_str).ok()?;
      89              : 
      90         1648 :         let start_lsn = Lsn::from_hex(lsn_start_str).ok()?;
      91         1648 :         let end_lsn = Lsn::from_hex(lsn_end_str).ok()?;
      92              : 
      93         1642 :         if start_lsn >= end_lsn {
      94            2 :             return None;
      95              :             // or panic?
      96         1640 :         }
      97         1640 : 
      98         1640 :         if key_start >= key_end {
      99            0 :             return None;
     100              :             // or panic?
     101         1640 :         }
     102         1640 : 
     103         1640 :         Some(DeltaLayerName {
     104         1640 :             key_range: key_start..key_end,
     105         1640 :             lsn_range: start_lsn..end_lsn,
     106         1640 :         })
     107         3262 :     }
     108              : }
     109              : 
     110              : impl fmt::Display for DeltaLayerName {
     111        38046 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     112        38046 :         write!(
     113        38046 :             f,
     114        38046 :             "{}-{}__{:016X}-{:016X}",
     115        38046 :             self.key_range.start,
     116        38046 :             self.key_range.end,
     117        38046 :             u64::from(self.lsn_range.start),
     118        38046 :             u64::from(self.lsn_range.end),
     119        38046 :         )
     120        38046 :     }
     121              : }
     122              : 
     123              : #[derive(PartialEq, Eq, Clone, Hash)]
     124              : pub struct ImageLayerName {
     125              :     pub key_range: Range<Key>,
     126              :     pub lsn: Lsn,
     127              : }
     128              : 
     129              : impl std::fmt::Debug for ImageLayerName {
     130            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     131              :         use super::RangeDisplayDebug;
     132              : 
     133            0 :         f.debug_struct("ImageLayerName")
     134            0 :             .field("key_range", &RangeDisplayDebug(&self.key_range))
     135            0 :             .field("lsn", &self.lsn)
     136            0 :             .finish()
     137            0 :     }
     138              : }
     139              : 
     140              : impl PartialOrd for ImageLayerName {
     141            0 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
     142            0 :         Some(self.cmp(other))
     143            0 :     }
     144              : }
     145              : 
     146              : impl Ord for ImageLayerName {
     147            0 :     fn cmp(&self, other: &Self) -> Ordering {
     148            0 :         let mut cmp = self.key_range.start.cmp(&other.key_range.start);
     149            0 :         if cmp != Ordering::Equal {
     150            0 :             return cmp;
     151            0 :         }
     152            0 :         cmp = self.key_range.end.cmp(&other.key_range.end);
     153            0 :         if cmp != Ordering::Equal {
     154            0 :             return cmp;
     155            0 :         }
     156            0 :         cmp = self.lsn.cmp(&other.lsn);
     157            0 : 
     158            0 :         cmp
     159            0 :     }
     160              : }
     161              : 
     162              : impl ImageLayerName {
     163         1604 :     pub fn lsn_as_range(&self) -> Range<Lsn> {
     164         1604 :         // Saves from having to copypaste this all over
     165         1604 :         PersistentLayerDesc::image_layer_lsn_range(self.lsn)
     166         1604 :     }
     167              : }
     168              : 
     169              : ///
     170              : /// Represents the part of the Key-LSN space covered by an ImageLayer
     171              : ///
     172              : /// ```text
     173              : ///    <key start>-<key end>__<LSN>-<generation>
     174              : /// ```
     175              : impl ImageLayerName {
     176              :     /// Parse a string as then LayerName part of an image layer file name. Returns None if the
     177              :     /// filename does not match the expected pattern.
     178         3262 :     pub fn parse_str(fname: &str) -> Option<Self> {
     179         3262 :         let (key_parts, lsn_generation_parts) = fname.split_once("__")?;
     180         3262 :         let (key_start_str, key_end_str) = key_parts.split_once('-')?;
     181         1622 :         let lsn_str =
     182         3262 :             if let Some((lsn_str, maybe_generation)) = lsn_generation_parts.split_once('-') {
     183         1648 :                 if maybe_generation.starts_with("v") {
     184              :                     // vY-XXXXXXXX
     185            6 :                     lsn_str
     186         1642 :                 } else if maybe_generation.len() == 8 {
     187              :                     // XXXXXXXX
     188            2 :                     lsn_str
     189              :                 } else {
     190              :                     // likely a delta layer
     191         1640 :                     return None;
     192              :                 }
     193              :             } else {
     194         1614 :                 lsn_generation_parts
     195              :             };
     196              : 
     197         1622 :         let key_start = Key::from_hex(key_start_str).ok()?;
     198         1622 :         let key_end = Key::from_hex(key_end_str).ok()?;
     199              : 
     200         1622 :         let lsn = Lsn::from_hex(lsn_str).ok()?;
     201              : 
     202         1622 :         Some(ImageLayerName {
     203         1622 :             key_range: key_start..key_end,
     204         1622 :             lsn,
     205         1622 :         })
     206         3262 :     }
     207              : }
     208              : 
     209              : impl fmt::Display for ImageLayerName {
     210         3685 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     211         3685 :         write!(
     212         3685 :             f,
     213         3685 :             "{}-{}__{:016X}",
     214         3685 :             self.key_range.start,
     215         3685 :             self.key_range.end,
     216         3685 :             u64::from(self.lsn),
     217         3685 :         )
     218         3685 :     }
     219              : }
     220              : 
     221              : /// LayerName is the logical identity of a layer within a LayerMap at a moment in time.
     222              : ///
     223              : /// The LayerName is not a unique filename, as the same LayerName may have multiple physical incarnations
     224              : /// over time (e.g. across shard splits or compression). The physical filenames of layers in local
     225              : /// storage and object names in remote storage consist of the LayerName plus some extra qualifiers
     226              : /// that uniquely identify the physical incarnation of a layer (see [crate::tenant::remote_timeline_client::remote_layer_path])
     227              : /// and [`crate::tenant::storage_layer::layer::local_layer_path`])
     228              : #[derive(Debug, PartialEq, Eq, Hash, Clone)]
     229              : pub enum LayerName {
     230              :     Image(ImageLayerName),
     231              :     Delta(DeltaLayerName),
     232              : }
     233              : 
     234              : impl LayerName {
     235              :     /// Determines if this layer file is considered to be in future meaning we will discard these
     236              :     /// layers during timeline initialization from the given disk_consistent_lsn.
     237        17502 :     pub(crate) fn is_in_future(&self, disk_consistent_lsn: Lsn) -> bool {
     238              :         use LayerName::*;
     239         1083 :         match self {
     240         1083 :             Image(file_name) if file_name.lsn > disk_consistent_lsn => true,
     241        16419 :             Delta(file_name) if file_name.lsn_range.end > disk_consistent_lsn + 1 => true,
     242        17485 :             _ => false,
     243              :         }
     244        17502 :     }
     245              : 
     246            0 :     pub(crate) fn kind(&self) -> &'static str {
     247              :         use LayerName::*;
     248            0 :         match self {
     249            0 :             Delta(_) => "delta",
     250            0 :             Image(_) => "image",
     251              :         }
     252            0 :     }
     253              : 
     254              :     /// Gets the key range encoded in the layer name.
     255            8 :     pub fn key_range(&self) -> &Range<Key> {
     256            8 :         match &self {
     257            4 :             LayerName::Image(layer) => &layer.key_range,
     258            4 :             LayerName::Delta(layer) => &layer.key_range,
     259              :         }
     260            8 :     }
     261              : 
     262              :     /// Gets the LSN range encoded in the layer name.
     263            0 :     pub fn lsn_as_range(&self) -> Range<Lsn> {
     264            0 :         match &self {
     265            0 :             LayerName::Image(layer) => layer.lsn_as_range(),
     266            0 :             LayerName::Delta(layer) => layer.lsn_range.clone(),
     267              :         }
     268            0 :     }
     269              : 
     270            8 :     pub fn is_delta(&self) -> bool {
     271            8 :         matches!(self, LayerName::Delta(_))
     272            8 :     }
     273              : }
     274              : 
     275              : impl fmt::Display for LayerName {
     276         5802 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     277         5802 :         match self {
     278          909 :             Self::Image(fname) => write!(f, "{fname}"),
     279         4893 :             Self::Delta(fname) => write!(f, "{fname}"),
     280              :         }
     281         5802 :     }
     282              : }
     283              : 
     284              : impl From<ImageLayerName> for LayerName {
     285         1297 :     fn from(fname: ImageLayerName) -> Self {
     286         1297 :         Self::Image(fname)
     287         1297 :     }
     288              : }
     289              : impl From<DeltaLayerName> for LayerName {
     290         6665 :     fn from(fname: DeltaLayerName) -> Self {
     291         6665 :         Self::Delta(fname)
     292         6665 :     }
     293              : }
     294              : 
     295              : impl FromStr for LayerName {
     296              :     type Err = String;
     297              : 
     298              :     /// Conversion from either a physical layer filename, or the string-ization of
     299              :     /// Self. When loading a physical layer filename, we drop any extra information
     300              :     /// not needed to build Self.
     301         3262 :     fn from_str(value: &str) -> Result<Self, Self::Err> {
     302         3262 :         let delta = DeltaLayerName::parse_str(value);
     303         3262 :         let image = ImageLayerName::parse_str(value);
     304         3262 :         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         1640 :             (Some(delta), None) => Self::Delta(delta),
     311         1622 :             (None, Some(image)) => Self::Image(image),
     312            0 :             (Some(_), Some(_)) => unreachable!(),
     313              :         };
     314         3262 :         Ok(ok)
     315         3262 :     }
     316              : }
     317              : 
     318              : impl serde::Serialize for LayerName {
     319        35411 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     320        35411 :     where
     321        35411 :         S: serde::Serializer,
     322        35411 :     {
     323        35411 :         match self {
     324         2258 :             Self::Image(fname) => serializer.collect_str(fname),
     325        33153 :             Self::Delta(fname) => serializer.collect_str(fname),
     326              :         }
     327        35411 :     }
     328              : }
     329              : 
     330              : impl<'de> serde::Deserialize<'de> for LayerName {
     331         3188 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     332         3188 :     where
     333         3188 :         D: serde::Deserializer<'de>,
     334         3188 :     {
     335         3188 :         deserializer.deserialize_string(LayerNameVisitor)
     336         3188 :     }
     337              : }
     338              : 
     339              : struct LayerNameVisitor;
     340              : 
     341              : impl serde::de::Visitor<'_> 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         3188 :     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     351         3188 :     where
     352         3188 :         E: serde::de::Error,
     353         3188 :     {
     354         3188 :         v.parse().map_err(|e| E::custom(e))
     355         3188 :     }
     356              : }
     357              : 
     358              : #[cfg(test)]
     359              : mod test {
     360              :     use super::*;
     361              :     #[test]
     362            2 :     fn image_layer_parse() {
     363            2 :         let expected = LayerName::Image(ImageLayerName {
     364            2 :             key_range: Key::from_i128(0)
     365            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     366            2 :             lsn: Lsn::from_hex("00000000014FED58").unwrap(),
     367            2 :         });
     368            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-v1-00000001").unwrap();
     369            2 :         assert_eq!(parsed, expected);
     370              : 
     371            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-00000001").unwrap();
     372            2 :         assert_eq!(parsed, expected);
     373              : 
     374              :         // Omitting generation suffix is valid
     375            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58").unwrap();
     376            2 :         assert_eq!(parsed, expected);
     377            2 :     }
     378              : 
     379              :     #[test]
     380            2 :     fn delta_layer_parse() {
     381            2 :         let expected = LayerName::Delta(DeltaLayerName {
     382            2 :             key_range: Key::from_i128(0)
     383            2 :                 ..Key::from_hex("000000067F00000001000004DF0000000006").unwrap(),
     384            2 :             lsn_range: Lsn::from_hex("00000000014FED58").unwrap()
     385            2 :                 ..Lsn::from_hex("000000000154C481").unwrap(),
     386            2 :         });
     387            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-v1-00000001").unwrap();
     388            2 :         assert_eq!(parsed, expected);
     389              : 
     390            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481-00000001").unwrap();
     391            2 :         assert_eq!(parsed, expected);
     392              : 
     393              :         // Omitting generation suffix is valid
     394            2 :         let parsed = LayerName::from_str("000000000000000000000000000000000000-000000067F00000001000004DF0000000006__00000000014FED58-000000000154C481").unwrap();
     395            2 :         assert_eq!(parsed, expected);
     396            2 :     }
     397              : }
        

Generated by: LCOV version 2.1-beta