package granary
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=8b18780ea373be48301d9f333925860a2f9110fc0ac28684295118d72b65a67e
sha512=25ca3c9c5e2b528704a542502e0f37dc33ba003f65622d969b8c2b800778585f8ef0cf89b36e6679832e3993e8303aecddfc662742baf7044d6afe4a796b8f11
doc/granary.storage/Granary_storage/Btree/index.html
Module Granary_storage.BtreeSource
Copy-on-write B+-tree over the Pager layer.
Every modification (put/del) allocates fresh pages, writes the new state into them via Pager.write, and frees the old pages via Pager.free. Returns a new t whose root_page reflects the latest root.
Keys are sorted by Bytes.compare. Max key size 512 bytes, max value size 1024 bytes.
type error = | Pager_error of Pager.error| Key_too_large of int| Value_too_large of int| Tree_corrupt of string
Pretty-print the tree's root page and snapshot frame bound.
Pretty-print an error.
val create :
?snapshot_frames:int ->
?pin_set:(int64, unit) Hashtbl.t ->
Pager.t ->
root_page:int64 ->
tCreate a tree view. root_page=0L means an empty tree (no root yet). snapshot_frames: when Some n, reads resolve against WAL frames < n (RO-snapshot semantics); when None (default), reads consult the writer's dirty set and latest WAL. pin_set: when provided (RO snapshots only), reads through this view pin the pages they materialise into the given set (#159) so concurrent writer CoW churn can't evict the reader's working set; released via Pager.unpin_all.
The current root page id. Changes after each mutation. 0L means an empty tree.
Insert or replace. Returns an updated t whose root_page reflects the new root. Mutations stamp freed pages via Pager.get_txn_id; the pager manages the transaction ID internally — the caller is responsible only for calling Store.rw_begin which sets the correct txn_id.
put_x t key value inserts value at key in a single tree descent. Returns (t', None) when key was absent (value written). Returns (t, Some Bytes.empty) when key already existed (NOT overwritten). The returned bytes on conflict are a sentinel — callers that need the old value must fetch it separately via get.
Opaque cached position at a tree's rightmost leaf, enabling O(1) appends for a run of strictly-increasing inserts (#356). Held by the Store per tree-id; re-validated against the live page on every use.
The cursor's current maximum key (the tree's rightmost key).
type append_outcome = | Appended of append_cursor(*inserted in place; carries the updated cursor
*)| Not_applicable| Append_failed of error
Result of try_inplace_append.
val try_inplace_append :
t ->
append_cursor ->
key:bytes ->
value:bytes ->
append_outcome Lwt.ttry_inplace_append t ac ~key ~value appends (key, value) to the rightmost leaf cached in ac in O(1), if ac still matches the live page and the entry fits. key must exceed every key in the tree (the caller guarantees this; it is re-validated). Returns Not_applicable — never an error — when the cursor is stale or the leaf is full, so the caller falls back to put_x.
Descend the rightmost spine and build a fresh append_cursor for the tree's current rightmost leaf, or None for an empty tree. Used to (re)prime the cursor after a general-path append or a split.
Delete a key. No-op if absent. Returns an updated t.
Phase 1 deletion is lazy: an emptied leaf is left in the tree (callers won't see it as get returns None and the cursor skips it). The only structural change is that if the root itself becomes empty, root_page is reset to 0L.
Open a forward cursor over the tree. The cursor is positioned at the first entry, so the very first cursor_next returns the first entry.
val cursor_seek :
cursor ->
bytes ->
([ `Found | `Not_found_after of bytes ], error) result Lwt.tAdvance the cursor to the first entry >= the given key.
Return the entry at the current cursor position and advance. Returns None when the cursor has passed the last entry.