use crate::Result;
use crate::errors::PagedbError;
use crate::vfs::types::OpenMode;
use crate::vfs::{Vfs, VfsFile, read_exact_at, write_all_at};
const COPY_CHUNK_BYTES: usize = 64 * 1024;
#[must_use]
pub(crate) fn staged_image_path(main_db_path: &str) -> String {
format!("{main_db_path}.applying")
}
pub(crate) async fn clone_base_image<V: Vfs>(
vfs: &V,
base_path: &str,
staged_path: &str,
) -> Result<()> {
discard_staged_image(vfs, staged_path).await;
let mut base = vfs.open(base_path, OpenMode::Read).await?;
let total = base.len().await?;
let mut staged = vfs.open(staged_path, OpenMode::CreateOrOpen).await?;
staged.set_len(total).await?;
let mut buf = vec![0u8; COPY_CHUNK_BYTES];
let mut offset = 0u64;
while offset < total {
let want = usize::try_from(total.saturating_sub(offset))
.unwrap_or(COPY_CHUNK_BYTES)
.min(COPY_CHUNK_BYTES);
read_exact_at(&mut base, offset, &mut buf[..want]).await?;
write_all_at(&mut staged, offset, &buf[..want]).await?;
let advance = u64::try_from(want)
.map_err(|_| PagedbError::arithmetic_overflow("staged image copy offset"))?;
offset = offset.saturating_add(advance);
}
staged.sync().await
}
pub(crate) async fn discard_staged_image<V: Vfs>(vfs: &V, staged_path: &str) {
let _ = vfs.remove(staged_path).await;
}