Skip to main content

dbsp/trace/ord/fallback/
val_batch.rs

1use std::fmt::{Display, Formatter};
2use std::sync::Arc;
3
4use super::utils::{copy_to_builder, pick_merge_destination};
5use crate::storage::buffer_cache::CacheStats;
6use crate::storage::file::{FilterKind, FilterStats, TouchedWindowCount};
7use crate::trace::cursor::{DelegatingCursor, PushCursor};
8use crate::trace::ord::file::val_batch::FileValBuilder;
9use crate::trace::ord::vec::val_batch::VecValBuilder;
10use crate::trace::{BatchLocation, GroupFilter, MergeCursor};
11use crate::{
12    DBData, DBWeight, NumEntries, Timestamp,
13    dynamic::{
14        DataTrait, DynDataTyped, DynPair, DynVec, DynWeightedPairs, Erase, Factory, WeightTrait,
15    },
16    storage::file::reader::Error as ReaderError,
17    trace::{
18        Batch, BatchFactories, BatchReader, BatchReaderFactories, Builder, FileValBatch,
19        FileValBatchFactories, Filter, VecValBatch, VecValBatchFactories, WeightedItem,
20        ord::merge_batcher::MergeBatcher,
21    },
22};
23use derive_more::Debug;
24use feldera_storage::{FileReader, StoragePath};
25use rand::Rng;
26use rkyv::{Archive, Archived, Deserialize, Fallible, Serialize, ser::Serializer};
27use size_of::SizeOf;
28
29pub struct FallbackValBatchFactories<K, V, T, R>
30where
31    K: DataTrait + ?Sized,
32    V: DataTrait + ?Sized,
33    T: Timestamp,
34    R: WeightTrait + ?Sized,
35{
36    file: FileValBatchFactories<K, V, T, R>,
37    vec: VecValBatchFactories<K, V, T, R>,
38}
39
40impl<K, V, T, R> Clone for FallbackValBatchFactories<K, V, T, R>
41where
42    K: DataTrait + ?Sized,
43    V: DataTrait + ?Sized,
44    T: Timestamp,
45    R: WeightTrait + ?Sized,
46{
47    fn clone(&self) -> Self {
48        Self {
49            file: self.file.clone(),
50            vec: self.vec.clone(),
51        }
52    }
53}
54
55impl<K, V, T, R> BatchReaderFactories<K, V, T, R> for FallbackValBatchFactories<K, V, T, R>
56where
57    K: DataTrait + ?Sized,
58    V: DataTrait + ?Sized,
59    T: Timestamp,
60    R: WeightTrait + ?Sized,
61{
62    fn new<KType, VType, RType>() -> Self
63    where
64        KType: DBData + Erase<K>,
65        VType: DBData + Erase<V>,
66        RType: DBWeight + Erase<R>,
67    {
68        Self {
69            file: FileValBatchFactories::new::<KType, VType, RType>(),
70            vec: VecValBatchFactories::new::<KType, VType, RType>(),
71        }
72    }
73
74    fn key_factory(&self) -> &'static dyn Factory<K> {
75        self.file.key_factory()
76    }
77
78    fn keys_factory(&self) -> &'static dyn Factory<DynVec<K>> {
79        self.file.keys_factory()
80    }
81
82    fn val_factory(&self) -> &'static dyn Factory<V> {
83        self.file.val_factory()
84    }
85
86    fn weight_factory(&self) -> &'static dyn Factory<R> {
87        self.file.weight_factory()
88    }
89}
90
91impl<K, V, T, R> BatchFactories<K, V, T, R> for FallbackValBatchFactories<K, V, T, R>
92where
93    K: DataTrait + ?Sized,
94    V: DataTrait + ?Sized,
95    T: Timestamp,
96    R: WeightTrait + ?Sized,
97{
98    fn item_factory(&self) -> &'static dyn Factory<DynPair<K, V>> {
99        self.file.item_factory()
100    }
101
102    fn weighted_item_factory(&self) -> &'static dyn Factory<WeightedItem<K, V, R>> {
103        self.file.weighted_item_factory()
104    }
105
106    fn weighted_items_factory(&self) -> &'static dyn Factory<DynWeightedPairs<DynPair<K, V>, R>> {
107        self.file.weighted_items_factory()
108    }
109
110    fn weighted_vals_factory(&self) -> &'static dyn Factory<DynWeightedPairs<V, R>> {
111        self.file.weighted_vals_factory()
112    }
113
114    fn time_diffs_factory(
115        &self,
116    ) -> Option<&'static dyn Factory<DynWeightedPairs<DynDataTyped<T>, R>>> {
117        self.file.time_diffs_factory()
118    }
119}
120
121/// An immutable collection of update tuples, from a contiguous interval of
122/// logical times.
123#[derive(Debug, SizeOf)]
124pub struct FallbackValBatch<K, V, T, R>
125where
126    K: DataTrait + ?Sized,
127    V: DataTrait + ?Sized,
128    T: Timestamp,
129    R: WeightTrait + ?Sized,
130{
131    #[size_of(skip)]
132    #[debug(skip)]
133    factories: FallbackValBatchFactories<K, V, T, R>,
134    inner: Inner<K, V, T, R>,
135}
136
137#[derive(Debug, SizeOf)]
138enum Inner<K, V, T, R>
139where
140    K: DataTrait + ?Sized,
141    V: DataTrait + ?Sized,
142    T: Timestamp,
143    R: WeightTrait + ?Sized,
144{
145    Vec(VecValBatch<K, V, T, R>),
146    File(FileValBatch<K, V, T, R>),
147}
148
149impl<K, V, T, R> Clone for FallbackValBatch<K, V, T, R>
150where
151    K: DataTrait + ?Sized,
152    V: DataTrait + ?Sized,
153    T: Timestamp,
154    R: WeightTrait + ?Sized,
155{
156    fn clone(&self) -> Self {
157        Self {
158            factories: self.factories.clone(),
159            inner: match &self.inner {
160                Inner::Vec(vec) => Inner::Vec(vec.clone()),
161                Inner::File(file) => Inner::File(file.clone()),
162            },
163        }
164    }
165}
166
167impl<K, V, T, R> NumEntries for FallbackValBatch<K, V, T, R>
168where
169    K: DataTrait + ?Sized,
170    V: DataTrait + ?Sized,
171    T: Timestamp,
172    R: WeightTrait + ?Sized,
173{
174    const CONST_NUM_ENTRIES: Option<usize> = None;
175
176    #[inline]
177    fn num_entries_shallow(&self) -> usize {
178        match &self.inner {
179            Inner::Vec(vec) => vec.num_entries_shallow(),
180            Inner::File(file) => file.num_entries_shallow(),
181        }
182    }
183
184    #[inline]
185    fn num_entries_deep(&self) -> usize {
186        match &self.inner {
187            Inner::Vec(vec) => vec.num_entries_deep(),
188            Inner::File(file) => file.num_entries_deep(),
189        }
190    }
191}
192
193impl<K, V, T, R> Display for FallbackValBatch<K, V, T, R>
194where
195    K: DataTrait + ?Sized,
196    V: DataTrait + ?Sized,
197    T: Timestamp,
198    R: WeightTrait + ?Sized,
199{
200    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
201        match &self.inner {
202            Inner::Vec(vec) => Display::fmt(vec, f),
203            Inner::File(file) => Display::fmt(file, f),
204        }
205    }
206}
207
208impl<K, V, T, R> BatchReader for FallbackValBatch<K, V, T, R>
209where
210    K: DataTrait + ?Sized,
211    V: DataTrait + ?Sized,
212    T: Timestamp,
213    R: WeightTrait + ?Sized,
214{
215    type Factories = FallbackValBatchFactories<K, V, T, R>;
216    type Key = K;
217    type Val = V;
218    type Time = T;
219    type R = R;
220
221    type Cursor<'s> = DelegatingCursor<'s, K, V, T, R>;
222
223    fn factories(&self) -> Self::Factories {
224        self.factories.clone()
225    }
226
227    fn cursor(&self) -> Self::Cursor<'_> {
228        DelegatingCursor(match &self.inner {
229            Inner::Vec(vec) => Box::new(vec.cursor()),
230            Inner::File(file) => Box::new(file.cursor()),
231        })
232    }
233
234    fn push_cursor(
235        &self,
236    ) -> Box<dyn PushCursor<Self::Key, Self::Val, Self::Time, Self::R> + Send + '_> {
237        match &self.inner {
238            Inner::Vec(vec) => vec.push_cursor(),
239            Inner::File(file) => file.push_cursor(),
240        }
241    }
242
243    fn merge_cursor(
244        &self,
245        key_filter: Option<Filter<Self::Key>>,
246        value_filter: Option<GroupFilter<Self::Val>>,
247    ) -> Box<dyn MergeCursor<Self::Key, Self::Val, Self::Time, Self::R> + Send + '_> {
248        match &self.inner {
249            Inner::Vec(vec) => vec.merge_cursor(key_filter, value_filter),
250            Inner::File(file) => file.merge_cursor(key_filter, value_filter),
251        }
252    }
253
254    fn key_count(&self) -> usize {
255        match &self.inner {
256            Inner::Vec(vec) => vec.key_count(),
257            Inner::File(file) => file.key_count(),
258        }
259    }
260
261    fn len(&self) -> usize {
262        match &self.inner {
263            Inner::Vec(vec) => vec.len(),
264            Inner::File(file) => file.len(),
265        }
266    }
267
268    #[inline]
269    fn approximate_byte_size(&self) -> usize {
270        match &self.inner {
271            Inner::File(file) => file.approximate_byte_size(),
272            Inner::Vec(vec) => vec.approximate_byte_size(),
273        }
274    }
275
276    #[inline]
277    fn membership_filter_stats(&self) -> FilterStats {
278        match &self.inner {
279            Inner::File(file) => file.membership_filter_stats(),
280            Inner::Vec(vec) => vec.membership_filter_stats(),
281        }
282    }
283
284    #[inline]
285    fn membership_filter_kind(&self) -> FilterKind {
286        match &self.inner {
287            Inner::File(file) => file.membership_filter_kind(),
288            Inner::Vec(vec) => vec.membership_filter_kind(),
289        }
290    }
291
292    #[inline]
293    fn range_filter_stats(&self) -> FilterStats {
294        match &self.inner {
295            Inner::File(file) => file.range_filter_stats(),
296            Inner::Vec(vec) => vec.range_filter_stats(),
297        }
298    }
299
300    #[inline]
301    fn location(&self) -> BatchLocation {
302        match &self.inner {
303            Inner::Vec(vec) => vec.location(),
304            Inner::File(file) => file.location(),
305        }
306    }
307
308    fn cache_stats(&self) -> CacheStats {
309        match &self.inner {
310            Inner::Vec(vec) => vec.cache_stats(),
311            Inner::File(file) => file.cache_stats(),
312        }
313    }
314
315    fn sample_keys<RG>(&self, rng: &mut RG, sample_size: usize, output: &mut DynVec<Self::Key>)
316    where
317        RG: Rng,
318    {
319        match &self.inner {
320            Inner::Vec(vec) => vec.sample_keys(rng, sample_size, output),
321            Inner::File(file) => file.sample_keys(rng, sample_size, output),
322        }
323    }
324}
325
326impl<K, V, T, R> Batch for FallbackValBatch<K, V, T, R>
327where
328    K: DataTrait + ?Sized,
329    V: DataTrait + ?Sized,
330    T: Timestamp,
331    R: WeightTrait + ?Sized,
332{
333    type Timed<T2: Timestamp> = FallbackValBatch<K, V, T2, R>;
334    type Batcher = MergeBatcher<Self>;
335    type Builder = FallbackValBuilder<K, V, T, R>;
336
337    fn persisted(&self) -> Option<Self> {
338        match &self.inner {
339            Inner::Vec(vec) => {
340                let mut file = FileValBuilder::with_capacity(
341                    &self.factories.file,
342                    self.key_count(),
343                    self.len(),
344                );
345                copy_to_builder(&mut file, vec.cursor());
346                Some(Self {
347                    inner: Inner::File(file.done()),
348                    factories: self.factories.clone(),
349                })
350            }
351            Inner::File(_) => None,
352        }
353    }
354
355    fn file_reader(&self) -> Option<Arc<dyn FileReader>> {
356        match &self.inner {
357            Inner::Vec(vec) => vec.file_reader(),
358            Inner::File(file) => file.file_reader(),
359        }
360    }
361
362    fn from_path(factories: &Self::Factories, path: &StoragePath) -> Result<Self, ReaderError> {
363        Ok(Self {
364            factories: factories.clone(),
365            inner: Inner::File(FileValBatch::<K, V, T, R>::from_path(
366                &factories.file,
367                path,
368            )?),
369        })
370    }
371
372    fn key_bounds(&self) -> Option<(&Self::Key, &Self::Key)> {
373        match &self.inner {
374            Inner::File(file) => file.key_bounds(),
375            Inner::Vec(vec) => vec.key_bounds(),
376        }
377    }
378
379    fn negative_weight_count(&self) -> Option<u64> {
380        match &self.inner {
381            Inner::File(file) => file.negative_weight_count(),
382            Inner::Vec(vec) => vec.negative_weight_count(),
383        }
384    }
385
386    fn touched_window_count(&self) -> TouchedWindowCount {
387        match &self.inner {
388            Inner::File(file) => file.touched_window_count(),
389            Inner::Vec(vec) => vec.touched_window_count(),
390        }
391    }
392}
393
394/// A builder for creating layers from unsorted update tuples.
395#[derive(SizeOf)]
396pub struct FallbackValBuilder<K, V, T, R>
397where
398    K: DataTrait + ?Sized,
399    V: DataTrait + ?Sized,
400    T: Timestamp,
401    R: WeightTrait + ?Sized,
402{
403    #[size_of(skip)]
404    factories: FallbackValBatchFactories<K, V, T, R>,
405    inner: BuilderInner<K, V, T, R>,
406}
407
408#[derive(SizeOf)]
409enum BuilderInner<K, V, T, R>
410where
411    K: DataTrait + ?Sized,
412    V: DataTrait + ?Sized,
413    T: Timestamp,
414    R: WeightTrait + ?Sized,
415{
416    Vec(VecValBuilder<K, V, T, R, usize>),
417    File(FileValBuilder<K, V, T, R>),
418}
419
420impl<K, V, T, R> Builder<FallbackValBatch<K, V, T, R>> for FallbackValBuilder<K, V, T, R>
421where
422    Self: SizeOf,
423    K: DataTrait + ?Sized,
424    V: DataTrait + ?Sized,
425    T: Timestamp,
426    R: WeightTrait + ?Sized,
427{
428    fn with_capacity_in_location(
429        factories: &FallbackValBatchFactories<K, V, T, R>,
430        key_capacity: usize,
431        value_capacity: usize,
432        location: Option<BatchLocation>,
433    ) -> Self {
434        Self {
435            factories: factories.clone(),
436            inner: BuilderInner::Vec(VecValBuilder::with_capacity_in_location(
437                &factories.vec,
438                key_capacity,
439                value_capacity,
440                location,
441            )),
442        }
443    }
444
445    fn for_merge<'a, B, I>(
446        factories: &FallbackValBatchFactories<K, V, T, R>,
447        batches: I,
448        location: Option<BatchLocation>,
449    ) -> Self
450    where
451        B: Batch<Key = K, Val = V, Time = T, R = R>,
452        I: IntoIterator<Item = &'a B> + Clone,
453    {
454        let key_capacity = batches.clone().into_iter().map(|b| b.key_count()).sum();
455        let value_capacity = batches.clone().into_iter().map(|b| b.len()).sum();
456        Self {
457            factories: factories.clone(),
458            inner: match pick_merge_destination(batches.clone(), location) {
459                BatchLocation::Memory => BuilderInner::Vec(VecValBuilder::with_capacity(
460                    &factories.vec,
461                    key_capacity,
462                    value_capacity,
463                )),
464                BatchLocation::Storage => BuilderInner::File(FileValBuilder::for_merge(
465                    &factories.file,
466                    batches,
467                    location,
468                )),
469            },
470        }
471    }
472
473    fn push_time_diff(&mut self, time: &T, weight: &R) {
474        match &mut self.inner {
475            BuilderInner::Vec(vec) => vec.push_time_diff(time, weight),
476            BuilderInner::File(file) => file.push_time_diff(time, weight),
477        }
478    }
479
480    fn push_val(&mut self, val: &V) {
481        match &mut self.inner {
482            BuilderInner::Vec(vec) => vec.push_val(val),
483            BuilderInner::File(file) => file.push_val(val),
484        }
485    }
486
487    fn push_key(&mut self, key: &K) {
488        match &mut self.inner {
489            BuilderInner::Vec(vec) => vec.push_key(key),
490            BuilderInner::File(file) => file.push_key(key),
491        }
492    }
493
494    fn push_time_diff_mut(&mut self, time: &mut T, weight: &mut R) {
495        match &mut self.inner {
496            BuilderInner::Vec(vec) => vec.push_time_diff_mut(time, weight),
497            BuilderInner::File(file) => file.push_time_diff_mut(time, weight),
498        }
499    }
500
501    fn push_val_mut(&mut self, val: &mut V) {
502        match &mut self.inner {
503            BuilderInner::Vec(vec) => vec.push_val_mut(val),
504            BuilderInner::File(file) => file.push_val_mut(val),
505        }
506    }
507
508    fn push_key_mut(&mut self, key: &mut K) {
509        match &mut self.inner {
510            BuilderInner::Vec(vec) => vec.push_key_mut(key),
511            BuilderInner::File(file) => file.push_key_mut(key),
512        }
513    }
514
515    fn push_val_diff(&mut self, val: &V, weight: &R)
516    where
517        T: PartialEq<()>,
518    {
519        match &mut self.inner {
520            BuilderInner::Vec(vec) => vec.push_val_diff(val, weight),
521            BuilderInner::File(file) => file.push_val_diff(val, weight),
522        }
523    }
524
525    fn push_val_diff_mut(&mut self, val: &mut V, weight: &mut R)
526    where
527        T: PartialEq<()>,
528    {
529        match &mut self.inner {
530            BuilderInner::Vec(vec) => vec.push_val_diff_mut(val, weight),
531            BuilderInner::File(file) => file.push_val_diff_mut(val, weight),
532        }
533    }
534
535    fn reserve(&mut self, additional: usize) {
536        match &mut self.inner {
537            BuilderInner::Vec(vec) => vec.reserve(additional),
538            BuilderInner::File(file) => file.reserve(additional),
539        }
540    }
541
542    fn done(self) -> FallbackValBatch<K, V, T, R> {
543        FallbackValBatch {
544            factories: self.factories,
545            inner: match self.inner {
546                BuilderInner::File(file) => Inner::File(file.done()),
547                BuilderInner::Vec(vec) => Inner::Vec(vec.done()),
548            },
549        }
550    }
551
552    fn num_keys(&self) -> usize {
553        match &self.inner {
554            BuilderInner::Vec(vec) => vec.num_keys(),
555            BuilderInner::File(file) => file.num_keys(),
556        }
557    }
558
559    fn num_tuples(&self) -> usize {
560        match &self.inner {
561            BuilderInner::Vec(vec) => vec.num_tuples(),
562            BuilderInner::File(file) => file.num_tuples(),
563        }
564    }
565}
566
567impl<K, V, T, R> Archive for FallbackValBatch<K, V, T, R>
568where
569    K: DataTrait + ?Sized,
570    V: DataTrait + ?Sized,
571    T: Timestamp,
572    R: WeightTrait + ?Sized,
573{
574    type Archived = ();
575    type Resolver = ();
576
577    unsafe fn resolve(&self, _pos: usize, _resolver: Self::Resolver, _out: *mut Self::Archived) {
578        unimplemented!();
579    }
580}
581
582impl<K, V, T, R, S> Serialize<S> for FallbackValBatch<K, V, T, R>
583where
584    K: DataTrait + ?Sized,
585    V: DataTrait + ?Sized,
586    T: Timestamp,
587    R: WeightTrait + ?Sized,
588    S: Serializer + ?Sized,
589{
590    fn serialize(&self, _serializer: &mut S) -> Result<Self::Resolver, S::Error> {
591        unimplemented!();
592    }
593}
594
595impl<K, V, T, R, D> Deserialize<FallbackValBatch<K, V, T, R>, D>
596    for Archived<FallbackValBatch<K, V, T, R>>
597where
598    K: DataTrait + ?Sized,
599    V: DataTrait + ?Sized,
600    T: Timestamp,
601    R: WeightTrait + ?Sized,
602    D: Fallible,
603{
604    fn deserialize(&self, _deserializer: &mut D) -> Result<FallbackValBatch<K, V, T, R>, D::Error> {
605        unimplemented!();
606    }
607}