Add copy_to to io::File trait to support copying DB files

This commit is contained in:
PThorpe92
2025-08-04 18:58:09 -04:00
parent e23637b6ad
commit 039fe22405
3 changed files with 54 additions and 0 deletions

View File

@@ -52,6 +52,43 @@ pub trait File: Send + Sync {
}
fn size(&self) -> Result<u64>;
fn truncate(&self, len: usize, c: Completion) -> Result<Completion>;
fn copy_to(&self, io: &dyn IO, path: &str) -> Result<()> {
// Open or create the destination file
let dest_file = io.open_file(path, OpenFlags::Create, false)?;
// Get the size of the source file
let file_size = self.size()? as usize;
if file_size == 0 {
return Ok(());
}
// use 1MB chunk size
const BUFFER_SIZE: usize = 1024 * 1024;
let mut pos = 0;
while pos < file_size {
let chunk_size = (file_size - pos).min(BUFFER_SIZE);
// Read from source
let read_buffer = Arc::new(RefCell::new(Buffer::allocate(chunk_size, Rc::new(|_| {}))));
let read_completion = self.pread(
pos,
Completion::new_read(read_buffer.clone(), move |_, _| {}),
)?;
// Wait for read to complete
io.wait_for_completion(read_completion)?;
// Write to destination
let write_completion =
dest_file.pwrite(pos, read_buffer, Completion::new_write(|_| {}))?;
io.wait_for_completion(write_completion)?;
pos += chunk_size;
}
let sync_completion = dest_file.sync(Completion::new_sync(|_| {}))?;
io.wait_for_completion(sync_completion)?;
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq)]

View File

@@ -1737,6 +1737,17 @@ impl Connection {
pub fn get_pager(&self) -> Rc<Pager> {
self.pager.borrow().clone()
}
/// Copy the current Database and write out to a new file
pub fn copy_db(&self, file: &str) -> Result<()> {
let io = self._db.io.clone();
let disabled = false;
// checkpoint so everything is in the DB file before copying
self.pager
.borrow_mut()
.wal_checkpoint(disabled, CheckpointMode::Truncate)?;
self.pager.borrow_mut().db_file.copy_to(&*io, file)
}
}
pub struct Statement {

View File

@@ -22,6 +22,7 @@ pub trait DatabaseStorage: Send + Sync {
fn sync(&self, c: Completion) -> Result<Completion>;
fn size(&self) -> Result<u64>;
fn truncate(&self, len: usize, c: Completion) -> Result<Completion>;
fn copy_to(&self, io: &dyn crate::IO, path: &str) -> Result<()>;
}
#[cfg(feature = "fs")]
@@ -95,6 +96,11 @@ impl DatabaseStorage for DatabaseFile {
let c = self.file.truncate(len, c)?;
Ok(c)
}
#[instrument(skip_all, level = Level::INFO)]
fn copy_to(&self, io: &dyn crate::IO, path: &str) -> Result<()> {
self.file.copy_to(io, path)
}
}
#[cfg(feature = "fs")]