1#![allow(dead_code)]
3
4use std::collections::HashSet;
5
6use serde_json::Value;
7
8use crate::index::{
9 SequenceNumber, VersionPointer,
10 bloom::BloomFilter,
11 hot::HotIndex,
12 secondary::{FullTextSidecar, JsonTrieSidecar, RoaringBitmapSidecar, SlugMap, TimeFenceIndex},
13 sparse::SparseIndex,
14};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct MvccSnapshot {
19 pub sequence: SequenceNumber,
20}
21
22impl MvccSnapshot {
23 pub fn new(sequence: SequenceNumber) -> Self {
25 Self { sequence }
26 }
27
28 pub fn open() -> Self {
30 Self {
31 sequence: SequenceNumber::MAX,
32 }
33 }
34}
35
36#[derive(Clone)]
38pub struct IndexRegistry {
39 pub hot: HotIndex,
40 pub slug: SlugMap,
41 pub time_fence: TimeFenceIndex,
42 pub roaring: RoaringBitmapSidecar,
43 pub json_trie: JsonTrieSidecar,
44 pub fts: FullTextSidecar,
45}
46
47impl IndexRegistry {
48 pub fn new(
49 hot: HotIndex,
50 slug: SlugMap,
51 time_fence: TimeFenceIndex,
52 roaring: RoaringBitmapSidecar,
53 json_trie: JsonTrieSidecar,
54 fts: FullTextSidecar,
55 ) -> Self {
56 Self {
57 hot,
58 slug,
59 time_fence,
60 roaring,
61 json_trie,
62 fts,
63 }
64 }
65}
66
67pub struct SegmentAccelerators<'a> {
69 pub sparse: Option<&'a SparseIndex>,
70 pub bloom: Option<&'a BloomFilter>,
71}
72
73impl<'a> SegmentAccelerators<'a> {
74 pub fn empty() -> Self {
75 Self {
76 sparse: None,
77 bloom: None,
78 }
79 }
80}
81
82pub struct FilterRequest<'a> {
84 pub bitmap_tags: &'a [String],
85 pub json_equals: &'a [(&'a str, &'a Value)],
86}
87
88pub fn get(
91 registry: &IndexRegistry,
92 accelerators: SegmentAccelerators<'_>,
93 key: &[u8],
94 snapshot: MvccSnapshot,
95) -> Option<VersionPointer> {
96 if let Some(pointer) = registry.hot.get_latest(key, snapshot.sequence) {
97 return Some(pointer);
98 }
99
100 if let Some(filter) = accelerators.bloom {
101 if !filter.may_contain(key) {
102 return None;
103 }
104 }
105
106 accelerators
107 .sparse
108 .and_then(|sparse| sparse.locate(key, snapshot.sequence))
109}
110
111pub fn get_by_slug(
113 registry: &IndexRegistry,
114 slug: &str,
115 snapshot: MvccSnapshot,
116) -> Option<(Vec<u8>, VersionPointer)> {
117 if let Some((key, pointer)) = registry.slug.get_latest(slug, snapshot.sequence) {
118 if let Some(latest) = registry.hot.get_latest(&key, snapshot.sequence) {
119 return Some((key, latest));
120 }
121 return Some((key, pointer));
122 }
123
124 None
125}
126
127pub fn scan_time(
129 registry: &IndexRegistry,
130 start: i64,
131 end: i64,
132 snapshot: MvccSnapshot,
133) -> Vec<(Vec<u8>, VersionPointer)> {
134 let mut results = registry
135 .time_fence
136 .scan_range(start, end, snapshot.sequence);
137
138 for (key, pointer) in results.iter_mut() {
139 if let Some(latest) = registry.hot.get_latest(key, snapshot.sequence) {
140 *pointer = latest;
141 }
142 }
143
144 results
145 .into_iter()
146 .filter(|(_, pointer)| pointer.is_visible_at(snapshot.sequence))
147 .collect()
148}
149
150pub fn filter(
152 registry: &IndexRegistry,
153 request: &FilterRequest<'_>,
154 snapshot: MvccSnapshot,
155) -> Vec<(Vec<u8>, VersionPointer)> {
156 let mut candidates: Option<HashSet<Vec<u8>>> = None;
157
158 if !request.bitmap_tags.is_empty() {
159 let keys = registry
160 .roaring
161 .intersect_keys(request.bitmap_tags, snapshot.sequence);
162 candidates = Some(keys.into_iter().collect());
163 }
164
165 for (path, value) in request.json_equals {
166 let keys = registry
167 .json_trie
168 .query_equals(path, value, snapshot.sequence);
169 let set: HashSet<Vec<u8>> = keys.into_iter().collect();
170 candidates = match candidates {
171 Some(existing) => Some(existing.intersection(&set).cloned().collect()),
172 None => Some(set),
173 };
174 if let Some(current) = &candidates {
175 if current.is_empty() {
176 return Vec::new();
177 }
178 }
179 }
180
181 let keys = match candidates {
182 Some(set) => set.into_iter().collect::<Vec<_>>(),
183 None => Vec::new(),
184 };
185
186 keys.into_iter()
187 .filter_map(|key| {
188 registry
189 .hot
190 .get_latest(&key, snapshot.sequence)
191 .filter(|pointer| pointer.is_visible_at(snapshot.sequence))
192 .map(|pointer| (key, pointer))
193 })
194 .collect()
195}
196
197pub fn search(
199 registry: &IndexRegistry,
200 query: &str,
201 snapshot: MvccSnapshot,
202) -> Vec<(Vec<u8>, VersionPointer)> {
203 let terms: Vec<String> = query
204 .split_whitespace()
205 .map(|term| term.to_lowercase())
206 .collect();
207
208 if terms.is_empty() {
209 return Vec::new();
210 }
211
212 let keys = registry.fts.search(&terms, snapshot.sequence);
213
214 keys.into_iter()
215 .filter_map(|key| {
216 registry
217 .hot
218 .get_latest(&key, snapshot.sequence)
219 .filter(|pointer| pointer.is_visible_at(snapshot.sequence))
220 .map(|pointer| (key, pointer))
221 })
222 .collect()
223}
224
225pub fn scan_prefix(
228 registry: &IndexRegistry,
229 prefix: &[u8],
230 snapshot: MvccSnapshot,
231) -> Vec<(Vec<u8>, VersionPointer)> {
232 registry
233 .hot
234 .scan_prefix(prefix, snapshot.sequence)
235 .into_iter()
236 .filter(|(_, pointer)| pointer.is_visible_at(snapshot.sequence))
237 .collect()
238}