use super::super::{CsrShardSet, EdgeSchema};
use super::mvcc::MVCCManager;
use super::schema_add_column::PendingAddColumn;
use super::schema_drop_column::PendingDropColumn;
use super::stats::GroupSegmentStats;
use crate::edge::CsrWithProperties;
use crate::edge::IndexConsistency;
use crate::index::edge_index_manager::EdgePropertyIndex;
use crate::schema::LabelVersionHistory;
use linkrs_core::types::{EdgeId, LabelId, Timestamp};
use std::collections::{HashMap, HashSet};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
pub use super::config::{AutoMaintenanceConfig, EdgeTableConfig, UpdateEdgePropertyByKeyParams};
pub use super::iterator::EdgeTableScanIterator;
pub use index::EdgeIndexStatus;
pub use writes::IncidentDeletedEdge;
pub struct EdgeStore {
pub label: LabelId,
pub label_name: String,
pub src_label: LabelId,
pub dst_label: LabelId,
pub schema: EdgeSchema,
pub out_csr: CsrShardSet,
pub in_csr: CsrShardSet,
pub mvcc: MVCCManager,
pub properties: CsrWithProperties,
pub properties_dirty: bool,
pub(crate) property_column_dirt: HashMap<u32, HashSet<Arc<str>>>,
pub is_open: bool,
pub next_edge_id: EdgeId,
pub config: EdgeTableConfig,
pub stats_manager: Option<std::sync::Arc<linkrs_metrics::StatsManager>>,
pub version_history: Arc<Mutex<LabelVersionHistory>>,
pub property_index_cache: HashMap<std::sync::Arc<str>, usize>,
pub property_index: Option<EdgePropertyIndex>,
pub index_write_failures: u64,
pub index_consistency: IndexConsistency,
pub index_lag_baseline: u64,
pub(crate) index_pool_capacity: u64,
pub(crate) index_stale_since: Option<std::time::Instant>,
pub(crate) group_write_counts: HashMap<u32, u64>,
pub(crate) form_width_bytes: AtomicU64,
pub(crate) form_width_samples: AtomicU64,
pub(crate) form_reads: AtomicU64,
pub(crate) form_writes: AtomicU64,
pub(crate) form_out_reads: AtomicU64,
pub(crate) form_in_reads: AtomicU64,
pub(crate) last_auto_migrated_to_bundled: bool,
pub(crate) pending_add_column: Option<PendingAddColumn>,
pub(crate) pending_drop_column: Option<PendingDropColumn>,
pub(crate) edge_owner: owner::EdgeOwnerMap,
pub(crate) segment_stats: HashMap<u32, GroupSegmentStats>,
pub(crate) commit_scratch: super::staging::CommitScratch,
pub(crate) last_reclaim_bound: Timestamp,
pub(crate) last_reclaim_tombstones: usize,
pub(crate) wal_dir: Option<std::path::PathBuf>,
pub(crate) property_fallback_rewrites: u64,
pub(crate) pending_rename_column: Option<super::schema_rename_column::PendingRenameColumn>,
pub(crate) migration_pending_checkpoint: bool,
pub(crate) maintenance_reclaim_skips: u64,
pub(crate) maintenance_migrate_skips: u64,
pub(crate) maintenance_index_skips: u64,
}
impl std::fmt::Debug for EdgeStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EdgeStore")
.field("label", &self.label)
.field("label_name", &self.label_name)
.field("out_csr", &self.out_csr)
.field("in_csr", &self.in_csr)
.field("is_open", &self.is_open)
.field("next_edge_id", &self.next_edge_id)
.field("config", &self.config)
.finish()
}
}
impl EdgeStore {
pub(crate) fn observe_form_write(&self, props: &[(std::sync::Arc<str>, linkrs_core::Value)]) {
use super::stats::estimate_props_bytes;
let bytes = estimate_props_bytes(props);
self.form_width_bytes.fetch_add(bytes, Ordering::Relaxed);
self.form_width_samples.fetch_add(1, Ordering::Relaxed);
self.form_writes.fetch_add(1, Ordering::Relaxed);
}
pub(crate) fn observe_form_read(&self, rows: u64) {
self.form_reads.fetch_add(rows.max(1), Ordering::Relaxed);
}
pub(crate) fn observe_direction_read(&self, outgoing: bool, rows: u64) {
let rows = rows.max(1);
if outgoing {
self.form_out_reads.fetch_add(rows, Ordering::Relaxed);
} else {
self.form_in_reads.fetch_add(rows, Ordering::Relaxed);
}
}
pub fn direction_usage_snapshot(&self) -> maintenance::DirectionUsageSnapshot {
maintenance::DirectionUsageSnapshot {
out_reads: self.form_out_reads.load(Ordering::Relaxed),
in_reads: self.form_in_reads.load(Ordering::Relaxed),
}
}
pub fn form_profile_snapshot(&self) -> super::stats::FormProfileSnapshot {
super::stats::FormProfileSnapshot {
width_bytes: self.form_width_bytes.load(Ordering::Relaxed),
width_samples: self.form_width_samples.load(Ordering::Relaxed),
reads: self.form_reads.load(Ordering::Relaxed),
writes: self.form_writes.load(Ordering::Relaxed),
}
}
pub(crate) fn restore_form_profile(&self, snapshot: super::stats::FormProfileSnapshot) {
self.form_width_bytes
.store(snapshot.width_bytes, Ordering::Relaxed);
self.form_width_samples
.store(snapshot.width_samples, Ordering::Relaxed);
self.form_reads.store(snapshot.reads, Ordering::Relaxed);
self.form_writes.store(snapshot.writes, Ordering::Relaxed);
}
}
mod index;
mod maintenance;
pub use maintenance::{
DirectionMigrationStats, DirectionNarrowingSuggestion, DirectionUsageSnapshot,
EdgeStorageBreakdown,
};
pub(crate) mod owner;
mod query;
mod reads;
mod recovery;
pub use recovery::EdgeWalRecoveryMode;
mod schema_ops;
mod store;
mod writes;
#[cfg(test)]
mod tests;