Tripwire for Wal Syncing + set syncing to true before calling sync

This commit is contained in:
pedrocarlo
2025-08-18 13:40:13 -03:00
parent 2954e2e7bf
commit aa7f8fbfc4
3 changed files with 19 additions and 12 deletions

View File

@@ -410,7 +410,7 @@ pub struct Pager {
commit_info: RefCell<CommitInfo>, commit_info: RefCell<CommitInfo>,
checkpoint_state: RefCell<CheckpointState>, checkpoint_state: RefCell<CheckpointState>,
syncing: Rc<RefCell<bool>>, syncing: Rc<Cell<bool>>,
auto_vacuum_mode: RefCell<AutoVacuumMode>, auto_vacuum_mode: RefCell<AutoVacuumMode>,
/// 0 -> Database is empty, /// 0 -> Database is empty,
/// 1 -> Database is being initialized, /// 1 -> Database is being initialized,
@@ -521,7 +521,7 @@ impl Pager {
commit_info: RefCell::new(CommitInfo { commit_info: RefCell::new(CommitInfo {
state: CommitState::Start, state: CommitState::Start,
}), }),
syncing: Rc::new(RefCell::new(false)), syncing: Rc::new(Cell::new(false)),
checkpoint_state: RefCell::new(CheckpointState::Checkpoint), checkpoint_state: RefCell::new(CheckpointState::Checkpoint),
buffer_pool, buffer_pool,
auto_vacuum_mode: RefCell::new(AutoVacuumMode::None), auto_vacuum_mode: RefCell::new(AutoVacuumMode::None),
@@ -1233,6 +1233,7 @@ impl Pager {
io_yield_one!(c); io_yield_one!(c);
} }
CommitState::AfterSyncWal => { CommitState::AfterSyncWal => {
turso_assert!(!wal.borrow().is_syncing(), "wal should have synced");
if wal_auto_checkpoint_disabled || !wal.borrow().should_checkpoint() { if wal_auto_checkpoint_disabled || !wal.borrow().should_checkpoint() {
self.commit_info.borrow_mut().state = CommitState::Start; self.commit_info.borrow_mut().state = CommitState::Start;
break PagerCommitResult::WalWritten; break PagerCommitResult::WalWritten;
@@ -1249,7 +1250,7 @@ impl Pager {
io_yield_one!(c); io_yield_one!(c);
} }
CommitState::AfterSyncDbFile => { CommitState::AfterSyncDbFile => {
turso_assert!(!*self.syncing.borrow(), "should have finished syncing"); turso_assert!(!self.syncing.get(), "should have finished syncing");
self.commit_info.borrow_mut().state = CommitState::Start; self.commit_info.borrow_mut().state = CommitState::Start;
break PagerCommitResult::Checkpointed(checkpoint_result); break PagerCommitResult::Checkpointed(checkpoint_result);
} }
@@ -1341,7 +1342,7 @@ impl Pager {
io_yield_one!(c); io_yield_one!(c);
} }
CheckpointState::CheckpointDone { res } => { CheckpointState::CheckpointDone { res } => {
turso_assert!(!*self.syncing.borrow(), "syncing should be done"); turso_assert!(!self.syncing.get(), "syncing should be done");
self.checkpoint_state.replace(CheckpointState::Checkpoint); self.checkpoint_state.replace(CheckpointState::Checkpoint);
return Ok(IOResult::Done(res)); return Ok(IOResult::Done(res));
} }

View File

@@ -63,7 +63,7 @@ use crate::storage::pager::Pager;
use crate::storage::wal::{PendingFlush, READMARK_NOT_USED}; use crate::storage::wal::{PendingFlush, READMARK_NOT_USED};
use crate::types::{RawSlice, RefValue, SerialType, SerialTypeKind, TextRef, TextSubtype}; use crate::types::{RawSlice, RefValue, SerialType, SerialTypeKind, TextRef, TextSubtype};
use crate::{bail_corrupt_error, turso_assert, File, Result, WalFileShared}; use crate::{bail_corrupt_error, turso_assert, File, Result, WalFileShared};
use std::cell::{RefCell, UnsafeCell}; use std::cell::{Cell, UnsafeCell};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::pin::Pin; use std::pin::Pin;
@@ -1055,12 +1055,12 @@ pub fn write_pages_vectored(
#[instrument(skip_all, level = Level::DEBUG)] #[instrument(skip_all, level = Level::DEBUG)]
pub fn begin_sync( pub fn begin_sync(
db_file: Arc<dyn DatabaseStorage>, db_file: Arc<dyn DatabaseStorage>,
syncing: Rc<RefCell<bool>>, syncing: Rc<Cell<bool>>,
) -> Result<Completion> { ) -> Result<Completion> {
assert!(!*syncing.borrow()); assert!(!syncing.get());
*syncing.borrow_mut() = true; syncing.set(true);
let completion = Completion::new_sync(move |_| { let completion = Completion::new_sync(move |_| {
*syncing.borrow_mut() = false; syncing.set(false);
}); });
#[allow(clippy::arc_with_non_send_sync)] #[allow(clippy::arc_with_non_send_sync)]
db_file.sync(completion) db_file.sync(completion)

View File

@@ -7,7 +7,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use strum::EnumString; use strum::EnumString;
use tracing::{instrument, Level}; use tracing::{instrument, Level};
use std::fmt::Formatter; use std::fmt::{Debug, Formatter};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::{cell::Cell, fmt, rc::Rc, sync::Arc}; use std::{cell::Cell, fmt, rc::Rc, sync::Arc};
@@ -213,7 +213,7 @@ impl TursoRwLock {
} }
/// Write-ahead log (WAL). /// Write-ahead log (WAL).
pub trait Wal { pub trait Wal: Debug {
/// Begin a read transaction. /// Begin a read transaction.
fn begin_read_tx(&mut self) -> Result<(LimboResult, bool)>; fn begin_read_tx(&mut self) -> Result<(LimboResult, bool)>;
@@ -277,6 +277,7 @@ pub trait Wal {
mode: CheckpointMode, mode: CheckpointMode,
) -> Result<IOResult<CheckpointResult>>; ) -> Result<IOResult<CheckpointResult>>;
fn sync(&mut self) -> Result<Completion>; fn sync(&mut self) -> Result<Completion>;
fn is_syncing(&self) -> bool;
fn get_max_frame_in_wal(&self) -> u64; fn get_max_frame_in_wal(&self) -> u64;
fn get_max_frame(&self) -> u64; fn get_max_frame(&self) -> u64;
fn get_min_frame(&self) -> u64; fn get_min_frame(&self) -> u64;
@@ -1122,11 +1123,16 @@ impl Wal for WalFile {
syncing.set(false); syncing.set(false);
}); });
let shared = self.get_shared(); let shared = self.get_shared();
let c = shared.file.sync(completion)?;
self.syncing.set(true); self.syncing.set(true);
let c = shared.file.sync(completion)?;
Ok(c) Ok(c)
} }
// Currently used for assertion purposes
fn is_syncing(&self) -> bool {
self.syncing.get()
}
fn get_max_frame_in_wal(&self) -> u64 { fn get_max_frame_in_wal(&self) -> u64 {
self.get_shared().max_frame.load(Ordering::Acquire) self.get_shared().max_frame.load(Ordering::Acquire)
} }