Skip to main content

mito2/memtable/
version.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Memtable version.
16
17use std::sync::Arc;
18use std::time::Duration;
19
20use common_time::Timestamp;
21use smallvec::SmallVec;
22use store_api::metadata::RegionMetadataRef;
23use store_api::storage::SequenceNumber;
24
25use crate::error::Result;
26use crate::memtable::time_partition::TimePartitionsRef;
27use crate::memtable::{MemtableId, MemtableRef};
28
29pub(crate) type SmallMemtableVec = SmallVec<[MemtableRef; 2]>;
30
31/// A version of current memtables in a region.
32#[derive(Debug, Clone)]
33pub(crate) struct MemtableVersion {
34    /// Mutable memtable.
35    pub(crate) mutable: TimePartitionsRef,
36    /// Immutable memtables.
37    ///
38    /// We only allow one flush job per region but if a flush job failed, then we
39    /// might need to store more than one immutable memtable on the next time we
40    /// flush the region.
41    immutables: SmallMemtableVec,
42}
43
44pub(crate) type MemtableVersionRef = Arc<MemtableVersion>;
45
46impl MemtableVersion {
47    /// Returns a new [MemtableVersion] with specific mutable memtable.
48    pub(crate) fn new(mutable: TimePartitionsRef) -> MemtableVersion {
49        MemtableVersion {
50            mutable,
51            immutables: SmallVec::new(),
52        }
53    }
54
55    /// Immutable memtables.
56    pub(crate) fn immutables(&self) -> &[MemtableRef] {
57        &self.immutables
58    }
59
60    /// Lists mutable and immutable memtables.
61    pub(crate) fn list_memtables(&self) -> Vec<MemtableRef> {
62        let mut mems = Vec::with_capacity(self.immutables.len() + self.mutable.num_partitions());
63        self.mutable.list_memtables(&mut mems);
64        mems.extend_from_slice(&self.immutables);
65        mems
66    }
67
68    /// Returns a sequence lower bound covering mutable and immutable memtables.
69    /// Empty memtables impose no compaction barrier, including newly forked ones.
70    pub(crate) fn min_sequence(&self) -> Option<SequenceNumber> {
71        self.list_memtables()
72            .iter()
73            .filter(|mem| !mem.is_empty())
74            .map(|mem| mem.min_sequence())
75            .min()
76    }
77
78    /// Returns a new [MemtableVersion] which switches the old mutable memtable to immutable
79    /// memtable.
80    ///
81    /// It will switch to use the `time_window` provided.
82    ///
83    /// Returns `None` if the mutable memtable is empty.
84    pub(crate) fn freeze_mutable(
85        &self,
86        metadata: &RegionMetadataRef,
87        time_window: Option<Duration>,
88    ) -> Result<Option<MemtableVersion>> {
89        if self.mutable.is_empty() {
90            // No need to freeze the mutable memtable, but we need to check the time window.
91            if Some(self.mutable.part_duration()) == time_window {
92                // If the time window is the same, we don't need to update it.
93                return Ok(None);
94            }
95
96            // Update the time window.
97            let mutable = self.mutable.new_with_part_duration(time_window, None);
98            common_telemetry::debug!(
99                "Freeze empty memtable, update partition duration from {:?} to {:?}",
100                self.mutable.part_duration(),
101                time_window
102            );
103            return Ok(Some(MemtableVersion {
104                mutable: Arc::new(mutable),
105                immutables: self.immutables.clone(),
106            }));
107        }
108
109        // Marks the mutable memtable as immutable so it can free the memory usage from our
110        // soft limit.
111        self.mutable.freeze()?;
112        // Fork the memtable.
113        if Some(self.mutable.part_duration()) != time_window {
114            common_telemetry::debug!(
115                "Fork memtable, update partition duration from {:?}, to {:?}",
116                self.mutable.part_duration(),
117                time_window
118            );
119        }
120        let mutable = Arc::new(self.mutable.fork(metadata, time_window));
121
122        let mut immutables =
123            SmallVec::with_capacity(self.immutables.len() + self.mutable.num_partitions());
124        immutables.extend(self.immutables.iter().cloned());
125        // Pushes the mutable memtable to immutable list.
126        self.mutable.list_memtables_to_small_vec(&mut immutables);
127
128        Ok(Some(MemtableVersion {
129            mutable,
130            immutables,
131        }))
132    }
133
134    /// Removes memtables by ids from immutable memtables.
135    pub(crate) fn remove_memtables(&mut self, ids: &[MemtableId]) {
136        self.immutables = self
137            .immutables
138            .iter()
139            .filter(|mem| !ids.contains(&mem.id()))
140            .cloned()
141            .collect();
142    }
143
144    /// Returns the memory usage of the mutable memtable.
145    pub(crate) fn mutable_usage(&self) -> usize {
146        self.mutable.memory_usage()
147    }
148
149    /// Returns the memory usage of the immutable memtables.
150    pub(crate) fn immutables_usage(&self) -> usize {
151        self.immutables
152            .iter()
153            .map(|mem| mem.stats().estimated_bytes)
154            .sum()
155    }
156
157    /// Returns the number of rows in memtables.
158    pub(crate) fn num_rows(&self) -> u64 {
159        self.immutables
160            .iter()
161            .map(|mem| mem.stats().num_rows as u64)
162            .sum::<u64>()
163            + self.mutable.num_rows()
164    }
165
166    /// Returns the time range covered by the memtables, if any hold data.
167    pub(crate) fn time_range(&self) -> Option<(Timestamp, Timestamp)> {
168        let mut mutables = Vec::new();
169        self.mutable.list_memtables(&mut mutables);
170        self.immutables
171            .iter()
172            .chain(mutables.iter())
173            .filter_map(|mem| mem.stats().time_range())
174            .reduce(|(min_a, max_a), (min_b, max_b)| (min_a.min(min_b), max_a.max(max_b)))
175    }
176
177    /// Returns true if the memtable version is empty.
178    ///
179    /// The version is empty when mutable memtable is empty and there is no
180    /// immutable memtables.
181    pub(crate) fn is_empty(&self) -> bool {
182        self.mutable.is_empty() && self.immutables.is_empty()
183    }
184}