LCOV - differential code coverage report
Current view: top level - libs/pageserver_api/src - reltag.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 95.8 % 48 46 2 46
Current Date: 2024-01-09 02:06:09 Functions: 34.5 % 29 10 19 10
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

           TLA  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 CBC    55577047 : #[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                 : impl PartialOrd for RelTag {
      36         5510860 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
      37         5510860 :         Some(self.cmp(other))
      38         5510860 :     }
      39                 : }
      40                 : 
      41                 : impl Ord for RelTag {
      42         5510860 :     fn cmp(&self, other: &Self) -> Ordering {
      43         5510860 :         // Custom ordering where we put forknum to the end of the list
      44         5510860 :         let other_tup = (other.spcnode, other.dbnode, other.relnode, other.forknum);
      45         5510860 :         (self.spcnode, self.dbnode, self.relnode, self.forknum).cmp(&other_tup)
      46         5510860 :     }
      47                 : }
      48                 : 
      49                 : /// Display RelTag in the same format that's used in most PostgreSQL debug messages:
      50                 : ///
      51                 : /// ```text
      52                 : /// <spcnode>/<dbnode>/<relnode>[_fsm|_vm|_init]
      53                 : /// ```
      54                 : impl fmt::Display for RelTag {
      55         3641531 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      56         3641531 :         if let Some(forkname) = forknumber_to_name(self.forknum) {
      57           77011 :             write!(
      58           77011 :                 f,
      59           77011 :                 "{}/{}/{}_{}",
      60           77011 :                 self.spcnode, self.dbnode, self.relnode, forkname
      61           77011 :             )
      62                 :         } else {
      63         3564520 :             write!(f, "{}/{}/{}", self.spcnode, self.dbnode, self.relnode)
      64                 :         }
      65         3641531 :     }
      66                 : }
      67                 : 
      68                 : impl RelTag {
      69           14018 :     pub fn to_segfile_name(&self, segno: u32) -> String {
      70           14018 :         let mut name = if self.spcnode == GLOBALTABLESPACE_OID {
      71             825 :             "global/".to_string()
      72                 :         } else {
      73           13193 :             format!("base/{}/", self.dbnode)
      74                 :         };
      75                 : 
      76           14018 :         name += &self.relnode.to_string();
      77                 : 
      78           14018 :         if let Some(fork_name) = forknumber_to_name(self.forknum) {
      79            3612 :             name += "_";
      80            3612 :             name += fork_name;
      81           10406 :         }
      82                 : 
      83           14018 :         if segno != 0 {
      84 UBC           0 :             name += ".";
      85               0 :             name += &segno.to_string();
      86 CBC       14018 :         }
      87                 : 
      88           14018 :         name
      89           14018 :     }
      90                 : 
      91           10406 :     pub fn with_forknum(&self, forknum: u8) -> Self {
      92           10406 :         RelTag {
      93           10406 :             forknum,
      94           10406 :             spcnode: self.spcnode,
      95           10406 :             dbnode: self.dbnode,
      96           10406 :             relnode: self.relnode,
      97           10406 :         }
      98           10406 :     }
      99                 : }
     100                 : 
     101                 : ///
     102                 : /// Non-relation transaction status files (clog (a.k.a. pg_xact) and
     103                 : /// pg_multixact) in Postgres are handled by SLRU (Simple LRU) buffer,
     104                 : /// hence the name.
     105                 : ///
     106                 : /// These files are global for a postgres instance.
     107                 : ///
     108                 : /// These files are divided into segments, which are divided into
     109                 : /// pages of the same BLCKSZ as used for relation files.
     110                 : ///
     111        16161267 : #[derive(Debug, Clone, Copy, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
     112                 : pub enum SlruKind {
     113                 :     Clog,
     114                 :     MultiXactMembers,
     115                 :     MultiXactOffsets,
     116                 : }
     117                 : 
     118                 : impl SlruKind {
     119            1692 :     pub fn to_str(&self) -> &'static str {
     120            1692 :         match self {
     121             558 :             Self::Clog => "pg_xact",
     122             576 :             Self::MultiXactMembers => "pg_multixact/members",
     123             558 :             Self::MultiXactOffsets => "pg_multixact/offsets",
     124                 :         }
     125            1692 :     }
     126                 : }
        

Generated by: LCOV version 2.1-beta