core/storage: Wrap Pager::allocate_page_state with RwLock

This commit is contained in:
Pekka Enberg
2025-09-17 13:22:54 +03:00
parent 365f606cce
commit e6d994dee0

View File

@@ -511,9 +511,9 @@ pub struct Pager {
/// Mutex for synchronizing database initialization to prevent race conditions
init_lock: Arc<Mutex<()>>,
/// The state of the current allocate page operation.
allocate_page_state: RefCell<AllocatePageState>,
allocate_page_state: RwLock<AllocatePageState>,
/// The state of the current allocate page1 operation.
allocate_page1_state: RefCell<AllocatePage1State>,
allocate_page1_state: RwLock<AllocatePage1State>,
/// Cache page_size and reserved_space at Pager init and reuse for subsequent
/// `usable_space` calls. TODO: Invalidate reserved_space when we add the functionality
/// to change it.
@@ -594,9 +594,9 @@ impl Pager {
init_lock: Arc<Mutex<()>>,
) -> Result<Self> {
let allocate_page1_state = if !db_state.is_initialized() {
RefCell::new(AllocatePage1State::Start)
RwLock::new(AllocatePage1State::Start)
} else {
RefCell::new(AllocatePage1State::Done)
RwLock::new(AllocatePage1State::Done)
};
let now = io.now();
Ok(Self {
@@ -623,7 +623,7 @@ impl Pager {
page_size: Cell::new(None),
reserved_space: Cell::new(None),
free_page_state: RefCell::new(FreePageState::Start),
allocate_page_state: RefCell::new(AllocatePageState::Start),
allocate_page_state: RwLock::new(AllocatePageState::Start),
max_page_count: Cell::new(DEFAULT_MAX_PAGE_COUNT),
#[cfg(not(feature = "omit_autovacuum"))]
ptrmap_get_state: RefCell::new(PtrMapGetState::Start),
@@ -1923,7 +1923,7 @@ impl Pager {
#[instrument(skip_all, level = Level::DEBUG)]
pub fn allocate_page1(&self) -> Result<IOResult<PageRef>> {
let state = self.allocate_page1_state.borrow().clone();
let state = self.allocate_page1_state.read().clone();
match state {
AllocatePage1State::Start => {
tracing::trace!("allocate_page1(Start)");
@@ -1973,8 +1973,7 @@ impl Pager {
);
let c = begin_write_btree_page(self, &page1)?;
self.allocate_page1_state
.replace(AllocatePage1State::Writing { page: page1 });
*self.allocate_page1_state.write() = AllocatePage1State::Writing { page: page1 };
io_yield_one!(c);
}
AllocatePage1State::Writing { page } => {
@@ -1986,7 +1985,7 @@ impl Pager {
LimboError::InternalError(format!("Failed to insert page 1 into cache: {e:?}"))
})?;
self.db_state.set(DbState::Initialized);
self.allocate_page1_state.replace(AllocatePage1State::Done);
*self.allocate_page1_state.write() = AllocatePage1State::Done;
Ok(IOResult::Done(page.clone()))
}
AllocatePage1State::Done => unreachable!("cannot try to allocate page 1 again"),
@@ -1995,7 +1994,7 @@ impl Pager {
pub fn allocating_page1(&self) -> bool {
matches!(
*self.allocate_page1_state.borrow(),
*self.allocate_page1_state.read(),
AllocatePage1State::Writing { .. }
)
}
@@ -2019,7 +2018,7 @@ impl Pager {
let header = header_ref.borrow_mut();
loop {
let mut state = self.allocate_page_state.borrow_mut();
let mut state = self.allocate_page_state.write();
tracing::debug!("allocate_page(state={:?})", state);
match &mut *state {
AllocatePageState::Start => {
@@ -2284,7 +2283,7 @@ impl Pager {
self.syncing.store(false, Ordering::SeqCst);
self.commit_info.state.set(CommitState::PrepareWal);
self.commit_info.time.set(self.io.now());
self.allocate_page_state.replace(AllocatePageState::Start);
*self.allocate_page_state.write() = AllocatePageState::Start;
self.free_page_state.replace(FreePageState::Start);
#[cfg(not(feature = "omit_autovacuum"))]
{