mirror of
https://github.com/neondatabase/neon.git
synced 2025-12-22 21:59:59 +00:00
The 1.88.0 stable release is near (this Thursday). We'd like to fix most warnings beforehand so that the compiler upgrade doesn't require approval from too many teams. This is therefore a preparation PR (like similar PRs before it). There is a lot of changes for this release, mostly because the `uninlined_format_args` lint has been added to the `style` lint group. One can read more about the lint [here](https://rust-lang.github.io/rust-clippy/master/#/uninlined_format_args). The PR is the result of `cargo +beta clippy --fix` and `cargo fmt`. One remaining warning is left for the proxy team. --------- Co-authored-by: Conrad Ludgate <conrad@neon.tech>
134 lines
4.4 KiB
Rust
134 lines
4.4 KiB
Rust
//! This module defines the WAL record format used within the pageserver.
|
|
|
|
use bytes::Bytes;
|
|
use postgres_ffi::walrecord::{MultiXactMember, describe_postgres_wal_record};
|
|
use postgres_ffi::{MultiXactId, MultiXactOffset, TimestampTz, TransactionId};
|
|
use serde::{Deserialize, Serialize};
|
|
use utils::bin_ser::DeserializeError;
|
|
|
|
/// Each update to a page is represented by a NeonWalRecord. It can be a wrapper
|
|
/// around a PostgreSQL WAL record, or a custom neon-specific "record".
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
pub enum NeonWalRecord {
|
|
/// Native PostgreSQL WAL record
|
|
Postgres { will_init: bool, rec: Bytes },
|
|
|
|
/// Clear bits in heap visibility map. ('flags' is bitmap of bits to clear)
|
|
ClearVisibilityMapFlags {
|
|
new_heap_blkno: Option<u32>,
|
|
old_heap_blkno: Option<u32>,
|
|
flags: u8,
|
|
},
|
|
/// Mark transaction IDs as committed on a CLOG page
|
|
ClogSetCommitted {
|
|
xids: Vec<TransactionId>,
|
|
timestamp: TimestampTz,
|
|
},
|
|
/// Mark transaction IDs as aborted on a CLOG page
|
|
ClogSetAborted { xids: Vec<TransactionId> },
|
|
/// Extend multixact offsets SLRU
|
|
MultixactOffsetCreate {
|
|
mid: MultiXactId,
|
|
moff: MultiXactOffset,
|
|
},
|
|
/// Extend multixact members SLRU.
|
|
MultixactMembersCreate {
|
|
moff: MultiXactOffset,
|
|
members: Vec<MultiXactMember>,
|
|
},
|
|
/// Update the map of AUX files, either writing or dropping an entry
|
|
AuxFile {
|
|
file_path: String,
|
|
content: Option<Bytes>,
|
|
},
|
|
// Truncate visibility map page
|
|
TruncateVisibilityMap {
|
|
trunc_byte: usize,
|
|
trunc_offs: usize,
|
|
},
|
|
|
|
/// A testing record for unit testing purposes. It supports append data to an existing image, or clear it.
|
|
#[cfg(feature = "testing")]
|
|
Test {
|
|
/// Append a string to the image.
|
|
append: String,
|
|
/// Clear the image before appending.
|
|
clear: bool,
|
|
/// Treat this record as an init record. `clear` should be set to true if this field is set
|
|
/// to true. This record does not need the history WALs to reconstruct. See [`NeonWalRecord::will_init`] and
|
|
/// its references in `timeline.rs`.
|
|
will_init: bool,
|
|
/// Only append the record if the current image is the same as the one specified in this field.
|
|
only_if: Option<String>,
|
|
},
|
|
}
|
|
|
|
impl NeonWalRecord {
|
|
/// Does replaying this WAL record initialize the page from scratch, or does
|
|
/// it need to be applied over the previous image of the page?
|
|
pub fn will_init(&self) -> bool {
|
|
// If you change this function, you'll also need to change ValueBytes::will_init
|
|
match self {
|
|
NeonWalRecord::Postgres { will_init, rec: _ } => *will_init,
|
|
#[cfg(feature = "testing")]
|
|
NeonWalRecord::Test { will_init, .. } => *will_init,
|
|
// None of the special neon record types currently initialize the page
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "testing")]
|
|
pub fn wal_append(s: impl AsRef<str>) -> Self {
|
|
Self::Test {
|
|
append: s.as_ref().to_string(),
|
|
clear: false,
|
|
will_init: false,
|
|
only_if: None,
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "testing")]
|
|
pub fn wal_append_conditional(s: impl AsRef<str>, only_if: impl AsRef<str>) -> Self {
|
|
Self::Test {
|
|
append: s.as_ref().to_string(),
|
|
clear: false,
|
|
will_init: false,
|
|
only_if: Some(only_if.as_ref().to_string()),
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "testing")]
|
|
pub fn wal_clear(s: impl AsRef<str>) -> Self {
|
|
Self::Test {
|
|
append: s.as_ref().to_string(),
|
|
clear: true,
|
|
will_init: false,
|
|
only_if: None,
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "testing")]
|
|
pub fn wal_init(s: impl AsRef<str>) -> Self {
|
|
Self::Test {
|
|
append: s.as_ref().to_string(),
|
|
clear: true,
|
|
will_init: true,
|
|
only_if: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Build a human-readable string to describe a WAL record
|
|
///
|
|
/// For debugging purposes
|
|
pub fn describe_wal_record(rec: &NeonWalRecord) -> Result<String, DeserializeError> {
|
|
match rec {
|
|
NeonWalRecord::Postgres { will_init, rec } => Ok(format!(
|
|
"will_init: {}, {}",
|
|
will_init,
|
|
describe_postgres_wal_record(rec)?
|
|
)),
|
|
_ => Ok(format!("{rec:?}")),
|
|
}
|
|
}
|