use crate::graph::dir_graph::DirGraph;
use crate::graph::storage::backend::GraphBackend;
use crate::graph::storage::disk::graph::DiskGraph;
use crate::graph::storage::MappedGraph;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StorageMode {
Memory,
Mapped,
Disk,
}
impl StorageMode {
pub fn parse(s: &str) -> Result<Self, String> {
match s {
"memory" | "default" => Ok(Self::Memory),
"mapped" => Ok(Self::Mapped),
"disk" => Ok(Self::Disk),
other => Err(format!(
"Unknown storage mode '{other}'. Expected 'memory', 'mapped', or 'disk'."
)),
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::Memory => "memory",
Self::Mapped => "mapped",
Self::Disk => "disk",
}
}
}
pub fn new_dir_graph_in_mode(mode: StorageMode, path: Option<&Path>) -> Result<DirGraph, String> {
let mut graph = DirGraph::new();
match mode {
StorageMode::Memory => {}
StorageMode::Mapped => {
graph.graph = GraphBackend::Mapped(MappedGraph::new());
graph.memory_limit = Some(0);
}
StorageMode::Disk => {
let dir =
path.ok_or_else(|| "storage mode 'disk' requires a directory path".to_string())?;
let dg = DiskGraph::new_at_path(dir)
.map_err(|e| format!("Failed to create disk graph at '{}': {e}", dir.display()))?;
graph.graph = GraphBackend::Disk(Box::new(dg));
}
}
Ok(graph)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::storage::GraphRead;
#[test]
fn parse_roundtrip() {
for m in [StorageMode::Memory, StorageMode::Mapped, StorageMode::Disk] {
assert_eq!(StorageMode::parse(m.as_str()), Ok(m));
}
assert_eq!(StorageMode::parse("default"), Ok(StorageMode::Memory));
assert!(StorageMode::parse("nope").is_err());
}
#[test]
fn memory_mode_is_in_memory() {
let g = new_dir_graph_in_mode(StorageMode::Memory, None).unwrap();
assert!(!g.graph.is_mapped() && !g.graph.is_disk());
}
#[test]
fn mapped_mode_switches_backend() {
let g = new_dir_graph_in_mode(StorageMode::Mapped, None).unwrap();
assert!(g.graph.is_mapped());
assert_eq!(g.memory_limit, Some(0));
}
#[test]
fn disk_mode_requires_path() {
assert!(new_dir_graph_in_mode(StorageMode::Disk, None).is_err());
}
#[test]
fn disk_mode_creates_at_path() {
let tmp = std::env::temp_dir().join(format!("kgl_mode_test_{}", std::process::id()));
let _ = std::fs::remove_dir_all(&tmp);
let g = new_dir_graph_in_mode(StorageMode::Disk, Some(&tmp)).unwrap();
assert!(g.graph.is_disk());
let _ = std::fs::remove_dir_all(&tmp);
}
}