pub struct PushIndex { /* private fields */ }Expand description
The reverse index: guard value → connection slots, plus the always-visited scan set and a refcounted union of split-edit keys.
A connection is registered in exactly one place: under its guard’s column
(once per guard value) in the eq map, or in the scan set when it
has no extractable guard — unless its guard has empty values (never-matching),
in which case it is registered nowhere. insert /
remove are symmetric so the invariant survives slot recycling.
Implementations§
Source§impl PushIndex
impl PushIndex
pub fn new() -> PushIndex
Sourcepub fn insert(
&mut self,
slot: u32,
guard: Option<&PushGuard>,
split_edit_keys: &[ColId],
)
pub fn insert( &mut self, slot: u32, guard: Option<&PushGuard>, split_edit_keys: &[ColId], )
Register slot under guard (or the scan set when None), and refcount its
split_edit_keys into the union. Idempotent per (slot, guard) pair only in
the sense the caller enforces: ConnTable inserts once per connect.
Sourcepub fn remove(
&mut self,
slot: u32,
guard: Option<&PushGuard>,
split_edit_keys: &[ColId],
)
pub fn remove( &mut self, slot: u32, guard: Option<&PushGuard>, split_edit_keys: &[ColId], )
Un-register slot — the exact inverse of insert, driven by
the connection’s own still-present guard (so it names precisely which
buckets to remove it from). Empty buckets and column maps are pruned so the
per-push column iteration stays proportional to live guarded columns. Any
dynamic guard values the slot accumulated are drained as well.
Sourcepub fn add_guard_value(&mut self, slot: u32, col: ColId, v: OwnedValue)
pub fn add_guard_value(&mut self, slot: u32, col: ColId, v: OwnedValue)
Add one dynamic guard value for slot on col (design 310 §4.1, the 205
extension for a family root’s growing binding set): the slot becomes a push
candidate for writes whose col cell is identical to v. Repeated values
stack (one bucket entry each) and un-stack one at a time, so two bindings that
share a first-column value keep the slot indexed until both are gone.
The 205 safety argument is unchanged: the index stays a superset filter and the
exact predicate re-checks every visit — provided the caller adds the guard value
before the predicate starts accepting the value, and removes it after the
predicate stops (the ordering discipline Graph::bind_family_partition follows),
and only ever between pushes.
Sourcepub fn remove_guard_value(&mut self, slot: u32, col: ColId, v: &OwnedValue)
pub fn remove_guard_value(&mut self, slot: u32, col: ColId, v: &OwnedValue)
Remove one dynamic guard value previously added with
add_guard_value (one stacked entry). A value that was
never added is a no-op.
Sourcepub fn size(&self) -> usize
pub fn size(&self) -> usize
The number of entries the index holds — bucket memberships, scan slots, and dynamic values (a dynamic value counts twice: its bucket membership and its dynamic-map entry) — a churn/leak probe’s size signal.
Sourcepub fn push_candidates(&self, change: &SourceChange) -> Vec<u32>
pub fn push_candidates(&self, change: &SourceChange) -> Vec<u32>
Slots that may satisfy predicate(old) || predicate(new) for change — a
superset by construction (module docs). Sorted ascending and deduped, so
the fan-out visits in slot order exactly as the full-scan loop does today.
Starts from every scan slot, then for each guarded column looks up the
change’s relevant cell(s): Add/Remove contribute the one row’s cell;
Edit contributes both row[col] and old[col] (an edit can leave one
guard set and enter another).
Sourcepub fn split_keys(&self) -> impl Iterator<Item = ColId> + '_
pub fn split_keys(&self) -> impl Iterator<Item = ColId> + '_
The distinct split-edit keys across all registered connections. should_split
is split_keys().any(|k| !values_equal(row[k], old[k])) — exactly equivalent
to today’s any-of-any over per-connection key lists, at O(distinct keys).
Sourcepub fn has_split_keys(&self) -> bool
pub fn has_split_keys(&self) -> bool
true iff no connection lists any split-edit key — lets the caller skip the
edit-split check entirely.