LCOV - code coverage report
Current view: top level - libs/pageserver_api/src - reltag.rs (source / functions) Coverage Total Hit
Test: 8ac049b474321fdc72ddcb56d7165153a1a900e8.info Lines: 93.2 % 59 55
Test Date: 2023-09-06 10:18:01 Functions: 28.9 % 38 11

            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 custo Ord and PartialOrd implementations below with
      26              : // deriving them.
      27    160747596 : #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize)]
      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      4964985 :     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
      37      4964985 :         Some(self.cmp(other))
      38      4964985 :     }
      39              : }
      40              : 
      41              : impl Ord for RelTag {
      42      4964985 :     fn cmp(&self, other: &Self) -> Ordering {
      43      4964985 :         let mut cmp = self.spcnode.cmp(&other.spcnode);
      44      4964985 :         if cmp != Ordering::Equal {
      45            0 :             return cmp;
      46      4964985 :         }
      47      4964985 :         cmp = self.dbnode.cmp(&other.dbnode);
      48      4964985 :         if cmp != Ordering::Equal {
      49            0 :             return cmp;
      50      4964985 :         }
      51      4964985 :         cmp = self.relnode.cmp(&other.relnode);
      52      4964985 :         if cmp != Ordering::Equal {
      53      4769442 :             return cmp;
      54       195543 :         }
      55       195543 :         cmp = self.forknum.cmp(&other.forknum);
      56       195543 : 
      57       195543 :         cmp
      58      4964985 :     }
      59              : }
      60              : 
      61              : /// Display RelTag in the same format that's used in most PostgreSQL debug messages:
      62              : ///
      63              : /// ```text
      64              : /// <spcnode>/<dbnode>/<relnode>[_fsm|_vm|_init]
      65              : /// ```
      66              : impl fmt::Display for RelTag {
      67              :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      68      4599611 :         if let Some(forkname) = forknumber_to_name(self.forknum) {
      69        87868 :             write!(
      70        87868 :                 f,
      71        87868 :                 "{}/{}/{}_{}",
      72        87868 :                 self.spcnode, self.dbnode, self.relnode, forkname
      73        87868 :             )
      74              :         } else {
      75      4511743 :             write!(f, "{}/{}/{}", self.spcnode, self.dbnode, self.relnode)
      76              :         }
      77      4599611 :     }
      78              : }
      79              : 
      80              : impl RelTag {
      81         8412 :     pub fn to_segfile_name(&self, segno: u32) -> String {
      82         8412 :         let mut name = if self.spcnode == GLOBALTABLESPACE_OID {
      83          495 :             "global/".to_string()
      84              :         } else {
      85         7917 :             format!("base/{}/", self.dbnode)
      86              :         };
      87              : 
      88         8412 :         name += &self.relnode.to_string();
      89              : 
      90         8412 :         if let Some(fork_name) = forknumber_to_name(self.forknum) {
      91         2167 :             name += "_";
      92         2167 :             name += fork_name;
      93         6245 :         }
      94              : 
      95         8412 :         if segno != 0 {
      96            0 :             name += ".";
      97            0 :             name += &segno.to_string();
      98         8412 :         }
      99              : 
     100         8412 :         name
     101         8412 :     }
     102              : 
     103         6245 :     pub fn with_forknum(&self, forknum: u8) -> Self {
     104         6245 :         RelTag {
     105         6245 :             forknum,
     106         6245 :             spcnode: self.spcnode,
     107         6245 :             dbnode: self.dbnode,
     108         6245 :             relnode: self.relnode,
     109         6245 :         }
     110         6245 :     }
     111              : }
     112              : 
     113              : ///
     114              : /// Non-relation transaction status files (clog (a.k.a. pg_xact) and
     115              : /// pg_multixact) in Postgres are handled by SLRU (Simple LRU) buffer,
     116              : /// hence the name.
     117              : ///
     118              : /// These files are global for a postgres instance.
     119              : ///
     120              : /// These files are divided into segments, which are divided into
     121              : /// pages of the same BLCKSZ as used for relation files.
     122              : ///
     123     28082876 : #[derive(Debug, Clone, Copy, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
     124              : pub enum SlruKind {
     125              :     Clog,
     126              :     MultiXactMembers,
     127              :     MultiXactOffsets,
     128              : }
     129              : 
     130              : impl SlruKind {
     131         2001 :     pub fn to_str(&self) -> &'static str {
     132         2001 :         match self {
     133          661 :             Self::Clog => "pg_xact",
     134          679 :             Self::MultiXactMembers => "pg_multixact/members",
     135          661 :             Self::MultiXactOffsets => "pg_multixact/offsets",
     136              :         }
     137         2001 :     }
     138              : }
        

Generated by: LCOV version 2.1-beta