LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_desc.rs (source / functions) Coverage Total Hit
Test: 20b6afc7b7f34578dcaab2b3acdaecfe91cd8bf1.info Lines: 86.6 % 172 149
Test Date: 2024-11-25 17:48:16 Functions: 60.0 % 30 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 pageserver_api::key::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           44 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      48           44 :         write!(
      49           44 :             f,
      50           44 :             "{}..{} {}..{} is_delta={}",
      51           44 :             self.key_range.start,
      52           44 :             self.key_range.end,
      53           44 :             self.lsn_range.start,
      54           44 :             self.lsn_range.end,
      55           44 :             self.is_delta
      56           44 :         )
      57           44 :     }
      58              : }
      59              : 
      60              : impl From<ImageLayerName> for PersistentLayerKey {
      61            0 :     fn from(image_layer_name: ImageLayerName) -> Self {
      62            0 :         Self {
      63            0 :             key_range: image_layer_name.key_range,
      64            0 :             lsn_range: PersistentLayerDesc::image_layer_lsn_range(image_layer_name.lsn),
      65            0 :             is_delta: false,
      66            0 :         }
      67            0 :     }
      68              : }
      69              : 
      70              : impl From<DeltaLayerName> for PersistentLayerKey {
      71            0 :     fn from(delta_layer_name: DeltaLayerName) -> Self {
      72            0 :         Self {
      73            0 :             key_range: delta_layer_name.key_range,
      74            0 :             lsn_range: delta_layer_name.lsn_range,
      75            0 :             is_delta: true,
      76            0 :         }
      77            0 :     }
      78              : }
      79              : 
      80              : impl From<LayerName> for PersistentLayerKey {
      81            0 :     fn from(layer_name: LayerName) -> Self {
      82            0 :         match layer_name {
      83            0 :             LayerName::Image(i) => i.into(),
      84            0 :             LayerName::Delta(d) => d.into(),
      85              :         }
      86            0 :     }
      87              : }
      88              : impl PersistentLayerDesc {
      89       488190 :     pub fn key(&self) -> PersistentLayerKey {
      90       488190 :         PersistentLayerKey {
      91       488190 :             key_range: self.key_range.clone(),
      92       488190 :             lsn_range: self.lsn_range.clone(),
      93       488190 :             is_delta: self.is_delta,
      94       488190 :         }
      95       488190 :     }
      96              : 
      97         1970 :     pub fn short_id(&self) -> impl Display {
      98         1970 :         self.layer_name()
      99         1970 :     }
     100              : 
     101              :     #[cfg(test)]
     102           10 :     pub fn new_test(key_range: Range<Key>, lsn_range: Range<Lsn>, is_delta: bool) -> Self {
     103           10 :         Self {
     104           10 :             tenant_shard_id: TenantShardId::unsharded(TenantId::generate()),
     105           10 :             timeline_id: TimelineId::generate(),
     106           10 :             key_range,
     107           10 :             lsn_range,
     108           10 :             is_delta,
     109           10 :             file_size: 0,
     110           10 :         }
     111           10 :     }
     112              : 
     113          332 :     pub fn new_img(
     114          332 :         tenant_shard_id: TenantShardId,
     115          332 :         timeline_id: TimelineId,
     116          332 :         key_range: Range<Key>,
     117          332 :         lsn: Lsn,
     118          332 :         file_size: u64,
     119          332 :     ) -> Self {
     120          332 :         Self {
     121          332 :             tenant_shard_id,
     122          332 :             timeline_id,
     123          332 :             key_range,
     124          332 :             lsn_range: Self::image_layer_lsn_range(lsn),
     125          332 :             is_delta: false,
     126          332 :             file_size,
     127          332 :         }
     128          332 :     }
     129              : 
     130         1448 :     pub fn new_delta(
     131         1448 :         tenant_shard_id: TenantShardId,
     132         1448 :         timeline_id: TimelineId,
     133         1448 :         key_range: Range<Key>,
     134         1448 :         lsn_range: Range<Lsn>,
     135         1448 :         file_size: u64,
     136         1448 :     ) -> Self {
     137         1448 :         Self {
     138         1448 :             tenant_shard_id,
     139         1448 :             timeline_id,
     140         1448 :             key_range,
     141         1448 :             lsn_range,
     142         1448 :             is_delta: true,
     143         1448 :             file_size,
     144         1448 :         }
     145         1448 :     }
     146              : 
     147           24 :     pub fn from_filename(
     148           24 :         tenant_shard_id: TenantShardId,
     149           24 :         timeline_id: TimelineId,
     150           24 :         filename: LayerName,
     151           24 :         file_size: u64,
     152           24 :     ) -> Self {
     153           24 :         match filename {
     154            4 :             LayerName::Image(i) => {
     155            4 :                 Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
     156              :             }
     157           20 :             LayerName::Delta(d) => Self::new_delta(
     158           20 :                 tenant_shard_id,
     159           20 :                 timeline_id,
     160           20 :                 d.key_range,
     161           20 :                 d.lsn_range,
     162           20 :                 file_size,
     163           20 :             ),
     164              :         }
     165           24 :     }
     166              : 
     167              :     /// Get the LSN that the image layer covers.
     168      2540658 :     pub fn image_layer_lsn(&self) -> Lsn {
     169      2540658 :         assert!(!self.is_delta);
     170      2540658 :         assert!(self.lsn_range.start + 1 == self.lsn_range.end);
     171      2540658 :         self.lsn_range.start
     172      2540658 :     }
     173              : 
     174              :     /// Get the LSN range corresponding to a single image layer LSN.
     175         2078 :     pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
     176         2078 :         lsn..(lsn + 1)
     177         2078 :     }
     178              : 
     179              :     /// Get a delta layer name for this layer.
     180              :     ///
     181              :     /// Panic: if this is not a delta layer.
     182         7964 :     pub fn delta_layer_name(&self) -> DeltaLayerName {
     183         7964 :         assert!(self.is_delta);
     184         7964 :         DeltaLayerName {
     185         7964 :             key_range: self.key_range.clone(),
     186         7964 :             lsn_range: self.lsn_range.clone(),
     187         7964 :         }
     188         7964 :     }
     189              : 
     190              :     /// Get a image layer name for this layer.
     191              :     ///
     192              :     /// Panic: if this is not an image layer, or the lsn range is invalid
     193         1528 :     pub fn image_layer_name(&self) -> ImageLayerName {
     194         1528 :         assert!(!self.is_delta);
     195         1528 :         assert!(self.lsn_range.start + 1 == self.lsn_range.end);
     196         1528 :         ImageLayerName {
     197         1528 :             key_range: self.key_range.clone(),
     198         1528 :             lsn: self.lsn_range.start,
     199         1528 :         }
     200         1528 :     }
     201              : 
     202         9492 :     pub fn layer_name(&self) -> LayerName {
     203         9492 :         if self.is_delta {
     204         7964 :             self.delta_layer_name().into()
     205              :         } else {
     206         1528 :             self.image_layer_name().into()
     207              :         }
     208         9492 :     }
     209              : 
     210              :     // TODO: remove this in the future once we refactor timeline APIs.
     211              : 
     212      3575587 :     pub fn get_lsn_range(&self) -> Range<Lsn> {
     213      3575587 :         self.lsn_range.clone()
     214      3575587 :     }
     215              : 
     216        94660 :     pub fn get_key_range(&self) -> Range<Key> {
     217        94660 :         self.key_range.clone()
     218        94660 :     }
     219              : 
     220            0 :     pub fn get_timeline_id(&self) -> TimelineId {
     221            0 :         self.timeline_id
     222            0 :     }
     223              : 
     224              :     /// Does this layer only contain some data for the key-range (incremental),
     225              :     /// or does it contain a version of every page? This is important to know
     226              :     /// for garbage collecting old layers: an incremental layer depends on
     227              :     /// the previous non-incremental layer.
     228         5340 :     pub fn is_incremental(&self) -> bool {
     229         5340 :         self.is_delta
     230         5340 :     }
     231              : 
     232      5703727 :     pub fn is_delta(&self) -> bool {
     233      5703727 :         self.is_delta
     234      5703727 :     }
     235              : 
     236           16 :     pub fn dump(&self) {
     237           16 :         if self.is_delta {
     238           14 :             println!(
     239           14 :                 "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
     240           14 :                 self.tenant_shard_id,
     241           14 :                 self.timeline_id,
     242           14 :                 self.key_range.start,
     243           14 :                 self.key_range.end,
     244           14 :                 self.lsn_range.start,
     245           14 :                 self.lsn_range.end,
     246           14 :                 self.is_incremental(),
     247           14 :                 self.file_size,
     248           14 :             );
     249           14 :         } else {
     250            2 :             println!(
     251            2 :                 "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
     252            2 :                 self.tenant_shard_id,
     253            2 :                 self.timeline_id,
     254            2 :                 self.key_range.start,
     255            2 :                 self.key_range.end,
     256            2 :                 self.image_layer_lsn(),
     257            2 :                 self.is_incremental(),
     258            2 :                 self.file_size
     259            2 :             );
     260            2 :         }
     261           16 :     }
     262              : 
     263          158 :     pub fn file_size(&self) -> u64 {
     264          158 :         self.file_size
     265          158 :     }
     266              : }
        

Generated by: LCOV version 2.1-beta