use std::sync::Arc;
use tessarikv_format::{ManifestEdit, TableMeta, TableRef};
use super::Compactions;
use super::pick::Pick;
use crate::db::flush_job::table_path;
use crate::db::installer::Flusher;
use crate::db::view::TableFile;
use crate::{Error, Result};
impl Compactions {
pub(super) async fn commit(
&mut self,
flusher: &mut Flusher,
keyspace: u32,
pick: &Pick,
outputs: Vec<TableFile>,
) -> Result<()> {
let moved = outputs.is_empty() && pick.is_move();
let added: Vec<TableFile> = if moved {
let current = flusher.view.load();
let level = u8::try_from(pick.output_level).map_err(|_| Error::CompactionFailed)?;
current
.files(keyspace)
.filter(|file| pick.inputs.iter().any(|input| input.id == file.meta.id))
.map(|file| TableFile {
meta: Arc::new(TableMeta {
level,
..(*file.meta).clone()
}),
..file.clone()
})
.collect()
} else {
outputs
};
let edit = ManifestEdit {
next_file: Some(flusher.numbers.bound()),
added: added.iter().map(|file| (*file.meta).clone()).collect(),
removed: pick
.inputs
.iter()
.chain(&pick.overlaps)
.map(|table| TableRef {
keyspace: table.keyspace,
level: table.level,
id: table.id,
})
.collect(),
..ManifestEdit::default()
};
let mut manifest = flusher.manifest.take().ok_or(Error::CompactionFailed)?;
let (manifest, appended) = tokio::task::spawn_blocking(move || {
let appended = manifest.append(&edit);
(manifest, appended)
})
.await
.map_err(|_| Error::CompactionFailed)?;
flusher.manifest = Some(manifest);
appended.map_err(|_| Error::CompactionFailed)?;
let removed: Vec<u64> = pick
.inputs
.iter()
.chain(&pick.overlaps)
.map(|table| table.id)
.collect();
let current = flusher.view.load_full();
if !moved {
self.obsolete.extend(
current
.files(keyspace)
.filter(|file| removed.contains(&file.meta.id))
.map(|file| {
(
Arc::downgrade(&file.blocks),
file.meta.id,
table_path(&flusher.dir, file.meta.id),
)
}),
);
}
flusher.view.store(Arc::new(
current.after_compaction(keyspace, &removed, added),
));
Ok(())
}
}