Line data Source code
1 : //! This module defines the WAL record format used within the pageserver.
2 :
3 : use bytes::Bytes;
4 : use postgres_ffi::walrecord::{describe_postgres_wal_record, MultiXactMember};
5 : use postgres_ffi::{MultiXactId, MultiXactOffset, TimestampTz, TransactionId};
6 : use serde::{Deserialize, Serialize};
7 : use utils::bin_ser::DeserializeError;
8 :
9 : /// Each update to a page is represented by a NeonWalRecord. It can be a wrapper
10 : /// around a PostgreSQL WAL record, or a custom neon-specific "record".
11 2277 : #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12 : pub enum NeonWalRecord {
13 : /// Native PostgreSQL WAL record
14 : Postgres { will_init: bool, rec: Bytes },
15 :
16 : /// Clear bits in heap visibility map. ('flags' is bitmap of bits to clear)
17 : ClearVisibilityMapFlags {
18 : new_heap_blkno: Option<u32>,
19 : old_heap_blkno: Option<u32>,
20 : flags: u8,
21 : },
22 : /// Mark transaction IDs as committed on a CLOG page
23 : ClogSetCommitted {
24 : xids: Vec<TransactionId>,
25 : timestamp: TimestampTz,
26 : },
27 : /// Mark transaction IDs as aborted on a CLOG page
28 : ClogSetAborted { xids: Vec<TransactionId> },
29 : /// Extend multixact offsets SLRU
30 : MultixactOffsetCreate {
31 : mid: MultiXactId,
32 : moff: MultiXactOffset,
33 : },
34 : /// Extend multixact members SLRU.
35 : MultixactMembersCreate {
36 : moff: MultiXactOffset,
37 : members: Vec<MultiXactMember>,
38 : },
39 : /// Update the map of AUX files, either writing or dropping an entry
40 : AuxFile {
41 : file_path: String,
42 : content: Option<Bytes>,
43 : },
44 :
45 : /// A testing record for unit testing purposes. It supports append data to an existing image, or clear it.
46 : #[cfg(feature = "testing")]
47 : Test {
48 : /// Append a string to the image.
49 : append: String,
50 : /// Clear the image before appending.
51 : clear: bool,
52 : /// Treat this record as an init record. `clear` should be set to true if this field is set
53 : /// to true. This record does not need the history WALs to reconstruct. See [`NeonWalRecord::will_init`] and
54 : /// its references in `timeline.rs`.
55 : will_init: bool,
56 : },
57 : }
58 :
59 : impl NeonWalRecord {
60 : /// Does replaying this WAL record initialize the page from scratch, or does
61 : /// it need to be applied over the previous image of the page?
62 146997 : pub fn will_init(&self) -> bool {
63 146997 : // If you change this function, you'll also need to change ValueBytes::will_init
64 146997 : match self {
65 145626 : NeonWalRecord::Postgres { will_init, rec: _ } => *will_init,
66 : #[cfg(feature = "testing")]
67 1351 : NeonWalRecord::Test { will_init, .. } => *will_init,
68 : // None of the special neon record types currently initialize the page
69 20 : _ => false,
70 : }
71 146997 : }
72 :
73 : #[cfg(feature = "testing")]
74 201 : pub fn wal_append(s: impl AsRef<str>) -> Self {
75 201 : Self::Test {
76 201 : append: s.as_ref().to_string(),
77 201 : clear: false,
78 201 : will_init: false,
79 201 : }
80 201 : }
81 :
82 : #[cfg(feature = "testing")]
83 2 : pub fn wal_clear(s: impl AsRef<str>) -> Self {
84 2 : Self::Test {
85 2 : append: s.as_ref().to_string(),
86 2 : clear: true,
87 2 : will_init: false,
88 2 : }
89 2 : }
90 :
91 : #[cfg(feature = "testing")]
92 52 : pub fn wal_init(s: impl AsRef<str>) -> Self {
93 52 : Self::Test {
94 52 : append: s.as_ref().to_string(),
95 52 : clear: true,
96 52 : will_init: true,
97 52 : }
98 52 : }
99 : }
100 :
101 : /// Build a human-readable string to describe a WAL record
102 : ///
103 : /// For debugging purposes
104 0 : pub fn describe_wal_record(rec: &NeonWalRecord) -> Result<String, DeserializeError> {
105 0 : match rec {
106 0 : NeonWalRecord::Postgres { will_init, rec } => Ok(format!(
107 0 : "will_init: {}, {}",
108 0 : will_init,
109 0 : describe_postgres_wal_record(rec)?
110 : )),
111 0 : _ => Ok(format!("{:?}", rec)),
112 : }
113 0 : }
|