Bedrock.DataPlane.Materializer.Olivine.IndexManager (bedrock v0.5.2)
View SourcePage management core for the Olivine storage driver.
Implements Phase 2.1 of the Olivine implementation plan:
- 5-second sliding time window for version retention
- Version advancement and window expiry
- Page eviction when versions exit window with efficient page collection
- Version filtering for queries
- Binary page encoding/decoding with 32-byte header format
- Page creation and key lookup within pages
- Simple median split algorithm (256 key threshold)
- Page ID allocation with max_id tracking
The output queue stores modified pages alongside version metadata to enable efficient collection during eviction without redundant filtering operations.
Summary
Functions
Advances the window by determining what to evict and updating both buffer tracking and hot set. This is the complete window advancement operation that combines
Applies a single transaction binary to the version manager. Creates a new version and applies all mutations in the transaction. Uses a two-pass approach: first collect all instructions, then process each page.
Extracts the complete page_map from the current version's index. Used during compaction to get all current pages.
Types
@type loader_fn() :: (Bedrock.key(), Bedrock.version() -> {:ok, Bedrock.value()} | {:error, :not_found})
@type modified_pages() :: %{ required(Bedrock.DataPlane.Materializer.Olivine.Index.Page.id()) => {Bedrock.DataPlane.Materializer.Olivine.Index.Page.t(), Bedrock.DataPlane.Materializer.Olivine.Index.Page.id()} }
@type operation() :: {:set, Bedrock.version()} | :clear
@type page() :: Bedrock.DataPlane.Materializer.Olivine.Index.Page.t()
@type page_id() :: Bedrock.DataPlane.Materializer.Olivine.Index.Page.id()
@type t() :: %Bedrock.DataPlane.Materializer.Olivine.IndexManager{ current_version: Bedrock.version(), id_allocator: Bedrock.DataPlane.Materializer.Olivine.IdAllocator.t(), last_version_ended_at_offset: non_neg_integer(), n_keys: non_neg_integer(), output_queue: :queue.queue(), versions: version_list(), window_lag_time_μs: pos_integer(), window_size_in_microseconds: pos_integer() }
@type version_data() :: {Bedrock.DataPlane.Materializer.Olivine.Index.t(), modified_pages()}
@type version_list() :: [{Bedrock.version(), version_data()}]
@type version_update_data() :: Bedrock.DataPlane.Materializer.Olivine.IndexUpdate.t()
Functions
@spec advance_window(t(), pos_integer()) :: {:no_eviction, t()} | {:evict, non_neg_integer(), t(), [any()], Bedrock.version()}
Advances the window by determining what to evict and updating both buffer tracking and hot set. This is the complete window advancement operation that combines:
- Calculating window edge (newest version in buffer - 5 seconds)
- Determining eviction batch based on size and time constraints, collecting modified pages
- Trimming hot set to match eviction point
Returns either {:no_eviction, updated_manager} or {:evict, evicted_count, updated_manager, collected_pages, eviction_version}. The collected_pages contain all modified pages from evicted versions for efficient persistence.
@spec apply_transaction( t(), binary(), Bedrock.DataPlane.Materializer.Olivine.Database.t() ) :: {t(), Bedrock.DataPlane.Materializer.Olivine.Database.t()}
Applies a single transaction binary to the version manager. Creates a new version and applies all mutations in the transaction. Uses a two-pass approach: first collect all instructions, then process each page.
@spec apply_transactions( index_manager :: t(), encoded_transactions :: [binary()], database :: Bedrock.DataPlane.Materializer.Olivine.Database.t() ) :: {t(), Bedrock.DataPlane.Materializer.Olivine.Database.t()}
@spec get_complete_page_map(t()) :: %{ required(Bedrock.DataPlane.Materializer.Olivine.Index.Page.id()) => {Bedrock.DataPlane.Materializer.Olivine.Index.Page.t(), Bedrock.DataPlane.Materializer.Olivine.Index.Page.id()} }
Extracts the complete page_map from the current version's index. Used during compaction to get all current pages.
@spec new() :: t()
@spec page_for_key(t(), key :: Bedrock.key(), Bedrock.version()) :: {:ok, Bedrock.DataPlane.Materializer.Olivine.Index.Page.t()} | {:error, :not_found} | {:error, :version_too_new}
@spec page_for_key(t(), Bedrock.KeySelector.t(), Bedrock.version()) :: {:ok, resolved_key :: binary(), Bedrock.DataPlane.Materializer.Olivine.Index.Page.t()} | {:partial, keys_available :: non_neg_integer()} | {:error, :not_found | :version_too_new | :version_too_old}
@spec pages_for_range( t(), start_key :: Bedrock.key(), end_key :: Bedrock.key(), Bedrock.version() ) :: {:ok, [Bedrock.DataPlane.Materializer.Olivine.Index.Page.t()]} | {:error, :version_too_new} | {:error, :version_too_old}
@spec pages_for_range( t(), Bedrock.KeySelector.t(), Bedrock.KeySelector.t(), Bedrock.version() ) :: {:ok, {resolved_start :: binary(), resolved_end :: binary()}, [Bedrock.DataPlane.Materializer.Olivine.Index.Page.t()]} | {:error, :version_too_new | :version_too_old | :invalid_range}
@spec recover_from_database( database :: Bedrock.DataPlane.Materializer.Olivine.Database.t() ) :: {:ok, t()} | {:error, :missing_pages}