risingwave_storage/hummock/iterator/
merge_inner.rs1use std::collections::binary_heap::PeekMut;
16use std::collections::{BinaryHeap, LinkedList};
17use std::ops::{Deref, DerefMut};
18
19use risingwave_hummock_sdk::key::FullKey;
20
21use crate::hummock::HummockResult;
22use crate::hummock::iterator::{
23 DirectionEnum, HummockIterator, HummockIteratorDirection, ValueMeta,
24};
25use crate::hummock::value::HummockValue;
26use crate::monitor::StoreLocalStatistic;
27
28pub struct Node<I: HummockIterator> {
29 iter: I,
30}
31
32impl<I: HummockIterator> Eq for Node<I> where Self: PartialEq {}
33impl<I: HummockIterator> PartialOrd for Node<I>
34where
35 Self: Ord,
36{
37 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
38 Some(self.cmp(other))
39 }
40}
41
42impl<I: HummockIterator> Ord for Node<I> {
44 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
45 match I::Direction::direction() {
49 DirectionEnum::Forward => other.iter.key().cmp(&self.iter.key()),
50 DirectionEnum::Backward => self.iter.key().cmp(&other.iter.key()),
51 }
52 }
53}
54
55impl<I: HummockIterator> PartialEq for Node<I> {
56 fn eq(&self, other: &Self) -> bool {
57 self.iter.key() == other.iter.key()
58 }
59}
60
61pub struct MergeIterator<I: HummockIterator> {
63 unused_iters: LinkedList<Node<I>>,
65
66 heap: BinaryHeap<Node<I>>,
68
69 retired_stats: Option<Box<StoreLocalStatistic>>,
71}
72
73impl<I: HummockIterator> MergeIterator<I> {
74 fn collect_local_statistic_impl(&self, stats: &mut StoreLocalStatistic) {
75 if let Some(retired_stats) = &self.retired_stats {
76 stats.add(retired_stats);
77 }
78 for node in &self.heap {
79 node.iter.collect_local_statistic(stats);
80 }
81 for node in &self.unused_iters {
82 node.iter.collect_local_statistic(stats);
83 }
84 }
85}
86
87impl<I: HummockIterator> MergeIterator<I> {
88 pub fn new(iterators: impl IntoIterator<Item = I>) -> Self {
89 Self::create(iterators)
90 }
91
92 pub fn for_compactor(iterators: impl IntoIterator<Item = I>) -> Self {
93 Self::create(iterators)
94 }
95
96 fn create(iterators: impl IntoIterator<Item = I>) -> Self {
97 Self {
98 unused_iters: iterators.into_iter().map(|iter| Node { iter }).collect(),
99 heap: BinaryHeap::new(),
100 retired_stats: None,
101 }
102 }
103}
104
105impl<I: HummockIterator> MergeIterator<I>
106where
107 Node<I>: Ord,
108{
109 fn reset_heap(&mut self) {
111 self.unused_iters.extend(self.heap.drain());
112 }
113
114 fn build_heap(&mut self) {
117 assert!(self.heap.is_empty());
118
119 self.heap = self
120 .unused_iters
121 .extract_if(|i| i.iter.is_valid())
122 .collect();
123 }
124}
125
126struct PeekMutGuard<'a, T: Ord> {
141 peek: Option<PeekMut<'a, T>>,
142 unused: &'a mut LinkedList<T>,
143}
144
145impl<'a, T: Ord> PeekMutGuard<'a, T> {
146 fn peek_mut(heap: &'a mut BinaryHeap<T>, unused: &'a mut LinkedList<T>) -> Option<Self> {
149 heap.peek_mut().map(|peek| Self {
150 peek: Some(peek),
151 unused,
152 })
153 }
154
155 fn pop(mut self) -> T {
157 PeekMut::pop(self.peek.take().expect("should not be None"))
158 }
159
160 fn used(mut self) {
162 self.peek.take().expect("should not be None");
163 }
164}
165
166impl<T: Ord> Deref for PeekMutGuard<'_, T> {
167 type Target = T;
168
169 fn deref(&self) -> &Self::Target {
170 self.peek.as_ref().expect("should not be None")
171 }
172}
173
174impl<T: Ord> DerefMut for PeekMutGuard<'_, T> {
175 fn deref_mut(&mut self) -> &mut Self::Target {
176 self.peek.as_mut().expect("should not be None")
177 }
178}
179
180impl<T: Ord> Drop for PeekMutGuard<'_, T> {
181 fn drop(&mut self) {
184 if let Some(peek) = self.peek.take() {
185 tracing::debug!(
186 "PeekMut are dropped without used. May be caused by future cancellation"
187 );
188 let top = PeekMut::pop(peek);
189 self.unused.push_back(top);
190 }
191 }
192}
193
194impl<I: HummockIterator> HummockIterator for MergeIterator<I>
195where
196 Node<I>: Ord,
197{
198 type Direction = I::Direction;
199
200 async fn next(&mut self) -> HummockResult<()> {
201 let mut node =
202 PeekMutGuard::peek_mut(&mut self.heap, &mut self.unused_iters).expect("no inner iter");
203
204 match node.iter.next().await {
209 Ok(_) => {}
210 Err(e) => {
211 let node = node.pop();
215 let retired_stats = self
216 .retired_stats
217 .get_or_insert_with(|| Box::new(StoreLocalStatistic::default()));
218 node.iter.collect_local_statistic(retired_stats);
219 for node in self.heap.drain() {
220 node.iter.collect_local_statistic(retired_stats);
221 }
222 return Err(e);
223 }
224 }
225
226 if !node.iter.is_valid() {
227 let node = node.pop();
229 self.unused_iters.push_back(node);
230 } else {
231 node.used();
233 }
234
235 Ok(())
236 }
237
238 fn key(&self) -> FullKey<&[u8]> {
239 self.heap.peek().expect("no inner iter").iter.key()
240 }
241
242 fn value(&self) -> HummockValue<&[u8]> {
243 self.heap.peek().expect("no inner iter").iter.value()
244 }
245
246 fn is_valid(&self) -> bool {
247 self.heap.peek().is_some_and(|n| n.iter.is_valid())
248 }
249
250 async fn rewind(&mut self) -> HummockResult<()> {
251 self.reset_heap();
252 futures::future::try_join_all(self.unused_iters.iter_mut().map(|x| x.iter.rewind()))
253 .await?;
254 self.build_heap();
255 Ok(())
256 }
257
258 async fn seek<'a>(&'a mut self, key: FullKey<&'a [u8]>) -> HummockResult<()> {
259 self.reset_heap();
260 futures::future::try_join_all(self.unused_iters.iter_mut().map(|x| x.iter.seek(key)))
261 .await?;
262 self.build_heap();
263 Ok(())
264 }
265
266 fn collect_local_statistic(&self, stats: &mut StoreLocalStatistic) {
267 self.collect_local_statistic_impl(stats);
268 }
269
270 fn value_meta(&self) -> ValueMeta {
271 self.heap.peek().expect("no inner iter").iter.value_meta()
272 }
273}