use crate::{db::DBInner, ffi, ffi_util::to_cpath, Error, DB};
use libc::{c_int, c_uchar};
use std::path::Path;
pub struct BackupEngineInfo {
pub timestamp: i64,
pub backup_id: u32,
pub size: u64,
pub num_files: u32,
}
pub struct BackupEngine {
inner: *mut ffi::rocksdb_backup_engine_t,
}
pub struct BackupEngineOptions {
inner: *mut ffi::rocksdb_options_t,
}
pub struct RestoreOptions {
inner: *mut ffi::rocksdb_restore_options_t,
}
impl BackupEngine {
pub fn open<P: AsRef<Path>>(opts: &BackupEngineOptions, path: P) -> Result<Self, Error> {
let cpath = to_cpath(path)?;
let be: *mut ffi::rocksdb_backup_engine_t;
unsafe {
be = ffi_try!(ffi::rocksdb_backup_engine_open(opts.inner, cpath.as_ptr()));
}
if be.is_null() {
return Err(Error::new("Could not initialize backup engine.".to_owned()));
}
Ok(Self { inner: be })
}
pub fn create_new_backup(&mut self, db: &DB) -> Result<(), Error> {
self.create_new_backup_flush(db, false)
}
pub fn create_new_backup_flush(
&mut self,
db: &DB,
flush_before_backup: bool,
) -> Result<(), Error> {
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_create_new_backup_flush(
self.inner,
db.inner.inner(),
c_uchar::from(flush_before_backup),
));
Ok(())
}
}
pub fn purge_old_backups(&mut self, num_backups_to_keep: usize) -> Result<(), Error> {
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_purge_old_backups(
self.inner,
num_backups_to_keep as u32,
));
Ok(())
}
}
pub fn restore_from_latest_backup<D: AsRef<Path>, W: AsRef<Path>>(
&mut self,
db_dir: D,
wal_dir: W,
opts: &RestoreOptions,
) -> Result<(), Error> {
let c_db_dir = to_cpath(db_dir)?;
let c_wal_dir = to_cpath(wal_dir)?;
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_restore_db_from_latest_backup(
self.inner,
c_db_dir.as_ptr(),
c_wal_dir.as_ptr(),
opts.inner,
));
}
Ok(())
}
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 c_db_dir = to_cpath(db_dir)?;
let c_wal_dir = to_cpath(wal_dir)?;
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(())
}
pub fn verify_backup(&self, backup_id: u32) -> Result<(), Error> {
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_verify_backup(
self.inner, backup_id,
));
}
Ok(())
}
pub fn get_backup_info(&self) -> Vec<BackupEngineInfo> {
unsafe {
let i = ffi::rocksdb_backup_engine_get_backup_info(self.inner);
let n = ffi::rocksdb_backup_engine_info_count(i);
let mut info = Vec::with_capacity(n as usize);
for index in 0..n {
info.push(BackupEngineInfo {
timestamp: ffi::rocksdb_backup_engine_info_timestamp(i, index),
backup_id: ffi::rocksdb_backup_engine_info_backup_id(i, index),
size: ffi::rocksdb_backup_engine_info_size(i, index),
num_files: ffi::rocksdb_backup_engine_info_number_files(i, index),
});
}
ffi::rocksdb_backup_engine_info_destroy(i);
info
}
}
}
impl BackupEngineOptions {
}
impl RestoreOptions {
pub fn set_keep_log_files(&mut self, keep_log_files: bool) {
unsafe {
ffi::rocksdb_restore_options_set_keep_log_files(
self.inner,
c_int::from(keep_log_files),
);
}
}
}
impl Default for BackupEngineOptions {
fn default() -> Self {
unsafe {
let opts = ffi::rocksdb_options_create();
assert!(!opts.is_null(), "Could not create RocksDB backup options");
Self { inner: opts }
}
}
}
impl Default for RestoreOptions {
fn default() -> Self {
unsafe {
let opts = ffi::rocksdb_restore_options_create();
assert!(!opts.is_null(), "Could not create RocksDB restore options");
Self { inner: opts }
}
}
}
impl Drop for BackupEngine {
fn drop(&mut self) {
unsafe {
ffi::rocksdb_backup_engine_close(self.inner);
}
}
}
impl Drop for BackupEngineOptions {
fn drop(&mut self) {
unsafe {
ffi::rocksdb_options_destroy(self.inner);
}
}
}
impl Drop for RestoreOptions {
fn drop(&mut self) {
unsafe {
ffi::rocksdb_restore_options_destroy(self.inner);
}
}
}