Skip to main content

icydb_core/db/registry/
handle.rs

1use crate::db::{
2    data::DataStore,
3    index::{IndexState, IndexStore},
4    schema::SchemaStore,
5};
6use std::{cell::RefCell, thread::LocalKey};
7
8///
9/// StoreHandle
10///
11/// StoreHandle binds the row, index, and schema stores for one generated schema
12/// `Store` path.
13/// It is the stable access token passed across commit, recovery, executor, and
14/// diagnostics boundaries instead of exposing registry internals directly.
15///
16
17#[derive(Clone, Copy, Debug)]
18pub struct StoreHandle {
19    data: &'static LocalKey<RefCell<DataStore>>,
20    index: &'static LocalKey<RefCell<IndexStore>>,
21    schema: &'static LocalKey<RefCell<SchemaStore>>,
22    allocations: StoreAllocationIdentities,
23}
24
25///
26/// StoreAllocationIdentity
27///
28/// Durable allocation identity for one physical stable-memory role.
29///
30
31#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32pub struct StoreAllocationIdentity {
33    memory_id: u8,
34    stable_key: &'static str,
35}
36
37impl StoreAllocationIdentity {
38    /// Build one stable allocation identity descriptor.
39    #[must_use]
40    pub const fn new(memory_id: u8, stable_key: &'static str) -> Self {
41        Self {
42            memory_id,
43            stable_key,
44        }
45    }
46
47    /// Stable-memory manager ID.
48    #[must_use]
49    pub const fn memory_id(self) -> u8 {
50        self.memory_id
51    }
52
53    /// Durable stable-memory key.
54    #[must_use]
55    pub const fn stable_key(self) -> &'static str {
56        self.stable_key
57    }
58}
59
60///
61/// StoreAllocationIdentities
62///
63/// Durable allocation identities for one logical store's data, index, and
64/// schema memories.
65///
66
67#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
68pub struct StoreAllocationIdentities {
69    data: Option<StoreAllocationIdentity>,
70    index: Option<StoreAllocationIdentity>,
71    schema: Option<StoreAllocationIdentity>,
72}
73
74impl StoreAllocationIdentities {
75    /// Build an absent allocation identity bundle.
76    #[must_use]
77    pub const fn absent() -> Self {
78        Self {
79            data: None,
80            index: None,
81            schema: None,
82        }
83    }
84
85    /// Build one allocation identity bundle.
86    #[must_use]
87    pub const fn new(
88        data: StoreAllocationIdentity,
89        index: StoreAllocationIdentity,
90        schema: StoreAllocationIdentity,
91    ) -> Self {
92        Self {
93            data: Some(data),
94            index: Some(index),
95            schema: Some(schema),
96        }
97    }
98
99    /// Return data-memory allocation identity.
100    #[must_use]
101    pub const fn data(self) -> Option<StoreAllocationIdentity> {
102        self.data
103    }
104
105    /// Return index-memory allocation identity.
106    #[must_use]
107    pub const fn index(self) -> Option<StoreAllocationIdentity> {
108        self.index
109    }
110
111    /// Return schema-memory allocation identity.
112    #[must_use]
113    pub const fn schema(self) -> Option<StoreAllocationIdentity> {
114        self.schema
115    }
116}
117
118impl StoreHandle {
119    /// Build a store handle with an explicit allocation identity decision.
120    #[must_use]
121    pub const fn new(
122        data: &'static LocalKey<RefCell<DataStore>>,
123        index: &'static LocalKey<RefCell<IndexStore>>,
124        schema: &'static LocalKey<RefCell<SchemaStore>>,
125        allocations: StoreAllocationIdentities,
126    ) -> Self {
127        Self {
128            data,
129            index,
130            schema,
131            allocations,
132        }
133    }
134
135    /// Borrow the row store immutably.
136    pub fn with_data<R>(&self, f: impl FnOnce(&DataStore) -> R) -> R {
137        #[cfg(feature = "diagnostics")]
138        {
139            crate::db::physical_access::measure_physical_access_operation(|| {
140                self.data.with_borrow(f)
141            })
142        }
143
144        #[cfg(not(feature = "diagnostics"))]
145        {
146            self.data.with_borrow(f)
147        }
148    }
149
150    /// Borrow the row store mutably.
151    pub fn with_data_mut<R>(&self, f: impl FnOnce(&mut DataStore) -> R) -> R {
152        self.data.with_borrow_mut(f)
153    }
154
155    /// Borrow the index store immutably.
156    pub fn with_index<R>(&self, f: impl FnOnce(&IndexStore) -> R) -> R {
157        #[cfg(feature = "diagnostics")]
158        {
159            crate::db::physical_access::measure_physical_access_operation(|| {
160                self.index.with_borrow(f)
161            })
162        }
163
164        #[cfg(not(feature = "diagnostics"))]
165        {
166            self.index.with_borrow(f)
167        }
168    }
169
170    /// Borrow the index store mutably.
171    pub fn with_index_mut<R>(&self, f: impl FnOnce(&mut IndexStore) -> R) -> R {
172        self.index.with_borrow_mut(f)
173    }
174
175    /// Borrow the schema store immutably.
176    pub fn with_schema<R>(&self, f: impl FnOnce(&SchemaStore) -> R) -> R {
177        self.schema.with_borrow(f)
178    }
179
180    /// Borrow the schema store mutably.
181    pub fn with_schema_mut<R>(&self, f: impl FnOnce(&mut SchemaStore) -> R) -> R {
182        self.schema.with_borrow_mut(f)
183    }
184
185    /// Return the explicit lifecycle state of the bound index store.
186    #[must_use]
187    pub(in crate::db) fn index_state(&self) -> IndexState {
188        self.with_index(IndexStore::state)
189    }
190
191    /// Mark the bound index store as Building.
192    pub(in crate::db) fn mark_index_building(&self) {
193        self.with_index_mut(IndexStore::mark_building);
194    }
195
196    /// Mark the bound index store as Ready.
197    pub(in crate::db) fn mark_index_ready(&self) {
198        self.with_index_mut(IndexStore::mark_ready);
199    }
200
201    /// Return the raw row-store accessor.
202    #[must_use]
203    pub const fn data_store(&self) -> &'static LocalKey<RefCell<DataStore>> {
204        self.data
205    }
206
207    /// Return the raw index-store accessor.
208    #[must_use]
209    pub const fn index_store(&self) -> &'static LocalKey<RefCell<IndexStore>> {
210        self.index
211    }
212
213    /// Return the raw schema-store accessor.
214    #[must_use]
215    pub const fn schema_store(&self) -> &'static LocalKey<RefCell<SchemaStore>> {
216        self.schema
217    }
218
219    /// Return the data-memory allocation identity when generated wiring
220    /// supplied it.
221    #[must_use]
222    pub const fn data_allocation(&self) -> Option<StoreAllocationIdentity> {
223        self.allocations.data()
224    }
225
226    /// Return the index-memory allocation identity when generated wiring
227    /// supplied it.
228    #[must_use]
229    pub const fn index_allocation(&self) -> Option<StoreAllocationIdentity> {
230        self.allocations.index()
231    }
232
233    /// Return the schema-memory allocation identity when generated wiring
234    /// supplied it.
235    #[must_use]
236    pub const fn schema_allocation(&self) -> Option<StoreAllocationIdentity> {
237        self.allocations.schema()
238    }
239}