1use std::fmt::Debug;
5use std::sync::Arc;
6
7use futures::{StreamExt, stream::FuturesUnordered};
8use rand::Rng;
9use rkyv::ser::Serializer;
10use rkyv::{Archive, Archived, Deserialize, Fallible, Serialize};
11use size_of::SizeOf;
12
13use super::SpineCursor;
14use crate::NumEntries;
15use crate::dynamic::{DynVec, Factory};
16use crate::storage::file::FilterStats;
17use crate::trace::cursor::{CursorFactory, CursorList};
18use crate::trace::{
19 Batch, BatchReader, BatchReaderFactories, Cursor, Spine, merge_batches,
20 sample_keys_from_batches,
21};
22
23pub trait WithSnapshot: Sized {
24 type Batch: Batch;
25
26 fn into_ro_snapshot(self) -> SpineSnapshot<Self::Batch> {
27 self.ro_snapshot()
28 }
29
30 fn ro_snapshot(&self) -> SpineSnapshot<Self::Batch>;
33}
34
35pub trait BatchReaderWithSnapshot:
36 BatchReader<
37 Key = <Self::Batch as BatchReader>::Key,
38 Val = <Self::Batch as BatchReader>::Val,
39 Time = <Self::Batch as BatchReader>::Time,
40 R = <Self::Batch as BatchReader>::R,
41 > + WithSnapshot
42{
43}
44
45impl<B> BatchReaderWithSnapshot for B where
46 B: BatchReader<
47 Key = <Self::Batch as BatchReader>::Key,
48 Val = <Self::Batch as BatchReader>::Val,
49 Time = <Self::Batch as BatchReader>::Time,
50 R = <Self::Batch as BatchReader>::R,
51 > + WithSnapshot
52{
53}
54
55#[derive(Clone, SizeOf)]
56pub struct SpineSnapshot<B>
57where
58 B: Batch + Send + Sync,
59{
60 batches: Vec<Arc<B>>,
61 #[size_of(skip)]
62 factories: B::Factories,
63}
64
65impl<B> WithSnapshot for SpineSnapshot<B>
66where
67 B: Batch + Send + Sync,
68{
69 type Batch = B;
70
71 fn into_ro_snapshot(self) -> SpineSnapshot<Self::Batch> {
72 self
73 }
74
75 fn ro_snapshot(&self) -> SpineSnapshot<B> {
76 self.clone()
77 }
78}
79
80impl<B> WithSnapshot for B
81where
82 B: Batch,
83{
84 type Batch = B;
85 fn into_ro_snapshot(self) -> SpineSnapshot<B> {
86 let factories = self.factories();
87
88 SpineSnapshot {
89 batches: vec![Arc::new(self)],
90 factories,
91 }
92 }
93
94 fn ro_snapshot(&self) -> SpineSnapshot<Self::Batch> {
95 SpineSnapshot {
96 batches: vec![Arc::new(self.clone())],
97 factories: self.factories(),
98 }
99 }
100}
101
102impl<B: Batch + Send + Sync> Debug for SpineSnapshot<B> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("SpineSnapshot")
105 .field("batches", &self.batches)
106 .finish()
107 }
108}
109
110impl<B> SpineSnapshot<B>
111where
112 B: Batch + Send + Sync,
113{
114 pub fn new(factories: B::Factories) -> Self {
115 Self {
116 batches: Vec::new(),
117 factories,
118 }
119 }
120
121 pub fn with_batches(factories: &B::Factories, batches: Vec<Arc<B>>) -> Self {
122 Self {
123 batches,
124 factories: factories.clone(),
125 }
126 }
127
128 pub fn extend(&mut self, other: Self) {
129 self.batches.extend(other.batches.iter().cloned())
130 }
131
132 pub fn extend_with_batches<I>(&mut self, batches: I)
133 where
134 I: IntoIterator<Item = Arc<B>>,
135 {
136 self.batches.extend(batches);
137 }
138
139 pub fn concat<'a, I>(factories: B::Factories, snapshots: I) -> Self
140 where
141 I: IntoIterator<Item = &'a Self>,
142 {
143 Self {
144 batches: snapshots
145 .into_iter()
146 .flat_map(|snapshot| snapshot.batches.iter().cloned())
147 .collect::<Vec<_>>(),
148 factories,
149 }
150 }
151
152 pub fn batches(&self) -> &[Arc<B>] {
153 &self.batches
154 }
155
156 pub fn consolidate(&self) -> B {
157 merge_batches(
158 &self.factories,
159 self.batches().iter().map(|b| b.as_ref().clone()),
160 &None,
161 &None,
162 )
163 }
164
165 pub fn into_batches(self) -> Vec<Arc<B>> {
166 self.batches
167 }
168}
169
170impl<B> From<&Spine<B>> for SpineSnapshot<B>
171where
172 B: Batch + Send + Sync,
173{
174 fn from(spine: &Spine<B>) -> Self {
175 Self {
176 batches: spine.merger.get_batches(),
177 factories: spine.factories.clone(),
178 }
179 }
180}
181
182impl<B> NumEntries for SpineSnapshot<B>
183where
184 B: Batch + Send + Sync,
185{
186 const CONST_NUM_ENTRIES: Option<usize> = None;
187
188 fn num_entries_shallow(&self) -> usize {
189 self.batches.iter().fold(0, |acc, batch| acc + batch.len())
190 }
191
192 fn num_entries_deep(&self) -> usize {
193 self.num_entries_shallow()
194 }
195}
196
197impl<B> BatchReader for SpineSnapshot<B>
198where
199 B: Batch + Send + Sync,
200{
201 type Factories = B::Factories;
202 type Key = B::Key;
203 type Val = B::Val;
204 type Time = B::Time;
205 type R = B::R;
206
207 type Cursor<'s> = SpineCursor<B>;
208
209 fn factories(&self) -> Self::Factories {
210 self.factories.clone()
211 }
212
213 fn cursor(&self) -> Self::Cursor<'_> {
214 SpineCursor::new_cursor(&self.factories, self.batches.clone())
215 }
216
217 fn key_count(&self) -> usize {
218 self.batches
219 .iter()
220 .fold(0, |acc, batch| acc + batch.key_count())
221 }
222
223 fn len(&self) -> usize {
224 self.batches.iter().fold(0, |acc, batch| acc + batch.len())
225 }
226
227 fn approximate_byte_size(&self) -> usize {
228 self.batches
229 .iter()
230 .fold(0, |acc, batch| acc + batch.approximate_byte_size())
231 }
232
233 fn membership_filter_stats(&self) -> FilterStats {
234 self.batches
235 .iter()
236 .map(|b| b.membership_filter_stats())
237 .sum()
238 }
239
240 fn range_filter_stats(&self) -> FilterStats {
241 self.batches.iter().map(|b| b.range_filter_stats()).sum()
242 }
243
244 fn sample_keys<RG>(&self, rng: &mut RG, sample_size: usize, sample: &mut DynVec<Self::Key>)
245 where
246 RG: Rng,
247 {
248 let total_keys = self
249 .batches
250 .iter()
251 .map(|batch| batch.key_count())
252 .sum::<usize>();
253 let batch_refs: Vec<_> = self.batches.iter().map(Arc::as_ref).collect();
254 sample_keys_from_batches(
255 &self.factories,
256 &batch_refs,
257 rng,
258 |batch| {
259 if sample_size == 0 || total_keys == 0 {
260 0
261 } else {
262 ((batch.key_count() as u128) * (sample_size as u128) / (total_keys as u128))
263 as usize
264 }
265 },
266 sample,
267 );
268 }
269
270 async fn fetch<K>(
271 &self,
272 keys: &K,
273 ) -> Option<Box<dyn CursorFactory<Self::Key, Self::Val, Self::Time, Self::R>>>
274 where
275 K: BatchReader<Key = Self::Key, Time = ()>,
276 {
277 Some(Box::new(
278 FetchList::new(self.batches.clone(), keys, self.factories.weight_factory()).await,
279 ))
280 }
281}
282
283pub struct FetchList<B>
284where
285 B: BatchReader,
286{
287 weight_factory: &'static dyn Factory<B::R>,
288 batches: Vec<Arc<B>>,
289 fetched: Vec<Box<dyn CursorFactory<B::Key, B::Val, B::Time, B::R>>>,
290}
291
292impl<B> FetchList<B>
293where
294 B: BatchReader,
295{
296 pub async fn new<K>(
297 inputs: Vec<Arc<B>>,
298 keys: &K,
299 weight_factory: &'static dyn Factory<B::R>,
300 ) -> Self
301 where
302 K: BatchReader<Key = B::Key, Time = ()>,
303 {
304 let mut batches = Vec::new();
305 let mut fetched = Vec::new();
306 let mut futures = inputs
307 .into_iter()
308 .map(|b| async move { (b.clone(), b.fetch(keys).await) })
309 .collect::<FuturesUnordered<_>>();
310 while let Some((batch, fetch)) = futures.next().await {
311 if let Some(fetch) = fetch {
312 fetched.push(fetch);
313 } else {
314 batches.push(batch);
315 }
316 }
317
318 Self {
319 weight_factory,
320 batches,
321 fetched,
322 }
323 }
324}
325
326impl<B> CursorFactory<B::Key, B::Val, B::Time, B::R> for FetchList<B>
327where
328 B: Batch,
329{
330 fn get_cursor<'a>(&'a self) -> Box<dyn Cursor<B::Key, B::Val, B::Time, B::R> + 'a> {
331 let cursors =
332 self.fetched
333 .iter()
334 .map(|hc| hc.get_cursor())
335 .chain(self.batches.iter().map(|b| {
336 Box::new(b.cursor()) as Box<dyn Cursor<B::Key, B::Val, B::Time, B::R>>
337 }))
338 .collect::<Vec<_>>();
339 Box::new(CursorList::new(self.weight_factory, cursors))
340 }
341}
342
343impl<B> Archive for SpineSnapshot<B>
344where
345 B: Batch + Send + Sync,
346{
347 type Archived = ();
348 type Resolver = ();
349
350 unsafe fn resolve(&self, _pos: usize, _resolver: Self::Resolver, _out: *mut Self::Archived) {
351 unimplemented!();
352 }
353}
354
355impl<B, S: Serializer + ?Sized> Serialize<S> for SpineSnapshot<B>
356where
357 B: Batch + Send + Sync,
358{
359 fn serialize(&self, _serializer: &mut S) -> Result<Self::Resolver, S::Error> {
360 unimplemented!();
361 }
362}
363
364impl<B, D: Fallible> Deserialize<SpineSnapshot<B>, D> for Archived<SpineSnapshot<B>>
365where
366 B: Batch + Send + Sync,
367{
368 fn deserialize(&self, _deserializer: &mut D) -> Result<SpineSnapshot<B>, D::Error> {
369 unimplemented!();
370 }
371}