use crate::{
encryption::EncryptionProvider,
file::{CURRENT_VERSION_FILE, fsync_directory, rewrite_atomic},
fs::{Fs, SyncMode},
manifest_blocks::{current_digest, writer::ManifestArchiveWriter},
runtime_config::RuntimeConfig,
version::Version,
};
use byteorder::{LittleEndian, WriteBytesExt};
use std::{path::Path, sync::Arc};
pub fn persist_version(
folder: &Path,
version: &Version,
comparator_name: &str,
fs: &dyn Fs,
runtime: Arc<RuntimeConfig>,
encryption: Option<Arc<dyn EncryptionProvider>>,
sync_mode: SyncMode,
) -> crate::Result<()> {
if comparator_name.len() > crate::comparator::MAX_COMPARATOR_NAME_BYTES {
return Err(crate::Error::from(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!(
"comparator name is {} bytes (max {})",
comparator_name.len(),
crate::comparator::MAX_COMPARATOR_NAME_BYTES,
),
)));
}
log::trace!(
"Persisting version {} in {}",
version.id(),
folder.display(),
);
let path = folder.join(format!("v{}", version.id()));
let mut writer = ManifestArchiveWriter::create(&path, fs, runtime, encryption, sync_mode)?;
version.encode_into(&mut writer, comparator_name)?;
let footer = writer.finish()?;
fsync_directory(folder, fs, sync_mode)?;
let checksum = current_digest::compute(version.id(), &footer)?;
let mut current_file_content = vec![];
current_file_content.write_u64::<LittleEndian>(version.id())?;
current_file_content.write_u128::<LittleEndian>(checksum)?;
current_file_content.write_u8(0)?;
rewrite_atomic(
&folder.join(CURRENT_VERSION_FILE),
¤t_file_content,
fs,
sync_mode,
)?;
Ok(())
}