icydb_core/db/registry/
registry.rs1use crate::{
2 db::{
3 data::DataStore,
4 index::IndexStore,
5 registry::{
6 StoreAllocationIdentities, StoreHandle, StoreRegistryError,
7 StoreRuntimeStorageCapabilities,
8 },
9 schema::SchemaStore,
10 },
11 error::InternalError,
12};
13use std::{cell::RefCell, thread::LocalKey};
14
15#[derive(Default)]
25pub struct StoreRegistry {
26 stores: Vec<(&'static str, StoreHandle)>,
27}
28
29impl StoreRegistry {
30 #[must_use]
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn iter(&self) -> impl Iterator<Item = (&'static str, StoreHandle)> {
42 self.stores.iter().copied()
43 }
44
45 pub fn register_store(
53 &mut self,
54 name: &'static str,
55 data: &'static LocalKey<RefCell<DataStore>>,
56 index: &'static LocalKey<RefCell<IndexStore>>,
57 schema: &'static LocalKey<RefCell<SchemaStore>>,
58 allocations: StoreAllocationIdentities,
59 capabilities: StoreRuntimeStorageCapabilities,
60 ) -> Result<(), InternalError> {
61 if self
62 .stores
63 .iter()
64 .any(|(existing_name, _)| *existing_name == name)
65 {
66 return Err(StoreRegistryError::StoreAlreadyRegistered(name.to_string()).into());
67 }
68
69 if let Some(existing_name) =
72 self.stores
73 .iter()
74 .find_map(|(existing_name, existing_handle)| {
75 (std::ptr::eq(existing_handle.data_store(), data)
76 && std::ptr::eq(existing_handle.index_store(), index)
77 && std::ptr::eq(existing_handle.schema_store(), schema))
78 .then_some(*existing_name)
79 })
80 {
81 return Err(StoreRegistryError::StoreHandleTripletAlreadyRegistered {
82 name: name.to_string(),
83 existing_name: existing_name.to_string(),
84 }
85 .into());
86 }
87
88 if allocations.allocation_identity_capability() != Some(capabilities.allocation_identity())
89 {
90 return Err(
91 StoreRegistryError::StoreAllocationCapabilityMismatch(name.to_string()).into(),
92 );
93 }
94
95 self.stores.push((
96 name,
97 StoreHandle::new(data, index, schema, allocations, capabilities),
98 ));
99
100 Ok(())
101 }
102
103 pub fn try_get_store(&self, path: &str) -> Result<StoreHandle, InternalError> {
105 self.stores
106 .iter()
107 .find_map(|(existing_path, handle)| (*existing_path == path).then_some(*handle))
108 .ok_or_else(|| StoreRegistryError::StoreNotFound(path.to_string()).into())
109 }
110}