Small cleanups to pager/wal/vdbe - mostly naming

- Instead of using a confusing CheckpointStatus for many different things,
  introduce the following statuses:
    * PagerCacheflushStatus - cacheflush can result in either:
      - the WAL being written to disk and fsynced
      - but also a checkpoint to the main BD file, and fsyncing the main DB file

      Reflect this in the type.
    * WalFsyncStatus - previously CheckpointStatus was also used for this, even
      though fsyncing the WAL doesn't checkpoint.
    * CheckpointStatus/CheckpointResult is now used only for actual checkpointing.

- Rename HaltState to CommitState (program.halt_state -> program.commit_state)
- Make WAL a non-optional property in Pager
  * This gets rid of a lot of if let Some(...) boilerplate
  * For ephemeral indexes, provide a DummyWAL implementation that does nothing.
- Rename program.halt() to program.commit_txn()
- Add some documentation comments to structs and functions
This commit is contained in:
Jussi Saurio
2025-05-26 10:37:34 +03:00
parent be89809335
commit 3ba9f2ab97
7 changed files with 237 additions and 160 deletions

View File

@@ -28,7 +28,7 @@ use crate::{
error::LimboError,
fast_lock::SpinLock,
function::{AggFunc, FuncCtx},
storage::sqlite3_ondisk::SmallVec,
storage::{pager::PagerCacheflushStatus, sqlite3_ondisk::SmallVec},
};
use crate::{
@@ -38,8 +38,6 @@ use crate::{
vdbe::{builder::CursorType, insn::Insn},
};
use crate::CheckpointStatus;
#[cfg(feature = "json")]
use crate::json::JsonCacheCell;
use crate::{Connection, MvStore, Result, TransactionState};
@@ -234,9 +232,16 @@ impl Drop for VTabOpaqueCursor {
}
}
#[derive(Copy, Clone)]
enum HaltState {
Checkpointing,
#[derive(Copy, Clone, PartialEq, Eq)]
/// The commit state of the program.
/// There are two states:
/// - Ready: The program is ready to run the next instruction, or has shut down after
/// the last instruction.
/// - Committing: The program is committing a write transaction. It is waiting for the pager to finish flushing the cache to disk,
/// primarily to the WAL, but also possibly checkpointing the WAL to the database file.
enum CommitState {
Ready,
Committing,
}
#[derive(Debug, Clone)]
@@ -269,7 +274,7 @@ pub struct ProgramState {
pub(crate) mv_tx_id: Option<crate::mvcc::database::TxID>,
interrupted: bool,
parameters: HashMap<NonZero<usize>, Value>,
halt_state: Option<HaltState>,
commit_state: CommitState,
#[cfg(feature = "json")]
json_cache: JsonCacheCell,
op_idx_delete_state: Option<OpIdxDeleteState>,
@@ -293,7 +298,7 @@ impl ProgramState {
mv_tx_id: None,
interrupted: false,
parameters: HashMap::new(),
halt_state: None,
commit_state: CommitState::Ready,
#[cfg(feature = "json")]
json_cache: JsonCacheCell::new(),
op_idx_delete_state: None,
@@ -417,7 +422,7 @@ impl Program {
}
}
pub fn halt(
pub fn commit_txn(
&self,
pager: Rc<Pager>,
program_state: &mut ProgramState,
@@ -441,18 +446,14 @@ impl Program {
.expect("only weak ref to connection?");
let auto_commit = connection.auto_commit.get();
tracing::trace!("Halt auto_commit {}", auto_commit);
assert!(
program_state.halt_state.is_none()
|| (matches!(program_state.halt_state.unwrap(), HaltState::Checkpointing))
);
if program_state.halt_state.is_some() {
self.step_end_write_txn(&pager, &mut program_state.halt_state, connection.deref())
if program_state.commit_state == CommitState::Committing {
self.step_end_write_txn(&pager, &mut program_state.commit_state, connection.deref())
} else if auto_commit {
let current_state = connection.transaction_state.get();
match current_state {
TransactionState::Write => self.step_end_write_txn(
&pager,
&mut program_state.halt_state,
&mut program_state.commit_state,
connection.deref(),
),
TransactionState::Read => {
@@ -476,23 +477,23 @@ impl Program {
fn step_end_write_txn(
&self,
pager: &Rc<Pager>,
halt_state: &mut Option<HaltState>,
commit_state: &mut CommitState,
connection: &Connection,
) -> Result<StepResult> {
let checkpoint_status = pager.end_tx()?;
match checkpoint_status {
CheckpointStatus::Done(_) => {
let cacheflush_status = pager.end_tx()?;
match cacheflush_status {
PagerCacheflushStatus::Done(_) => {
if self.change_cnt_on {
if let Some(conn) = self.connection.upgrade() {
conn.set_changes(self.n_change.get());
}
}
connection.transaction_state.replace(TransactionState::None);
let _ = halt_state.take();
*commit_state = CommitState::Ready;
}
CheckpointStatus::IO => {
tracing::trace!("Checkpointing IO");
*halt_state = Some(HaltState::Checkpointing);
PagerCacheflushStatus::IO => {
tracing::trace!("Cacheflush IO");
*commit_state = CommitState::Committing;
return Ok(StepResult::IO);
}
}