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 : }
|