mz_row_spine/
arc_batch.rs1use std::sync::Arc;
28
29use differential_dataflow::trace::implementations::merge_batcher::Sealer;
30use differential_dataflow::trace::implementations::spine_fueled::{Merger, SpineBatch};
31use differential_dataflow::trace::{Builder, Cursor, Navigable};
32use timely::progress::frontier::AntichainRef;
33
34pub struct ArcBatch<B>(pub Arc<B>);
39
40impl<B> Clone for ArcBatch<B> {
45 fn clone(&self) -> Self {
46 ArcBatch(Arc::clone(&self.0))
47 }
48}
49
50impl<B> ArcBatch<B> {
51 pub fn new(batch: B) -> Self {
53 ArcBatch(Arc::new(batch))
54 }
55}
56
57impl<B> std::ops::Deref for ArcBatch<B> {
58 type Target = B;
59 fn deref(&self) -> &B {
60 &self.0
61 }
62}
63
64impl<B: Navigable> Navigable for ArcBatch<B> {
65 type Cursor = ArcBatchCursor<B::Cursor>;
66 fn cursor(&self) -> Self::Cursor {
67 ArcBatchCursor::new(<B as Navigable>::cursor(&self.0))
70 }
71}
72
73impl<B: SpineBatch> SpineBatch for ArcBatch<B> {
74 type Time = B::Time;
75 type Merger = ArcMerger<B>;
76 fn len(&self) -> usize {
77 self.0.len()
78 }
79}
80
81pub struct ArcBatchCursor<C> {
83 cursor: C,
84}
85
86impl<C> ArcBatchCursor<C> {
87 fn new(cursor: C) -> Self {
88 ArcBatchCursor { cursor }
89 }
90}
91
92impl<C: Cursor> Cursor for ArcBatchCursor<C> {
93 type Storage = ArcBatch<C::Storage>;
94
95 type Key<'a> = C::Key<'a>;
96 type ValOwn = C::ValOwn;
97 type Val<'a> = C::Val<'a>;
98 type Time = C::Time;
99 type TimeGat<'a> = C::TimeGat<'a>;
100 type Diff = C::Diff;
101 type DiffGat<'a> = C::DiffGat<'a>;
102 type KeyContainer = C::KeyContainer;
103 type ValContainer = C::ValContainer;
104 type TimeContainer = C::TimeContainer;
105 type DiffContainer = C::DiffContainer;
106
107 #[inline]
108 fn key_valid(&self, storage: &Self::Storage) -> bool {
109 self.cursor.key_valid(&storage.0)
110 }
111 #[inline]
112 fn val_valid(&self, storage: &Self::Storage) -> bool {
113 self.cursor.val_valid(&storage.0)
114 }
115
116 #[inline]
117 fn key<'a>(&self, storage: &'a Self::Storage) -> Self::Key<'a> {
118 self.cursor.key(&storage.0)
119 }
120 #[inline]
121 fn val<'a>(&self, storage: &'a Self::Storage) -> Self::Val<'a> {
122 self.cursor.val(&storage.0)
123 }
124
125 #[inline]
126 fn get_key<'a>(&self, storage: &'a Self::Storage) -> Option<Self::Key<'a>> {
127 self.cursor.get_key(&storage.0)
128 }
129 #[inline]
130 fn get_val<'a>(&self, storage: &'a Self::Storage) -> Option<Self::Val<'a>> {
131 self.cursor.get_val(&storage.0)
132 }
133
134 #[inline]
135 fn map_times<L: FnMut(Self::TimeGat<'_>, Self::DiffGat<'_>)>(
136 &mut self,
137 storage: &Self::Storage,
138 logic: L,
139 ) {
140 self.cursor.map_times(&storage.0, logic)
141 }
142
143 #[inline]
144 fn step_key(&mut self, storage: &Self::Storage) {
145 self.cursor.step_key(&storage.0)
146 }
147 #[inline]
148 fn seek_key(&mut self, storage: &Self::Storage, key: Self::Key<'_>) {
149 self.cursor.seek_key(&storage.0, key)
150 }
151
152 #[inline]
153 fn step_val(&mut self, storage: &Self::Storage) {
154 self.cursor.step_val(&storage.0)
155 }
156 #[inline]
157 fn seek_val(&mut self, storage: &Self::Storage, val: Self::Val<'_>) {
158 self.cursor.seek_val(&storage.0, val)
159 }
160
161 #[inline]
162 fn rewind_keys(&mut self, storage: &Self::Storage) {
163 self.cursor.rewind_keys(&storage.0)
164 }
165 #[inline]
166 fn rewind_vals(&mut self, storage: &Self::Storage) {
167 self.cursor.rewind_vals(&storage.0)
168 }
169}
170
171pub struct ArcBuilder<B> {
173 builder: B,
174}
175
176impl<B: Default> Default for ArcBuilder<B> {
177 fn default() -> Self {
178 ArcBuilder {
179 builder: B::default(),
180 }
181 }
182}
183
184impl<B: Builder> Builder for ArcBuilder<B> {
185 type Input = B::Input;
186 type Time = B::Time;
187 type Output = ArcBatch<B::Output>;
188 fn push(&mut self, input: &mut Self::Input) {
189 self.builder.push(input)
190 }
191 fn done(self) -> Option<ArcBatch<B::Output>> {
192 self.builder.done().map(ArcBatch::new)
193 }
194}
195
196impl<C, B: Sealer<C>> Sealer<C> for ArcBuilder<B> {
197 type Output = ArcBatch<B::Output>;
198 fn seal(chain: &mut Vec<C>) -> Option<Self::Output> {
199 B::seal(chain).map(ArcBatch::new)
200 }
201}
202
203impl<B: Builder + mz_timely_util::columnar::chunk::ChainState>
204 mz_timely_util::columnar::chunk::ChainState for ArcBuilder<B>
205{
206 type State = B::State;
207
208 fn wants_bodies() -> bool {
209 B::wants_bodies()
210 }
211
212 fn observe(state: &mut Self::State, input: &Self::Input) {
213 B::observe(state, input)
214 }
215
216 fn observe_records(state: &mut Self::State, records: usize) {
217 B::observe_records(state, records)
218 }
219
220 fn from_state(state: Self::State) -> Self {
221 ArcBuilder {
222 builder: B::from_state(state),
223 }
224 }
225}
226
227pub struct ArcMerger<B: SpineBatch> {
229 merger: B::Merger,
230}
231
232impl<B: SpineBatch> Merger<ArcBatch<B>> for ArcMerger<B> {
233 fn new(
234 source1: &ArcBatch<B>,
235 source2: &ArcBatch<B>,
236 compaction_frontier: AntichainRef<B::Time>,
237 ) -> Self {
238 ArcMerger {
239 merger: B::Merger::new(&source1.0, &source2.0, compaction_frontier),
240 }
241 }
242 fn work(&mut self, source1: &ArcBatch<B>, source2: &ArcBatch<B>, fuel: &mut isize) {
243 self.merger.work(&source1.0, &source2.0, fuel)
244 }
245 fn done(self) -> Option<ArcBatch<B>> {
246 self.merger.done().map(ArcBatch::new)
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use differential_dataflow::batcher::{Batcher, Extract};
253 use differential_dataflow::trace::Navigable;
254 use differential_dataflow::trace::cursor::Cursor;
255 use timely::progress::Antichain;
256
257 use crate::ArcOrdValBatcher;
258
259 #[mz_ore::test]
268 fn arc_batch_reads_from_other_thread() {
269 fn assert_send_sync<T: Send + Sync>(_: &T) {}
270
271 let mut batcher = ArcOrdValBatcher::<u64, u64, usize, i64>::new(None, 0);
272 let mut updates: Vec<((u64, u64), usize, i64)> = vec![((1, 2), 0, 1), ((2, 3), 1, 1)];
273 batcher.insert(&mut updates);
274 let (batch, _frontier) = batcher.extract(Antichain::from_elem(2).borrow());
275 let batch = batch.expect("updates were pushed, so the batch is non-empty");
276
277 assert_send_sync(&batch);
278
279 let read = std::thread::spawn(move || {
280 let mut cursor = batch.cursor();
281 cursor.to_vec(&batch, |k| *k, |v| *v)
282 })
283 .join()
284 .expect("reader thread panicked");
285
286 assert_eq!(read, vec![((1, 2), vec![(0, 1)]), ((2, 3), vec![(1, 1)])]);
287 }
288}