1use std::future::Future;
16use std::iter::once;
17use std::ops::Bound;
18use std::sync::Arc;
19
20use await_tree::{InstrumentAwait, SpanExt};
21use bytes::Bytes;
22use risingwave_common::bitmap::Bitmap;
23use risingwave_common::catalog::{TableId, TableOption};
24use risingwave_common::hash::VirtualNode;
25use risingwave_common::util::epoch::{EpochPair, MAX_EPOCH, MAX_SPILL_TIMES};
26use risingwave_hummock_sdk::key::{
27 FullKey, TableKey, TableKeyRange, UserKey, is_empty_key_range, vnode_range,
28};
29use risingwave_hummock_sdk::sstable_info::SstableInfo;
30use risingwave_hummock_sdk::{EpochWithGap, HummockEpoch};
31use tracing::{Instrument, warn};
32
33use super::version::VersionUpdate;
34use crate::error::StorageResult;
35use crate::hummock::event_handler::hummock_event_handler::HummockEventSender;
36use crate::hummock::event_handler::{HummockEvent, HummockReadVersionRef, LocalInstanceGuard};
37use crate::hummock::iterator::{
38 Backward, BackwardUserIterator, ConcatIteratorInner, Forward, HummockIteratorUnion,
39 IteratorFactory, MergeIterator, UserIterator,
40};
41use crate::hummock::local_version::pinned_version::PinnedVersion;
42use crate::hummock::shared_buffer::TableMemoryMetrics;
43use crate::hummock::shared_buffer::shared_buffer_batch::{
44 SharedBufferBatch, SharedBufferBatchIterator, SharedBufferBatchOldValues, SharedBufferItem,
45 SharedBufferValue,
46};
47use crate::hummock::store::version::{HummockVersionReader, read_filter_for_version};
48use crate::hummock::utils::{
49 do_delete_sanity_check, do_insert_sanity_check, do_update_sanity_check, sanity_check_enabled,
50 wait_for_epoch,
51};
52use crate::hummock::write_limiter::WriteLimiterRef;
53use crate::hummock::{
54 BackwardSstableIterator, HummockError, MemoryLimiter, SstableIterator,
55 SstableIteratorReadOptions, SstableStoreRef,
56};
57use crate::mem_table::{KeyOp, MemTable, MemTableHummockIterator, MemTableHummockRevIterator};
58use crate::monitor::{HummockStateStoreMetrics, IterLocalMetricsGuard, StoreLocalStatistic};
59use crate::store::*;
60
61pub struct LocalHummockStorage {
64 mem_table: MemTable,
65
66 spill_offset: u16,
67 epoch: Option<EpochPair>,
68
69 table_id: TableId,
70 op_consistency_level: OpConsistencyLevel,
71 table_option: TableOption,
72
73 instance_guard: LocalInstanceGuard,
74
75 read_version: HummockReadVersionRef,
77
78 is_replicated: bool,
89
90 upload_on_flush: bool,
92
93 event_sender: HummockEventSender,
95
96 memory_limiter: Arc<MemoryLimiter>,
97
98 hummock_version_reader: HummockVersionReader,
99
100 table_memory_metrics: Arc<TableMemoryMetrics>,
101
102 write_limiter: WriteLimiterRef,
103
104 version_update_notifier_tx: Arc<tokio::sync::watch::Sender<PinnedVersion>>,
105
106 mem_table_spill_threshold: usize,
107}
108
109impl LocalHummockFlushedSnapshotReader {
110 async fn get_flushed<'a, O>(
111 hummock_version_reader: &'a HummockVersionReader,
112 read_version: &HummockReadVersionRef,
113 user_key: UserKey<Bytes>,
114 table_option: TableOption,
115 read_options: ReadOptions,
116 on_key_value_fn: impl KeyValueFn<'a, O>,
117 epoch: HummockEpoch,
118 ) -> StorageResult<Option<O>> {
119 let table_key_range = (
120 Bound::Included(user_key.table_key.clone()),
121 Bound::Included(user_key.table_key.clone()),
122 );
123
124 let (table_key_range, read_snapshot) =
125 read_filter_for_version(epoch, user_key.table_id, table_key_range, read_version)?;
126
127 if is_empty_key_range(&table_key_range) {
128 return Ok(None);
129 }
130
131 hummock_version_reader
132 .get(
133 user_key.table_key,
134 epoch,
135 user_key.table_id,
136 table_option,
137 read_options,
138 read_snapshot,
139 on_key_value_fn,
140 )
141 .await
142 }
143
144 async fn iter_flushed(
145 &self,
146 table_key_range: TableKeyRange,
147 read_options: ReadOptions,
148 epoch: HummockEpoch,
149 ) -> StorageResult<HummockStorageIterator> {
150 let (table_key_range, read_snapshot) =
151 read_filter_for_version(epoch, self.table_id, table_key_range, &self.read_version)?;
152
153 let table_key_range = table_key_range;
154
155 self.hummock_version_reader
156 .iter(
157 table_key_range,
158 epoch,
159 self.table_id,
160 self.table_option,
161 read_options,
162 read_snapshot,
163 )
164 .await
165 }
166
167 async fn rev_iter_flushed(
168 &self,
169 table_key_range: TableKeyRange,
170 read_options: ReadOptions,
171 epoch: HummockEpoch,
172 ) -> StorageResult<HummockStorageRevIterator> {
173 let (table_key_range, read_snapshot) =
174 read_filter_for_version(epoch, self.table_id, table_key_range, &self.read_version)?;
175
176 let table_key_range = table_key_range;
177
178 self.hummock_version_reader
179 .rev_iter(
180 table_key_range,
181 epoch,
182 self.table_id,
183 self.table_option,
184 read_options,
185 read_snapshot,
186 None,
187 )
188 .await
189 }
190}
191
192impl LocalHummockStorage {
193 fn epoch(&self) -> u64 {
194 self.epoch.expect("should have set the epoch").curr
195 }
196
197 fn current_epoch_with_gap(&self) -> EpochWithGap {
198 EpochWithGap::new(self.epoch(), self.spill_offset)
199 }
200
201 fn mem_table_iter(&self) -> MemTableHummockIterator<'_> {
202 MemTableHummockIterator::new(
203 &self.mem_table.buffer,
204 self.current_epoch_with_gap(),
205 self.table_id,
206 )
207 }
208
209 fn mem_table_rev_iter(&self) -> MemTableHummockRevIterator<'_> {
210 MemTableHummockRevIterator::new(
211 &self.mem_table.buffer,
212 self.current_epoch_with_gap(),
213 self.table_id,
214 )
215 }
216
217 async fn iter_all(
218 &self,
219 table_key_range: TableKeyRange,
220 epoch: u64,
221 read_options: ReadOptions,
222 ) -> StorageResult<LocalHummockStorageIterator<'_>> {
223 let (table_key_range, read_snapshot) =
224 read_filter_for_version(epoch, self.table_id, table_key_range, &self.read_version)?;
225
226 self.hummock_version_reader
227 .iter_with_memtable(
228 table_key_range,
229 epoch,
230 self.table_id,
231 self.table_option,
232 read_options,
233 read_snapshot,
234 Some(self.mem_table_iter()),
235 )
236 .await
237 }
238
239 async fn rev_iter_all(
240 &self,
241 table_key_range: TableKeyRange,
242 epoch: u64,
243 read_options: ReadOptions,
244 ) -> StorageResult<LocalHummockStorageRevIterator<'_>> {
245 let (table_key_range, read_snapshot) =
246 read_filter_for_version(epoch, self.table_id, table_key_range, &self.read_version)?;
247
248 self.hummock_version_reader
249 .rev_iter(
250 table_key_range,
251 epoch,
252 self.table_id,
253 self.table_option,
254 read_options,
255 read_snapshot,
256 Some(self.mem_table_rev_iter()),
257 )
258 .await
259 }
260}
261
262#[derive(Clone)]
263pub struct LocalHummockFlushedSnapshotReader {
264 table_id: TableId,
265 table_option: TableOption,
266 read_version: HummockReadVersionRef,
267 hummock_version_reader: HummockVersionReader,
268 epoch: HummockEpoch,
269}
270
271impl StateStoreGet for LocalHummockFlushedSnapshotReader {
272 async fn on_key_value<'a, O: Send + 'a>(
273 &'a self,
274 key: TableKey<Bytes>,
275 read_options: ReadOptions,
276 on_key_value_fn: impl KeyValueFn<'a, O>,
277 ) -> StorageResult<Option<O>> {
278 let key = UserKey::new(self.table_id, key);
279 Self::get_flushed(
280 &self.hummock_version_reader,
281 &self.read_version,
282 key,
283 self.table_option,
284 read_options,
285 on_key_value_fn,
286 self.epoch,
287 )
288 .await
289 }
290}
291
292impl StateStoreRead for LocalHummockFlushedSnapshotReader {
293 type Iter = HummockStorageIterator;
294 type RevIter = HummockStorageRevIterator;
295
296 fn read_epoch(&self) -> Option<u64> {
297 Some(self.epoch)
298 }
299
300 fn iter(
301 &self,
302 key_range: TableKeyRange,
303 read_options: ReadOptions,
304 ) -> impl Future<Output = StorageResult<Self::Iter>> + '_ {
305 self.iter_flushed(key_range, read_options, self.epoch)
306 .instrument(tracing::trace_span!("hummock_iter"))
307 }
308
309 fn rev_iter(
310 &self,
311 key_range: TableKeyRange,
312 read_options: ReadOptions,
313 ) -> impl Future<Output = StorageResult<Self::RevIter>> + '_ {
314 self.rev_iter_flushed(key_range, read_options, self.epoch)
315 .instrument(tracing::trace_span!("hummock_rev_iter"))
316 }
317}
318
319impl StateStoreGet for LocalHummockStorage {
320 async fn on_key_value<'a, O: Send + 'a>(
321 &'a self,
322 key: TableKey<Bytes>,
323 read_options: ReadOptions,
324 on_key_value_fn: impl KeyValueFn<'a, O>,
325 ) -> StorageResult<Option<O>> {
326 let key = UserKey::new(self.table_id, key);
327 match self.mem_table.buffer.get(&key.table_key) {
328 None => {
329 LocalHummockFlushedSnapshotReader::get_flushed(
330 &self.hummock_version_reader,
331 &self.read_version,
332 key,
333 self.table_option,
334 read_options,
335 on_key_value_fn,
336 self.epoch(),
337 )
338 .await
339 }
340 Some(op) => match op {
341 KeyOp::Insert(value) | KeyOp::Update((_, value)) => Ok({
342 Some(on_key_value_fn(
343 FullKey::new_with_gap_epoch(
344 self.table_id,
345 key.table_key.to_ref(),
346 self.current_epoch_with_gap(),
347 ),
348 value.as_ref(),
349 )?)
350 }),
351 KeyOp::Delete(_) => Ok(None),
352 },
353 }
354 }
355}
356
357impl LocalStateStore for LocalHummockStorage {
358 type FlushedSnapshotReader = LocalHummockFlushedSnapshotReader;
359 type Iter<'a> = LocalHummockStorageIterator<'a>;
360 type RevIter<'a> = LocalHummockStorageRevIterator<'a>;
361
362 async fn iter(
363 &self,
364 key_range: TableKeyRange,
365 read_options: ReadOptions,
366 ) -> StorageResult<Self::Iter<'_>> {
367 let (l_vnode_inclusive, r_vnode_exclusive) = vnode_range(&key_range);
368 assert_eq!(
369 r_vnode_exclusive - l_vnode_inclusive,
370 1,
371 "read range {:?} for table {} iter contains more than one vnode",
372 key_range,
373 self.table_id
374 );
375 self.iter_all(key_range.clone(), self.epoch(), read_options)
376 .await
377 }
378
379 async fn rev_iter(
380 &self,
381 key_range: TableKeyRange,
382 read_options: ReadOptions,
383 ) -> StorageResult<Self::RevIter<'_>> {
384 let (l_vnode_inclusive, r_vnode_exclusive) = vnode_range(&key_range);
385 assert_eq!(
386 r_vnode_exclusive - l_vnode_inclusive,
387 1,
388 "read range {:?} for table {} iter contains more than one vnode",
389 key_range,
390 self.table_id
391 );
392 self.rev_iter_all(key_range.clone(), self.epoch(), read_options)
393 .await
394 }
395
396 fn new_flushed_snapshot_reader(&self) -> Self::FlushedSnapshotReader {
397 assert_eq!(
398 self.table_option.retention_seconds, None,
399 "flushed snapshot reader should not work with table {} with ttl",
400 self.table_id
401 );
402 self.new_flushed_snapshot_reader_inner(MAX_EPOCH)
403 }
404
405 fn get_table_watermark(&self, vnode: VirtualNode) -> Option<Bytes> {
406 self.read_version.read().latest_watermark(vnode)
407 }
408
409 fn insert(
410 &mut self,
411 key: TableKey<Bytes>,
412 new_val: Bytes,
413 old_val: Option<Bytes>,
414 ) -> StorageResult<()> {
415 match old_val {
416 None => self.mem_table.insert(key, new_val)?,
417 Some(old_val) => self.mem_table.update(key, old_val, new_val)?,
418 };
419
420 Ok(())
421 }
422
423 fn delete(&mut self, key: TableKey<Bytes>, old_val: Bytes) -> StorageResult<()> {
424 self.mem_table.delete(key, old_val)?;
425
426 Ok(())
427 }
428
429 async fn update_vnode_bitmap(&mut self, vnodes: Arc<Bitmap>) -> StorageResult<Arc<Bitmap>> {
430 self.update_vnode_bitmap_impl(vnodes).await
431 }
432}
433
434impl StateStoreWriteEpochControl for LocalHummockStorage {
435 async fn flush(&mut self) -> StorageResult<usize> {
436 let buffer = self.mem_table.drain().into_parts();
437 let mut kv_pairs = Vec::with_capacity(buffer.len());
438 let mut old_values = if self.is_flush_old_value() {
439 Some(Vec::with_capacity(buffer.len()))
440 } else {
441 None
442 };
443 let sanity_check_flushed_snapshot_reader = if sanity_check_enabled() {
444 Some(self.new_flushed_snapshot_reader_inner(self.epoch()))
445 } else {
446 None
447 };
448 for (key, key_op) in buffer {
449 match key_op {
450 KeyOp::Insert(value) => {
454 if let Some(sanity_check_reader) = &sanity_check_flushed_snapshot_reader {
455 do_insert_sanity_check(
456 self.table_id,
457 &key,
458 &value,
459 sanity_check_reader,
460 &self.op_consistency_level,
461 )
462 .await?;
463 }
464 kv_pairs.push((key, SharedBufferValue::Insert(value)));
465 if let Some(old_values) = &mut old_values {
466 old_values.push(Bytes::new());
467 }
468 }
469 KeyOp::Delete(old_value) => {
470 if let Some(sanity_check_reader) = &sanity_check_flushed_snapshot_reader {
471 do_delete_sanity_check(
472 self.table_id,
473 &key,
474 &old_value,
475 sanity_check_reader,
476 &self.op_consistency_level,
477 )
478 .await?;
479 }
480 kv_pairs.push((key, SharedBufferValue::Delete));
481 if let Some(old_values) = &mut old_values {
482 old_values.push(old_value);
483 }
484 }
485 KeyOp::Update((old_value, new_value)) => {
486 if let Some(sanity_check_reader) = &sanity_check_flushed_snapshot_reader {
487 do_update_sanity_check(
488 self.table_id,
489 &key,
490 &old_value,
491 &new_value,
492 sanity_check_reader,
493 &self.op_consistency_level,
494 )
495 .await?;
496 }
497 kv_pairs.push((key, SharedBufferValue::Update(new_value)));
498 if let Some(old_values) = &mut old_values {
499 old_values.push(old_value);
500 }
501 }
502 }
503 }
504 self.flush_inner(kv_pairs, old_values).await
505 }
506
507 async fn try_flush(&mut self) -> StorageResult<()> {
508 if self.mem_table_spill_threshold != 0
509 && self.mem_table.kv_size.size() > self.mem_table_spill_threshold
510 {
511 if self.spill_offset < MAX_SPILL_TIMES {
512 self.flush().await?;
513 self.table_memory_metrics.mem_table_spill_counts.inc();
514 } else {
515 tracing::warn!("No mem table spill occurs, the gap epoch exceeds available range.");
516 }
517 }
518
519 Ok(())
520 }
521
522 async fn init(&mut self, options: InitOptions) -> StorageResult<()> {
523 let epoch = options.epoch;
524 wait_for_epoch(&self.version_update_notifier_tx, epoch.prev, self.table_id).await?;
525 assert_eq!(
526 self.epoch.replace(epoch),
527 None,
528 "local state store of table id {:?} is init for more than once",
529 self.table_id
530 );
531 self.read_version.write().init();
532 if !self.is_replicated {
533 self.event_sender
534 .send(HummockEvent::InitEpoch {
535 instance_id: self.instance_id(),
536 init_epoch: options.epoch.curr,
537 })
538 .map_err(|_| {
539 HummockError::other("failed to send InitEpoch. maybe shutting down")
540 })?;
541 }
542 Ok(())
543 }
544
545 fn seal_current_epoch(&mut self, next_epoch: u64, mut opts: SealCurrentEpochOptions) {
546 assert!(!self.mem_table.is_dirty());
547 if !self.is_replicated {
548 if self.upload_on_flush {
549 debug_assert_eq!(self.read_version.write().pending_imm_size(), 0);
550 } else {
551 let pending_imms = self.read_version.write().start_upload_pending_imms();
552 if !pending_imms.is_empty()
553 && self
554 .event_sender
555 .send(HummockEvent::ImmToUploader {
556 instance_id: self.instance_id(),
557 imms: pending_imms,
558 })
559 .is_err()
560 {
561 warn!("failed to send ImmToUploader during seal. maybe shutting down");
562 }
563 }
564 }
565
566 if let Some(new_level) = &opts.switch_op_consistency_level {
567 self.mem_table.op_consistency_level.update(new_level);
568 self.op_consistency_level.update(new_level);
569 }
570 let epoch = self
571 .epoch
572 .as_mut()
573 .expect("should have init epoch before seal the first epoch");
574 let prev_epoch = epoch.curr;
575 epoch.prev = prev_epoch;
576 epoch.curr = next_epoch;
577 self.spill_offset = 0;
578 assert!(
579 next_epoch > prev_epoch,
580 "new epoch {} should be greater than current epoch: {}",
581 next_epoch,
582 prev_epoch
583 );
584
585 if let Some((direction, watermarks, watermark_type)) = &mut opts.table_watermarks {
586 let mut read_version = self.read_version.write();
587 read_version.filter_regress_watermarks(watermarks);
588 if !watermarks.is_empty() {
589 read_version.update(VersionUpdate::NewTableWatermark {
590 direction: *direction,
591 epoch: prev_epoch,
592 vnode_watermarks: watermarks.clone(),
593 watermark_type: *watermark_type,
594 });
595 }
596 }
597
598 if !self.is_replicated
599 && self
600 .event_sender
601 .send(HummockEvent::LocalSealEpoch {
602 instance_id: self.instance_id(),
603 next_epoch,
604 opts,
605 })
606 .is_err()
607 {
608 warn!("failed to send LocalSealEpoch. maybe shutting down");
609 }
610 }
611}
612
613impl LocalHummockStorage {
614 async fn update_vnode_bitmap_impl(
615 &mut self,
616 vnodes: Arc<Bitmap>,
617 ) -> StorageResult<Arc<Bitmap>> {
618 wait_for_epoch(
619 &self.version_update_notifier_tx,
620 self.epoch.expect("should have init").prev,
621 self.table_id,
622 )
623 .await?;
624 assert!(!self.mem_table.is_dirty());
625 let mut read_version = self.read_version.write();
626 assert!(
627 read_version.staging().is_empty(),
628 "There is uncommitted staging data in read version table_id {:?} instance_id {:?} on vnode bitmap update",
629 self.table_id(),
630 self.instance_id()
631 );
632 Ok(read_version.update_vnode_bitmap(vnodes))
633 }
634
635 fn new_flushed_snapshot_reader_inner(
636 &self,
637 epoch: HummockEpoch,
638 ) -> LocalHummockFlushedSnapshotReader {
639 LocalHummockFlushedSnapshotReader {
640 table_id: self.table_id,
641 table_option: self.table_option,
642 read_version: self.read_version.clone(),
643 hummock_version_reader: self.hummock_version_reader.clone(),
644 epoch,
645 }
646 }
647
648 async fn flush_inner(
649 &mut self,
650 sorted_items: Vec<SharedBufferItem>,
651 old_values: Option<Vec<Bytes>>,
652 ) -> StorageResult<usize> {
653 let epoch = self.epoch();
654 let table_id = self.table_id;
655
656 self.table_memory_metrics
657 .write_batch_tuple_counts
658 .inc_by(sorted_items.len() as _);
659 let timer = self.table_memory_metrics.write_batch_duration.start_timer();
660
661 let imm_size = if !sorted_items.is_empty() {
662 let (size, old_value_size) =
663 SharedBufferBatch::measure_batch_size(&sorted_items, old_values.as_deref());
664
665 let old_values = old_values.map(|old_values| {
666 SharedBufferBatchOldValues::new(
667 old_values,
668 old_value_size,
669 self.table_memory_metrics.old_value_size.clone(),
670 )
671 });
672
673 let instance_id = self.instance_guard.instance_id;
674 let imm = SharedBufferBatch::build_shared_buffer_batch(
675 epoch,
676 self.spill_offset,
677 sorted_items,
678 old_values,
679 size,
680 table_id,
681 self.table_memory_metrics.clone(),
682 );
683 self.spill_offset += 1;
684
685 if self.is_replicated {
686 self.read_version.write().add_replicated_imm(imm);
692 } else {
693 self.write_limiter.wait_permission(self.table_id).await;
694 let limiter = &self.memory_limiter;
695 let (tracker, fast_required_memory) = match limiter.try_require_memory(size as u64)
696 {
697 Some(tracker) => (tracker, true),
698 None => {
699 warn!(
700 "blocked at requiring memory: {}, current {}",
701 size,
702 limiter.get_memory_usage()
703 );
704 self.event_sender
705 .send(HummockEvent::BufferMayFlush)
706 .expect("should be able to send");
707 let tracker = limiter
708 .require_memory(size as u64)
709 .instrument_await("hummock_require_memory".verbose())
710 .await;
711 warn!(
712 "successfully requiring memory: {}, current {}",
713 size,
714 limiter.get_memory_usage()
715 );
716 (tracker, false)
717 }
718 };
719 let mut read_version = self.read_version.write();
720 read_version.add_pending_imm(imm, tracker);
721 if self.upload_on_flush
722 || read_version.pending_imm_size() >= self.mem_table_spill_threshold
723 || !fast_required_memory
724 {
725 let imms = read_version.start_upload_pending_imms();
726 self.event_sender
727 .send(HummockEvent::ImmToUploader { instance_id, imms })
728 .map_err(|_| {
729 HummockError::other(
730 "failed to send imm to uploader. maybe shutting down",
731 )
732 })?;
733 }
734 }
735
736 size
737 } else {
738 0
739 };
740
741 timer.observe_duration();
742
743 self.table_memory_metrics
744 .write_batch_size
745 .observe(imm_size as _);
746 Ok(imm_size)
747 }
748}
749
750impl LocalHummockStorage {
751 pub fn new(
752 instance_guard: LocalInstanceGuard,
753 read_version: HummockReadVersionRef,
754 hummock_version_reader: HummockVersionReader,
755 event_sender: HummockEventSender,
756 memory_limiter: Arc<MemoryLimiter>,
757 write_limiter: WriteLimiterRef,
758 option: NewLocalOptions,
759 version_update_notifier_tx: Arc<tokio::sync::watch::Sender<PinnedVersion>>,
760 mem_table_spill_threshold: usize,
761 ) -> Self {
762 let table_memory_metrics = Arc::new(TableMemoryMetrics::new(
763 hummock_version_reader.stats(),
764 option.table_id,
765 option.fragment_id,
766 option.is_replicated,
767 ));
768 Self {
769 mem_table: MemTable::new(option.table_id, option.op_consistency_level.clone()),
770 spill_offset: 0,
771 epoch: None,
772 table_id: option.table_id,
773 op_consistency_level: option.op_consistency_level,
774 table_option: option.table_option,
775 is_replicated: option.is_replicated,
776 instance_guard,
777 read_version,
778 event_sender,
779 memory_limiter,
780 hummock_version_reader,
781 table_memory_metrics,
782 write_limiter,
783 version_update_notifier_tx,
784 mem_table_spill_threshold,
785 upload_on_flush: option.upload_on_flush,
786 }
787 }
788
789 pub fn read_version(&self) -> HummockReadVersionRef {
791 self.read_version.clone()
792 }
793
794 pub fn table_id(&self) -> TableId {
795 self.instance_guard.table_id
796 }
797
798 pub fn instance_id(&self) -> u64 {
799 self.instance_guard.instance_id
800 }
801
802 fn is_flush_old_value(&self) -> bool {
803 matches!(
804 &self.op_consistency_level,
805 OpConsistencyLevel::ConsistentOldValue {
806 is_log_store: true,
807 ..
808 }
809 )
810 }
811}
812
813pub type StagingDataIterator = MergeIterator<
814 HummockIteratorUnion<Forward, SharedBufferBatchIterator<Forward>, SstableIterator>,
815>;
816pub type StagingDataRevIterator = MergeIterator<
817 HummockIteratorUnion<Backward, SharedBufferBatchIterator<Backward>, BackwardSstableIterator>,
818>;
819pub type HummockStorageIteratorPayloadInner<'a> = MergeIterator<
820 HummockIteratorUnion<
821 Forward,
822 StagingDataIterator,
823 SstableIterator,
824 ConcatIteratorInner<SstableIterator>,
825 MemTableHummockIterator<'a>,
826 >,
827>;
828
829pub type StorageRevIteratorPayloadInner<'a> = MergeIterator<
830 HummockIteratorUnion<
831 Backward,
832 StagingDataRevIterator,
833 BackwardSstableIterator,
834 ConcatIteratorInner<BackwardSstableIterator>,
835 MemTableHummockRevIterator<'a>,
836 >,
837>;
838
839pub type HummockStorageIterator = HummockStorageIteratorInner<'static>;
840pub type HummockStorageRevIterator = HummockStorageRevIteratorInner<'static>;
841pub type LocalHummockStorageIterator<'a> = HummockStorageIteratorInner<'a>;
842pub type LocalHummockStorageRevIterator<'a> = HummockStorageRevIteratorInner<'a>;
843
844pub struct HummockStorageIteratorInner<'a> {
845 inner: UserIterator<HummockStorageIteratorPayloadInner<'a>>,
846 initial_read: bool,
847 stats_guard: IterLocalMetricsGuard,
848}
849
850impl StateStoreIter for HummockStorageIteratorInner<'_> {
851 async fn try_next(&mut self) -> StorageResult<Option<StateStoreKeyedRowRef<'_>>> {
852 let iter = &mut self.inner;
853 if !self.initial_read {
854 self.initial_read = true;
855 } else {
856 iter.next().await?;
857 }
858
859 if iter.is_valid() {
860 Ok(Some((iter.key(), iter.value())))
861 } else {
862 Ok(None)
863 }
864 }
865}
866
867impl<'a> HummockStorageIteratorInner<'a> {
868 pub fn new(
869 inner: UserIterator<HummockStorageIteratorPayloadInner<'a>>,
870 metrics: Arc<HummockStateStoreMetrics>,
871 table_id: TableId,
872 mut local_stats: StoreLocalStatistic,
873 ) -> Self {
874 local_stats.found_key = inner.is_valid();
875 local_stats.sub_iter_count = local_stats.staging_imm_iter_count
876 + local_stats.staging_sst_iter_count
877 + local_stats.overlapping_iter_count
878 + local_stats.non_overlapping_iter_count;
879 Self {
880 inner,
881 initial_read: false,
882 stats_guard: IterLocalMetricsGuard::new(metrics, table_id, local_stats),
883 }
884 }
885}
886
887impl Drop for HummockStorageIteratorInner<'_> {
888 fn drop(&mut self) {
889 self.inner
890 .collect_local_statistic(&mut self.stats_guard.local_stats);
891 }
892}
893
894#[derive(Default)]
895pub struct ForwardIteratorFactory {
896 non_overlapping_iters: Vec<ConcatIteratorInner<SstableIterator>>,
897 overlapping_iters: Vec<SstableIterator>,
898 staging_iters:
899 Vec<HummockIteratorUnion<Forward, SharedBufferBatchIterator<Forward>, SstableIterator>>,
900}
901
902impl ForwardIteratorFactory {
903 pub fn build(
904 self,
905 mem_table: Option<MemTableHummockIterator<'_>>,
906 ) -> HummockStorageIteratorPayloadInner<'_> {
907 let staging_iter = StagingDataIterator::new(self.staging_iters);
909 MergeIterator::new(
910 once(HummockIteratorUnion::First(staging_iter))
911 .chain(
912 self.overlapping_iters
913 .into_iter()
914 .map(HummockIteratorUnion::Second),
915 )
916 .chain(
917 self.non_overlapping_iters
918 .into_iter()
919 .map(HummockIteratorUnion::Third),
920 )
921 .chain(mem_table.into_iter().map(HummockIteratorUnion::Fourth)),
922 )
923 }
924}
925
926pub struct HummockStorageRevIteratorInner<'a> {
927 inner: BackwardUserIterator<StorageRevIteratorPayloadInner<'a>>,
928 initial_read: bool,
929 stats_guard: IterLocalMetricsGuard,
930}
931
932impl StateStoreIter for HummockStorageRevIteratorInner<'_> {
933 async fn try_next(&mut self) -> StorageResult<Option<StateStoreKeyedRowRef<'_>>> {
934 let iter = &mut self.inner;
935 if !self.initial_read {
936 self.initial_read = true;
937 } else {
938 iter.next().await?;
939 }
940
941 if iter.is_valid() {
942 Ok(Some((iter.key(), iter.value())))
943 } else {
944 Ok(None)
945 }
946 }
947}
948
949impl<'a> HummockStorageRevIteratorInner<'a> {
950 pub fn new(
951 inner: BackwardUserIterator<StorageRevIteratorPayloadInner<'a>>,
952 metrics: Arc<HummockStateStoreMetrics>,
953 table_id: TableId,
954 mut local_stats: StoreLocalStatistic,
955 ) -> Self {
956 local_stats.found_key = inner.is_valid();
957 local_stats.sub_iter_count = local_stats.staging_imm_iter_count
958 + local_stats.staging_sst_iter_count
959 + local_stats.overlapping_iter_count
960 + local_stats.non_overlapping_iter_count;
961 Self {
962 inner,
963 initial_read: false,
964 stats_guard: IterLocalMetricsGuard::new(metrics, table_id, local_stats),
965 }
966 }
967}
968
969impl Drop for HummockStorageRevIteratorInner<'_> {
970 fn drop(&mut self) {
971 self.inner
972 .collect_local_statistic(&mut self.stats_guard.local_stats);
973 }
974}
975
976impl IteratorFactory for ForwardIteratorFactory {
977 type Direction = Forward;
978 type SstableIteratorType = SstableIterator;
979
980 fn add_batch_iter(&mut self, batch: SharedBufferBatch) {
981 self.staging_iters
982 .push(HummockIteratorUnion::First(batch.into_forward_iter()));
983 }
984
985 fn add_staging_sst_iter(&mut self, iter: Self::SstableIteratorType) {
986 self.staging_iters.push(HummockIteratorUnion::Second(iter));
987 }
988
989 fn add_overlapping_sst_iter(&mut self, iter: Self::SstableIteratorType) {
990 self.overlapping_iters.push(iter);
991 }
992
993 fn add_concat_sst_iter(
994 &mut self,
995 tables: Vec<SstableInfo>,
996 sstable_store: SstableStoreRef,
997 read_options: Arc<SstableIteratorReadOptions>,
998 ) {
999 self.non_overlapping_iters
1000 .push(ConcatIteratorInner::<Self::SstableIteratorType>::new(
1001 tables,
1002 sstable_store,
1003 read_options,
1004 ));
1005 }
1006}
1007
1008#[derive(Default)]
1009pub struct BackwardIteratorFactory {
1010 non_overlapping_iters: Vec<ConcatIteratorInner<BackwardSstableIterator>>,
1011 overlapping_iters: Vec<BackwardSstableIterator>,
1012 staging_iters: Vec<
1013 HummockIteratorUnion<
1014 Backward,
1015 SharedBufferBatchIterator<Backward>,
1016 BackwardSstableIterator,
1017 >,
1018 >,
1019}
1020
1021impl BackwardIteratorFactory {
1022 pub fn build(
1023 self,
1024 mem_table: Option<MemTableHummockRevIterator<'_>>,
1025 ) -> StorageRevIteratorPayloadInner<'_> {
1026 let staging_iter = StagingDataRevIterator::new(self.staging_iters);
1028 MergeIterator::new(
1029 once(HummockIteratorUnion::First(staging_iter))
1030 .chain(
1031 self.overlapping_iters
1032 .into_iter()
1033 .map(HummockIteratorUnion::Second),
1034 )
1035 .chain(
1036 self.non_overlapping_iters
1037 .into_iter()
1038 .map(HummockIteratorUnion::Third),
1039 )
1040 .chain(mem_table.into_iter().map(HummockIteratorUnion::Fourth)),
1041 )
1042 }
1043}
1044
1045impl IteratorFactory for BackwardIteratorFactory {
1046 type Direction = Backward;
1047 type SstableIteratorType = BackwardSstableIterator;
1048
1049 fn add_batch_iter(&mut self, batch: SharedBufferBatch) {
1050 self.staging_iters
1051 .push(HummockIteratorUnion::First(batch.into_backward_iter()));
1052 }
1053
1054 fn add_staging_sst_iter(&mut self, iter: Self::SstableIteratorType) {
1055 self.staging_iters.push(HummockIteratorUnion::Second(iter));
1056 }
1057
1058 fn add_overlapping_sst_iter(&mut self, iter: Self::SstableIteratorType) {
1059 self.overlapping_iters.push(iter);
1060 }
1061
1062 fn add_concat_sst_iter(
1063 &mut self,
1064 mut tables: Vec<SstableInfo>,
1065 sstable_store: SstableStoreRef,
1066 read_options: Arc<SstableIteratorReadOptions>,
1067 ) {
1068 tables.reverse();
1069 self.non_overlapping_iters
1070 .push(ConcatIteratorInner::<Self::SstableIteratorType>::new(
1071 tables,
1072 sstable_store,
1073 read_options,
1074 ));
1075 }
1076}