store_api/
mito_engine_options.rs1use std::collections::HashMap;
19
20pub use common_wal::options::WAL_OPTIONS_KEY;
22pub const APPEND_MODE_KEY: &str = "append_mode";
24pub const WRITE_BUFFER_SIZE_KEY: &str = "write_buffer_size";
26pub const MERGE_MODE_KEY: &str = "merge_mode";
28pub const TTL_KEY: &str = "ttl";
30pub const AUTO_FLUSH_INTERVAL_KEY: &str = "auto_flush_interval";
32pub const COMPACTION_TYPE: &str = "compaction.type";
34pub const COMPACTION_OVERRIDE: &str = "compaction.override";
36pub const COMPACTION_TYPE_TWCS: &str = "twcs";
38pub const TWCS_TRIGGER_FILE_NUM: &str = "compaction.twcs.trigger_file_num";
40pub const TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM: &str =
42 "compaction.twcs.active_window.trigger_file_num";
43pub const TWCS_ACTIVE_WINDOW_L1_MERGE_TRIGGER: &str =
45 "compaction.twcs.active_window.l1_merge_trigger";
46pub const TWCS_INACTIVE_WINDOW_TRIGGER_FILE_NUM: &str =
48 "compaction.twcs.inactive_window.trigger_file_num";
49pub const TWCS_INACTIVE_WINDOW_L1_MERGE_TRIGGER: &str =
51 "compaction.twcs.inactive_window.l1_merge_trigger";
52pub const TWCS_MAX_OUTPUT_FILE_SIZE: &str = "compaction.twcs.max_output_file_size";
54pub const TWCS_TIME_WINDOW: &str = "compaction.twcs.time_window";
56pub const TWCS_REMOTE_COMPACTION: &str = "compaction.twcs.remote_compaction";
58pub const TWCS_FALLBACK_TO_LOCAL: &str = "compaction.twcs.fallback_to_local";
60pub const MEMTABLE_TYPE: &str = "memtable.type";
62pub const MEMTABLE_BULK_MERGE_THRESHOLD: &str = "memtable.bulk.merge_threshold";
64pub const MEMTABLE_BULK_ENCODE_ROW_THRESHOLD: &str = "memtable.bulk.encode_row_threshold";
66pub const MEMTABLE_BULK_ENCODE_BYTES_THRESHOLD: &str = "memtable.bulk.encode_bytes_threshold";
68pub const MEMTABLE_BULK_MAX_MERGE_GROUPS: &str = "memtable.bulk.max_merge_groups";
70pub const MEMTABLE_PARTITION_TREE_INDEX_MAX_KEYS_PER_SHARD: &str =
72 "memtable.partition_tree.index_max_keys_per_shard";
73pub const MEMTABLE_PARTITION_TREE_DATA_FREEZE_THRESHOLD: &str =
75 "memtable.partition_tree.data_freeze_threshold";
76pub const MEMTABLE_PARTITION_TREE_FORK_DICTIONARY_BYTES: &str =
78 "memtable.partition_tree.fork_dictionary_bytes";
79pub const SKIP_WAL_KEY: &str = "skip_wal";
81pub const SST_FORMAT_KEY: &str = "sst_format";
83pub const MAX_ROW_GROUP_ROW_COUNT: &str = "max_row_group_row_count";
85pub const MAX_ROW_GROUP_ROW_COUNT_LIMIT: usize = 10 * 1024 * 1024;
87pub const PRESERVE_ROW_SEQUENCE: &str = "preserve_row_sequence";
89pub const EXPERIMENTAL_SST_FLOAT_FIELD_ENCODING: &str = "experimental_sst_float_field_encoding";
91
92#[derive(
94 Debug,
95 Default,
96 Clone,
97 Copy,
98 PartialEq,
99 Eq,
100 Hash,
101 serde::Serialize,
102 serde::Deserialize,
103 strum::EnumString,
104)]
105#[serde(rename_all = "snake_case")]
106#[strum(serialize_all = "snake_case")]
107pub enum FloatFieldEncoding {
108 #[default]
110 Default,
111 ByteStreamSplit,
113}
114#[derive(Debug, PartialEq, Eq)]
118pub struct TwcsTriggerOptionConflict {
119 pub legacy_value: String,
121 pub canonical_value: String,
123}
124
125pub fn normalize_twcs_trigger_options(
127 options: &mut HashMap<String, String>,
128) -> Result<(), TwcsTriggerOptionConflict> {
129 let Some(canonical_value) = options.get(TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM).cloned() else {
130 return Ok(());
131 };
132 if let Some(legacy_value) = options.get(TWCS_TRIGGER_FILE_NUM)
133 && legacy_value != &canonical_value
134 {
135 return Err(TwcsTriggerOptionConflict {
136 legacy_value: legacy_value.clone(),
137 canonical_value,
138 });
139 }
140
141 options.remove(TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM);
142 options.insert(TWCS_TRIGGER_FILE_NUM.to_string(), canonical_value);
143 Ok(())
144}
145
146pub fn is_mito_engine_option_key(key: &str) -> bool {
148 [
149 "ttl",
150 WRITE_BUFFER_SIZE_KEY,
151 AUTO_FLUSH_INTERVAL_KEY,
152 COMPACTION_TYPE,
153 COMPACTION_OVERRIDE,
154 TWCS_TRIGGER_FILE_NUM,
155 TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM,
156 TWCS_ACTIVE_WINDOW_L1_MERGE_TRIGGER,
157 TWCS_INACTIVE_WINDOW_TRIGGER_FILE_NUM,
158 TWCS_INACTIVE_WINDOW_L1_MERGE_TRIGGER,
159 TWCS_MAX_OUTPUT_FILE_SIZE,
160 TWCS_TIME_WINDOW,
161 TWCS_REMOTE_COMPACTION,
162 TWCS_FALLBACK_TO_LOCAL,
163 "storage",
164 "index.inverted_index.ignore_column_ids",
165 "index.inverted_index.segment_row_count",
166 WAL_OPTIONS_KEY,
167 MEMTABLE_TYPE,
168 MEMTABLE_BULK_MERGE_THRESHOLD,
169 MEMTABLE_BULK_ENCODE_ROW_THRESHOLD,
170 MEMTABLE_BULK_ENCODE_BYTES_THRESHOLD,
171 MEMTABLE_BULK_MAX_MERGE_GROUPS,
172 MEMTABLE_PARTITION_TREE_INDEX_MAX_KEYS_PER_SHARD,
173 MEMTABLE_PARTITION_TREE_DATA_FREEZE_THRESHOLD,
174 MEMTABLE_PARTITION_TREE_FORK_DICTIONARY_BYTES,
175 APPEND_MODE_KEY,
177 MERGE_MODE_KEY,
178 SST_FORMAT_KEY,
179 MAX_ROW_GROUP_ROW_COUNT,
180 PRESERVE_ROW_SEQUENCE,
181 EXPERIMENTAL_SST_FLOAT_FIELD_ENCODING,
182 ]
183 .contains(&key)
184}
185
186#[cfg(test)]
187mod tests {
188 use std::collections::HashMap;
189
190 use super::*;
191
192 #[test]
193 fn test_is_mito_engine_option_key() {
194 assert!(is_mito_engine_option_key("ttl"));
195 assert!(is_mito_engine_option_key("write_buffer_size"));
196 assert!(is_mito_engine_option_key("auto_flush_interval"));
197 assert!(is_mito_engine_option_key("compaction.type"));
198 assert!(is_mito_engine_option_key("compaction.override"));
199 assert!(is_mito_engine_option_key(
200 "compaction.twcs.trigger_file_num"
201 ));
202 assert!(is_mito_engine_option_key(
203 "compaction.twcs.active_window.trigger_file_num"
204 ));
205 assert!(is_mito_engine_option_key(
206 "compaction.twcs.active_window.l1_merge_trigger"
207 ));
208 assert!(is_mito_engine_option_key(
209 "compaction.twcs.inactive_window.trigger_file_num"
210 ));
211 assert!(is_mito_engine_option_key(
212 "compaction.twcs.inactive_window.l1_merge_trigger"
213 ));
214 assert!(is_mito_engine_option_key("compaction.twcs.time_window"));
215 assert!(is_mito_engine_option_key("storage"));
216 assert!(is_mito_engine_option_key(
217 "index.inverted_index.ignore_column_ids"
218 ));
219 assert!(is_mito_engine_option_key(
220 "index.inverted_index.segment_row_count"
221 ));
222 assert!(is_mito_engine_option_key("wal_options"));
223 assert!(is_mito_engine_option_key("memtable.type"));
224 assert!(is_mito_engine_option_key("memtable.bulk.merge_threshold"));
225 assert!(is_mito_engine_option_key(
226 "memtable.bulk.encode_row_threshold"
227 ));
228 assert!(is_mito_engine_option_key(
229 "memtable.bulk.encode_bytes_threshold"
230 ));
231 assert!(is_mito_engine_option_key("memtable.bulk.max_merge_groups"));
232 assert!(is_mito_engine_option_key(
233 "memtable.partition_tree.index_max_keys_per_shard"
234 ));
235 assert!(is_mito_engine_option_key(
236 "memtable.partition_tree.data_freeze_threshold"
237 ));
238 assert!(is_mito_engine_option_key(
239 "memtable.partition_tree.fork_dictionary_bytes"
240 ));
241 assert!(is_mito_engine_option_key("append_mode"));
242 assert!(is_mito_engine_option_key("max_row_group_row_count"));
243 assert!(is_mito_engine_option_key("preserve_row_sequence"));
244 assert!(is_mito_engine_option_key(
245 EXPERIMENTAL_SST_FLOAT_FIELD_ENCODING
246 ));
247 assert!(!is_mito_engine_option_key("foo"));
248 }
249
250 #[test]
251 fn test_float_field_encoding_values() {
252 assert_eq!(
253 "default".parse::<FloatFieldEncoding>(),
254 Ok(FloatFieldEncoding::Default)
255 );
256 assert_eq!(
257 "byte_stream_split".parse::<FloatFieldEncoding>(),
258 Ok(FloatFieldEncoding::ByteStreamSplit)
259 );
260 assert_eq!(
261 serde_json::from_str::<FloatFieldEncoding>("\"byte_stream_split\"").unwrap(),
262 FloatFieldEncoding::ByteStreamSplit
263 );
264 assert!(serde_json::from_str::<FloatFieldEncoding>("\"unknown\"").is_err());
265 }
266
267 #[test]
268 fn test_normalize_twcs_trigger_aliases_to_legacy_key() {
269 let expected = HashMap::from([(TWCS_TRIGGER_FILE_NUM.to_string(), "4".to_string())]);
270 for mut options in [
271 HashMap::from([(TWCS_TRIGGER_FILE_NUM.to_string(), "4".to_string())]),
272 HashMap::from([(
273 TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM.to_string(),
274 "4".to_string(),
275 )]),
276 HashMap::from([
277 (TWCS_TRIGGER_FILE_NUM.to_string(), "4".to_string()),
278 (
279 TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM.to_string(),
280 "4".to_string(),
281 ),
282 ]),
283 ] {
284 normalize_twcs_trigger_options(&mut options).unwrap();
285 assert_eq!(expected, options);
286 }
287 }
288
289 #[test]
290 fn test_normalize_twcs_trigger_conflicting_aliases() {
291 let mut options = HashMap::from([
292 (TWCS_TRIGGER_FILE_NUM.to_string(), "4".to_string()),
293 (
294 TWCS_ACTIVE_WINDOW_TRIGGER_FILE_NUM.to_string(),
295 "8".to_string(),
296 ),
297 ]);
298 let original = options.clone();
299
300 let error = normalize_twcs_trigger_options(&mut options).unwrap_err();
301
302 assert_eq!("4", error.legacy_value);
303 assert_eq!("8", error.canonical_value);
304 assert_eq!(original, options);
305 }
306}