Bedrock.DataPlane.Materializer.Olivine.Index.Page (bedrock v0.5.2)
View SourcePage management routines for the Olivine storage driver.
Pages are the fundamental storage unit in the Olivine B-tree index. Each page contains sorted key-locator pairs and chain pointers for traversal.
Key Features
- Binary encoding: Pages are stored as optimized binary data for efficiency
- Chain linking: Pages form a linked list via
next_idpointers - Sorted keys: Keys within each page are maintained in ascending order
- Version tracking: Each key has an associated locator for MVCC support
- Size limits: Pages are split when they exceed 256 keys to maintain performance
Operations
- Page creation, encoding, and decoding
- Page splitting for size management
- Key range queries within pages
- Chain traversal for ordered iteration
- Validation of page structure and invariants
Summary
Functions
Applies a map of operations to a binary page, returning the updated binary page. Operations can be {:set, locator} or :clear.
Applies operations to a binary page, returning per-key segments for efficient splitting.
Builds a binary page from pre-computed segments.
Builds a binary page from iodata (already materialized segments).
Checks if a page is empty (has no keys).
Creates a page with key-locator tuples. Returns the binary-encoded page with next_id set to 0.
Types
@type id() :: non_neg_integer()
@type operation() :: {:set, Bedrock.DataPlane.Materializer.Olivine.Database.locator()} | :clear
@type page_map() :: %{ id: id(), next_id: id(), key_locators: [ {binary(), Bedrock.DataPlane.Materializer.Olivine.Database.locator()} ] }
@type segment() :: {non_neg_integer(), non_neg_integer()} | binary()
Functions
@spec apply_operations(binary(), %{required(Bedrock.key()) => operation()}) :: binary()
Applies a map of operations to a binary page, returning the updated binary page. Operations can be {:set, locator} or :clear.
@spec apply_operations_as_segments(binary(), %{required(Bedrock.key()) => operation()}) :: {[segment()], key_count :: non_neg_integer(), rightmost_key :: binary() | nil}
Applies operations to a binary page, returning per-key segments for efficient splitting.
Returns a tuple of:
- page_id: The page ID from the header
- segments: Reversed list of per-key segments (each segment is one {key, locator} entry)
{offset, length}for unchanged keys (reference to old binary)<<binary>>for new/modified keys
- key_count: Final number of keys after operations
- rightmost_key: The rightmost key in the page (or nil if empty)
The segments list is in reverse order (rightmost key first), which is natural from the merge algorithm and gives us the rightmost key for free.
@spec build_from_segments( id(), [segment()], non_neg_integer(), binary(), binary() | nil ) :: binary()
Builds a binary page from pre-computed segments.
Takes a page ID, list of segments (in reverse order), final key count, original page,
and the rightmost key. The segments list and rightmost key should come from
apply_operations_as_segments/2.
Returns a complete binary page with proper header and payload.
@spec build_from_segments_iodata(id(), iodata(), non_neg_integer(), binary() | nil) :: binary()
Builds a binary page from iodata (already materialized segments).
Takes a page ID, iodata payload, key count, and rightmost key.
This is used when segments have already been materialized by take_and_materialize.
Returns a complete binary page with proper header and payload.
@spec decode_entry_at_position(binary(), non_neg_integer(), non_neg_integer()) :: {:ok, {key :: binary(), locator :: binary()}} | :out_of_bounds
Checks if a page is empty (has no keys).
@spec key_count(t()) :: non_neg_integer()
@spec key_locators(t()) :: [ {binary(), Bedrock.DataPlane.Materializer.Olivine.Database.locator()} ]
@spec locator_for_key(t(), Bedrock.key()) :: {:ok, Bedrock.DataPlane.Materializer.Olivine.Database.locator()} | {:error, :not_found}
@spec new( id :: id(), key_locators :: [ {binary(), Bedrock.DataPlane.Materializer.Olivine.Database.locator()} ] ) :: binary()
Creates a page with key-locator tuples. Returns the binary-encoded page with next_id set to 0.
@spec search_entries_with_position(binary(), non_neg_integer(), Bedrock.key()) :: {:found, pos :: non_neg_integer()} | {:not_found, insertion_point :: non_neg_integer()}
@spec stream_key_locators_in_range(Enumerable.t(t()), Bedrock.key(), Bedrock.key()) :: Enumerable.t( {Bedrock.key(), Bedrock.DataPlane.Materializer.Olivine.Database.locator()} )