1use std::sync::{Arc, RwLock};
27use std::time::Duration;
28
29use common_telemetry::info;
30use store_api::metadata::RegionMetadataRef;
31use store_api::storage::{RegionId, SequenceNumber};
32
33use crate::error::Result;
34use crate::manifest::action::{RegionEdit, TruncateKind};
35use crate::memtable::time_partition::TimePartitions;
36use crate::memtable::version::{MemtableVersion, MemtableVersionRef};
37use crate::memtable::{MemtableBuilderRef, MemtableId};
38use crate::region::options::RegionOptions;
39use crate::sst::file::FileMeta;
40use crate::sst::file_purger::FilePurgerRef;
41use crate::sst::version::{SstVersion, SstVersionRef};
42use crate::wal::EntryId;
43
44#[derive(Debug)]
49pub(crate) struct VersionControl {
50 data: RwLock<VersionControlData>,
51}
52
53impl VersionControl {
54 pub(crate) fn new(version: Version) -> VersionControl {
56 let (flushed_sequence, flushed_entry_id) =
58 (version.flushed_sequence, version.flushed_entry_id);
59 VersionControl {
60 data: RwLock::new(VersionControlData {
61 version: Arc::new(version),
62 last_sequence: flushed_sequence,
63 committed_sequence: flushed_sequence,
64 last_entry_id: flushed_entry_id,
65 is_dropped: false,
66 }),
67 }
68 }
69
70 pub(crate) fn region_id(&self) -> RegionId {
72 self.data.read().unwrap().version.metadata.region_id
73 }
74
75 pub(crate) fn current(&self) -> VersionControlData {
77 self.data.read().unwrap().clone()
78 }
79
80 pub(crate) fn update_last_sequence(&self, seq: SequenceNumber) {
82 let mut data = self.data.write().unwrap();
83 data.last_sequence = data.last_sequence.max(seq);
84 }
85
86 pub(crate) fn set_committed_sequence(&self, seq: SequenceNumber) {
88 let mut data = self.data.write().unwrap();
89 data.committed_sequence = data.committed_sequence.max(seq);
90 data.last_sequence = data.last_sequence.max(data.committed_sequence);
91 }
92
93 pub(crate) fn set_sequence_and_entry_id(&self, seq: SequenceNumber, entry_id: EntryId) {
95 let mut data = self.data.write().unwrap();
96 data.committed_sequence = data.committed_sequence.max(seq);
97 data.last_sequence = data.last_sequence.max(data.committed_sequence);
98 data.last_entry_id = entry_id;
99 }
100
101 pub(crate) fn set_entry_id(&self, entry_id: EntryId) {
103 let mut data = self.data.write().unwrap();
104 data.last_entry_id = entry_id;
105 }
106
107 pub(crate) fn committed_sequence(&self) -> SequenceNumber {
109 self.data.read().unwrap().committed_sequence
110 }
111
112 pub(crate) fn freeze_mutable(&self) -> Result<()> {
114 let version = self.current().version;
115 let time_window = version.compaction_time_window;
116
117 let Some(new_memtables) = version
118 .memtables
119 .freeze_mutable(&version.metadata, time_window)?
120 else {
121 return Ok(());
122 };
123
124 let new_version = Arc::new(
126 VersionBuilder::from_version(version)
127 .memtables(new_memtables)
128 .build(),
129 );
130
131 let mut version_data = self.data.write().unwrap();
132 version_data.version = new_version;
133
134 Ok(())
135 }
136
137 pub(crate) fn alter_options(&self, options: RegionOptions) {
139 let version = self.current().version;
140 let new_version = Arc::new(
141 VersionBuilder::from_version(version)
142 .options(options)
143 .build(),
144 );
145 let mut version_data = self.data.write().unwrap();
146 version_data.version = new_version;
147 }
148
149 pub(crate) fn apply_edit(
153 &self,
154 edit: Option<RegionEdit>,
155 memtables_to_remove: &[MemtableId],
156 purger: FilePurgerRef,
157 ) {
158 let version = self.current().version;
159 let builder = VersionBuilder::from_version(version);
160 let committed_sequence = edit.as_ref().and_then(|e| e.committed_sequence);
161 let builder = if let Some(edit) = edit {
162 builder.apply_edit(edit, purger)
163 } else {
164 builder
165 };
166 let new_version = Arc::new(builder.remove_memtables(memtables_to_remove).build());
167
168 let mut version_data = self.data.write().unwrap();
169 version_data.committed_sequence = if let Some(committed_in_edit) = committed_sequence {
170 version_data.committed_sequence.max(committed_in_edit)
171 } else {
172 version_data.committed_sequence
173 };
174 version_data.last_sequence = version_data
175 .last_sequence
176 .max(version_data.committed_sequence);
177 version_data.version = new_version;
178 }
179
180 pub(crate) fn mark_dropped(&self) {
182 let version = self.current().version;
183 let memtable_builder = version.memtables.mutable.memtable_builder().clone();
184 let new_mutable =
185 Self::new_mutable_from_version(&version, version.metadata.clone(), memtable_builder);
186
187 let mut data = self.data.write().unwrap();
188 data.is_dropped = true;
189 data.version.ssts.mark_all_deleted();
190 let new_version =
192 Arc::new(VersionBuilder::new(version.metadata.clone(), new_mutable).build());
193 data.version = new_version;
194 }
195
196 pub(crate) fn alter_schema(&self, metadata: RegionMetadataRef) {
201 let version = self.current().version;
202 let memtable_builder = version.memtables.mutable.memtable_builder().clone();
203 let new_mutable =
204 Self::new_mutable_from_version(&version, metadata.clone(), memtable_builder);
205 debug_assert!(version.memtables.mutable.is_empty());
206 debug_assert!(version.memtables.immutables().is_empty());
207 let new_version = Arc::new(
208 VersionBuilder::from_version(version)
209 .metadata(metadata)
210 .memtables(MemtableVersion::new(new_mutable))
211 .build(),
212 );
213
214 let mut version_data = self.data.write().unwrap();
215 version_data.version = new_version;
216 }
217
218 pub(crate) fn alter_metadata(&self, metadata: RegionMetadataRef) {
220 let version = self.current().version;
221 let new_version = Arc::new(
222 VersionBuilder::from_version(version)
223 .metadata(metadata)
224 .build(),
225 );
226
227 let mut version_data = self.data.write().unwrap();
228 version_data.version = new_version;
229 }
230
231 pub(crate) fn alter_schema_and_format(
236 &self,
237 metadata: RegionMetadataRef,
238 options: RegionOptions,
239 memtable_builder: MemtableBuilderRef,
240 ) {
241 let version = self.current().version;
242 let new_mutable =
244 Self::new_mutable_from_version(&version, metadata.clone(), memtable_builder);
245 debug_assert!(version.memtables.mutable.is_empty());
246 debug_assert!(version.memtables.immutables().is_empty());
247 let new_version = Arc::new(
248 VersionBuilder::from_version(version)
249 .metadata(metadata)
250 .options(options)
251 .memtables(MemtableVersion::new(new_mutable))
252 .build(),
253 );
254
255 let mut version_data = self.data.write().unwrap();
256 version_data.version = new_version;
257 }
258
259 pub(crate) fn truncate(&self, truncate_kind: TruncateKind) {
261 let version = self.current().version;
262
263 match truncate_kind {
264 TruncateKind::All {
265 truncated_entry_id,
266 truncated_sequence,
267 } => {
268 let memtable_builder = version.memtables.mutable.memtable_builder().clone();
269 let new_mutable = Self::new_mutable_from_version(
270 &version,
271 version.metadata.clone(),
272 memtable_builder,
273 );
274 let new_version = Arc::new(
275 VersionBuilder::from_version(version)
276 .memtables(MemtableVersion::new(new_mutable))
277 .clear_files()
278 .flushed_entry_id(truncated_entry_id)
279 .flushed_sequence(truncated_sequence)
280 .truncated_entry_id(Some(truncated_entry_id))
281 .build(),
282 );
283
284 let mut version_data = self.data.write().unwrap();
285 version_data.version.ssts.mark_all_deleted();
286 version_data.version = new_version;
287 }
288 TruncateKind::Partial { files_to_remove } => {
289 let new_version = Arc::new(
290 VersionBuilder::from_version(version)
291 .remove_files(files_to_remove.into_iter())
292 .build(),
293 );
294
295 let mut version_data = self.data.write().unwrap();
296 version_data.version = new_version;
298 }
299 };
300 }
301
302 pub(crate) fn discard_unflushed(
304 &self,
305 discarded_entry_id: EntryId,
306 discarded_sequence: SequenceNumber,
307 ) {
308 let version = self.current().version;
309 let memtable_builder = version.memtables.mutable.memtable_builder().clone();
310 let new_mutable =
311 Self::new_mutable_from_version(&version, version.metadata.clone(), memtable_builder);
312 let new_version = Arc::new(
313 VersionBuilder::from_version(version)
314 .memtables(MemtableVersion::new(new_mutable))
315 .flushed_entry_id(discarded_entry_id)
316 .flushed_sequence(discarded_sequence)
317 .build(),
318 );
319
320 let mut version_data = self.data.write().unwrap();
321 version_data.version = new_version;
322 }
323
324 pub(crate) fn overwrite_current(&self, version: VersionRef) {
326 let mut version_data = self.data.write().unwrap();
327 version_data.last_sequence = version_data.last_sequence.max(version.flushed_sequence);
328 version_data.version = version;
329 }
330
331 fn new_mutable_from_version(
332 version: &Version,
333 metadata: RegionMetadataRef,
334 memtable_builder: MemtableBuilderRef,
335 ) -> TimePartitions {
336 TimePartitions::new(
337 metadata,
338 memtable_builder,
339 version.memtables.mutable.next_memtable_id(),
340 Some(version.memtables.mutable.part_duration()),
341 )
342 }
343}
344
345pub(crate) type VersionControlRef = Arc<VersionControl>;
346
347#[derive(Debug, Clone)]
349pub(crate) struct VersionControlData {
350 pub(crate) version: VersionRef,
352 pub(crate) last_sequence: SequenceNumber,
354 pub(crate) committed_sequence: SequenceNumber,
358 pub(crate) last_entry_id: EntryId,
362 pub(crate) is_dropped: bool,
364}
365
366impl VersionControlData {
367 pub(crate) fn series_count(&self) -> usize {
369 self.version.memtables.mutable.series_count()
370 }
371}
372
373#[derive(Clone, Debug)]
375pub(crate) struct Version {
376 pub(crate) metadata: RegionMetadataRef,
381 pub(crate) memtables: MemtableVersionRef,
385 pub(crate) ssts: SstVersionRef,
387 pub(crate) flushed_entry_id: EntryId,
389 pub(crate) flushed_sequence: SequenceNumber,
391 pub(crate) truncated_entry_id: Option<EntryId>,
395 pub(crate) compaction_time_window: Option<Duration>,
400 pub(crate) options: RegionOptions,
402}
403
404pub(crate) type VersionRef = Arc<Version>;
405
406pub(crate) struct VersionBuilder {
408 metadata: RegionMetadataRef,
409 memtables: MemtableVersionRef,
410 ssts: SstVersionRef,
411 flushed_entry_id: EntryId,
412 flushed_sequence: SequenceNumber,
413 truncated_entry_id: Option<EntryId>,
414 compaction_time_window: Option<Duration>,
415 options: RegionOptions,
416}
417
418impl VersionBuilder {
419 pub(crate) fn new(metadata: RegionMetadataRef, mutable: TimePartitions) -> Self {
421 VersionBuilder {
422 metadata: metadata.clone(),
423 memtables: Arc::new(MemtableVersion::new(mutable)),
424 ssts: Arc::new(SstVersion::new(metadata)),
425 flushed_entry_id: 0,
426 flushed_sequence: 0,
427 truncated_entry_id: None,
428 compaction_time_window: None,
429 options: RegionOptions::default(),
430 }
431 }
432
433 pub(crate) fn from_version(version: VersionRef) -> Self {
435 VersionBuilder {
436 metadata: version.metadata.clone(),
437 memtables: version.memtables.clone(),
438 ssts: version.ssts.clone(),
439 flushed_entry_id: version.flushed_entry_id,
440 flushed_sequence: version.flushed_sequence,
441 truncated_entry_id: version.truncated_entry_id,
442 compaction_time_window: version.compaction_time_window,
443 options: version.options.clone(),
444 }
445 }
446
447 pub(crate) fn memtables(mut self, memtables: MemtableVersion) -> Self {
449 self.memtables = Arc::new(memtables);
450 self
451 }
452
453 pub(crate) fn metadata(mut self, metadata: RegionMetadataRef) -> Self {
455 if !Arc::ptr_eq(&self.metadata, &metadata) {
456 Arc::make_mut(&mut self.ssts).set_metadata(metadata.clone());
457 }
458 self.metadata = metadata;
459 self
460 }
461
462 pub(crate) fn flushed_entry_id(mut self, entry_id: EntryId) -> Self {
464 self.flushed_entry_id = entry_id;
465 self
466 }
467
468 pub(crate) fn flushed_sequence(mut self, sequence: SequenceNumber) -> Self {
470 self.flushed_sequence = sequence;
471 self
472 }
473
474 pub(crate) fn truncated_entry_id(mut self, entry_id: Option<EntryId>) -> Self {
476 self.truncated_entry_id = entry_id;
477 self
478 }
479
480 pub(crate) fn compaction_time_window(mut self, window: Option<Duration>) -> Self {
482 self.compaction_time_window = window;
483 self
484 }
485
486 pub(crate) fn options(mut self, options: RegionOptions) -> Self {
488 self.options = options;
489 self
490 }
491
492 pub(crate) fn apply_edit(mut self, edit: RegionEdit, file_purger: FilePurgerRef) -> Self {
494 if let Some(entry_id) = edit.flushed_entry_id {
495 self.flushed_entry_id = self.flushed_entry_id.max(entry_id);
496 }
497 if let Some(sequence) = edit.flushed_sequence {
498 self.flushed_sequence = self.flushed_sequence.max(sequence);
499 }
500 if let Some(window) = edit.compaction_time_window {
501 self.compaction_time_window = Some(window);
502 }
503 if !edit.files_to_add.is_empty() || !edit.files_to_remove.is_empty() {
504 let mut ssts = (*self.ssts).clone();
505 ssts.add_files(file_purger, edit.files_to_add.into_iter());
506 ssts.remove_files(edit.files_to_remove.into_iter());
507 self.ssts = Arc::new(ssts);
508 }
509
510 self
511 }
512
513 pub(crate) fn remove_memtables(mut self, ids: &[MemtableId]) -> Self {
515 if !ids.is_empty() {
516 let mut memtables = (*self.memtables).clone();
517 memtables.remove_memtables(ids);
518 self.memtables = Arc::new(memtables);
519 }
520 self
521 }
522
523 pub(crate) fn add_files(
525 mut self,
526 file_purger: FilePurgerRef,
527 files: impl Iterator<Item = FileMeta>,
528 ) -> Self {
529 let mut ssts = (*self.ssts).clone();
530 ssts.add_files(file_purger, files);
531 self.ssts = Arc::new(ssts);
532
533 self
534 }
535
536 pub(crate) fn remove_files(mut self, files: impl Iterator<Item = FileMeta>) -> Self {
537 let mut ssts = (*self.ssts).clone();
538 ssts.remove_files(files);
539 self.ssts = Arc::new(ssts);
540
541 self
542 }
543
544 pub(crate) fn clear_files(mut self) -> Self {
546 self.ssts = Arc::new(SstVersion::new(self.metadata.clone()));
547 self
548 }
549
550 pub(crate) fn build(self) -> Version {
553 let compaction_time_window = self
554 .options
555 .compaction
556 .time_window()
557 .or(self.compaction_time_window);
558 if self.compaction_time_window.is_some()
559 && compaction_time_window != self.compaction_time_window
560 {
561 info!(
562 "VersionBuilder overwrites region compaction time window from {:?} to {:?}, region: {}",
563 self.compaction_time_window, compaction_time_window, self.metadata.region_id
564 );
565 }
566
567 Version {
568 metadata: self.metadata,
569 memtables: self.memtables,
570 ssts: self.ssts,
571 flushed_entry_id: self.flushed_entry_id,
572 flushed_sequence: self.flushed_sequence,
573 truncated_entry_id: self.truncated_entry_id,
574 compaction_time_window,
575 options: self.options,
576 }
577 }
578}
579
580#[cfg(test)]
581mod tests {
582 use super::*;
583 use crate::test_util::version_util::VersionControlBuilder;
584
585 #[test]
586 fn test_sequence_watermarks_are_monotonic() {
587 let builder = VersionControlBuilder::new();
588 let mut version = builder.build_version();
589 version.flushed_sequence = 8;
590 version.flushed_entry_id = 4;
591 let vc = VersionControl::new(version);
592 assert_eq!(
593 (vc.current().last_sequence, vc.committed_sequence()),
594 (8, 8)
595 );
596
597 vc.update_last_sequence(20);
598 vc.update_last_sequence(9);
599 vc.set_committed_sequence(10);
600 vc.set_committed_sequence(9);
601 assert_eq!(
602 (vc.current().last_sequence, vc.committed_sequence()),
603 (20, 10)
604 );
605 assert_eq!(vc.current().last_entry_id, 4);
606 vc.set_sequence_and_entry_id(12, 5);
607 vc.set_sequence_and_entry_id(4, 6);
608 assert_eq!(
609 (vc.current().last_sequence, vc.committed_sequence()),
610 (20, 12)
611 );
612 assert_eq!(vc.current().version.flushed_sequence, 8);
613
614 for sequence in [25, 11] {
615 vc.apply_edit(
616 Some(RegionEdit {
617 files_to_add: vec![],
618 files_to_remove: vec![],
619 timestamp_ms: None,
620 compaction_time_window: None,
621 flushed_entry_id: None,
622 flushed_sequence: None,
623 committed_sequence: Some(sequence),
624 }),
625 &[],
626 builder.file_purger(),
627 );
628 assert_eq!(
629 (vc.current().last_sequence, vc.committed_sequence()),
630 (25, 25)
631 );
632 assert_eq!(vc.current().last_entry_id, 6);
633 }
634 }
635}