LCOV - code coverage report
Current view: top level - pageserver/src/tenant/storage_layer - layer_desc.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 90.2 % 143 129
Test Date: 2024-02-07 07:37:29 Functions: 60.0 % 35 21

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

Generated by: LCOV version 2.1-beta