use serde::{Deserialize, Serialize}; use crate::lsm_storage::LsmStorageState; #[derive(Debug, Clone)] pub struct SimpleLeveledCompactionOptions { pub size_ratio_percent: usize, pub level0_file_num_compaction_trigger: usize, pub max_levels: usize, } #[derive(Debug, Serialize, Deserialize)] pub struct SimpleLeveledCompactionTask { // if upper_level is `None`, then it is L0 compaction pub upper_level: Option, pub upper_level_sst_ids: Vec, pub lower_level: usize, pub lower_level_sst_ids: Vec, pub is_lower_level_bottom_level: bool, } pub struct SimpleLeveledCompactionController { options: SimpleLeveledCompactionOptions, } impl SimpleLeveledCompactionController { pub fn new(options: SimpleLeveledCompactionOptions) -> Self { Self { options } } /// Generates a compaction task. /// /// Returns `None` if no compaction needs to be scheduled. The order of SSTs in the compaction task id vector matters. pub fn generate_compaction_task( &self, _snapshot: &LsmStorageState, ) -> Option { unimplemented!() } /// Apply the compaction result. /// /// The compactor will call this function with the compaction task and the list of SST ids generated. This function applies the /// result and generates a new LSM state. The functions should only change `l0_sstables` and `levels` without changing memtables /// and `sstables` hash map. Though there should only be one thread running compaction jobs, you should think about the case /// where an L0 SST gets flushed while the compactor generates new SSTs, and with that in mind, you should do some sanity checks /// in your implementation. pub fn apply_compaction_result( &self, _snapshot: &LsmStorageState, _task: &SimpleLeveledCompactionTask, _output: &[usize], ) -> (LsmStorageState, Vec) { unimplemented!() } }