use super::slot_mirror::SlotMirror;
use super::undo::UndoJournal;
use super::{MemoryGraph, MemoryPeerCounts};
use crate::graph::schema::InternedKey;
use crate::graph::schema::{EdgeData, NodeData};
use petgraph::stable_graph::StableDiGraph;
use petgraph::visit::{EdgeIndexable, NodeIndexable};
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use rustc_hash::FxHashMap;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::RwLock;
use std::time::Instant;
impl MemoryGraph {
pub(crate) fn invalidate_peer_counts(&mut self) {
if let Ok(mut cache) = self.peer_counts.write() {
cache.clear();
}
}
pub(crate) fn ensure_peer_counts(&self, conn_type: InternedKey) -> Arc<MemoryPeerCounts> {
self.ensure_peer_counts_with_deadline(conn_type, None)
.expect("peer-count build without a deadline cannot time out")
}
pub(crate) fn ensure_peer_counts_with_deadline(
&self,
conn_type: InternedKey,
deadline: Option<Instant>,
) -> Result<Arc<MemoryPeerCounts>, String> {
let key = conn_type.as_u64();
if let Ok(cache) = self.peer_counts.read() {
if let Some(counts) = cache.get(&key) {
return Ok(Arc::clone(counts));
}
}
let mut by_target = HashMap::new();
let mut by_source = HashMap::new();
for (edge_idx, edge) in self.inner.edge_references().enumerate() {
if edge_idx.is_multiple_of(1 << 20) && deadline.is_some_and(|dl| Instant::now() > dl) {
return Err("Query timed out".to_string());
}
if edge.weight().connection_type != conn_type {
continue;
}
*by_target.entry(edge.target().index() as u32).or_insert(0) += 1;
*by_source.entry(edge.source().index() as u32).or_insert(0) += 1;
}
let built = Arc::new(MemoryPeerCounts {
by_target: Arc::new(by_target),
by_source: Arc::new(by_source),
});
let mut cache = match self.peer_counts.write() {
Ok(cache) => cache,
Err(_) => return Ok(built),
};
Ok(Arc::clone(cache.entry(key).or_insert(built)))
}
}
impl Clone for MemoryGraph {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
column_stores: self.column_stores.clone(),
peer_counts: RwLock::new(HashMap::new()),
undo: None,
slot_mirror: self.slot_mirror.clone(),
}
}
}
impl MemoryGraph {
#[inline]
pub(crate) fn deep_clone(&self) -> Self {
self.clone()
}
#[inline]
pub fn new() -> Self {
Self::from_graph(StableDiGraph::new())
}
#[inline]
pub(crate) fn from_graph(inner: StableDiGraph<NodeData, EdgeData>) -> Self {
let slot_mirror = SlotMirror::for_adopted_graph(
inner.node_count(),
inner.node_bound(),
inner.edge_count(),
inner.edge_bound(),
);
Self {
inner,
column_stores: FxHashMap::default(),
peer_counts: RwLock::new(HashMap::new()),
undo: None,
slot_mirror,
}
}
#[inline]
pub(crate) fn begin_undo(&mut self) {
self.undo = Some(Box::new(UndoJournal::new()));
}
#[inline]
pub(crate) fn take_undo(&mut self) -> Option<Box<UndoJournal>> {
self.undo.take()
}
#[inline]
pub(crate) fn undo_journal_mut(&mut self) -> Option<&mut UndoJournal> {
self.undo.as_deref_mut()
}
#[inline]
pub fn inner(&self) -> &StableDiGraph<NodeData, EdgeData> {
&self.inner
}
#[inline]
pub fn inner_mut(&mut self) -> &mut StableDiGraph<NodeData, EdgeData> {
&mut self.inner
}
}