diff --git a/src/lib.rs b/src/lib.rs index e99b2b8..0a032fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ use crossbeam_channel::{Receiver, Sender}; use fs4::FileExt; use log::{debug, info, trace, warn}; use std::cmp::Ordering; +use std::collections::HashMap; use std::fmt; use std::fs::{self, File}; use std::io::{Error, ErrorKind, Result}; @@ -471,6 +472,51 @@ impl Wal { pub fn clear(&mut self) -> Result<()> { self.truncate(self.first_index()) } + + /// Copy all files to the given path directory. directory should exist and be empty + pub fn copy_to_path

(&self, path: P) -> Result<()> + where + P: AsRef, + { + if fs::read_dir(path.as_ref())?.next().is_some() { + return Err(Error::new( + ErrorKind::AlreadyExists, + format!("path {:?} not empty", path.as_ref()), + )); + }; + + let open_segment_file = self.open_segment.segment.path().file_name().unwrap(); + let close_segment_files: HashMap<_, _> = self + .closed_segments + .iter() + .map(|segment| { + ( + segment.segment.path().file_name().unwrap(), + &segment.segment, + ) + }) + .collect(); + + for entry in fs::read_dir(self.path())? { + let entry = entry?; + if !entry.metadata()?.is_file() { + continue; + } + + // if file is locked by any Segment, call copy_to_path on it + let entry_file_name = entry.file_name(); + let dst_path = path.as_ref().to_owned().join(entry_file_name.clone()); + if entry_file_name == open_segment_file { + self.open_segment.segment.copy_to_path(&dst_path)?; + } else if let Some(segment) = close_segment_files.get(entry_file_name.as_os_str()) { + segment.copy_to_path(&dst_path)?; + } else { + // if file is not locked by any Segment, just copy it + fs::copy(&entry.path(), &dst_path)?; + } + } + Ok(()) + } } impl fmt::Debug for Wal { diff --git a/src/segment.rs b/src/segment.rs index 9590aa5..f0e76fb 100644 --- a/src/segment.rs +++ b/src/segment.rs @@ -643,6 +643,27 @@ impl Segment { } } } + + pub(crate) fn copy_to_path

(&self, path: P) -> Result<()> + where + P: AsRef, + { + if path.as_ref().exists() { + return Err(Error::new( + ErrorKind::AlreadyExists, + format!("Path {:?} already exists", path.as_ref()), + )); + } + + let mut other = Self::create(path, self.capacity())?; + unsafe { + other + .mmap + .as_mut_slice() + .copy_from_slice(self.mmap.as_slice()); + } + Ok(()) + } } impl fmt::Debug for Segment {