modelvault_core/db/
handle_registry.rs1use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5use std::sync::{Arc, Mutex, OnceLock, RwLock};
6
7use crate::catalog::Catalog;
8use crate::error::DbError;
9use crate::index::IndexState;
10
11use super::LatestMap;
12
13#[derive(Debug, Clone)]
15pub struct SharedDbState {
16 pub catalog: Catalog,
17 pub latest: LatestMap,
18 pub indexes: IndexState,
19 pub segment_start: u64,
20 pub format_minor: u16,
21 pub generation: u64,
23}
24
25pub type SharedDbHandle = Arc<RwLock<Arc<SharedDbState>>>;
27
28pub fn registry_key(path: &Path) -> PathBuf {
30 path.canonicalize().unwrap_or_else(|_| path.to_path_buf())
31}
32
33fn map() -> &'static Mutex<HashMap<PathBuf, SharedDbHandle>> {
34 static MAP: OnceLock<Mutex<HashMap<PathBuf, SharedDbHandle>>> = OnceLock::new();
35 MAP.get_or_init(|| Mutex::new(HashMap::new()))
36}
37
38pub fn register(path: &Path, state: SharedDbState) -> Result<SharedDbHandle, DbError> {
39 let key = registry_key(path);
40 let mut g = map()
41 .lock()
42 .map_err(|_| DbError::Io(std::io::Error::other("handle registry lock poisoned")))?;
43 if let Some(existing) = g.get(&key) {
44 let gen = existing
45 .read()
46 .map_err(|_| DbError::Io(std::io::Error::other("shared database lock poisoned")))?
47 .generation
48 .saturating_add(1);
49 let mut state = state;
50 state.generation = gen;
51 let mut w = existing
52 .write()
53 .map_err(|_| DbError::Io(std::io::Error::other("shared database lock poisoned")))?;
54 *w = Arc::new(state);
55 return Ok(Arc::clone(existing));
56 }
57 let mut state = state;
58 state.generation = 0;
59 let arc = Arc::new(RwLock::new(Arc::new(state)));
60 g.insert(key, Arc::clone(&arc));
61 Ok(arc)
62}
63
64pub fn get(path: &Path) -> Option<SharedDbHandle> {
65 let key = registry_key(path);
66 map().lock().ok().and_then(|g| g.get(&key).cloned())
67}
68
69#[allow(dead_code)]
70pub fn unregister(path: &Path) {
71 let key = registry_key(path);
72 if let Ok(mut g) = map().lock() {
73 g.remove(&key);
74 }
75}