pub struct Pager {
pub db_file: Arc<dyn DatabaseStorage>,
pub buffer_pool: Arc<BufferPool>,
pub io: Arc<dyn IO>,
/* private fields */
}Expand description
The pager interface implements the persistence layer by providing access to pages of the database file, including caching, concurrency control, and transaction management.
Fields§
§db_file: Arc<dyn DatabaseStorage>Source of the database pages.
buffer_pool: Arc<BufferPool>Buffer pool for temporary data storage.
io: Arc<dyn IO>I/O interface for input/output operations.
Implementations§
Source§impl Pager
impl Pager
pub fn new( db_file: Arc<dyn DatabaseStorage>, wal: Option<Arc<dyn Wal>>, io: Arc<dyn IO>, page_cache: PageCache, buffer_pool: Arc<BufferPool>, init_lock: Arc<Mutex<()>>, init_page_1: Arc<ArcSwapOption<Page>>, ) -> Result<Self>
Sourcepub fn get_sync_type(&self) -> FileSyncType
pub fn get_sync_type(&self) -> FileSyncType
Get the sync type setting. On non-Apple platforms, always returns Fsync (compile-time constant).
Sourcepub fn set_sync_type(&self, _value: FileSyncType)
pub fn set_sync_type(&self, _value: FileSyncType)
Set the sync type. No-op on non-Apple platforms.
pub fn init_page_1(&self) -> Arc<ArcSwapOption<Page>> ⓘ
Sourcepub fn set_spill_enabled(&self, enabled: bool)
pub fn set_spill_enabled(&self, enabled: bool)
Set whether cache spilling is enabled.
Sourcepub fn get_spill_enabled(&self) -> bool
pub fn get_spill_enabled(&self) -> bool
Get whether cache spilling is enabled.
Sourcepub fn open_subjournal(&self) -> Result<()>
pub fn open_subjournal(&self) -> Result<()>
Open the subjournal if not yet open. The subjournal is a file that is used to store the “before images” of pages for the current savepoint. If the savepoint is rolled back, the pages can be restored from the subjournal.
Currently uses MemoryIO, but should eventually be backed by temporary on-disk files.
Sourcepub fn subjournal_page_if_required(&self, page: &Page) -> Result<()>
pub fn subjournal_page_if_required(&self, page: &Page) -> Result<()>
Write page to subjournal if the current savepoint does not currently contain an an entry for it. In case of a statement-level rollback, the page image can be restored from the subjournal.
A buffer of length page_size + 4 bytes is allocated and the page id is written to the beginning of the buffer. The rest of the buffer is filled with the page contents.
Sourcepub fn try_use_subjournal(&self) -> Result<()>
pub fn try_use_subjournal(&self) -> Result<()>
try to “acquire” ownership on the subjournal of the connection-scoped pager if another statement owns the subjournal - return Busy error and let the caller retry attempt later
Sourcepub fn stop_use_subjournal(&self)
pub fn stop_use_subjournal(&self)
release ownership of the subjournal caller must guarantee that Self::stop_use_subjournal is called only after successful call to the Self::try_use_subjournal
Sourcepub fn subjournal_in_use(&self) -> bool
pub fn subjournal_in_use(&self) -> bool
check if subjournal is in use for some statement
pub fn open_savepoint(&self, db_size: u32) -> Result<()>
Sourcepub fn release_savepoint(&self) -> Result<()>
pub fn release_savepoint(&self) -> Result<()>
Release i.e. commit the current savepoint. This basically just means removing it.
Sourcepub fn open_named_savepoint(
&self,
name: String,
db_size: u32,
starts_transaction: bool,
deferred_fk_violations: isize,
) -> Result<()>
pub fn open_named_savepoint( &self, name: String, db_size: u32, starts_transaction: bool, deferred_fk_violations: isize, ) -> Result<()>
Opens a named savepoint and captures rollback metadata for the current transaction state.
If starts_transaction is true, releasing this savepoint at the root depth commits the
transaction.
Sourcepub fn release_named_savepoint(&self, name: &str) -> Result<SavepointResult>
pub fn release_named_savepoint(&self, name: &str) -> Result<SavepointResult>
Releases the newest matching named savepoint and all nested savepoints opened after it.
pub fn clear_savepoints(&self) -> Result<()>
Sourcepub fn rollback_to_newest_savepoint(&self) -> Result<bool>
pub fn rollback_to_newest_savepoint(&self) -> Result<bool>
Rollback to the newest savepoint. This basically just means reading the subjournal from the start offset of the savepoint to the end of the subjournal and restoring the page images to the page cache.
Sourcepub fn rollback_to_named_savepoint(&self, name: &str) -> Result<Option<isize>>
pub fn rollback_to_named_savepoint(&self, name: &str) -> Result<Option<isize>>
Rollback to the newest matching named savepoint while keeping the named savepoint active.
Returns deferred FK counter snapshot for the rolled-back savepoint.
pub const fn get_pending_byte() -> u32
Sourcepub fn pending_byte_page_id(&self) -> Option<u32>
pub fn pending_byte_page_id(&self) -> Option<u32>
From SQLITE: https://github.com/sqlite/sqlite/blob/7e38287da43ea3b661da3d8c1f431aa907d648c9/src/btreeInt.h#L608
The database page the [PENDING_BYTE] occupies. This page is never used.
Sourcepub fn get_max_page_count(&self) -> u32
pub fn get_max_page_count(&self) -> u32
Get the maximum page count for this database
Sourcepub fn set_max_page_count(&self, new_max: u32) -> Result<IOResult<u32>>
pub fn set_max_page_count(&self, new_max: u32) -> Result<IOResult<u32>>
Set the maximum page count for this database Returns the new maximum page count (may be clamped to current database size)
pub fn set_wal(&mut self, wal: Arc<dyn Wal>)
pub fn get_auto_vacuum_mode(&self) -> AutoVacuumMode
pub fn set_auto_vacuum_mode(&self, mode: AutoVacuumMode)
Sourcepub fn persist_auto_vacuum_mode(&self, mode: AutoVacuumMode) -> Result<()>
pub fn persist_auto_vacuum_mode(&self, mode: AutoVacuumMode) -> Result<()>
Persist the auto-vacuum mode to page 1 and keep the pager cache in sync.
Sourcepub fn ptrmap_get(
&self,
target_page_num: u32,
) -> Result<IOResult<Option<PtrmapEntry>>>
pub fn ptrmap_get( &self, target_page_num: u32, ) -> Result<IOResult<Option<PtrmapEntry>>>
Retrieves the pointer map entry for a given database page.
target_page_num (1-indexed) is the page whose entry is sought.
Returns Ok(None) if the page is not supposed to have a ptrmap entry (e.g. header, or a ptrmap page itself).
Sourcepub fn ptrmap_put(
&self,
db_page_no_to_update: u32,
entry_type: PtrmapType,
parent_page_no: u32,
) -> Result<IOResult<()>>
pub fn ptrmap_put( &self, db_page_no_to_update: u32, entry_type: PtrmapType, parent_page_no: u32, ) -> Result<IOResult<()>>
Writes or updates the pointer map entry for a given database page.
db_page_no_to_update (1-indexed) is the page whose entry is to be set.
entry_type and parent_page_no define the new entry.
Sourcepub fn btree_create(&self, flags: &CreateBTreeFlags) -> Result<IOResult<u32>>
pub fn btree_create(&self, flags: &CreateBTreeFlags) -> Result<IOResult<u32>>
This method is used to allocate a new root page for a btree, both for tables and indexes FIXME: handle no room in page cache
Sourcepub fn allocate_overflow_page(&self) -> Result<IOResult<PageRef>>
pub fn allocate_overflow_page(&self) -> Result<IOResult<PageRef>>
Allocate a new overflow page. This is done when a cell overflows and new space is needed.
Sourcepub fn do_allocate_page(
&self,
page_type: PageType,
offset: usize,
_alloc_mode: BtreePageAllocMode,
) -> Result<IOResult<PageRef>>
pub fn do_allocate_page( &self, page_type: PageType, offset: usize, _alloc_mode: BtreePageAllocMode, ) -> Result<IOResult<PageRef>>
Allocate a new page to the btree via the pager. This marks the page as dirty and writes the page header.
Sourcepub fn usable_space(&self) -> usize
pub fn usable_space(&self) -> usize
The “usable size” of a database page is the page size specified by the 2-byte integer at offset 16 in the header, minus the “reserved” space size recorded in the 1-byte integer at offset 20 in the header. The usable size of a page might be an odd number. However, the usable size is not allowed to be less than 480. In other words, if the page size is 512, then the reserved space size cannot exceed 32.
pub fn db_initialized(&self) -> bool
Sourcepub fn set_initial_page_size(&self, size: PageSize) -> Result<()>
pub fn set_initial_page_size(&self, size: PageSize) -> Result<()>
Set the initial page size for the database. Should only be called before the database is initialized
Sourcepub fn set_initial_journal_version(&self, version: Version) -> Result<()>
pub fn set_initial_journal_version(&self, version: Version) -> Result<()>
Set the initial journal version in page 1 before the database is initialized.
Sourcepub fn get_page_size(&self) -> Option<PageSize>
pub fn get_page_size(&self) -> Option<PageSize>
Get the current page size. Returns None if not set yet.
Sourcepub fn get_page_size_unchecked(&self) -> PageSize
pub fn get_page_size_unchecked(&self) -> PageSize
Get the current page size, panicking if not set.
Sourcepub fn set_page_size(&self, size: PageSize)
pub fn set_page_size(&self, size: PageSize)
Set the page size. Used internally when page size is determined.
Sourcepub fn get_reserved_space(&self) -> Option<u8>
pub fn get_reserved_space(&self) -> Option<u8>
Get the current reserved space. Returns None if not set yet.
Sourcepub fn set_reserved_space(&self, space: u8)
pub fn set_reserved_space(&self, space: u8)
Set the reserved space. Must fit in u8.
Get the cached schema cookie. Returns None if not set yet.
Set the schema cookie cache.
Get the schema cookie, using the cached value if available to avoid reading page 1.
Sourcepub fn wal_pos(&self) -> (u32, u64)
pub fn wal_pos(&self) -> (u32, u64)
This connection’s frozen WAL position (checkpoint_seq, max_frame) — the read mark for a
reader, or the post-commit position for a writer. (u32::MAX, u64::MAX) when there is no
WAL (no WAL materialization hazard). See Wal::connection_wal_pos.
Sourcepub fn min_pinned_read_frame(&self) -> Option<u64>
pub fn min_pinned_read_frame(&self) -> Option<u64>
Lowest WAL frame any active reader is pinned at, or None if none / no WAL. Used as the
Passive-checkpoint version-store GC floor (includes readers pinned via begin_read_tx
before they publish an MVCC transaction). See MvStore::rootpage_gc_protected.
Sourcepub fn wal_backfill_frame(&self) -> Option<u64>
pub fn wal_backfill_frame(&self) -> Option<u64>
The WAL backfill boundary (frames at or below this are durable in the DB file). The MVCC Version-store GC floor for passive checkpoints: a materialized version may be reclaimed only once its materialization frame is backfilled here, so every snapshot can read it from the btree.
pub fn begin_read_tx(&self) -> Result<()>
Sourcepub fn mvcc_refresh_if_db_changed(&self)
pub fn mvcc_refresh_if_db_changed(&self)
MVCC-only: refresh connection-private WAL change counters without starting a read tx and invalidate cache if needed.
pub fn maybe_allocate_page1(&self) -> Result<IOResult<()>>
Sourcepub fn begin_write_tx(
&self,
allowed_auto_actions: WalAutoActions,
) -> Result<IOResult<()>>
pub fn begin_write_tx( &self, allowed_auto_actions: WalAutoActions, ) -> Result<IOResult<()>>
allowed_auto_actions controls which automatic WAL maintenance the
caller permits during this begin. The only action consulted here is
WalAutoActions::Restart, which gates the WAL-header restart inside
try_restart_log_before_write. Callers managing WAL state externally
(sync engine) must not pass Restart because rotating the WAL header
behind their back invalidates watermarks they have already published.
Sourcepub fn begin_vacuum_blocking_tx(&self) -> Result<IOResult<()>>
pub fn begin_vacuum_blocking_tx(&self) -> Result<IOResult<()>>
Acquire exclusive WAL access + block new transactions (used by VACUUM).
This is a blocking alternative to normal begin_read_tx.
VACUUM runs on an existing database, so page 1 must already be allocated and a WAL must be present.
Sourcepub fn commit_tx(
&self,
connection: &Connection,
update_transaction_state: bool,
) -> Result<IOResult<()>>
pub fn commit_tx( &self, connection: &Connection, update_transaction_state: bool, ) -> Result<IOResult<()>>
commit dirty pages from current transaction in WAL mode if this is not nested statement (for nested statements, parent will do the commit) if update_transaction_state set to false, then Connection::transaction_state left unchanged if update_transaction_state set to true, then Connection::transaction_state reset to [TransactionState::None] in case when method completes without error
pub fn rollback_tx(&self, connection: &Connection)
pub fn end_read_tx(&self)
Sourcepub fn end_write_tx(&self)
pub fn end_write_tx(&self)
End just the write transaction on the WAL, without affecting the read lock.
Sourcepub fn holds_read_lock(&self) -> bool
pub fn holds_read_lock(&self) -> bool
Returns true if this pager’s WAL currently holds a read lock.
pub fn holds_write_lock(&self) -> bool
Sourcepub fn rollback_attached(&self)
pub fn rollback_attached(&self)
Rollback and clean up an attached database pager’s transaction. Unlike rollback_tx, this doesn’t modify connection-level state.
Sourcepub fn read_page_no_cache(
&self,
page_idx: i64,
frame_watermark: Option<u64>,
allow_empty_read: bool,
) -> Result<(PageRef, Completion)>
pub fn read_page_no_cache( &self, page_idx: i64, frame_watermark: Option<u64>, allow_empty_read: bool, ) -> Result<(PageRef, Completion)>
Reads a page from disk (either WAL or DB file) bypassing page-cache
Sourcepub fn read_page(
&self,
page_idx: i64,
) -> Result<IOResult<(PageRef, Option<Completion>)>>
pub fn read_page( &self, page_idx: i64, ) -> Result<IOResult<(PageRef, Option<Completion>)>>
Issue a non-blocking page read, inserting into the page cache, may spill to disk.
Done((page, None)): page was already in cache, no IO needed.Done((page, Some(c_disk))): page was not in cache; it has been inserted into the cache and a disk-read is in flight against it. The caller must yield onc_diskbefore readingpagecontents.IO(c_spill): the page cache was full and a spill is in flight. Caller must yield onc_spilland then callread_page_nonblock(idx)again. The disk read for this page has already been issued and will be reused on re-entry viapending_reads(no duplicate IO).
Re-entrancy contract: the caller may invoke this with the same
page_idx arbitrarily many times. Each Some(page_idx) mapping in
pending_reads corresponds to a single outstanding disk read; the
entry is removed exactly when this method returns Done.
pub fn cache_get(&self, page_idx: usize) -> Result<Option<PageRef>>
Sourcepub fn cache_get_for_checkpoint(
&self,
page_idx: usize,
target_frame: u64,
seq: u32,
) -> Result<Option<PageRef>>
pub fn cache_get_for_checkpoint( &self, page_idx: usize, target_frame: u64, seq: u32, ) -> Result<Option<PageRef>>
Get a page from cache only if it matches the target frame
Sourcepub fn change_page_cache_size(
&self,
capacity: usize,
) -> Result<CacheResizeResult>
pub fn change_page_cache_size( &self, capacity: usize, ) -> Result<CacheResizeResult>
Changes the size of the page cache.
pub fn add_dirty(&self, page: &Page) -> Result<()>
pub fn wal_state(&self) -> Result<WalState>
Sourcepub fn cacheflush(&self) -> Result<IOResult<Vec<Completion>>>
pub fn cacheflush(&self) -> Result<IOResult<Vec<Completion>>>
Flush all dirty pages to disk (async/re-entrant). Unlike commit_wal, this function does not commit, checkpoint nor sync the WAL/Database.
Sourcepub fn commit_wal(
&self,
allowed_auto_actions: WalAutoActions,
sync_mode: SyncMode,
data_sync_retry: bool,
) -> Result<IOResult<()>>
pub fn commit_wal( &self, allowed_auto_actions: WalAutoActions, sync_mode: SyncMode, data_sync_retry: bool, ) -> Result<IOResult<()>>
Commit the write transaction to the WAL: write any dirty pages as WAL
frames, fsync the WAL if it is dirty, and publish the commit. The WAL
can be dirty without any dirty pages (frames inserted through
write_frame_raw bypass dirty-page tracking), so under
synchronous=FULL this fsyncs even when there is nothing to write.
If the WAL size is over the checkpoint threshold, it will checkpoint the WAL to
the database file and then fsync the database file.
allowed_auto_actions controls automatic WAL maintenance permitted at
commit time. Only WalAutoActions::Checkpoint is consulted here — it
gates the post-commit auto-checkpoint when should_checkpoint() is
true.
pub fn commit_wal_end(&self)
pub fn wal_changed_pages_after(&self, frame_watermark: u64) -> Result<Vec<u32>>
pub fn wal_get_frame( &self, frame_no: u64, frame: &mut [u8], ) -> Result<Completion>
pub fn wal_insert_frame( &self, frame_no: u64, frame: &[u8], ) -> Result<WalFrameInfo>
pub fn is_checkpointing(&self) -> bool
Sourcepub fn clear_checkpoint_state(&self)
pub fn clear_checkpoint_state(&self)
Reset checkpoint state machine to initial state. Use this to clean up after a failed explicit checkpoint (PRAGMA wal_checkpoint).
Sourcepub fn cleanup_after_auto_checkpoint_failure(&self)
pub fn cleanup_after_auto_checkpoint_failure(&self)
Clean up after a auto-checkpoint failure. Auto-checkpoint executed outside of the main transaction - so WAL transaction was already finalized
pub fn cleanup_after_checkpoint_failure(&self)
Sourcepub fn checkpoint(
&self,
mode: CheckpointMode,
sync_mode: SyncMode,
clear_page_cache: bool,
) -> Result<IOResult<CheckpointResult>>
pub fn checkpoint( &self, mode: CheckpointMode, sync_mode: SyncMode, clear_page_cache: bool, ) -> Result<IOResult<CheckpointResult>>
Checkpoint the WAL to the database file (if needed). Args:
- mode: The checkpoint mode to use (PASSIVE, FULL, RESTART, TRUNCATE)
- sync_mode: The fsync mode to use (OFF, NORMAL, FULL)
- clear_page_cache: Whether to clear the page cache after checkpointing
pub fn vacuum_checkpoint_with_held_lock( &self, sync_mode: SyncMode, clear_page_cache: bool, ) -> Result<IOResult<CheckpointResult>>
Sourcepub fn clear_page_cache(&self, clear_dirty: bool)
pub fn clear_page_cache(&self, clear_dirty: bool)
Invalidates entire page cache by removing all dirty and clean pages. Usually used in case of a rollback or in case we want to invalidate page cache after starting a read transaction right after new writes happened which would invalidate current page cache.
Sourcepub fn checkpoint_shutdown(
&self,
allowed_auto_actions: WalAutoActions,
sync_mode: SyncMode,
) -> Result<()>
pub fn checkpoint_shutdown( &self, allowed_auto_actions: WalAutoActions, sync_mode: SyncMode, ) -> Result<()>
Checkpoint in Truncate mode and delete the WAL file. This method is only to be called for shutting down the last remaining connection to a database.
sqlite3.h Usually, when a database in [WAL mode] is closed or detached from a database handle, SQLite checks if if there are other connections to the same database, and if there are no other database connection (if the connection being closed is the last open connection to the database), then SQLite performs a [checkpoint] before closing the connection and deletes the WAL file.
Sourcepub fn blocking_checkpoint(
&self,
mode: CheckpointMode,
sync_mode: SyncMode,
) -> Result<CheckpointResult>
pub fn blocking_checkpoint( &self, mode: CheckpointMode, sync_mode: SyncMode, ) -> Result<CheckpointResult>
Perform a blocking checkpoint with the specified mode.
This is a convenience wrapper around checkpoint() that blocks until completion.
Explicit checkpoints clear the page cache after completion.
pub fn freepage_list(&self) -> u32
pub fn free_page( &self, page: Option<PageRef>, page_id: usize, ) -> Result<IOResult<()>>
pub fn allocate_page1(&self) -> Result<IOResult<PageRef>>
pub fn allocating_page1(&self) -> bool
Sourcepub fn allocate_page(&self) -> Result<IOResult<PageRef>>
pub fn allocate_page(&self) -> Result<IOResult<PageRef>>
Tries to reuse a page from the freelist if available. If not, allocates a new page which increases the database size.
FIXME: implement sqlite’s ‘nearby’ parameter and use AllocMode. SQLite’s allocate_page() equivalent has a parameter ‘nearby’ which is a hint about the page number we want to have for the allocated page. We should use this parameter to allocate the page in the same way as SQLite does; instead now we just either take the first available freelist page or allocate a new page.
pub fn upsert_page_in_cache( &self, id: usize, page: PageRef, dirty_page_must_exist: bool, ) -> Result<(), LimboError>
pub fn rollback( &self, schema_did_change: bool, connection: &Connection, is_write: bool, )
pub fn with_header<T>( &self, f: impl Fn(&DatabaseHeader) -> T, ) -> Result<IOResult<T>>
pub fn with_header_mut<T>( &self, f: impl Fn(&mut DatabaseHeader) -> T, ) -> Result<IOResult<T>>
pub fn is_encryption_ctx_set(&self) -> bool
pub fn is_encryption_enabled(&self) -> bool
pub fn set_encryption_context( &self, cipher_mode: CipherMode, key: &EncryptionKey, ) -> Result<()>
pub fn reset_checksum_context(&self)
pub fn set_reserved_space_bytes(&self, value: u8)
Sourcepub fn enable_encryption(&self, enable: bool)
pub fn enable_encryption(&self, enable: bool)
Encryption is an opt-in feature. If the flag is passed, then enable the encryption on pager, which is then used to set it on the IOContext.
Auto Trait Implementations§
impl !Freeze for Pager
impl !RefUnwindSafe for Pager
impl !UnwindSafe for Pager
impl Send for Pager
impl Sync for Pager
impl Unpin for Pager
impl UnsafeUnpin for Pager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more