Files
neon/safekeeper/tests/walproposer_sim/walproposer_disk.rs
Erik Grinaker 96e35e11a6 postgres_ffi: add WAL generator for tests/benchmarks (#9503)
## Problem

We don't have a convenient way to generate WAL records for benchmarks
and tests.

## Summary of changes

Adds a WAL generator, exposed as an iterator. It currently only
generates logical messages (noops), but will be extended to write actual
table rows later.

Some existing code for WAL generation has been replaced with this
generator, to reduce duplication.
2024-10-30 14:46:39 +03:00

73 lines
2.0 KiB
Rust

use std::{ffi::CStr, sync::Arc};
use parking_lot::{Mutex, MutexGuard};
use postgres_ffi::v16::wal_generator::WalGenerator;
use utils::lsn::Lsn;
use super::block_storage::BlockStorage;
/// Simulation implementation of walproposer WAL storage.
pub struct DiskWalProposer {
state: Mutex<State>,
}
impl DiskWalProposer {
pub fn new() -> Arc<DiskWalProposer> {
Arc::new(DiskWalProposer {
state: Mutex::new(State {
internal_available_lsn: Lsn(0),
prev_lsn: Lsn(0),
disk: BlockStorage::new(),
wal_generator: WalGenerator::new(),
}),
})
}
pub fn lock(&self) -> MutexGuard<State> {
self.state.lock()
}
}
pub struct State {
// flush_lsn
internal_available_lsn: Lsn,
// needed for WAL generation
prev_lsn: Lsn,
// actual WAL storage
disk: BlockStorage,
// WAL record generator
wal_generator: WalGenerator,
}
impl State {
pub fn read(&self, pos: u64, buf: &mut [u8]) {
self.disk.read(pos, buf);
// TODO: fail on reading uninitialized data
}
pub fn write(&mut self, pos: u64, buf: &[u8]) {
self.disk.write(pos, buf);
}
/// Update the internal available LSN to the given value.
pub fn reset_to(&mut self, lsn: Lsn) {
self.internal_available_lsn = lsn;
self.prev_lsn = Lsn(0); // Safekeeper doesn't care if this is omitted
self.wal_generator.lsn = self.internal_available_lsn;
self.wal_generator.prev_lsn = self.prev_lsn;
}
/// Get current LSN.
pub fn flush_rec_ptr(&self) -> Lsn {
self.internal_available_lsn
}
/// Inserts a logical record in the WAL at the current LSN.
pub fn insert_logical_message(&mut self, prefix: &CStr, msg: &[u8]) {
let record = self.wal_generator.generate_logical_message(prefix, msg);
self.disk.write(self.internal_available_lsn.into(), &record);
self.prev_lsn = self.internal_available_lsn;
self.internal_available_lsn += record.len() as u64;
}
}