1pub mod neighbors;
13pub mod provider;
14pub mod quant;
15pub mod vectors;
16
17mod locks;
18
19pub use provider::{
21 AsVectorDtype, BfTreePaths, BfTreeProvider, BfTreeProviderParameters, CreateQuantProvider,
22 FullAccessor, GraphParams, Hidden, QuantAccessor, StartPoint, VectorDtype,
23};
24
25pub use bf_tree::Config;
26
27use diskann::{
28 error::{RankedError, TransientError},
29 ANNError, ANNResult,
30};
31
32#[derive(Debug, Clone, Copy)]
33pub struct NoStore;
34
35#[derive(Debug, Clone)]
37pub struct ConfigError(pub bf_tree::ConfigError);
38
39impl std::fmt::Display for ConfigError {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 write!(f, "BfTree configuration error: {:?}", self.0)
42 }
43}
44
45impl std::error::Error for ConfigError {}
46
47impl From<ConfigError> for ANNError {
48 #[track_caller]
49 #[inline(never)]
50 fn from(error: ConfigError) -> ANNError {
51 ANNError::new(diskann::ANNErrorKind::IndexError, error)
52 }
53}
54
55#[derive(Debug)]
59pub enum VectorError {
60 Deleted,
62 NotFound,
64}
65
66#[derive(Debug)]
67pub struct VectorUnavailable {
68 pub id: usize,
69 pub err: VectorError,
70}
71
72impl std::fmt::Display for VectorUnavailable {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self.err {
75 VectorError::Deleted => write!(f, "vector {} was deleted", self.id),
76 VectorError::NotFound => write!(f, "vector {} not found", self.id),
77 }
78 }
79}
80
81impl TransientError<ANNError> for VectorUnavailable {
82 fn acknowledge<D>(self, _why: D)
83 where
84 D: std::fmt::Display,
85 {
86 }
88
89 fn escalate<D>(self, why: D) -> ANNError
90 where
91 D: std::fmt::Display,
92 {
93 ANNError::log_index_error(format!("{self}, escalated: {why}"))
94 }
95}
96
97pub type AccessError = RankedError<VectorUnavailable, ANNError>;
98
99pub(crate) fn validate_record_size(
102 provider_name: &str,
103 config: &bf_tree::Config,
104 key_size: usize,
105 value_size: usize,
106) -> ANNResult<()> {
107 let required = key_size + value_size;
108 let configured_max = config.get_cb_max_record_size();
109 if required > configured_max {
110 return Err(ANNError::log_index_error(format!(
111 "{provider_name}: cb_max_record_size ({configured_max}) is too small; \
112 a record requires {required} bytes ({key_size}-byte key + {value_size}-byte value); \
113 increase cb_max_record_size to at least {required}"
114 )));
115 }
116 Ok(())
117}
118
119#[derive(Debug, Clone)]
121#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
122pub struct ContextMetrics {
123 pub spawns: usize,
124 pub clones: usize,
125}
126
127#[cfg(test)]
132pub(crate) struct TestCallCount {
133 count: std::sync::atomic::AtomicUsize,
134}
135
136#[cfg(test)]
137impl TestCallCount {
138 pub fn new() -> Self {
139 Self {
140 count: std::sync::atomic::AtomicUsize::new(0),
141 }
142 }
143
144 pub fn enabled() -> bool {
145 true
146 }
147
148 pub fn increment(&self) {
149 self.count
150 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
151 }
152
153 pub fn get(&self) -> usize {
154 self.count.load(std::sync::atomic::Ordering::Relaxed)
155 }
156}
157
158#[cfg(not(test))]
159#[allow(dead_code)]
160pub(crate) struct TestCallCount {}
161
162#[cfg(not(test))]
163#[allow(dead_code)]
164impl TestCallCount {
165 pub fn new() -> Self {
166 Self {}
167 }
168
169 pub fn enabled() -> bool {
170 false
171 }
172
173 pub fn increment(&self) {}
174
175 pub fn get(&self) -> usize {
176 0
177 }
178}
179
180impl Default for TestCallCount {
181 fn default() -> Self {
182 Self::new()
183 }
184}
185
186#[expect(
193 clippy::disallowed_methods,
194 reason = "this is the allowed way to call this method"
195)]
196fn bftree_insert(tree: &bf_tree::BfTree, key: &[u8], value: &[u8]) -> Result<(), InsertError> {
197 match tree.insert(key, value) {
198 bf_tree::LeafInsertResult::Success => Ok(()),
199 bf_tree::LeafInsertResult::InvalidKV(s) => Err(InsertError(s)),
200 }
201}
202
203#[derive(Debug)]
204pub struct InsertError(String);
205
206impl std::fmt::Display for InsertError {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 write!(f, "insert into a `bftree` failed: {}", self.0)
209 }
210}
211
212impl std::error::Error for InsertError {}
213
214impl From<InsertError> for ANNError {
215 #[track_caller]
216 fn from(error: InsertError) -> Self {
217 ANNError::new(diskann::ANNErrorKind::IndexError, error)
218 }
219}