Support restoring from a specified backup (#561)

* Support restoring from specified backup

* Refactor backup test
master
Zichao Zhang 3 years ago committed by GitHub
parent 870e135ed6
commit db407cd050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      src/backup.rs
  2. 50
      tests/test_backup.rs

@ -170,6 +170,50 @@ impl BackupEngine {
Ok(()) Ok(())
} }
/// Restore from a specified backup
///
/// The specified backup id should be passed in as an additional parameter.
pub fn restore_from_backup<D: AsRef<Path>, W: AsRef<Path>>(
&mut self,
db_dir: D,
wal_dir: W,
opts: &RestoreOptions,
backup_id: u32,
) -> Result<(), Error> {
let db_dir = db_dir.as_ref();
let c_db_dir = if let Ok(c) = CString::new(db_dir.to_string_lossy().as_bytes()) {
c
} else {
return Err(Error::new(
"Failed to convert db_dir to CString \
when restoring from latest backup"
.to_owned(),
));
};
let wal_dir = wal_dir.as_ref();
let c_wal_dir = if let Ok(c) = CString::new(wal_dir.to_string_lossy().as_bytes()) {
c
} else {
return Err(Error::new(
"Failed to convert wal_dir to CString \
when restoring from latest backup"
.to_owned(),
));
};
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_restore_db_from_backup(
self.inner,
c_db_dir.as_ptr(),
c_wal_dir.as_ptr(),
opts.inner,
backup_id,
));
}
Ok(())
}
/// Checks that each file exists and that the size of the file matches our /// Checks that each file exists and that the size of the file matches our
/// expectations. it does not check file checksum. /// expectations. it does not check file checksum.
/// ///

@ -23,17 +23,17 @@ use rocksdb::{
use util::DBPath; use util::DBPath;
#[test] #[test]
fn backup_restore() { fn restore_from_latest() {
// create backup // create backup
let path = DBPath::new("backup_test"); let path = DBPath::new("restore_from_latest_test");
let restore_path = DBPath::new("restore_from_backup_path"); let restore_path = DBPath::new("restore_from_latest_path");
{ {
let db = DB::open_default(&path).unwrap(); let db = DB::open_default(&path).unwrap();
assert!(db.put(b"k1", b"v1111").is_ok()); assert!(db.put(b"k1", b"v1111").is_ok());
let value = db.get(b"k1"); let value = db.get(b"k1");
assert_eq!(value.unwrap().unwrap(), b"v1111"); assert_eq!(value.unwrap().unwrap(), b"v1111");
{ {
let backup_path = DBPath::new("backup_path"); let backup_path = DBPath::new("backup_path_1");
let backup_opts = BackupEngineOptions::default(); let backup_opts = BackupEngineOptions::default();
let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap(); let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();
assert!(backup_engine.create_new_backup(&db).is_ok()); assert!(backup_engine.create_new_backup(&db).is_ok());
@ -61,3 +61,45 @@ fn backup_restore() {
} }
} }
} }
#[test]
fn restore_from_backup() {
// create backup
let path = DBPath::new("restore_from_backup_test");
let restore_path = DBPath::new("restore_from_backup_path");
{
let db = DB::open_default(&path).unwrap();
assert!(db.put(b"k1", b"v1111").is_ok());
let value = db.get(b"k1");
assert_eq!(value.unwrap().unwrap(), b"v1111");
{
let backup_path = DBPath::new("backup_path_2");
let backup_opts = BackupEngineOptions::default();
let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();
assert!(backup_engine.create_new_backup(&db).is_ok());
// check backup info
let info = backup_engine.get_backup_info();
assert!(!info.is_empty());
info.iter().for_each(|i| {
assert!(backup_engine.verify_backup(i.backup_id).is_ok());
assert!(i.size > 0);
});
let backup_id = info.get(0).unwrap().backup_id;
let mut restore_option = RestoreOptions::default();
restore_option.set_keep_log_files(false); // true to keep log files
let restore_status = backup_engine.restore_from_backup(
&restore_path,
&restore_path,
&restore_option,
backup_id,
);
assert!(restore_status.is_ok());
let db_restore = DB::open_default(&restore_path).unwrap();
let value = db_restore.get(b"k1");
assert_eq!(value.unwrap().unwrap(), b"v1111");
}
}
}

Loading…
Cancel
Save