LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_desc.rs (source / functions) Coverage Total Hit
Test: 2b0730d767f560e20b6748f57465922aa8bb805e.info Lines: 97.4 % 153 149
Test Date: 2024-09-25 14:04:07 Functions: 66.7 % 27 18

            Line data    Source code
       1              : use core::fmt::Display;
       2              : use pageserver_api::shard::TenantShardId;
       3              : use std::ops::Range;
       4              : use utils::{id::TimelineId, lsn::Lsn};
       5              : 
       6              : use crate::repository::Key;
       7              : 
       8              : use super::{DeltaLayerName, ImageLayerName, LayerName};
       9              : 
      10              : use serde::{Deserialize, Serialize};
      11              : 
      12              : #[cfg(test)]
      13              : use utils::id::TenantId;
      14              : 
      15              : /// A unique identifier of a persistent layer.
      16              : ///
      17              : /// This is different from `LayerDescriptor`, which is only used in the benchmarks.
      18              : /// This struct contains all necessary information to find the image / delta layer. It also provides
      19              : /// a unified way to generate layer information like file name.
      20            0 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Hash)]
      21              : pub struct PersistentLayerDesc {
      22              :     pub tenant_shard_id: TenantShardId,
      23              :     pub timeline_id: TimelineId,
      24              :     /// Range of keys that this layer covers
      25              :     pub key_range: Range<Key>,
      26              :     /// Inclusive start, exclusive end of the LSN range that this layer holds.
      27              :     ///
      28              :     /// - For an open in-memory layer, the end bound is MAX_LSN
      29              :     /// - For a frozen in-memory layer or a delta layer, the end bound is a valid lsn after the
      30              :     ///   range start
      31              :     /// - An image layer represents snapshot at one LSN, so end_lsn is always the snapshot LSN + 1
      32              :     pub lsn_range: Range<Lsn>,
      33              :     /// Whether this is a delta layer, and also, is this incremental.
      34              :     pub is_delta: bool,
      35              :     pub file_size: u64,
      36              : }
      37              : 
      38              : /// A unique identifier of a persistent layer within the context of one timeline.
      39              : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
      40              : pub struct PersistentLayerKey {
      41              :     pub key_range: Range<Key>,
      42              :     pub lsn_range: Range<Lsn>,
      43              :     pub is_delta: bool,
      44              : }
      45              : 
      46              : impl std::fmt::Display for PersistentLayerKey {
      47           48 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      48           48 :         write!(
      49           48 :             f,
      50           48 :             "{}..{} {}..{} is_delta={}",
      51           48 :             self.key_range.start,
      52           48 :             self.key_range.end,
      53           48 :             self.lsn_range.start,
      54           48 :             self.lsn_range.end,
      55           48 :             self.is_delta
      56           48 :         )
      57           48 :     }
      58              : }
      59              : 
      60              : impl PersistentLayerDesc {
      61      1694350 :     pub fn key(&self) -> PersistentLayerKey {
      62      1694350 :         PersistentLayerKey {
      63      1694350 :             key_range: self.key_range.clone(),
      64      1694350 :             lsn_range: self.lsn_range.clone(),
      65      1694350 :             is_delta: self.is_delta,
      66      1694350 :         }
      67      1694350 :     }
      68              : 
      69         5850 :     pub fn short_id(&self) -> impl Display {
      70         5850 :         self.layer_name()
      71         5850 :     }
      72              : 
      73              :     #[cfg(test)]
      74           30 :     pub fn new_test(key_range: Range<Key>, lsn_range: Range<Lsn>, is_delta: bool) -> Self {
      75           30 :         Self {
      76           30 :             tenant_shard_id: TenantShardId::unsharded(TenantId::generate()),
      77           30 :             timeline_id: TimelineId::generate(),
      78           30 :             key_range,
      79           30 :             lsn_range,
      80           30 :             is_delta,
      81           30 :             file_size: 0,
      82           30 :         }
      83           30 :     }
      84              : 
      85          966 :     pub fn new_img(
      86          966 :         tenant_shard_id: TenantShardId,
      87          966 :         timeline_id: TimelineId,
      88          966 :         key_range: Range<Key>,
      89          966 :         lsn: Lsn,
      90          966 :         file_size: u64,
      91          966 :     ) -> Self {
      92          966 :         Self {
      93          966 :             tenant_shard_id,
      94          966 :             timeline_id,
      95          966 :             key_range,
      96          966 :             lsn_range: Self::image_layer_lsn_range(lsn),
      97          966 :             is_delta: false,
      98          966 :             file_size,
      99          966 :         }
     100          966 :     }
     101              : 
     102         4308 :     pub fn new_delta(
     103         4308 :         tenant_shard_id: TenantShardId,
     104         4308 :         timeline_id: TimelineId,
     105         4308 :         key_range: Range<Key>,
     106         4308 :         lsn_range: Range<Lsn>,
     107         4308 :         file_size: u64,
     108         4308 :     ) -> Self {
     109         4308 :         Self {
     110         4308 :             tenant_shard_id,
     111         4308 :             timeline_id,
     112         4308 :             key_range,
     113         4308 :             lsn_range,
     114         4308 :             is_delta: true,
     115         4308 :             file_size,
     116         4308 :         }
     117         4308 :     }
     118              : 
     119           72 :     pub fn from_filename(
     120           72 :         tenant_shard_id: TenantShardId,
     121           72 :         timeline_id: TimelineId,
     122           72 :         filename: LayerName,
     123           72 :         file_size: u64,
     124           72 :     ) -> Self {
     125           72 :         match filename {
     126           12 :             LayerName::Image(i) => {
     127           12 :                 Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
     128              :             }
     129           60 :             LayerName::Delta(d) => Self::new_delta(
     130           60 :                 tenant_shard_id,
     131           60 :                 timeline_id,
     132           60 :                 d.key_range,
     133           60 :                 d.lsn_range,
     134           60 :                 file_size,
     135           60 :             ),
     136              :         }
     137           72 :     }
     138              : 
     139              :     /// Get the LSN that the image layer covers.
     140      7628844 :     pub fn image_layer_lsn(&self) -> Lsn {
     141      7628844 :         assert!(!self.is_delta);
     142      7628844 :         assert!(self.lsn_range.start + 1 == self.lsn_range.end);
     143      7628844 :         self.lsn_range.start
     144      7628844 :     }
     145              : 
     146              :     /// Get the LSN range corresponding to a single image layer LSN.
     147         5988 :     pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
     148         5988 :         lsn..(lsn + 1)
     149         5988 :     }
     150              : 
     151              :     /// Get a delta layer name for this layer.
     152              :     ///
     153              :     /// Panic: if this is not a delta layer.
     154        19585 :     pub fn delta_layer_name(&self) -> DeltaLayerName {
     155        19585 :         assert!(self.is_delta);
     156        19585 :         DeltaLayerName {
     157        19585 :             key_range: self.key_range.clone(),
     158        19585 :             lsn_range: self.lsn_range.clone(),
     159        19585 :         }
     160        19585 :     }
     161              : 
     162              :     /// Get a image layer name for this layer.
     163              :     ///
     164              :     /// Panic: if this is not an image layer, or the lsn range is invalid
     165         3556 :     pub fn image_layer_name(&self) -> ImageLayerName {
     166         3556 :         assert!(!self.is_delta);
     167         3556 :         assert!(self.lsn_range.start + 1 == self.lsn_range.end);
     168         3556 :         ImageLayerName {
     169         3556 :             key_range: self.key_range.clone(),
     170         3556 :             lsn: self.lsn_range.start,
     171         3556 :         }
     172         3556 :     }
     173              : 
     174        23141 :     pub fn layer_name(&self) -> LayerName {
     175        23141 :         if self.is_delta {
     176        19585 :             self.delta_layer_name().into()
     177              :         } else {
     178         3556 :             self.image_layer_name().into()
     179              :         }
     180        23141 :     }
     181              : 
     182              :     // TODO: remove this in the future once we refactor timeline APIs.
     183              : 
     184     11255347 :     pub fn get_lsn_range(&self) -> Range<Lsn> {
     185     11255347 :         self.lsn_range.clone()
     186     11255347 :     }
     187              : 
     188       325230 :     pub fn get_key_range(&self) -> Range<Key> {
     189       325230 :         self.key_range.clone()
     190       325230 :     }
     191              : 
     192            0 :     pub fn get_timeline_id(&self) -> TimelineId {
     193            0 :         self.timeline_id
     194            0 :     }
     195              : 
     196              :     /// Does this layer only contain some data for the key-range (incremental),
     197              :     /// or does it contain a version of every page? This is important to know
     198              :     /// for garbage collecting old layers: an incremental layer depends on
     199              :     /// the previous non-incremental layer.
     200        15846 :     pub fn is_incremental(&self) -> bool {
     201        15846 :         self.is_delta
     202        15846 :     }
     203              : 
     204     17269927 :     pub fn is_delta(&self) -> bool {
     205     17269927 :         self.is_delta
     206     17269927 :     }
     207              : 
     208           48 :     pub fn dump(&self) {
     209           48 :         if self.is_delta {
     210           42 :             println!(
     211           42 :                 "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
     212           42 :                 self.tenant_shard_id,
     213           42 :                 self.timeline_id,
     214           42 :                 self.key_range.start,
     215           42 :                 self.key_range.end,
     216           42 :                 self.lsn_range.start,
     217           42 :                 self.lsn_range.end,
     218           42 :                 self.is_incremental(),
     219           42 :                 self.file_size,
     220           42 :             );
     221           42 :         } else {
     222            6 :             println!(
     223            6 :                 "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
     224            6 :                 self.tenant_shard_id,
     225            6 :                 self.timeline_id,
     226            6 :                 self.key_range.start,
     227            6 :                 self.key_range.end,
     228            6 :                 self.image_layer_lsn(),
     229            6 :                 self.is_incremental(),
     230            6 :                 self.file_size
     231            6 :             );
     232            6 :         }
     233           48 :     }
     234              : 
     235          312 :     pub fn file_size(&self) -> u64 {
     236          312 :         self.file_size
     237          312 :     }
     238              : }
        

Generated by: LCOV version 2.1-beta