diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 6eddbc3335..6d966ce0a2 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -77,11 +77,16 @@ jobs: submodules: true fetch-depth: 1 - - name: Set pg revision for caching + - name: Set pg 14 revision for caching id: pg_v14_rev run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v14) shell: bash -euxo pipefail {0} + - name: Set pg 15 revision for caching + id: pg_v15_rev + run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v15) + shell: bash -euxo pipefail {0} + # Set some environment variables used by all the steps. # # CARGO_FLAGS is extra options to pass to "cargo build", "cargo test" etc. @@ -125,15 +130,27 @@ jobs: v7-${{ runner.os }}-${{ matrix.build_type }}-cargo-${{ matrix.rust_toolchain }}- - name: Cache postgres v14 build - id: cache_pg + id: cache_pg_14 uses: actions/cache@v3 with: path: pg_install/v14 key: v1-${{ runner.os }}-${{ matrix.build_type }}-pg-${{ steps.pg_v14_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }} - - name: Build postgres - if: steps.cache_pg.outputs.cache-hit != 'true' - run: mold -run make postgres -j$(nproc) + - name: Cache postgres v15 build + id: cache_pg_15 + uses: actions/cache@v3 + with: + path: pg_install/v15 + key: v1-${{ runner.os }}-${{ matrix.build_type }}-pg-${{ steps.pg_v15_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }} + + - name: Build postgres v14 + if: steps.cache_pg_14.outputs.cache-hit != 'true' + run: mold -run make postgres-v14 -j$(nproc) + shell: bash -euxo pipefail {0} + + - name: Build postgres v15 + if: steps.cache_pg_15.outputs.cache-hit != 'true' + run: mold -run make postgres-v15 -j$(nproc) shell: bash -euxo pipefail {0} - name: Build neon extensions diff --git a/Dockerfile b/Dockerfile index d379c05051..3e173f4d5b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,23 +5,21 @@ ARG REPOSITORY=369495373322.dkr.ecr.eu-central-1.amazonaws.com ARG IMAGE=rust ARG TAG=pinned -# ARGs don't get replaced in RUN commands in Kaniko -# so use hardcoded value below -# ARG PG_VERSION=v14 # Build Postgres FROM $REPOSITORY/$IMAGE:$TAG AS pg-build WORKDIR /home/nonroot -ARG PG_VERSION=v14 COPY --chown=nonroot vendor/postgres-v14 vendor/postgres-v14 +COPY --chown=nonroot vendor/postgres-v15 vendor/postgres-v15 COPY --chown=nonroot pgxn pgxn COPY --chown=nonroot Makefile Makefile ENV BUILD_TYPE release RUN set -e \ - && mold -run make -j $(nproc) -s neon-pg-ext-v14 \ + && mold -run make -j $(nproc) -s neon-pg-ext \ && rm -rf pg_install/v14/build \ + && rm -rf pg_install/v15/build \ && tar -C pg_install/v14 -czf /home/nonroot/postgres_install.tar.gz . # Build zenith binaries @@ -39,8 +37,8 @@ ARG CACHEPOT_BUCKET=neon-github-dev #ARG AWS_ACCESS_KEY_ID #ARG AWS_SECRET_ACCESS_KEY -ARG PG_VERSION=v14 COPY --from=pg-build /home/nonroot/pg_install/v14/include/postgresql/server pg_install/v14/include/postgresql/server +COPY --from=pg-build /home/nonroot/pg_install/v15/include/postgresql/server pg_install/v15/include/postgresql/server COPY . . # Show build caching stats to check if it was used in the end. @@ -70,7 +68,6 @@ COPY --from=build --chown=zenith:zenith /home/nonroot/target/release/safekeeper COPY --from=build --chown=zenith:zenith /home/nonroot/target/release/proxy /usr/local/bin # v14 is default for now -ARG PG_VERSION=v14 COPY --from=pg-build /home/nonroot/pg_install/v14 /usr/local/ COPY --from=pg-build /home/nonroot/postgres_install.tar.gz /data/ diff --git a/Makefile b/Makefile index 0b2b097ebc..0e7ceec15b 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ all: neon postgres neon-pg-ext # # The 'postgres_ffi' depends on the Postgres headers. .PHONY: neon -neon: postgres-v14-headers +neon: postgres-v14-headers postgres-v15-headers +@echo "Compiling Neon" $(CARGO_CMD_PREFIX) cargo build $(CARGO_BUILD_FLAGS) diff --git a/libs/postgres_ffi/README.md b/libs/postgres_ffi/README.md index 5656314fd7..de046eb3da 100644 --- a/libs/postgres_ffi/README.md +++ b/libs/postgres_ffi/README.md @@ -9,9 +9,11 @@ should be auto-generated too, but that's a TODO. The PostgreSQL on-disk file format is not portable across different CPU architectures and operating systems. It is also subject to change -in each major PostgreSQL version. Currently, this module is based on -PostgreSQL v14, but in the future we will probably need a separate -copy for each PostgreSQL version. +in each major PostgreSQL version. Currently, this module supports +PostgreSQL v14 and v15: bindings and code that depends on them are version-specific. +This code is organized in modules: `postgres_ffi::v14` and `postgres_ffi::v15` +Version independend code is explicitly exported into shared `postgres_ffi`. + TODO: Currently, there is also some code that deals with WAL records in pageserver/src/waldecoder.rs. That should be moved into this diff --git a/libs/postgres_ffi/build.rs b/libs/postgres_ffi/build.rs index 19507f0557..8389ac37fe 100644 --- a/libs/postgres_ffi/build.rs +++ b/libs/postgres_ffi/build.rs @@ -48,90 +48,98 @@ fn main() { // Finding the location of C headers for the Postgres server: // - if POSTGRES_INSTALL_DIR is set look into it, otherwise look into `/pg_install` - // - if there's a `bin/pg_config` file use it for getting include server, otherwise use `/pg_install/v14/include/postgresql/server` - let mut pg_install_dir = if let Some(postgres_install_dir) = env::var_os("POSTGRES_INSTALL_DIR") - { + // - if there's a `bin/pg_config` file use it for getting include server, otherwise use `/pg_install/{PG_MAJORVERSION}/include/postgresql/server` + let pg_install_dir = if let Some(postgres_install_dir) = env::var_os("POSTGRES_INSTALL_DIR") { postgres_install_dir.into() } else { PathBuf::from("pg_install") }; - // Currently, we only expect to find PostgreSQL v14 sources, in "pg_install/v14". In the - // future, we will run this for all supported PostgreSQL versions. - pg_install_dir.push("v14"); - if pg_install_dir.is_relative() { - let cwd = env::current_dir().unwrap(); - pg_install_dir = cwd.join("..").join("..").join(pg_install_dir); - } - - let pg_config_bin = pg_install_dir.join("bin").join("pg_config"); - let inc_server_path: String = if pg_config_bin.exists() { - let output = Command::new(pg_config_bin) - .arg("--includedir-server") - .output() - .expect("failed to execute `pg_config --includedir-server`"); - - if !output.status.success() { - panic!("`pg_config --includedir-server` failed") + for pg_version in &["v14", "v15"] { + let mut pg_install_dir_versioned = pg_install_dir.join(pg_version); + if pg_install_dir_versioned.is_relative() { + let cwd = env::current_dir().unwrap(); + pg_install_dir_versioned = cwd.join("..").join("..").join(pg_install_dir_versioned); } - String::from_utf8(output.stdout).unwrap().trim_end().into() - } else { - pg_install_dir - .join("include") - .join("postgresql") - .join("server") - .into_os_string() - .into_string() - .unwrap() - }; + let pg_config_bin = pg_install_dir_versioned + .join(pg_version) + .join("bin") + .join("pg_config"); + let inc_server_path: String = if pg_config_bin.exists() { + let output = Command::new(pg_config_bin) + .arg("--includedir-server") + .output() + .expect("failed to execute `pg_config --includedir-server`"); - // The bindgen::Builder is the main entry point - // to bindgen, and lets you build up options for - // the resulting bindings. - let bindings = bindgen::Builder::default() - // - // All the needed PostgreSQL headers are included from 'bindgen_deps.h' - // - .header("bindgen_deps.h") - // - // Tell cargo to invalidate the built crate whenever any of the - // included header files changed. - // - .parse_callbacks(Box::new(PostgresFfiCallbacks)) - // - // These are the types and constants that we want to generate bindings for - // - .allowlist_type("BlockNumber") - .allowlist_type("OffsetNumber") - .allowlist_type("MultiXactId") - .allowlist_type("MultiXactOffset") - .allowlist_type("MultiXactStatus") - .allowlist_type("ControlFileData") - .allowlist_type("CheckPoint") - .allowlist_type("FullTransactionId") - .allowlist_type("XLogRecord") - .allowlist_type("XLogPageHeaderData") - .allowlist_type("XLogLongPageHeaderData") - .allowlist_var("XLOG_PAGE_MAGIC") - .allowlist_var("PG_CONTROL_FILE_SIZE") - .allowlist_var("PG_CONTROLFILEDATA_OFFSETOF_CRC") - .allowlist_type("PageHeaderData") - .allowlist_type("DBState") - // Because structs are used for serialization, tell bindgen to emit - // explicit padding fields. - .explicit_padding(true) - // - .clang_arg(format!("-I{inc_server_path}")) - // - // Finish the builder and generate the bindings. - // - .generate() - .expect("Unable to generate bindings"); + if !output.status.success() { + panic!("`pg_config --includedir-server` failed") + } - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); + String::from_utf8(output.stdout).unwrap().trim_end().into() + } else { + pg_install_dir_versioned + .join("include") + .join("postgresql") + .join("server") + .into_os_string() + .into_string() + .unwrap() + }; + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // + // All the needed PostgreSQL headers are included from 'bindgen_deps.h' + // + .header("bindgen_deps.h") + // + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + // + .parse_callbacks(Box::new(PostgresFfiCallbacks)) + // + // These are the types and constants that we want to generate bindings for + // + .allowlist_type("BlockNumber") + .allowlist_type("OffsetNumber") + .allowlist_type("XLogRecPtr") + .allowlist_type("XLogSegNo") + .allowlist_type("TimeLineID") + .allowlist_type("TimestampTz") + .allowlist_type("MultiXactId") + .allowlist_type("MultiXactOffset") + .allowlist_type("MultiXactStatus") + .allowlist_type("ControlFileData") + .allowlist_type("CheckPoint") + .allowlist_type("FullTransactionId") + .allowlist_type("XLogRecord") + .allowlist_type("XLogPageHeaderData") + .allowlist_type("XLogLongPageHeaderData") + .allowlist_var("XLOG_PAGE_MAGIC") + .allowlist_var("PG_CONTROL_FILE_SIZE") + .allowlist_var("PG_CONTROLFILEDATA_OFFSETOF_CRC") + .allowlist_type("PageHeaderData") + .allowlist_type("DBState") + // Because structs are used for serialization, tell bindgen to emit + // explicit padding fields. + .explicit_padding(true) + // + .clang_arg(format!("-I{inc_server_path}")) + // + // Finish the builder and generate the bindings. + // + .generate() + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings_$pg_version.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let filename = format!("bindings_{pg_version}.rs"); + + bindings + .write_to_file(out_path.join(filename)) + .expect("Couldn't write bindings!"); + } } diff --git a/libs/postgres_ffi/src/lib.rs b/libs/postgres_ffi/src/lib.rs index 022355329c..f43232ed0c 100644 --- a/libs/postgres_ffi/src/lib.rs +++ b/libs/postgres_ffi/src/lib.rs @@ -13,13 +13,17 @@ macro_rules! postgres_ffi { ($version:ident) => { #[path = "."] pub mod $version { - // fixme: does this have to be 'pub'? pub mod bindings { // bindgen generates bindings for a lot of stuff we don't need #![allow(dead_code)] use serde::{Deserialize, Serialize}; - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + include!(concat!( + env!("OUT_DIR"), + "/bindings_", + stringify!($version), + ".rs" + )); } pub mod controlfile_utils; pub mod nonrelfile_utils; @@ -28,6 +32,8 @@ macro_rules! postgres_ffi { pub mod waldecoder; pub mod xlog_utils; + pub const PG_MAJORVERSION: &str = stringify!($version); + // Re-export some symbols from bindings pub use bindings::DBState_DB_SHUTDOWNED; pub use bindings::{CheckPoint, ControlFileData, XLogRecord}; @@ -36,20 +42,26 @@ macro_rules! postgres_ffi { } postgres_ffi!(v14); +postgres_ffi!(v15); // Export some widely used datatypes that are unlikely to change across Postgres versions pub use v14::bindings::{uint32, uint64, Oid}; pub use v14::bindings::{BlockNumber, OffsetNumber}; pub use v14::bindings::{MultiXactId, TransactionId}; +pub use v14::bindings::{TimeLineID, TimestampTz, XLogRecPtr, XLogSegNo}; // Likewise for these, although the assumption that these don't change is a little more iffy. pub use v14::bindings::{MultiXactOffset, MultiXactStatus}; +pub use v14::xlog_utils::{XLOG_SIZE_OF_XLOG_RECORD, XLOG_SIZE_OF_XLOG_SHORT_PHD}; // from pg_config.h. These can be changed with configure options --with-blocksize=BLOCKSIZE and // --with-segsize=SEGSIZE, but assume the defaults for now. pub const BLCKSZ: u16 = 8192; pub const RELSEG_SIZE: u32 = 1024 * 1024 * 1024 / (BLCKSZ as u32); pub const XLOG_BLCKSZ: usize = 8192; +pub const WAL_SEGMENT_SIZE: usize = 16 * 1024 * 1024; + +pub const MAX_SEND_SIZE: usize = XLOG_BLCKSZ * 16; // PG timeline is always 1, changing it doesn't have any useful meaning in Neon. // diff --git a/libs/postgres_ffi/src/pg_constants.rs b/libs/postgres_ffi/src/pg_constants.rs index 42b5c5d842..8cc9fa7af6 100644 --- a/libs/postgres_ffi/src/pg_constants.rs +++ b/libs/postgres_ffi/src/pg_constants.rs @@ -7,7 +7,7 @@ //! comments on them. //! -use super::bindings::PageHeaderData; +use super::bindings::{PageHeaderData, XLogRecord}; use crate::BLCKSZ; // @@ -176,7 +176,7 @@ pub const XLOG_DBASE_DROP: u8 = 0x10; pub const XLOG_TBLSPC_CREATE: u8 = 0x00; pub const XLOG_TBLSPC_DROP: u8 = 0x10; -pub const SIZEOF_XLOGRECORD: u32 = 24; +pub const SIZEOF_XLOGRECORD: u32 = std::mem::size_of::() as u32; // // from xlogrecord.h @@ -206,15 +206,10 @@ pub const INVALID_TRANSACTION_ID: u32 = 0; pub const FIRST_BOOTSTRAP_OBJECT_ID: u32 = 12000; pub const FIRST_NORMAL_OBJECT_ID: u32 = 16384; -/* FIXME: pageserver should request wal_seg_size from compute node */ -pub const WAL_SEGMENT_SIZE: usize = 16 * 1024 * 1024; - pub const XLOG_CHECKPOINT_SHUTDOWN: u8 = 0x00; pub const XLOG_CHECKPOINT_ONLINE: u8 = 0x10; pub const XLP_LONG_HEADER: u16 = 0x0002; -pub const PG_MAJORVERSION: &str = "14"; - // List of subdirectories inside pgdata. // Copied from src/bin/initdb/initdb.c pub const PGDATA_SUBDIRS: [&str; 22] = [ diff --git a/libs/postgres_ffi/src/waldecoder.rs b/libs/postgres_ffi/src/waldecoder.rs index b509fc87a5..4d79e4b1d1 100644 --- a/libs/postgres_ffi/src/waldecoder.rs +++ b/libs/postgres_ffi/src/waldecoder.rs @@ -9,8 +9,8 @@ //! for that is in pageserver/src/walrecord.rs //! use super::bindings::{XLogLongPageHeaderData, XLogPageHeaderData, XLogRecord, XLOG_PAGE_MAGIC}; -use super::pg_constants; use super::xlog_utils::*; +use crate::WAL_SEGMENT_SIZE; use bytes::{Buf, BufMut, Bytes, BytesMut}; use crc32c::*; use log::*; @@ -133,7 +133,7 @@ impl WalStreamDecoder { // However, we may have to skip some page headers if we're processing the XLOG_SWITCH record or skipping padding for whatever reason. match self.state { State::WaitingForRecord | State::ReassemblingRecord { .. } => { - if self.lsn.segment_offset(pg_constants::WAL_SEGMENT_SIZE) == 0 { + if self.lsn.segment_offset(WAL_SEGMENT_SIZE) == 0 { // parse long header if self.inputbuf.remaining() < XLOG_SIZE_OF_XLOG_LONG_PHD { @@ -265,7 +265,7 @@ impl WalStreamDecoder { // to the next WAL segment. let next_lsn = if xlogrec.is_xlog_switch_record() { trace!("saw xlog switch record at {}", self.lsn); - self.lsn + self.lsn.calc_padding(pg_constants::WAL_SEGMENT_SIZE as u64) + self.lsn + self.lsn.calc_padding(WAL_SEGMENT_SIZE as u64) } else { // Pad to an 8-byte boundary self.lsn.align() diff --git a/libs/postgres_ffi/src/xlog_utils.rs b/libs/postgres_ffi/src/xlog_utils.rs index 0d9aaa4708..f8606b6e47 100644 --- a/libs/postgres_ffi/src/xlog_utils.rs +++ b/libs/postgres_ffi/src/xlog_utils.rs @@ -10,14 +10,14 @@ use crc32c::crc32c_append; use super::bindings::{ - CheckPoint, FullTransactionId, XLogLongPageHeaderData, XLogPageHeaderData, XLogRecord, - XLOG_PAGE_MAGIC, + CheckPoint, FullTransactionId, TimeLineID, TimestampTz, XLogLongPageHeaderData, + XLogPageHeaderData, XLogRecPtr, XLogRecord, XLogSegNo, XLOG_PAGE_MAGIC, }; use super::pg_constants; -use super::pg_constants::WAL_SEGMENT_SIZE; -use crate::v14::waldecoder::WalStreamDecoder; +use super::waldecoder::WalStreamDecoder; use crate::PG_TLI; use crate::{uint32, uint64, Oid}; +use crate::{WAL_SEGMENT_SIZE, XLOG_BLCKSZ}; use bytes::BytesMut; use bytes::{Buf, Bytes}; @@ -37,11 +37,9 @@ use utils::bin_ser::SerializeError; use utils::lsn::Lsn; pub const XLOG_FNAME_LEN: usize = 24; -pub const XLOG_BLCKSZ: usize = 8192; pub const XLP_FIRST_IS_CONTRECORD: u16 = 0x0001; pub const XLP_REM_LEN_OFFS: usize = 2 + 2 + 4 + 8; pub const XLOG_RECORD_CRC_OFFS: usize = 4 + 4 + 8 + 1 + 1 + 2; -pub const MAX_SEND_SIZE: usize = XLOG_BLCKSZ * 16; pub const XLOG_SIZE_OF_XLOG_SHORT_PHD: usize = std::mem::size_of::(); pub const XLOG_SIZE_OF_XLOG_LONG_PHD: usize = std::mem::size_of::(); @@ -49,11 +47,6 @@ pub const XLOG_SIZE_OF_XLOG_RECORD: usize = std::mem::size_of::(); #[allow(clippy::identity_op)] pub const SIZE_OF_XLOG_RECORD_DATA_HEADER_SHORT: usize = 1 * 2; -pub type XLogRecPtr = u64; -pub type TimeLineID = u32; -pub type TimestampTz = i64; -pub type XLogSegNo = u64; - /// Interval of checkpointing metadata file. We should store metadata file to enforce /// predicate that checkpoint.nextXid is larger than any XID in WAL. /// But flushing checkpoint file for each transaction seems to be too expensive, @@ -318,9 +311,9 @@ impl CheckPoint { // We need this segment to start compute node. // pub fn generate_wal_segment(segno: u64, system_id: u64) -> Result { - let mut seg_buf = BytesMut::with_capacity(pg_constants::WAL_SEGMENT_SIZE as usize); + let mut seg_buf = BytesMut::with_capacity(WAL_SEGMENT_SIZE as usize); - let pageaddr = XLogSegNoOffsetToRecPtr(segno, 0, pg_constants::WAL_SEGMENT_SIZE); + let pageaddr = XLogSegNoOffsetToRecPtr(segno, 0, WAL_SEGMENT_SIZE); let hdr = XLogLongPageHeaderData { std: { XLogPageHeaderData { @@ -333,7 +326,7 @@ pub fn generate_wal_segment(segno: u64, system_id: u64) -> Result Result Vec { #[cfg(test)] mod tests { + use super::super::PG_MAJORVERSION; use super::*; use regex::Regex; use std::cmp::min; @@ -434,23 +428,23 @@ mod tests { use utils::const_assert; fn init_logging() { - let _ = env_logger::Builder::from_env( - env_logger::Env::default() - .default_filter_or("wal_craft=info,postgres_ffi::xlog_utils=trace"), - ) + let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or( + format!("wal_craft=info,postgres_ffi::{PG_MAJORVERSION}::xlog_utils=trace"), + )) .is_test(true) .try_init(); } fn test_end_of_wal(test_name: &str) { use wal_craft::*; + // Craft some WAL let top_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("..") .join(".."); let cfg = Conf { - pg_distrib_dir: top_path.join("pg_install/v14"), - datadir: top_path.join(format!("test_output/{}", test_name)), + pg_distrib_dir: top_path.join(format!("pg_install/{PG_MAJORVERSION}")), + datadir: top_path.join(format!("test_output/{}-{PG_MAJORVERSION}", test_name)), }; if cfg.datadir.exists() { fs::remove_dir_all(&cfg.datadir).unwrap(); diff --git a/libs/postgres_ffi/wal_craft/src/lib.rs b/libs/postgres_ffi/wal_craft/src/lib.rs index 6ac5afb27f..2ad92d776d 100644 --- a/libs/postgres_ffi/wal_craft/src/lib.rs +++ b/libs/postgres_ffi/wal_craft/src/lib.rs @@ -4,10 +4,8 @@ use log::*; use once_cell::sync::Lazy; use postgres::types::PgLsn; use postgres::Client; -use postgres_ffi::v14::pg_constants::WAL_SEGMENT_SIZE; -use postgres_ffi::v14::xlog_utils::{ - XLOG_BLCKSZ, XLOG_SIZE_OF_XLOG_RECORD, XLOG_SIZE_OF_XLOG_SHORT_PHD, -}; +use postgres_ffi::{WAL_SEGMENT_SIZE, XLOG_BLCKSZ}; +use postgres_ffi::{XLOG_SIZE_OF_XLOG_RECORD, XLOG_SIZE_OF_XLOG_SHORT_PHD}; use std::cmp::Ordering; use std::fs; use std::path::{Path, PathBuf}; diff --git a/pageserver/src/basebackup.rs b/pageserver/src/basebackup.rs index 48b5f1a695..cd99c3c67d 100644 --- a/pageserver/src/basebackup.rs +++ b/pageserver/src/basebackup.rs @@ -30,7 +30,7 @@ use postgres_ffi::v14::xlog_utils::{generate_wal_segment, normalize_lsn, XLogFil use postgres_ffi::v14::{CheckPoint, ControlFileData}; use postgres_ffi::TransactionId; use postgres_ffi::PG_TLI; -use postgres_ffi::{BLCKSZ, RELSEG_SIZE}; +use postgres_ffi::{BLCKSZ, RELSEG_SIZE, WAL_SEGMENT_SIZE}; use utils::lsn::Lsn; /// This is short-living object only for the time of tarball creation, @@ -268,8 +268,11 @@ where None }; + // TODO pass this as a parameter + let pg_version = "14"; + if spcnode == pg_constants::GLOBALTABLESPACE_OID { - let version_bytes = pg_constants::PG_MAJORVERSION.as_bytes(); + let version_bytes = pg_version.as_bytes(); let header = new_tar_header("PG_VERSION", version_bytes.len() as u64)?; self.ar.append(&header, version_bytes)?; @@ -312,7 +315,7 @@ where if let Some(img) = relmap_img { let dst_path = format!("base/{}/PG_VERSION", dbnode); - let version_bytes = pg_constants::PG_MAJORVERSION.as_bytes(); + let version_bytes = pg_version.as_bytes(); let header = new_tar_header(&dst_path, version_bytes.len() as u64)?; self.ar.append(&header, version_bytes)?; @@ -358,7 +361,7 @@ where let mut checkpoint = CheckPoint::decode(&checkpoint_bytes)?; // Generate new pg_control needed for bootstrap - checkpoint.redo = normalize_lsn(self.lsn, pg_constants::WAL_SEGMENT_SIZE).0; + checkpoint.redo = normalize_lsn(self.lsn, WAL_SEGMENT_SIZE).0; //reset some fields we don't want to preserve //TODO Check this. @@ -392,13 +395,13 @@ where self.ar.append(&header, &pg_control_bytes[..])?; //send wal segment - let segno = self.lsn.segment_number(pg_constants::WAL_SEGMENT_SIZE); - let wal_file_name = XLogFileName(PG_TLI, segno, pg_constants::WAL_SEGMENT_SIZE); + let segno = self.lsn.segment_number(WAL_SEGMENT_SIZE); + let wal_file_name = XLogFileName(PG_TLI, segno, WAL_SEGMENT_SIZE); let wal_file_path = format!("pg_wal/{}", wal_file_name); - let header = new_tar_header(&wal_file_path, pg_constants::WAL_SEGMENT_SIZE as u64)?; + let header = new_tar_header(&wal_file_path, WAL_SEGMENT_SIZE as u64)?; let wal_seg = generate_wal_segment(segno, pg_control.system_identifier) .map_err(|e| anyhow!(e).context("Failed generating wal segment"))?; - ensure!(wal_seg.len() == pg_constants::WAL_SEGMENT_SIZE); + ensure!(wal_seg.len() == WAL_SEGMENT_SIZE); self.ar.append(&header, &wal_seg[..])?; Ok(()) } diff --git a/pageserver/src/import_datadir.rs b/pageserver/src/import_datadir.rs index 4cc3aafb0e..f8f614f8f4 100644 --- a/pageserver/src/import_datadir.rs +++ b/pageserver/src/import_datadir.rs @@ -21,7 +21,7 @@ use postgres_ffi::v14::waldecoder::*; use postgres_ffi::v14::xlog_utils::*; use postgres_ffi::v14::{pg_constants, ControlFileData, DBState_DB_SHUTDOWNED}; use postgres_ffi::Oid; -use postgres_ffi::BLCKSZ; +use postgres_ffi::{BLCKSZ, WAL_SEGMENT_SIZE}; use utils::lsn::Lsn; // Returns checkpoint LSN from controlfile @@ -238,15 +238,15 @@ fn import_slru( fn import_wal(walpath: &Path, tline: &Timeline, startpoint: Lsn, endpoint: Lsn) -> Result<()> { let mut waldecoder = WalStreamDecoder::new(startpoint); - let mut segno = startpoint.segment_number(pg_constants::WAL_SEGMENT_SIZE); - let mut offset = startpoint.segment_offset(pg_constants::WAL_SEGMENT_SIZE); + let mut segno = startpoint.segment_number(WAL_SEGMENT_SIZE); + let mut offset = startpoint.segment_offset(WAL_SEGMENT_SIZE); let mut last_lsn = startpoint; let mut walingest = WalIngest::new(tline, startpoint)?; while last_lsn <= endpoint { // FIXME: assume postgresql tli 1 for now - let filename = XLogFileName(1, segno, pg_constants::WAL_SEGMENT_SIZE); + let filename = XLogFileName(1, segno, WAL_SEGMENT_SIZE); let mut buf = Vec::new(); // Read local file @@ -265,7 +265,7 @@ fn import_wal(walpath: &Path, tline: &Timeline, startpoint: Lsn, endpoint: Lsn) } let nread = file.read_to_end(&mut buf)?; - if nread != pg_constants::WAL_SEGMENT_SIZE - offset as usize { + if nread != WAL_SEGMENT_SIZE - offset as usize { // Maybe allow this for .partial files? error!("read only {} bytes from WAL file", nread); } @@ -355,8 +355,8 @@ pub fn import_wal_from_tar( ) -> Result<()> { // Set up walingest mutable state let mut waldecoder = WalStreamDecoder::new(start_lsn); - let mut segno = start_lsn.segment_number(pg_constants::WAL_SEGMENT_SIZE); - let mut offset = start_lsn.segment_offset(pg_constants::WAL_SEGMENT_SIZE); + let mut segno = start_lsn.segment_number(WAL_SEGMENT_SIZE); + let mut offset = start_lsn.segment_offset(WAL_SEGMENT_SIZE); let mut last_lsn = start_lsn; let mut walingest = WalIngest::new(tline, start_lsn)?; @@ -373,7 +373,7 @@ pub fn import_wal_from_tar( match header.entry_type() { tar::EntryType::Regular => { // FIXME: assume postgresql tli 1 for now - let expected_filename = XLogFileName(1, segno, pg_constants::WAL_SEGMENT_SIZE); + let expected_filename = XLogFileName(1, segno, WAL_SEGMENT_SIZE); let file_name = file_path .file_name() .expect("missing wal filename") diff --git a/pageserver/src/pgdatadir_mapping.rs b/pageserver/src/pgdatadir_mapping.rs index 7bba64179c..ba48a77961 100644 --- a/pageserver/src/pgdatadir_mapping.rs +++ b/pageserver/src/pgdatadir_mapping.rs @@ -14,9 +14,8 @@ use crate::walrecord::ZenithWalRecord; use anyhow::{bail, ensure, Result}; use bytes::{Buf, Bytes}; use postgres_ffi::v14::pg_constants; -use postgres_ffi::v14::xlog_utils::TimestampTz; use postgres_ffi::BLCKSZ; -use postgres_ffi::{Oid, TransactionId}; +use postgres_ffi::{Oid, TimestampTz, TransactionId}; use serde::{Deserialize, Serialize}; use std::collections::{hash_map, HashMap, HashSet}; use std::ops::Range; diff --git a/pageserver/src/walrecord.rs b/pageserver/src/walrecord.rs index c56b1c6c0c..c718a4c30c 100644 --- a/pageserver/src/walrecord.rs +++ b/pageserver/src/walrecord.rs @@ -4,10 +4,10 @@ use anyhow::Result; use bytes::{Buf, Bytes}; use postgres_ffi::v14::pg_constants; -use postgres_ffi::v14::xlog_utils::{TimestampTz, XLOG_SIZE_OF_XLOG_RECORD}; +use postgres_ffi::v14::xlog_utils::XLOG_SIZE_OF_XLOG_RECORD; use postgres_ffi::v14::XLogRecord; use postgres_ffi::BLCKSZ; -use postgres_ffi::{BlockNumber, OffsetNumber}; +use postgres_ffi::{BlockNumber, OffsetNumber, TimestampTz}; use postgres_ffi::{MultiXactId, MultiXactOffset, MultiXactStatus, Oid, TransactionId}; use serde::{Deserialize, Serialize}; use tracing::*; diff --git a/safekeeper/src/json_ctrl.rs b/safekeeper/src/json_ctrl.rs index 3f84e7b183..16c1d36131 100644 --- a/safekeeper/src/json_ctrl.rs +++ b/safekeeper/src/json_ctrl.rs @@ -18,8 +18,8 @@ use crate::safekeeper::{ }; use crate::safekeeper::{SafeKeeperState, Term, TermHistory, TermSwitchEntry}; use crate::timeline::TimelineTools; -use postgres_ffi::v14::pg_constants; use postgres_ffi::v14::xlog_utils; +use postgres_ffi::WAL_SEGMENT_SIZE; use utils::{ lsn::Lsn, postgres_backend::PostgresBackend, @@ -100,7 +100,7 @@ fn prepare_safekeeper(spg: &mut SafekeeperPostgresHandler) -> Result<()> { ztli: spg.ztimelineid.unwrap(), tenant_id: spg.ztenantid.unwrap(), tli: 0, - wal_seg_size: pg_constants::WAL_SEGMENT_SIZE as u32, // 16MB, default for tests + wal_seg_size: WAL_SEGMENT_SIZE as u32, // 16MB, default for tests }); let response = spg.timeline.get().process_msg(&greeting_request)?; diff --git a/safekeeper/src/metrics.rs b/safekeeper/src/metrics.rs index 648f0634f8..c693035dd3 100644 --- a/safekeeper/src/metrics.rs +++ b/safekeeper/src/metrics.rs @@ -7,7 +7,7 @@ use metrics::{ proto::MetricFamily, Gauge, IntGaugeVec, }; -use postgres_ffi::v14::xlog_utils::XLogSegNo; +use postgres_ffi::XLogSegNo; use utils::{lsn::Lsn, zid::ZTenantTimelineId}; use crate::{ diff --git a/safekeeper/src/safekeeper.rs b/safekeeper/src/safekeeper.rs index ed34669dde..a2bdcb55e7 100644 --- a/safekeeper/src/safekeeper.rs +++ b/safekeeper/src/safekeeper.rs @@ -5,7 +5,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use etcd_broker::subscription_value::SkTimelineInfo; -use postgres_ffi::v14::xlog_utils::{TimeLineID, XLogSegNo, MAX_SEND_SIZE}; +use postgres_ffi::{TimeLineID, XLogSegNo, MAX_SEND_SIZE}; use serde::{Deserialize, Serialize}; use std::cmp::max; use std::cmp::min; diff --git a/safekeeper/src/send_wal.rs b/safekeeper/src/send_wal.rs index 38523f9f82..293cf67c57 100644 --- a/safekeeper/src/send_wal.rs +++ b/safekeeper/src/send_wal.rs @@ -6,9 +6,9 @@ use crate::timeline::{ReplicaState, Timeline, TimelineTools}; use crate::wal_storage::WalReader; use anyhow::{bail, Context, Result}; -use postgres_ffi::v14::xlog_utils::{get_current_timestamp, TimestampTz, MAX_SEND_SIZE}; - use bytes::Bytes; +use postgres_ffi::v14::xlog_utils::get_current_timestamp; +use postgres_ffi::{TimestampTz, MAX_SEND_SIZE}; use serde::{Deserialize, Serialize}; use std::cmp::min; use std::net::Shutdown; diff --git a/safekeeper/src/timeline.rs b/safekeeper/src/timeline.rs index f482dbb3aa..8d101e6ff6 100644 --- a/safekeeper/src/timeline.rs +++ b/safekeeper/src/timeline.rs @@ -6,7 +6,7 @@ use anyhow::{bail, Context, Result}; use etcd_broker::subscription_value::SkTimelineInfo; use once_cell::sync::Lazy; -use postgres_ffi::v14::xlog_utils::XLogSegNo; +use postgres_ffi::XLogSegNo; use serde::Serialize; use tokio::sync::watch; diff --git a/safekeeper/src/wal_backup.rs b/safekeeper/src/wal_backup.rs index 5c6991c196..6acc70e85a 100644 --- a/safekeeper/src/wal_backup.rs +++ b/safekeeper/src/wal_backup.rs @@ -11,8 +11,8 @@ use std::pin::Pin; use std::sync::Arc; use std::time::Duration; -use postgres_ffi::v14::xlog_utils::{XLogFileName, XLogSegNo, XLogSegNoOffsetToRecPtr}; -use postgres_ffi::PG_TLI; +use postgres_ffi::v14::xlog_utils::{XLogFileName, XLogSegNoOffsetToRecPtr}; +use postgres_ffi::{XLogSegNo, PG_TLI}; use remote_storage::GenericRemoteStorage; use tokio::fs::File; use tokio::runtime::Builder; diff --git a/safekeeper/src/wal_storage.rs b/safekeeper/src/wal_storage.rs index 6a45ae1411..644237a00d 100644 --- a/safekeeper/src/wal_storage.rs +++ b/safekeeper/src/wal_storage.rs @@ -14,9 +14,9 @@ use tokio::io::AsyncRead; use once_cell::sync::Lazy; use postgres_ffi::v14::xlog_utils::{ - find_end_of_wal, IsPartialXLogFileName, IsXLogFileName, XLogFromFileName, XLogSegNo, + find_end_of_wal, IsPartialXLogFileName, IsXLogFileName, XLogFromFileName, }; -use postgres_ffi::PG_TLI; +use postgres_ffi::{XLogSegNo, PG_TLI}; use std::cmp::min; use std::fs::{self, remove_file, File, OpenOptions};