icydb_core/db/registry/
registry.rs1use crate::{
2 db::{
3 data::DataStore,
4 index::IndexStore,
5 journal::JournalTailStore,
6 registry::{
7 StoreAllocationIdentities, StoreHandle, StoreRegistryError,
8 StoreRuntimeStorageCapabilities, StoreRuntimeStorageMode,
9 },
10 schema::SchemaStore,
11 },
12 error::InternalError,
13};
14use std::{cell::RefCell, thread::LocalKey};
15
16#[derive(Default)]
26pub struct StoreRegistry {
27 stores: Vec<(&'static str, StoreHandle)>,
28}
29
30impl StoreRegistry {
31 #[must_use]
33 pub fn new() -> Self {
34 Self::default()
35 }
36
37 pub fn iter(&self) -> impl Iterator<Item = (&'static str, StoreHandle)> {
43 self.stores.iter().copied()
44 }
45
46 pub fn register_store(
54 &mut self,
55 name: &'static str,
56 data: &'static LocalKey<RefCell<DataStore>>,
57 index: &'static LocalKey<RefCell<IndexStore>>,
58 schema: &'static LocalKey<RefCell<SchemaStore>>,
59 allocations: StoreAllocationIdentities,
60 capabilities: StoreRuntimeStorageCapabilities,
61 ) -> Result<(), InternalError> {
62 self.validate_register_store_shape(name, data, index, schema, allocations, capabilities)?;
63 if capabilities.storage_mode() == StoreRuntimeStorageMode::Journaled {
64 return Err(
65 StoreRegistryError::StoreAllocationCapabilityMismatch(name.to_string()).into(),
66 );
67 }
68
69 self.stores.push((
70 name,
71 StoreHandle::new(data, index, schema, allocations, capabilities),
72 ));
73
74 Ok(())
75 }
76
77 #[expect(
79 clippy::too_many_arguments,
80 reason = "generated journaled registration adds one journal-tail handle to the existing store triplet"
81 )]
82 pub fn register_journaled_store(
83 &mut self,
84 name: &'static str,
85 data: &'static LocalKey<RefCell<DataStore>>,
86 index: &'static LocalKey<RefCell<IndexStore>>,
87 schema: &'static LocalKey<RefCell<SchemaStore>>,
88 journal: &'static LocalKey<RefCell<JournalTailStore>>,
89 allocations: StoreAllocationIdentities,
90 capabilities: StoreRuntimeStorageCapabilities,
91 ) -> Result<(), InternalError> {
92 self.validate_register_store_shape(name, data, index, schema, allocations, capabilities)?;
93 if capabilities.storage_mode() != StoreRuntimeStorageMode::Journaled
94 || allocations.journal().is_none()
95 {
96 return Err(
97 StoreRegistryError::StoreAllocationCapabilityMismatch(name.to_string()).into(),
98 );
99 }
100
101 self.stores.push((
102 name,
103 StoreHandle::new_journaled(data, index, schema, journal, allocations, capabilities),
104 ));
105
106 Ok(())
107 }
108
109 pub fn try_get_store(&self, path: &str) -> Result<StoreHandle, InternalError> {
111 self.stores
112 .iter()
113 .find_map(|(existing_path, handle)| (*existing_path == path).then_some(*handle))
114 .ok_or_else(|| StoreRegistryError::StoreNotFound(path.to_string()).into())
115 }
116
117 fn validate_register_store_shape(
118 &self,
119 name: &'static str,
120 data: &'static LocalKey<RefCell<DataStore>>,
121 index: &'static LocalKey<RefCell<IndexStore>>,
122 schema: &'static LocalKey<RefCell<SchemaStore>>,
123 allocations: StoreAllocationIdentities,
124 capabilities: StoreRuntimeStorageCapabilities,
125 ) -> Result<(), InternalError> {
126 if self
127 .stores
128 .iter()
129 .any(|(existing_name, _)| *existing_name == name)
130 {
131 return Err(StoreRegistryError::StoreAlreadyRegistered(name.to_string()).into());
132 }
133
134 if let Some(existing_name) =
137 self.stores
138 .iter()
139 .find_map(|(existing_name, existing_handle)| {
140 (std::ptr::eq(existing_handle.data_store(), data)
141 && std::ptr::eq(existing_handle.index_store(), index)
142 && std::ptr::eq(existing_handle.schema_store(), schema))
143 .then_some(*existing_name)
144 })
145 {
146 return Err(StoreRegistryError::StoreHandleTripletAlreadyRegistered {
147 name: name.to_string(),
148 existing_name: existing_name.to_string(),
149 }
150 .into());
151 }
152
153 if allocations.allocation_identity_capability() != Some(capabilities.allocation_identity())
154 || !allocations.matches_storage_capabilities(capabilities)
155 {
156 return Err(
157 StoreRegistryError::StoreAllocationCapabilityMismatch(name.to_string()).into(),
158 );
159 }
160
161 Ok(())
162 }
163}