pub trait MutableCsrTrait: CsrBase {
Show 29 methods
// Required methods
fn insert_edge(
&mut self,
src_vid: u32,
dst: VertexId,
edge_id: EdgeId,
ts: u64,
) -> Result<(), StorageError>;
fn delete_edge(
&mut self,
src_vid: u32,
edge_id: EdgeId,
ts: u64,
) -> Result<bool, StorageError>;
fn delete_edge_by_dst(
&mut self,
src_vid: u32,
dst: VertexId,
ts: u64,
) -> usize;
fn delete_edge_by_offset(
&mut self,
src_vid: u32,
offset: i32,
ts: u64,
) -> Result<bool, StorageError>;
fn revert_delete_by_offset(
&mut self,
src_vid: u32,
offset: i32,
ts: u64,
) -> bool;
fn get_edge(&self, src_vid: u32, dst: VertexId, ts: u64) -> Option<Nbr>;
fn edges_of(&self, src_vid: u32, ts: u64) -> Vec<Nbr>;
fn used_memory_size(&self) -> usize;
// Provided methods
fn delete_edge_by_dst_reporting(
&mut self,
src_vid: u32,
dst: VertexId,
ts: u64,
_on_deleted: &mut dyn FnMut(EdgeId),
) -> usize { ... }
fn delete_edge_by_dst_reporting_positioned(
&mut self,
src_vid: u32,
dst: VertexId,
ts: u64,
on_deleted: &mut dyn FnMut(EdgeId, Option<EdgePosition>),
) -> usize { ... }
fn locate_edge(
&self,
_src_vid: u32,
_edge_id: EdgeId,
) -> Option<(EdgePosition, Nbr)> { ... }
fn delete_edge_at_position(
&mut self,
src_vid: u32,
_position: EdgePosition,
expected: EdgeId,
ts: u64,
) -> Result<bool, StorageError> { ... }
fn revert_delete_at_position(
&mut self,
src_vid: u32,
_position: EdgePosition,
expected: EdgeId,
ts: u64,
) -> bool { ... }
fn nbr_at_offset(&self, _src_vid: u32, _offset: i32) -> Option<Nbr> { ... }
fn get_edge_physical(&self, _src_vid: u32, _dst: VertexId) -> Option<Nbr> { ... }
fn physical_edges_of(&self, _src_vid: u32) -> Vec<Nbr> { ... }
fn fill_physical_into(&self, src_vid: u32, out: &mut Vec<Nbr>) { ... }
fn has_physical_entries(&self, _vid: u32) -> bool { ... }
fn primary_contains(&self, _src_vid: u32, _edge_id: EdgeId) -> bool { ... }
fn rollback_insert(&mut self, _src_vid: u32, _edge_id: EdgeId) -> bool { ... }
fn revert_delete_by_edge_id(
&mut self,
_src_vid: u32,
_edge_id: EdgeId,
_ts: u64,
) -> bool { ... }
fn compact_vertex_with_reporting(
&mut self,
_vid: u32,
_cutoff: u64,
_on_edge_removed: &mut dyn FnMut(EdgeId, u64),
) -> usize { ... }
fn reclaimable_count(&self, _vid: u32, _cutoff: u64) -> usize { ... }
fn vertex_needs_compact(&self, vid: u32, cutoff: u64) -> bool { ... }
fn vertex_census(&self, _vid: u32) -> (usize, usize, usize) { ... }
fn vertex_reclaim_probe(&self, vid: u32, cutoff: u64) -> (usize, usize) { ... }
fn row_gap(&self, _vid: u32) -> usize { ... }
fn row_density(&self, _vid: u32) -> f32 { ... }
fn rebalance_row(&mut self, _vid: u32) -> bool { ... }
}Required Methods§
Sourcefn insert_edge(
&mut self,
src_vid: u32,
dst: VertexId,
edge_id: EdgeId,
ts: u64,
) -> Result<(), StorageError>
fn insert_edge( &mut self, src_vid: u32, dst: VertexId, edge_id: EdgeId, ts: u64, ) -> Result<(), StorageError>
Insert an edge.
Topology and properties are decoupled: the CSR stores only the
topology (neighbor, edge_id, timestamps). Properties are stored
separately indexed by EdgeId.
Physical uniqueness only, without timestamp ordering checks. Snapshot visibility is decided by the version authority above this layer.
Returns Ok(()) on success, or an error explaining why insertion failed:
MutableCsr: checks for duplicate live (neighbor) keys across primary and overflow, writes to primary if space available, otherwise spills to overflow with auto-expansion. ReturnsEdgeAlreadyExistson duplicate.SingleMutableCsr: rejects a second live edge in an occupied slot withConflict, matching the table-layer Single contract. A tombstoned slot accepts a rebuild at any timestamp. No silent overwrite exists.
Sourcefn delete_edge(
&mut self,
src_vid: u32,
edge_id: EdgeId,
ts: u64,
) -> Result<bool, StorageError>
fn delete_edge( &mut self, src_vid: u32, edge_id: EdgeId, ts: u64, ) -> Result<bool, StorageError>
Delete an edge by edge_id.
Returns:
-
Ok(true)when the edge was deleted. -
Ok(false)when the edge does not exist or cannot be deleted atts(e.g.create_ts > ts), or when it was already deleted at exactlyts(idempotent re-delete). -
Err(StorageError::write_write_conflict)when the edge already exists but was deleted at a different timestamp. -
MutableCsr: usesedge_idto locate and delete the specific edge. -
SingleMutableCsr: the stored edge id must match exactly. No wildcard edge id is supported; callers pass the precise id or use endpoint addressing.
Sourcefn delete_edge_by_dst(&mut self, src_vid: u32, dst: VertexId, ts: u64) -> usize
fn delete_edge_by_dst(&mut self, src_vid: u32, dst: VertexId, ts: u64) -> usize
Delete all edges matching (src, dst) with full-match semantics.
One call deletes every live match; no first-only variant exists. Returns the deleted count so table rollback can reconcile by count and tombstone metrics can observe multi-match rows.
MutableCsr: scans primary and overflow, deletes all matching edges.SingleMutableCsr: deletes the single edge if dst matches (0 or 1).
Sourcefn delete_edge_by_offset(
&mut self,
src_vid: u32,
offset: i32,
ts: u64,
) -> Result<bool, StorageError>
fn delete_edge_by_offset( &mut self, src_vid: u32, offset: i32, ts: u64, ) -> Result<bool, StorageError>
Delete an edge by its offset position in the primary block.
Offset indexes into the live row degree, never into reserved capacity. Out-of-degree offsets fail without touching any slot. Conflict errors are propagated instead of folded into a failure value.
Sourcefn revert_delete_by_offset(
&mut self,
src_vid: u32,
offset: i32,
ts: u64,
) -> bool
fn revert_delete_by_offset( &mut self, src_vid: u32, offset: i32, ts: u64, ) -> bool
Revert a deleted edge by its offset position.
MutableCsr: offset indexes into the primary block degree.SingleMutableCsr: only offset == 0 is valid.
Sourcefn get_edge(&self, src_vid: u32, dst: VertexId, ts: u64) -> Option<Nbr>
fn get_edge(&self, src_vid: u32, dst: VertexId, ts: u64) -> Option<Nbr>
Get a specific edge by source and destination. Test-only row-stamp filter; production reads go through the version authority.
Sourcefn edges_of(&self, src_vid: u32, ts: u64) -> Vec<Nbr>
fn edges_of(&self, src_vid: u32, ts: u64) -> Vec<Nbr>
Get all valid edges of a vertex at the given timestamp. Test-only row-stamp filter; production reads go through the version authority. Test and offline use; production traversals use the visitor or caller-buffer fill paths instead of this allocating accessor.
Sourcefn used_memory_size(&self) -> usize
fn used_memory_size(&self) -> usize
Return the approximate memory usage in bytes.
Provided Methods§
Sourcefn delete_edge_by_dst_reporting(
&mut self,
src_vid: u32,
dst: VertexId,
ts: u64,
_on_deleted: &mut dyn FnMut(EdgeId),
) -> usize
fn delete_edge_by_dst_reporting( &mut self, src_vid: u32, dst: VertexId, ts: u64, _on_deleted: &mut dyn FnMut(EdgeId), ) -> usize
Delete all edges matching (src, dst), reporting every stamped id.
Same single-pass semantics as delete_edge_by_dst, plus one
on_deleted call per stamped edge so callers needing the ids (append
logs, audits) skip their own collection scan. The default routes
through delete_edge_by_dst and reports nothing; row stores override
it with an in-place reporting pass. A zero return covers both no match
and read-only refusal without invoking the callback; table write paths
reject frozen groups before reaching here so the two cases never merge
into one silent miss.
Sourcefn delete_edge_by_dst_reporting_positioned(
&mut self,
src_vid: u32,
dst: VertexId,
ts: u64,
on_deleted: &mut dyn FnMut(EdgeId, Option<EdgePosition>),
) -> usize
fn delete_edge_by_dst_reporting_positioned( &mut self, src_vid: u32, dst: VertexId, ts: u64, on_deleted: &mut dyn FnMut(EdgeId, Option<EdgePosition>), ) -> usize
Delete all edges matching (src, dst), reporting each stamped id with its row position.
Same single-pass semantics as delete_edge_by_dst_reporting, plus the
position of each stamped entry so the caller can revert or re-delete
the exact slot without rescanning the row. Positions are row-local and
valid only until the next compaction, rebalance, repack or removal of
the row; every positional write revalidates the edge id. Stores
without positional addressing report None and the caller falls back
to the edge-id path. The default adapts the id-only pass.
Sourcefn locate_edge(
&self,
_src_vid: u32,
_edge_id: EdgeId,
) -> Option<(EdgePosition, Nbr)>
fn locate_edge( &self, _src_vid: u32, _edge_id: EdgeId, ) -> Option<(EdgePosition, Nbr)>
Locate one stored edge, returning its row position and copy.
The default reports no position; row stores override it with a single scan shared by delete and revert callers.
Sourcefn delete_edge_at_position(
&mut self,
src_vid: u32,
_position: EdgePosition,
expected: EdgeId,
ts: u64,
) -> Result<bool, StorageError>
fn delete_edge_at_position( &mut self, src_vid: u32, _position: EdgePosition, expected: EdgeId, ts: u64, ) -> Result<bool, StorageError>
Delete the edge at position when it still holds expected id.
Stale positions are refused with Ok(false). Position-less stores
fail closed with an error so a cross-variant position can never fall
back to an id scan silently; positional stores override it with a
direct slot write.
Sourcefn revert_delete_at_position(
&mut self,
src_vid: u32,
_position: EdgePosition,
expected: EdgeId,
ts: u64,
) -> bool
fn revert_delete_at_position( &mut self, src_vid: u32, _position: EdgePosition, expected: EdgeId, ts: u64, ) -> bool
Revert the deletion at position when it still holds expected id.
Stale positions are refused with false. Position-less stores report
false so cross-form reuse is observable instead of silently
succeeding through another path; positional stores override it.
Sourcefn nbr_at_offset(&self, _src_vid: u32, _offset: i32) -> Option<Nbr>
fn nbr_at_offset(&self, _src_vid: u32, _offset: i32) -> Option<Nbr>
Read-only view of one primary slot for offset identity checks.
Sourcefn get_edge_physical(&self, _src_vid: u32, _dst: VertexId) -> Option<Nbr>
fn get_edge_physical(&self, _src_vid: u32, _dst: VertexId) -> Option<Nbr>
Locate the first live edge by endpoint without consulting snapshots.
Physical addressing only; tombstoned and gap slots are skipped. Snapshot visibility still needs the version authority above this layer, while tombstone access uses the full physical views.
Sourcefn physical_edges_of(&self, _src_vid: u32) -> Vec<Nbr>
fn physical_edges_of(&self, _src_vid: u32) -> Vec<Nbr>
Every physically stored entry of one vertex without timestamp filtering.
Test and offline use; production scans use fill_physical_into or
the visitor paths instead of this allocating accessor.
Sourcefn fill_physical_into(&self, src_vid: u32, out: &mut Vec<Nbr>)
fn fill_physical_into(&self, src_vid: u32, out: &mut Vec<Nbr>)
Fill a caller buffer with every physically stored entry of one vertex.
Same content as the allocating accessor above, without the per-vertex allocation. The default forwards to the allocating accessor; row stores override it with a direct fill.
Sourcefn has_physical_entries(&self, _vid: u32) -> bool
fn has_physical_entries(&self, _vid: u32) -> bool
Whether one vertex holds any physically stored entry.
Sourcefn primary_contains(&self, _src_vid: u32, _edge_id: EdgeId) -> bool
fn primary_contains(&self, _src_vid: u32, _edge_id: EdgeId) -> bool
Whether the primary row of one vertex holds edge_id.
Sourcefn rollback_insert(&mut self, _src_vid: u32, _edge_id: EdgeId) -> bool
fn rollback_insert(&mut self, _src_vid: u32, _edge_id: EdgeId) -> bool
Erase one just-inserted edge for insert rollback (no tombstone trace).
Insert-rollback only: erases the slot as if the edge never existed.
Never use for MVCC deletes, which must go through delete_edge so
the tombstone stays visible to the reclaim machinery. Reclaims the
slot and updates the edge count. Only implemented by writable
strategies; other strategies default to no-op.
Sourcefn revert_delete_by_edge_id(
&mut self,
_src_vid: u32,
_edge_id: EdgeId,
_ts: u64,
) -> bool
fn revert_delete_by_edge_id( &mut self, _src_vid: u32, _edge_id: EdgeId, _ts: u64, ) -> bool
Revert a deletion by edge id if it happened at or before ts.
Restores the entry as live. Only implemented by MutableCsr; other
strategies default to no-op.
Sourcefn compact_vertex_with_reporting(
&mut self,
_vid: u32,
_cutoff: u64,
_on_edge_removed: &mut dyn FnMut(EdgeId, u64),
) -> usize
fn compact_vertex_with_reporting( &mut self, _vid: u32, _cutoff: u64, _on_edge_removed: &mut dyn FnMut(EdgeId, u64), ) -> usize
Reclaim one vertex in place, dropping entries eligible for collection
at cutoff and tightening live entries without touching other rows.
Returns the number of removed entries. Reported removals flow through
on_edge_removed so tombstone promotion stays centralized.
Strategies without per-row fragmentation default to no-op.
Mutable-row entry only: production reclaim of frozen rows must go through the group-batched entries (one linear pass for any number of rows) instead of one call per row. Frozen implementations reject the single-row entry; every production trigger dispatches frozen groups to the batched path before reaching here.
Sourcefn reclaimable_count(&self, _vid: u32, _cutoff: u64) -> usize
fn reclaimable_count(&self, _vid: u32, _cutoff: u64) -> usize
Count entries of one vertex that are reclaimable at cutoff.
The write-path trigger consults this per-vertex count instead of a whole-table ratio, so small writes never cause large rebuilds.
Sourcefn vertex_needs_compact(&self, vid: u32, cutoff: u64) -> bool
fn vertex_needs_compact(&self, vid: u32, cutoff: u64) -> bool
Whether one vertex holds anything reclaimable at cutoff.
Sourcefn vertex_census(&self, _vid: u32) -> (usize, usize, usize)
fn vertex_census(&self, _vid: u32) -> (usize, usize, usize)
Physical entry census of one vertex: (live, dead, capacity).
Backs the per-vertex fragmentation view; strategies without rows report zeros.
Sourcefn vertex_reclaim_probe(&self, vid: u32, cutoff: u64) -> (usize, usize)
fn vertex_reclaim_probe(&self, vid: u32, cutoff: u64) -> (usize, usize)
Single-walk reclaim probe of one vertex: (dead, reclaimable).
Fuses the census and eligibility walks so maintenance passes pay one row scan instead of two. The default derives both from the separate primitives; row stores override it with one fused walk.
Sourcefn row_gap(&self, _vid: u32) -> usize
fn row_gap(&self, _vid: u32) -> usize
Reserved primary slots minus live primary entries of one row.
Steady-state write gaps; strategies without rows report zero.
Sourcefn row_density(&self, _vid: u32) -> f32
fn row_density(&self, _vid: u32) -> f32
Live primary entries per unit of reserved primary capacity.
Strategies without rows report full density.
Sourcefn rebalance_row(&mut self, _vid: u32) -> bool
fn rebalance_row(&mut self, _vid: u32) -> bool
Rebalance one row in place, pulling overflow entries into primary gaps and repacking leftover overflow. Returns true when the row no longer holds overflow. Strategies without rows report true.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".