LCOV - code coverage report
Current view: top level - libs/pageserver_api/src - reltag.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 82.5 % 57 47
Test Date: 2024-02-07 07:37:29 Functions: 36.8 % 38 14

            Line data    Source code
       1              : use serde::{Deserialize, Serialize};
       2              : use std::cmp::Ordering;
       3              : use std::fmt;
       4              : 
       5              : use postgres_ffi::pg_constants::GLOBALTABLESPACE_OID;
       6              : use postgres_ffi::relfile_utils::forknumber_to_name;
       7              : use postgres_ffi::Oid;
       8              : 
       9              : ///
      10              : /// Relation data file segment id throughout the Postgres cluster.
      11              : ///
      12              : /// Every data file in Postgres is uniquely identified by 4 numbers:
      13              : /// - relation id / node (`relnode`)
      14              : /// - database id (`dbnode`)
      15              : /// - tablespace id (`spcnode`), in short this is a unique id of a separate
      16              : ///   directory to store data files.
      17              : /// - forknumber (`forknum`) is used to split different kinds of data of the same relation
      18              : ///   between some set of files (`relnode`, `relnode_fsm`, `relnode_vm`).
      19              : ///
      20              : /// In native Postgres code `RelFileNode` structure and individual `ForkNumber` value
      21              : /// are used for the same purpose.
      22              : /// [See more related comments here](https:///github.com/postgres/postgres/blob/99c5852e20a0987eca1c38ba0c09329d4076b6a0/src/include/storage/relfilenode.h#L57).
      23              : ///
      24              : // FIXME: should move 'forknum' as last field to keep this consistent with Postgres.
      25              : // Then we could replace the custom Ord and PartialOrd implementations below with
      26              : // deriving them. This will require changes in walredoproc.c.
      27     68642302 : #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Serialize)]
      28              : pub struct RelTag {
      29              :     pub forknum: u8,
      30              :     pub spcnode: Oid,
      31              :     pub dbnode: Oid,
      32              :     pub relnode: Oid,
      33              : }
      34              : 
      35              : /// Block number within a relation or SLRU. This matches PostgreSQL's BlockNumber type.
      36              : pub type BlockNumber = u32;
      37              : 
      38              : impl PartialOrd for RelTag {
      39      6450103 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
      40      6450103 :         Some(self.cmp(other))
      41      6450103 :     }
      42              : }
      43              : 
      44              : impl Ord for RelTag {
      45      6450103 :     fn cmp(&self, other: &Self) -> Ordering {
      46      6450103 :         // Custom ordering where we put forknum to the end of the list
      47      6450103 :         let other_tup = (other.spcnode, other.dbnode, other.relnode, other.forknum);
      48      6450103 :         (self.spcnode, self.dbnode, self.relnode, self.forknum).cmp(&other_tup)
      49      6450103 :     }
      50              : }
      51              : 
      52              : /// Display RelTag in the same format that's used in most PostgreSQL debug messages:
      53              : ///
      54              : /// ```text
      55              : /// <spcnode>/<dbnode>/<relnode>[_fsm|_vm|_init]
      56              : /// ```
      57              : impl fmt::Display for RelTag {
      58      5618349 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      59      5618349 :         if let Some(forkname) = forknumber_to_name(self.forknum) {
      60       106001 :             write!(
      61       106001 :                 f,
      62       106001 :                 "{}/{}/{}_{}",
      63       106001 :                 self.spcnode, self.dbnode, self.relnode, forkname
      64       106001 :             )
      65              :         } else {
      66      5512348 :             write!(f, "{}/{}/{}", self.spcnode, self.dbnode, self.relnode)
      67              :         }
      68      5618349 :     }
      69              : }
      70              : 
      71              : impl RelTag {
      72        14018 :     pub fn to_segfile_name(&self, segno: u32) -> String {
      73        14018 :         let mut name = if self.spcnode == GLOBALTABLESPACE_OID {
      74          825 :             "global/".to_string()
      75              :         } else {
      76        13193 :             format!("base/{}/", self.dbnode)
      77              :         };
      78              : 
      79        14018 :         name += &self.relnode.to_string();
      80              : 
      81        14018 :         if let Some(fork_name) = forknumber_to_name(self.forknum) {
      82         3612 :             name += "_";
      83         3612 :             name += fork_name;
      84        10406 :         }
      85              : 
      86        14018 :         if segno != 0 {
      87            0 :             name += ".";
      88            0 :             name += &segno.to_string();
      89        14018 :         }
      90              : 
      91        14018 :         name
      92        14018 :     }
      93              : 
      94        10406 :     pub fn with_forknum(&self, forknum: u8) -> Self {
      95        10406 :         RelTag {
      96        10406 :             forknum,
      97        10406 :             spcnode: self.spcnode,
      98        10406 :             dbnode: self.dbnode,
      99        10406 :             relnode: self.relnode,
     100        10406 :         }
     101        10406 :     }
     102              : }
     103              : 
     104              : ///
     105              : /// Non-relation transaction status files (clog (a.k.a. pg_xact) and
     106              : /// pg_multixact) in Postgres are handled by SLRU (Simple LRU) buffer,
     107              : /// hence the name.
     108              : ///
     109              : /// These files are global for a postgres instance.
     110              : ///
     111              : /// These files are divided into segments, which are divided into
     112              : /// pages of the same BLCKSZ as used for relation files.
     113              : ///
     114              : #[derive(
     115            0 :     Debug,
     116            0 :     Clone,
     117              :     Copy,
     118            0 :     Hash,
     119            0 :     Serialize,
     120            0 :     Deserialize,
     121     18923388 :     PartialEq,
     122              :     Eq,
     123            0 :     PartialOrd,
     124            0 :     Ord,
     125         4233 :     strum_macros::EnumIter,
     126            0 :     strum_macros::FromRepr,
     127              : )]
     128              : #[repr(u8)]
     129              : pub enum SlruKind {
     130              :     Clog = 0,
     131              :     MultiXactMembers,
     132              :     MultiXactOffsets,
     133              : }
     134              : 
     135              : impl SlruKind {
     136         1845 :     pub fn to_str(&self) -> &'static str {
     137         1845 :         match self {
     138          621 :             Self::Clog => "pg_xact",
     139          621 :             Self::MultiXactMembers => "pg_multixact/members",
     140          603 :             Self::MultiXactOffsets => "pg_multixact/offsets",
     141              :         }
     142         1845 :     }
     143              : }
        

Generated by: LCOV version 2.1-beta