pub struct CsrIndex { /* private fields */ }Expand description
Dense integer CSR adjacency index with interned node IDs and labels.
Implementations§
Source§impl CsrIndex
impl CsrIndex
pub fn new() -> Self
Sourcepub fn add_node_label(&mut self, node: &str, label: &str) -> bool
pub fn add_node_label(&mut self, node: &str, label: &str) -> bool
Add a label to a node. Returns false if the 64-label limit is hit.
Sourcepub fn remove_node_label(&mut self, node: &str, label: &str)
pub fn remove_node_label(&mut self, node: &str, label: &str)
Remove a label from a node.
Sourcepub fn node_has_label(&self, node_id: u32, label: &str) -> bool
pub fn node_has_label(&self, node_id: u32, label: &str) -> bool
Check if a node has a specific label.
Sourcepub fn node_labels(&self, node_id: u32) -> Vec<&str>
pub fn node_labels(&self, node_id: u32) -> Vec<&str>
Get all label names for a node.
Sourcepub fn add_edge(&mut self, src: &str, label: &str, dst: &str)
pub fn add_edge(&mut self, src: &str, label: &str, dst: &str)
Incrementally add an unweighted edge (goes into mutable buffer). Uses weight 1.0 if the graph already has weighted edges.
Sourcepub fn add_edge_weighted(
&mut self,
src: &str,
label: &str,
dst: &str,
weight: f64,
)
pub fn add_edge_weighted( &mut self, src: &str, label: &str, dst: &str, weight: f64, )
Incrementally add a weighted edge (goes into mutable buffer).
If this is the first weighted edge (weight != 1.0), initializes the weight tracking infrastructure (backfills existing buffer entries with 1.0).
Sourcepub fn remove_edge(&mut self, src: &str, label: &str, dst: &str)
pub fn remove_edge(&mut self, src: &str, label: &str, dst: &str)
Incrementally remove an edge.
Sourcepub fn remove_node_edges(&mut self, node: &str) -> usize
pub fn remove_node_edges(&mut self, node: &str) -> usize
Remove ALL edges touching a node. Returns the number of edges removed.
Sourcepub fn remove_nodes_with_prefix(&mut self, prefix: &str)
pub fn remove_nodes_with_prefix(&mut self, prefix: &str)
Remove all edges touching any node whose ID starts with prefix.
Used for tenant purge: prefix = "{tenant_id}:" removes all
edges belonging to that tenant.
Sourcepub fn neighbors(
&self,
node: &str,
label_filter: Option<&str>,
direction: Direction,
) -> Vec<(String, String)>
pub fn neighbors( &self, node: &str, label_filter: Option<&str>, direction: Direction, ) -> Vec<(String, String)>
Get immediate neighbors.
Sourcepub fn neighbors_multi(
&self,
node: &str,
label_filters: &[&str],
direction: Direction,
) -> Vec<(String, String)>
pub fn neighbors_multi( &self, node: &str, label_filters: &[&str], direction: Direction, ) -> Vec<(String, String)>
Get neighbors with multi-label filter. Empty labels = all edges.
Sourcepub fn add_node(&mut self, name: &str) -> u32
pub fn add_node(&mut self, name: &str) -> u32
Add a node without any edges (used for isolated/dangling nodes). Returns the dense node ID. Idempotent — returns existing ID if present.
pub fn node_count(&self) -> usize
pub fn contains_node(&self, node: &str) -> bool
Sourcepub fn node_id(&self, name: &str) -> Option<u32>
pub fn node_id(&self, name: &str) -> Option<u32>
Look up the dense node ID for a string node ID.
Sourcepub fn label_name(&self, label_id: u16) -> &str
pub fn label_name(&self, label_id: u16) -> &str
Get the string label for a dense label index.
Sourcepub fn label_id(&self, name: &str) -> Option<u16>
pub fn label_id(&self, name: &str) -> Option<u16>
Look up the dense label ID for a string label.
Sourcepub fn out_degree(&self, node_id: u32) -> usize
pub fn out_degree(&self, node_id: u32) -> usize
Out-degree of a node (including buffer, excluding deleted).
Sourcepub fn edge_count(&self) -> usize
pub fn edge_count(&self) -> usize
Total edge count (dense + buffer - deleted). O(V).
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn record_access(&self, node_id: u32)
pub fn record_access(&self, node_id: u32)
Record a node access (called during traversals for hot/cold tracking).
Sourcepub fn cold_nodes(&self, threshold: u32) -> Vec<u32>
pub fn cold_nodes(&self, threshold: u32) -> Vec<u32>
Get nodes with access count below threshold (cold nodes).
Sourcepub fn hot_node_count(&self) -> usize
pub fn hot_node_count(&self) -> usize
Number of hot nodes (access count > 0).
Sourcepub fn query_epoch(&self) -> u64
pub fn query_epoch(&self) -> u64
Current query epoch (incremented per traversal call).
Sourcepub fn reset_access_counts(&mut self)
pub fn reset_access_counts(&mut self)
Reset access counters (called during compaction or periodically).
Sourcepub fn prefetch_node(&self, node_id: u32)
pub fn prefetch_node(&self, node_id: u32)
Predictive prefetch: hint the OS to load a node’s adjacency data into the page cache before the traversal touches it.
For in-memory dense CSR, this prefetches the cache line containing
the node’s offset/target entries. For future mmap’d cold segments,
this would call madvise(MADV_WILLNEED) on the relevant pages.
Called during BFS planning: when adding nodes to the next frontier, prefetch their neighbors’ data so it’s resident when the BFS loop reaches them on the next iteration.
Sourcepub fn prefetch_batch(&self, node_ids: &[u32])
pub fn prefetch_batch(&self, node_ids: &[u32])
Prefetch a batch of nodes (called during BFS frontier expansion).
Sourcepub fn evaluate_memory_pressure(
&self,
utilization: u8,
spill_threshold: u8,
restore_threshold: u8,
) -> (usize, usize)
pub fn evaluate_memory_pressure( &self, utilization: u8, spill_threshold: u8, restore_threshold: u8, ) -> (usize, usize)
Evaluate graph memory pressure and return promotion/demotion hints.
Uses SpillController-compatible thresholds (90%/75% hysteresis):
- Above spill threshold: demote cold nodes (spill to potential mmap)
- Below restore threshold: promote warm nodes back to hot RAM
utilization = estimated memory usage as percentage (0-100).
Returns (nodes_to_demote, nodes_to_promote) counts.
Sourcepub fn estimated_memory_bytes(&self) -> usize
pub fn estimated_memory_bytes(&self) -> usize
Estimated memory usage of the dense CSR in bytes.
Used for SpillController utilization calculation.
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn checkpoint_to_bytes(&self) -> Vec<u8> ⓘ
pub fn checkpoint_to_bytes(&self) -> Vec<u8> ⓘ
Serialize the index to rkyv bytes (with magic header) for storage.
rkyv is ~3x faster than MessagePack for both serialization and
deserialization. The magic header allows from_checkpoint to
auto-detect the format for backward compatibility.
Sourcepub fn from_checkpoint(bytes: &[u8]) -> Option<Self>
pub fn from_checkpoint(bytes: &[u8]) -> Option<Self>
Restore an index from a checkpoint snapshot.
Auto-detects format: rkyv (magic header RKCSR\0) or legacy MessagePack.
Backwards-compatible with old checkpoints.
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn node_to_id_map(&self) -> &HashMap<String, u32>
pub fn node_to_id_map(&self) -> &HashMap<String, u32>
Node-to-ID mapping (for snapshot cloning).
Sourcepub fn id_to_node_list(&self) -> &[String]
pub fn id_to_node_list(&self) -> &[String]
ID-to-node list (for snapshot cloning).
Sourcepub fn label_to_id_map(&self) -> &HashMap<String, u16>
pub fn label_to_id_map(&self) -> &HashMap<String, u16>
Label-to-ID mapping (for snapshot cloning).
Sourcepub fn id_to_label_list(&self) -> &[String]
pub fn id_to_label_list(&self) -> &[String]
ID-to-label list (for snapshot cloning).
Sourcepub fn out_offsets_slice(&self) -> &[u32]
pub fn out_offsets_slice(&self) -> &[u32]
Outbound offset array slice.
Sourcepub fn out_targets_slice(&self) -> &[u32]
pub fn out_targets_slice(&self) -> &[u32]
Outbound target array slice.
Sourcepub fn out_labels_slice(&self) -> &[u16]
pub fn out_labels_slice(&self) -> &[u16]
Outbound label array slice.
Sourcepub fn out_weights_slice(&self) -> Option<&[f64]>
pub fn out_weights_slice(&self) -> Option<&[f64]>
Outbound weight array slice (None if unweighted).
Sourcepub fn in_offsets_slice(&self) -> &[u32]
pub fn in_offsets_slice(&self) -> &[u32]
Inbound offset array slice.
Sourcepub fn in_targets_slice(&self) -> &[u32]
pub fn in_targets_slice(&self) -> &[u32]
Inbound target array slice.
Sourcepub fn in_labels_slice(&self) -> &[u16]
pub fn in_labels_slice(&self) -> &[u16]
Inbound label array slice.
Sourcepub fn in_weights_slice(&self) -> Option<&[f64]>
pub fn in_weights_slice(&self) -> Option<&[f64]>
Inbound weight array slice (None if unweighted).
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn compute_statistics(&self) -> GraphStatistics
pub fn compute_statistics(&self) -> GraphStatistics
Compute full graph statistics from the current CSR state.
O(V + E) — iterates all nodes and edges once. Intended for query planning, not hot-path execution.
Sourcepub fn label_edge_count(&self, label: &str) -> usize
pub fn label_edge_count(&self, label: &str) -> usize
Get the edge count for a specific label. O(E) unless cached.
Returns 0 if the label doesn’t exist.
Sourcepub fn label_selectivity(&self, label: &str) -> f64
pub fn label_selectivity(&self, label: &str) -> f64
Estimate the selectivity of a label: edge_count / total_edges.
Returns 1.0 for unknown labels (conservative — assume all edges). Returns 0.0 for graphs with no edges.
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn has_weights(&self) -> bool
pub fn has_weights(&self) -> bool
Whether this CSR has any weighted edges.
Sourcepub fn out_edge_weight(&self, edge_idx: usize) -> f64
pub fn out_edge_weight(&self, edge_idx: usize) -> f64
Get the weight of the i-th outbound edge from a node (dense CSR only).
edge_idx is the absolute index into out_targets/out_weights.
Returns 1.0 for unweighted graphs.
Sourcepub fn in_edge_weight(&self, edge_idx: usize) -> f64
pub fn in_edge_weight(&self, edge_idx: usize) -> f64
Get the weight of the i-th inbound edge to a node (dense CSR only).
Source§impl CsrIndex
impl CsrIndex
Sourcepub fn traverse_bfs(
&self,
start_nodes: &[&str],
label_filter: Option<&str>,
direction: Direction,
max_depth: usize,
max_visited: usize,
) -> Vec<String>
pub fn traverse_bfs( &self, start_nodes: &[&str], label_filter: Option<&str>, direction: Direction, max_depth: usize, max_visited: usize, ) -> Vec<String>
BFS traversal. Returns all reachable node IDs within max_depth hops.
max_visited caps the number of nodes visited to prevent supernode fan-out
explosion. Pass DEFAULT_MAX_VISITED for the standard limit.
Sourcepub fn traverse_bfs_with_depth(
&self,
start_nodes: &[&str],
label_filter: Option<&str>,
direction: Direction,
max_depth: usize,
max_visited: usize,
) -> Vec<(String, u8)>
pub fn traverse_bfs_with_depth( &self, start_nodes: &[&str], label_filter: Option<&str>, direction: Direction, max_depth: usize, max_visited: usize, ) -> Vec<(String, u8)>
BFS traversal returning nodes with depth information.
max_visited caps the number of nodes visited to prevent supernode fan-out
explosion. Pass DEFAULT_MAX_VISITED for the standard limit.
Sourcepub fn traverse_bfs_with_depth_multi(
&self,
start_nodes: &[&str],
label_filters: &[&str],
direction: Direction,
max_depth: usize,
max_visited: usize,
) -> Vec<(String, u8)>
pub fn traverse_bfs_with_depth_multi( &self, start_nodes: &[&str], label_filters: &[&str], direction: Direction, max_depth: usize, max_visited: usize, ) -> Vec<(String, u8)>
BFS traversal with multi-label filter. Empty labels = all edges.
max_visited caps the number of nodes visited to prevent supernode fan-out
explosion. Pass DEFAULT_MAX_VISITED for the standard limit.
Sourcepub fn shortest_path(
&self,
src: &str,
dst: &str,
label_filter: Option<&str>,
max_depth: usize,
max_visited: usize,
) -> Option<Vec<String>>
pub fn shortest_path( &self, src: &str, dst: &str, label_filter: Option<&str>, max_depth: usize, max_visited: usize, ) -> Option<Vec<String>>
Shortest path via bidirectional BFS.
max_visited caps the combined forward+backward visited set to prevent
supernode fan-out explosion. Pass DEFAULT_MAX_VISITED for the standard limit.
Sourcepub fn subgraph(
&self,
start_nodes: &[&str],
label_filter: Option<&str>,
max_depth: usize,
max_visited: usize,
) -> Vec<(String, String, String)>
pub fn subgraph( &self, start_nodes: &[&str], label_filter: Option<&str>, max_depth: usize, max_visited: usize, ) -> Vec<(String, String, String)>
Materialize a subgraph as edge tuples within max_depth.
max_visited caps the number of nodes visited to prevent supernode fan-out
explosion. Pass DEFAULT_MAX_VISITED for the standard limit.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for CsrIndex
impl !RefUnwindSafe for CsrIndex
impl Send for CsrIndex
impl !Sync for CsrIndex
impl Unpin for CsrIndex
impl UnsafeUnpin for CsrIndex
impl UnwindSafe for CsrIndex
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.