Struct spacetimedb_table::page::Page

source ·
#[repr(C, align(64))]
pub struct Page { /* private fields */ }
Expand description

A page of row data with an associated header and the raw row_data itself.

As a rough summary, the strategy employed by this page is:

  • The fixed-len parts of rows grows left-to-right and starts from the beginning of the row_data until its high water mark (fixed HWM), i.e., self.header.fixed.last.

  • The var-len parts of rows grows right-to-left and starts from the end of the row_data until its high water mark (variable HWM), i.e., self.header.var.first.

    Each var-len object is stored in terms of a linked-list of chunks. Each chunk in this case is a VarLenGranule taking up 64 bytes where:

    • 6 bits = length, 10 bits = next-cell-pointer
    • 62 bytes = the bytes of the object
  • As new rows are added, the HWMs move appropriately. When the fixed and variable HWMs meet, the page is full.

  • When rows are freed, a freelist strategy is used both for the fixed parts and each VarLenGranule. These freelists are then used first before using space from the gap. The head of these freelists are stored in next_free in the fixed and variable headers respectively.

  • As the fixed parts of rows may store pointers into the var-length section, to ensure that these pointers aren’t dangling, the page uses pointer fixups when adding to, deleting from, and copying the page. These fixups are handled by having callers provide VarLenMembers to find the var-len reference slots in the fixed parts.

Implementations§

source§

impl Page

source

pub fn new(fixed_row_size: Size) -> Box<Self>

Returns a new page allocated on the heap.

The new page supports fixed rows of size fixed_row_size.

source

pub fn num_rows(&self) -> usize

Returns the number of rows stored in this page.

source

pub fn get_row_data(&self, row: PageOffset, size: Size) -> &Bytes

Returns the range of row data starting at offset and lasting size bytes.

source

pub fn has_row_offset(&self, fixed_row_size: Size, offset: PageOffset) -> bool

Returns whether the row at offset is present or not.

source

pub fn split_fixed_var_mut(&mut self) -> (FixedView<'_>, VarView<'_>)

Returns split mutable views of this page over the fixed and variable sections.

source

pub fn total_granules_required_for_objects( objects: &[impl AsRef<[u8]>] ) -> usize

Return the total required var-len granules to store objects.

source

pub fn has_space_for_row_with_objects( &self, fixed_row_size: Size, var_len_objects: &[impl AsRef<[u8]>] ) -> bool

Does the page have space to store a row, where the fixed size part is fixed_row_size bytes large, and the row has the given var_len_objects?

source

pub fn has_space_for_row( &self, fixed_row_size: Size, num_granules: usize ) -> bool

Does the page have space to store a row, where the fixed size part is fixed_row_size bytes large, and the variable part requires num_granules.

source

pub fn is_full(&self, fixed_row_size: Size) -> bool

Returns whether the row is full with respect to storing a fixed row with fixed_row_size and no variable component.

source

pub unsafe fn insert_row( &mut self, fixed_row: &Bytes, var_len_objects: &[impl AsRef<[u8]>], var_len_visitor: &impl VarLenMembers, blob_store: &mut dyn BlobStore ) -> Result<PageOffset, Error>

Will leave partially-allocated chunks if fails prematurely, so always check Self::has_space_for_row before calling.

This method is provided for testing the page store directly; higher-level codepaths are expected to use [crate::bflatn::ser::write_av_to_page], which performs similar operations to this method, but handles rollback on failure appropriately.

This function will never fail if Self::has_space_for_row has returned true.

§Safety
  • var_len_visitor is suitable for visiting var-len refs in fixed_row.

  • fixed_row.len() must be consistent with var_len_visitor and self. That is, VarLenMembers must be specialized for a row type with that length, and all past, present, and future fixed-length rows stored in this Page must also be of that length.

source

pub unsafe fn alloc_fixed_len( &mut self, fixed_row_size: Size ) -> Result<PageOffset, Error>

Allocates space for a fixed size row of fixed_row_size bytes.

§Safety

fixed_row_size must be equal to the value passed to all other methods ever invoked on self.

source

pub fn iter_fixed_len(&self, fixed_row_size: Size) -> FixedLenRowsIter<'_>

Returns an iterator over all the PageOffsets of the fixed rows in this page.

The rows are assumed to be fixed_row_size bytes long.

NOTE: This method is not unsafe as it cannot trigger UB. However, when provided with garbage input, it will return garbage back. It is the caller’s responsibility to ensure that PageOffsets derived from this iterator are valid when used to do anything unsafe.

source

pub unsafe fn iter_var_len_object( &self, first_granule: PageOffset ) -> impl Clone + Iterator<Item = &VarLenGranule>

Returns an iterator over all the VarLenGranules of the var-len object that has its first granule at offset first_granule. An empty iterator will be returned when first_granule is NULL.

§Safety

first_granule must be an offset to a valid granule or NULL.

source

pub unsafe fn iter_vlo_data( &self, first_granule: PageOffset ) -> impl '_ + Clone + Iterator<Item = &[u8]>

Returns an iterator over the data of all the VarLenGranules of the var-len object that has its first granule at offset first_granule. An empty iterator will be returned when first_granule is NULL.

§Safety

first_granule must be an offset to a valid granule or NULL.

source

pub unsafe fn delete_row( &mut self, fixed_row: PageOffset, fixed_row_size: Size, var_len_visitor: &impl VarLenMembers, blob_store: &mut dyn BlobStore )

Free a row, marking its fixed-len and var-len storage granules as available for re-use.

§Safety
  • fixed_row must point to a valid row in this page.

  • fixed_row_size must be the size in bytes of the fixed part of all past, present, and future rows in this page and future rows in this page.

  • The var_len_visitor must visit the same set of VarLenRefs in the row as the visitor provided to insert_row.

source

pub unsafe fn row_total_granules( &self, fixed_row_offset: PageOffset, fixed_row_size: Size, var_len_visitor: &impl VarLenMembers ) -> usize

Returns the total number of granules used by the fixed row at fixed_row_offset and lasting fixed_row_size bytes where var_len_visitor is used to find the VarLenRefs in the fixed row.

§Safety
  • fixed_row_offset must refer to a previously-allocated and initialized row in self, and must not have been de-allocated. In other words, the fixed row must be valid.

  • fixed_row_size and var_len_visitor must be consistent with each other and with all other calls to any methods on self.

source

pub unsafe fn copy_filter_into( &self, starting_from: PageOffset, dst: &mut Page, fixed_row_size: Size, var_len_visitor: &impl VarLenMembers, blob_store: &mut dyn BlobStore, filter: impl FnMut(&Page, PageOffset) -> bool ) -> ControlFlow<(), PageOffset>

Copy as many rows from self for which filter returns true into dst as will fit, starting from starting_from.

If less than the entirety of self could be processed, return Continue(resume_point), where resume_point is the starting_from argument of a subsequent call to copy_filter_into that will complete the iteration. dst should be assumed to be full in this case, as it does not contain enough free space to store the row of self at resume_point.

If the entirety of self is processed, return Break. dst may or may not be full in this case, but is likely not full.

§Safety

The var_len_visitor must visit the same set of VarLenRefs in the row as the visitor provided to all other methods on self and dst.

The fixed_row_size must be consistent with the var_len_visitor, and be equal to the value provided to all other methods on self and dst.

The starting_from offset must point to a valid starting offset consistent with fixed_row_size. That is, it must not point into the middle of a row.

source

pub fn clear(&mut self)

Make self empty, removing all rows from it and resetting the high water marks to zero.

Auto Trait Implementations§

§

impl Freeze for Page

§

impl RefUnwindSafe for Page

§

impl Send for Page

§

impl Sync for Page

§

impl Unpin for Page

§

impl UnwindSafe for Page

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.