use super::{state::ChunkCount, TestDB};
use crate::{size::ByteSize, tests::util::size_bytes};
impl TestDB {
pub async fn compact<Bytes: AsRef<[u8]>>(
&mut self,
data_file_ids: Option<Vec<&str>>,
freed_bytes: Vec<Bytes>,
) -> Result<(), String> {
let mut compacted_free_bytes = 0;
macro_rules! compact_data_file {
($data_file_id:expr, $data_file:expr) => {
let freed_bytes = $data_file.write().await.compact().await.map_err(|err| {
format!("Failed to compact DataFile {} \n {err:?}", $data_file_id)
})?;
compacted_free_bytes += freed_bytes;
let ByteSize {
free_bytes: data_file_free_bytes,
..
} = self
.test_state
.data_file_byte_size_map
.entry($data_file_id.to_string())
.or_default();
let ChunkCount { free, .. } = self
.test_state
.data_file_chunk_count_map
.entry($data_file_id)
.or_default();
*free -= freed_bytes / self.chunk_size;
*data_file_free_bytes -= freed_bytes;
};
}
if let Some(data_file_ids) = data_file_ids {
let data_files = self.block_db.data_files.read().await.clone();
for data_file_id in data_file_ids {
compact_data_file!(
data_file_id.to_string(),
data_files
.get(data_file_id)
.ok_or(format!("Failed to get DataFile {data_file_id} to compact"))?
);
}
} else {
for (data_file_id, data_file) in self.block_db.data_files.read().await.clone() {
compact_data_file!(data_file_id, data_file);
}
}
let ByteSize {
free_bytes: block_db_free_bytes,
..
} = &mut self.test_state.block_db_byte_size;
*block_db_free_bytes -= compacted_free_bytes;
let compacted_bytes = freed_bytes
.iter()
.map(|bytes| size_bytes(bytes.as_ref(), self.chunk_size))
.sum::<usize>();
if compacted_bytes != compacted_free_bytes {
return Err(format!(
"{compacted_bytes} != {compacted_free_bytes} \n Invalid total compacted bytes size"
));
}
self.test_state
.assert_against_block_db(&self.block_db)
.await
}
}