Skip to content

Commit 648755a

Browse files
committed
add Lsn::block_offset, remaining_in_block, calc_padding
Replace open-coded math with member fns.
1 parent 1c775bd commit 648755a

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

pageserver/src/waldecoder.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use std::str;
66
use thiserror::Error;
77
use zenith_utils::lsn::Lsn;
88

9-
const XLOG_BLCKSZ: u32 = 8192;
10-
119
// FIXME: this is configurable in PostgreSQL, 16 MB is the default
1210
const WAL_SEGMENT_SIZE: u64 = 16 * 1024 * 1024;
1311

@@ -111,10 +109,7 @@ impl WalStreamDecoder {
111109

112110
self.lsn += SizeOfXLogLongPHD as u64;
113111
continue;
114-
} else if self.lsn.0 % (XLOG_BLCKSZ as u64) == 0 {
115-
// FIXME: make this a member of Lsn, but what should it be called?
116-
// parse page header
117-
112+
} else if self.lsn.block_offset() == 0 {
118113
if self.inputbuf.remaining() < SizeOfXLogShortPHD {
119114
return Ok(None);
120115
}
@@ -165,8 +160,7 @@ impl WalStreamDecoder {
165160
continue;
166161
} else {
167162
// we're continuing a record, possibly from previous page.
168-
// FIXME: Should any of this math be captured into Lsn or a related type?
169-
let pageleft: u32 = XLOG_BLCKSZ - (self.lsn.0 % (XLOG_BLCKSZ as u64)) as u32;
163+
let pageleft = self.lsn.remaining_in_block() as u32;
170164

171165
// read the rest of the record, or as much as fits on this page.
172166
let n = min(self.contlen, pageleft) as usize;
@@ -188,12 +182,10 @@ impl WalStreamDecoder {
188182
// to the next WAL segment.
189183
if is_xlog_switch_record(&recordbuf) {
190184
trace!("saw xlog switch record at {}", self.lsn);
191-
self.padlen = (WAL_SEGMENT_SIZE - (self.lsn.0 % WAL_SEGMENT_SIZE)) as u32;
192-
}
193-
194-
// FIXME: what does this code do?
195-
if self.lsn.0 % 8 != 0 {
196-
self.padlen = 8 - (self.lsn.0 % 8) as u32;
185+
self.padlen = self.lsn.calc_padding(WAL_SEGMENT_SIZE) as u32;
186+
} else {
187+
// Pad to an 8-byte boundary
188+
self.padlen = self.lsn.calc_padding(8u32) as u32;
197189
}
198190

199191
let result = (self.lsn, recordbuf);

pageserver/src/walreceiver.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,7 @@ async fn walreceiver_main(
166166
// FIXME: It probably would be better to always start streaming from the beginning
167167
// of the page, or the segment, so that we could check the page/segment headers
168168
// too. Just for the sake of paranoia.
169-
// FIXME: should any of this logic move inside the Lsn type?
170-
if startpoint.0 % 8 != 0 {
171-
startpoint += 8 - (startpoint.0 % 8);
172-
}
169+
startpoint += startpoint.calc_padding(8u32);
173170
}
174171
debug!(
175172
"last_valid_lsn {} starting replication from {} for timeline {}, server is at {}...",

zenith_utils/src/lsn.rs

+29
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ use std::path::Path;
66
use std::str::FromStr;
77
use std::sync::atomic::{AtomicU64, Ordering};
88

9+
/// Transaction log block size in bytes
10+
pub const XLOG_BLCKSZ: u32 = 8192;
11+
912
/// A Postgres LSN (Log Sequence Number), also known as an XLogRecPtr
1013
#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
1114
pub struct Lsn(pub u64);
@@ -54,6 +57,32 @@ impl Lsn {
5457
pub fn segment_number(self, seg_sz: u64) -> u64 {
5558
self.0 / seg_sz
5659
}
60+
61+
/// Compute the offset into a block
62+
pub fn block_offset(self) -> u64 {
63+
const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
64+
self.0 % BLCKSZ
65+
}
66+
67+
/// Compute the bytes remaining in this block
68+
///
69+
/// If the LSN is already at the block boundary, it will return `XLOG_BLCKSZ`.
70+
pub fn remaining_in_block(self) -> u64 {
71+
const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
72+
BLCKSZ - (self.0 % BLCKSZ)
73+
}
74+
75+
/// Compute the bytes remaining to fill a chunk of some size
76+
///
77+
/// If the LSN is already at the chunk boundary, it will return 0.
78+
pub fn calc_padding<T: Into<u64>>(self, sz: T) -> u64 {
79+
let sz: u64 = sz.into();
80+
// By using wrapping_sub, we can subtract first and then mod second.
81+
// If it's done the other way around, then we would return a full
82+
// chunk size if we're already at the chunk boundary.
83+
// (Regular subtraction will panic on overflow in debug builds.)
84+
(sz.wrapping_sub(self.0)) % sz
85+
}
5786
}
5887

5988
impl From<u64> for Lsn {

0 commit comments

Comments
 (0)