reddb_server/runtime/
impl_index_integrity.rs1use super::*;
2
3#[derive(Debug)]
5pub struct IndexIntegrityFinding {
6 pub index: String,
7 pub reason: String,
8}
9
10impl RedDBRuntime {
11 pub fn verify_persisted_indexes(
18 &self,
19 collection: &str,
20 ) -> RedDBResult<Vec<IndexIntegrityFinding>> {
21 use super::index_store::IndexMethodKind;
22 let topology = self.index_store_ref().collection_topology_lock(collection);
23 let _topology = topology.read();
24 let indexes = self.index_store_ref().list_indices(collection);
25 let store = self.db().store();
26 let manager = store
27 .get_collection(collection)
28 .ok_or_else(|| RedDBError::NotFound(collection.into()))?;
29 if !store.is_paged()
30 || indexes.iter().any(|index| {
31 !matches!(index.method, IndexMethodKind::Hash | IndexMethodKind::BTree)
32 })
33 {
34 return Err(RedDBError::InvalidOperation(
35 "persisted index verification requires paged HASH/BTREE indexes".into(),
36 ));
37 }
38 let (_scratch, limit_bytes) = self.reserve_index_scan(&manager)?;
39 let mut findings = Vec::new();
40 for index in indexes {
41 let mut names = vec![index.name.clone()];
42 if index.method == IndexMethodKind::BTree && (index.columns.len() == 1 || index.unique)
43 {
44 names.push(super::paged_btree_index::equality_storage_name(&index.name));
45 }
46 for name in names {
47 if let Some(reason) =
48 store.verify_persisted_secondary_index(collection, &name, limit_bytes)?
49 {
50 findings.push(IndexIntegrityFinding {
51 index: index.name.clone(),
52 reason: format!("{name:?}: {reason}"),
53 });
54 }
55 }
56 }
57 Ok(findings)
58 }
59}