Added basic support for backups.

master
Alexander Regueiro 8 years ago
parent 75622d3660
commit d28eba2ff5
  1. 5
      librocksdb-sys/src/test.rs
  2. 100
      src/backup.rs
  3. 49
      src/lib.rs
  4. 67
      src/rocksdb.rs
  5. 7
      src/rocksdb_options.rs

@ -41,11 +41,10 @@ fn internal() {
let rustpath = "_rust_rocksdb_internaltest";
let cpath = CString::new(rustpath).unwrap();
let cpath_ptr = cpath.as_ptr();
let mut err: *mut c_char = ptr::null_mut();
let err_ptr: *mut *mut c_char = &mut err;
let db = rocksdb_open(opts, cpath_ptr as *const _, err_ptr);
let db = rocksdb_open(opts, cpath.as_ptr() as *const _, err_ptr);
if !err.is_null() {
println!("failed to open rocksdb: {}", error_message(err));
}
@ -80,7 +79,7 @@ fn internal() {
rocksdb_readoptions_destroy(readopts);
assert!(err.is_null());
rocksdb_close(db);
rocksdb_destroy_db(opts, cpath_ptr as *const _, err_ptr);
rocksdb_destroy_db(opts, cpath.as_ptr() as *const _, err_ptr);
assert!(err.is_null());
}
}

@ -0,0 +1,100 @@
// Copyright 2016 Alex Regueiro
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
use std::ffi::CString;
use std::path::{Path};
use libc::{uint32_t};
use {DB, Error};
use ffi;
pub struct BackupEngine {
inner: *mut ffi::rocksdb_backup_engine_t,
}
pub struct BackupEngineOptions {
inner: *mut ffi::rocksdb_options_t,
}
impl BackupEngine {
/// Open a backup engine with the specified options.
pub fn open<P: AsRef<Path>>(opts: &BackupEngineOptions, path: P) -> Result<BackupEngine, Error> {
let path = path.as_ref();
let cpath = match CString::new(path.to_string_lossy().as_bytes()) {
Ok(c) => c,
Err(_) => {
return Err(Error::new("Failed to convert path to CString \
when opening backup engine"
.to_owned()))
}
};
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(BackupEngine {
inner: be,
})
}
fn create_new_backup(&mut self, db: &DB) -> Result<(), Error> {
unsafe {
ffi_try!(ffi::rocksdb_backup_engine_create_new_backup(self.inner, db.inner));
Ok(())
}
}
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 uint32_t));
Ok(())
}
}
}
impl Default for BackupEngineOptions {
fn default() -> BackupEngineOptions {
unsafe {
let opts = ffi::rocksdb_options_create();
if opts.is_null() {
panic!("Could not create backup options".to_owned());
}
BackupEngineOptions { 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);
}
}
}

@ -37,15 +37,60 @@ extern crate librocksdb_sys as ffi;
#[macro_use]
mod ffi_util;
pub mod backup;
mod comparator;
pub mod merge_operator;
mod rocksdb;
mod rocksdb_options;
pub use rocksdb::{DB, DBCompactionStyle, DBCompressionType, DBIterator, DBRecoveryMode, DBVector,
Direction, Error, IteratorMode, Snapshot, WriteBatch, new_bloom_filter};
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::path::{PathBuf};
pub use merge_operator::MergeOperands;
pub use rocksdb::{DBCompactionStyle, DBCompressionType, DBIterator, DBRecoveryMode, DBVector,
Direction, IteratorMode, Snapshot, WriteBatch, new_bloom_filter};
/// A RocksDB database.
pub struct DB {
inner: *mut ffi::rocksdb_t,
cfs: BTreeMap<String, *mut ffi::rocksdb_column_family_handle_t>,
path: PathBuf,
}
#[derive(Debug, PartialEq)]
pub struct Error {
message: String,
}
impl Error {
fn new(message: String) -> Error {
Error { message: message }
}
pub fn to_string(self) -> String {
self.into()
}
}
impl From<Error> for String {
fn from(e: Error) -> String {
e.message
}
}
impl error::Error for Error {
fn description(&self) -> &str {
&self.message
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.message.fmt(formatter)
}
}
/// For configuring block-based file storage.
pub struct BlockBasedOptions {

@ -14,19 +14,18 @@
//
use std::collections::BTreeMap;
use std::error;
use std::ffi::CString;
use std::fmt;
use std::fs;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::path::{Path};
use std::ptr;
use std::slice;
use std::str;
use libc::{self, c_char, c_int, c_uchar, c_void, size_t};
use {Options, WriteOptions};
use {DB, Error, Options, WriteOptions};
use ffi;
pub fn new_bloom_filter(bits: c_int) -> *mut ffi::rocksdb_filterpolicy_t {
@ -37,13 +36,6 @@ pub fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t {
unsafe { ffi::rocksdb_cache_create_lru(capacity) }
}
/// A RocksDB database.
pub struct DB {
inner: *mut ffi::rocksdb_t,
cfs: BTreeMap<String, *mut ffi::rocksdb_column_family_handle_t>,
path: PathBuf,
}
unsafe impl Send for DB {}
unsafe impl Sync for DB {}
@ -151,39 +143,6 @@ pub enum Direction {
pub type KVBytes = (Box<[u8]>, Box<[u8]>);
#[derive(Debug, PartialEq)]
pub struct Error {
message: String,
}
impl Error {
fn new(message: String) -> Error {
Error { message: message }
}
pub fn to_string(self) -> String {
self.into()
}
}
impl From<Error> for String {
fn from(e: Error) -> String {
e.message
}
}
impl error::Error for Error {
fn description(&self) -> &str {
&self.message
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.message.fmt(formatter)
}
}
impl Iterator for DBIterator {
type Item = KVBytes;
@ -357,23 +316,21 @@ impl DB {
///
/// # Panics
///
/// * Panics if the column family doesn't exist
/// * Panics if the column family doesn't exist.
pub fn open_cf<P: AsRef<Path>>(opts: &Options, path: P, cfs: &[&str]) -> Result<DB, Error> {
let path = path.as_ref();
let cpath = match CString::new(path.to_string_lossy().as_bytes()) {
Ok(c) => c,
Err(_) => {
return Err(Error::new("Failed to convert path to CString \
when opening rocksdb"
when opening DB."
.to_owned()))
}
};
let cpath_ptr = cpath.as_ptr();
if let Err(e) = fs::create_dir_all(&path) {
return Err(Error::new(format!("Failed to create rocksdb \
directory: {:?}",
return Err(Error::new(format!("Failed to create RocksDB\
directory: `{:?}`.",
e)));
}
@ -382,7 +339,7 @@ impl DB {
if cfs.len() == 0 {
unsafe {
db = ffi_try!(ffi::rocksdb_open(opts.inner, cpath_ptr as *const _));
db = ffi_try!(ffi::rocksdb_open(opts.inner, cpath.as_ptr() as *const _));
}
} else {
let mut cfs_v = cfs.to_vec();
@ -409,7 +366,7 @@ impl DB {
unsafe {
db = ffi_try!(ffi::rocksdb_open_column_families(opts.inner,
cpath_ptr as *const _,
cpath.as_ptr() as *const _,
cfs_v.len() as c_int,
cfnames.as_ptr() as *const _,
cfopts.as_ptr(),
@ -479,10 +436,10 @@ impl DB {
pub fn get_opt(&self, key: &[u8], readopts: &ReadOptions) -> Result<Option<DBVector>, Error> {
if readopts.inner.is_null() {
return Err(Error::new("Unable to create rocksdb read options. \
return Err(Error::new("Unable to create RocksDB read options. \
This is a fairly trivial call, and its \
failure may be indicative of a \
mis-compiled or mis-loaded rocksdb \
mis-compiled or mis-loaded RocksDB \
library."
.to_owned()));
}
@ -513,10 +470,10 @@ impl DB {
readopts: &ReadOptions)
-> Result<Option<DBVector>, Error> {
if readopts.inner.is_null() {
return Err(Error::new("Unable to create rocksdb read options. \
return Err(Error::new("Unable to create RocksDB read options. \
This is a fairly trivial call, and its \
failure may be indicative of a \
mis-compiled or mis-loaded rocksdb \
mis-compiled or mis-loaded RocksDB \
library."
.to_owned()));
}

@ -88,7 +88,7 @@ impl Default for BlockBasedOptions {
fn default() -> BlockBasedOptions {
let block_opts = unsafe { ffi::rocksdb_block_based_options_create() };
if block_opts.is_null() {
panic!("Could not create rocksdb block based options".to_owned());
panic!("Could not create RocksDB block based options");
}
BlockBasedOptions { inner: block_opts }
}
@ -828,14 +828,13 @@ impl Default for Options {
unsafe {
let opts = ffi::rocksdb_options_create();
if opts.is_null() {
panic!("Could not create rocksdb options".to_owned());
panic!("Could not create RocksDB options");
}
Options { inner: opts }
}
}
}
impl WriteOptions {
pub fn new() -> WriteOptions {
WriteOptions::default()
@ -858,7 +857,7 @@ impl Default for WriteOptions {
fn default() -> WriteOptions {
let write_opts = unsafe { ffi::rocksdb_writeoptions_create() };
if write_opts.is_null() {
panic!("Could not create rocksdb write options".to_owned());
panic!("Could not create RocksDB write options");
}
WriteOptions { inner: write_opts }
}

Loading…
Cancel
Save