|
|
@ -16,13 +16,12 @@ |
|
|
|
|
|
|
|
|
|
|
|
extern crate libc; |
|
|
|
extern crate libc; |
|
|
|
use self::libc::{c_void, size_t}; |
|
|
|
use self::libc::{c_void, size_t}; |
|
|
|
use std::ffi::CString; |
|
|
|
use std::ffi::{CString, CStr}; |
|
|
|
use std::fs::{self, PathExt}; |
|
|
|
use std::fs::{self, PathExt}; |
|
|
|
use std::ops::Deref; |
|
|
|
use std::ops::Deref; |
|
|
|
use std::path::Path; |
|
|
|
use std::path::Path; |
|
|
|
use std::ptr::Unique; |
|
|
|
use std::ptr::Unique; |
|
|
|
use std::slice; |
|
|
|
use std::slice; |
|
|
|
use std::str::from_c_str; |
|
|
|
|
|
|
|
use std::str::from_utf8; |
|
|
|
use std::str::from_utf8; |
|
|
|
|
|
|
|
|
|
|
|
use rocksdb_ffi; |
|
|
|
use rocksdb_ffi; |
|
|
@ -33,6 +32,12 @@ pub struct RocksDB { |
|
|
|
inner: rocksdb_ffi::RocksDBInstance, |
|
|
|
inner: rocksdb_ffi::RocksDBInstance, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn error_message<'a>(ptr: *const i8) -> &'a str { |
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
|
|
|
return from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl RocksDB { |
|
|
|
impl RocksDB { |
|
|
|
pub fn open_default(path: &str) -> Result<RocksDB, &str> { |
|
|
|
pub fn open_default(path: &str) -> Result<RocksDB, &str> { |
|
|
|
let opts = RocksDBOptions::new(); |
|
|
|
let opts = RocksDBOptions::new(); |
|
|
@ -41,71 +46,69 @@ impl RocksDB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn open(opts: RocksDBOptions, path: &str) -> Result<RocksDB, &str> { |
|
|
|
pub fn open(opts: RocksDBOptions, path: &str) -> Result<RocksDB, &str> { |
|
|
|
unsafe { |
|
|
|
let cpath = CString::new(path.as_bytes()).unwrap(); |
|
|
|
let cpath = CString::from_slice(path.as_bytes()); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
|
|
|
|
|
|
|
|
let ospath = Path::new(path); |
|
|
|
let ospath = Path::new(path); |
|
|
|
if !ospath.exists() { |
|
|
|
if !ospath.exists() { |
|
|
|
match fs::create_dir_all(&ospath) { |
|
|
|
match fs::create_dir_all(&ospath) { |
|
|
|
Err(_) => return Err(""), |
|
|
|
Err(e) => return Err(""), |
|
|
|
Ok(_) => (), |
|
|
|
Ok(_) => (), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let err = 0 as *mut i8; |
|
|
|
let err = 0 as *mut i8; |
|
|
|
let db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err); |
|
|
|
let db: rocksdb_ffi::RocksDBInstance; |
|
|
|
if !err.is_null() { |
|
|
|
|
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
unsafe { |
|
|
|
return Err(cs); |
|
|
|
db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err); |
|
|
|
} |
|
|
|
|
|
|
|
if db.0.is_null() { |
|
|
|
|
|
|
|
return Err("Could not initialize database."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(RocksDB{inner: db}) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !err.is_null() { |
|
|
|
|
|
|
|
return Err(error_message(err)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if db.0.is_null() { |
|
|
|
|
|
|
|
return Err("Could not initialize database."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(RocksDB{inner: db}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn destroy(opts: RocksDBOptions, path: &str) -> Result<(), &str> { |
|
|
|
pub fn destroy(opts: RocksDBOptions, path: &str) -> Result<(), &str> { |
|
|
|
unsafe { |
|
|
|
let cpath = CString::new(path.as_bytes()).unwrap(); |
|
|
|
let cpath = CString::from_slice(path.as_bytes()); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ospath = Path::new(path); |
|
|
|
let ospath = Path::new(path); |
|
|
|
if !ospath.exists() { |
|
|
|
if !ospath.exists() { |
|
|
|
return Err("path does not exist"); |
|
|
|
return Err("path does not exist"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let err = 0 as *mut i8; |
|
|
|
let err = 0 as *mut i8; |
|
|
|
let result = rocksdb_ffi::rocksdb_destroy_db( |
|
|
|
unsafe { |
|
|
|
opts.inner, cpath_ptr, err); |
|
|
|
rocksdb_ffi::rocksdb_destroy_db(opts.inner, cpath_ptr, err); |
|
|
|
if !err.is_null() { |
|
|
|
|
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
|
|
|
|
return Err(cs); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if !err.is_null() { |
|
|
|
|
|
|
|
return Err(error_message(err)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn repair(opts: RocksDBOptions, path: &str) -> Result<(), &str> { |
|
|
|
pub fn repair(opts: RocksDBOptions, path: &str) -> Result<(), &str> { |
|
|
|
unsafe { |
|
|
|
let cpath = CString::new(path.as_bytes()).unwrap(); |
|
|
|
let cpath = CString::from_slice(path.as_bytes()); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
let cpath_ptr = cpath.as_ptr(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ospath = Path::new(path); |
|
|
|
let ospath = Path::new(path); |
|
|
|
if !ospath.exists() { |
|
|
|
if !ospath.exists() { |
|
|
|
return Err("path does not exist"); |
|
|
|
return Err("path does not exist"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let err = 0 as *mut i8; |
|
|
|
let err = 0 as *mut i8; |
|
|
|
let result = rocksdb_ffi::rocksdb_repair_db( |
|
|
|
unsafe { |
|
|
|
opts.inner, cpath_ptr, err); |
|
|
|
rocksdb_ffi::rocksdb_repair_db(opts.inner, cpath_ptr, err); |
|
|
|
if !err.is_null() { |
|
|
|
} |
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
if !err.is_null() { |
|
|
|
return Err(cs); |
|
|
|
return Err(error_message(err)); |
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn create_snapshot(self) -> RocksDBSnapshot { |
|
|
|
pub fn create_snapshot(self) -> RocksDBSnapshot { |
|
|
@ -122,8 +125,7 @@ impl RocksDB { |
|
|
|
key.len() as size_t, value.as_ptr(), |
|
|
|
key.len() as size_t, value.as_ptr(), |
|
|
|
value.len() as size_t, err); |
|
|
|
value.len() as size_t, err); |
|
|
|
if !err.is_null() { |
|
|
|
if !err.is_null() { |
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
return Err(error_message(err)); |
|
|
|
return Err(cs); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return Ok(()) |
|
|
|
return Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
@ -137,8 +139,7 @@ impl RocksDB { |
|
|
|
key.len() as size_t, value.as_ptr(), |
|
|
|
key.len() as size_t, value.as_ptr(), |
|
|
|
value.len() as size_t, err); |
|
|
|
value.len() as size_t, err); |
|
|
|
if !err.is_null() { |
|
|
|
if !err.is_null() { |
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
return Err(error_message(err)); |
|
|
|
return Err(cs); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return Ok(()) |
|
|
|
return Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
@ -160,8 +161,7 @@ impl RocksDB { |
|
|
|
let val = rocksdb_ffi::rocksdb_get(self.inner, readopts, |
|
|
|
let val = rocksdb_ffi::rocksdb_get(self.inner, readopts, |
|
|
|
key.as_ptr(), key.len() as size_t, val_len_ptr, err) as *mut u8; |
|
|
|
key.as_ptr(), key.len() as size_t, val_len_ptr, err) as *mut u8; |
|
|
|
if !err.is_null() { |
|
|
|
if !err.is_null() { |
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
return RocksDBResult::Error(error_message(err)); |
|
|
|
return RocksDBResult::Error(cs); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
match val.is_null() { |
|
|
|
match val.is_null() { |
|
|
|
true => RocksDBResult::None, |
|
|
|
true => RocksDBResult::None, |
|
|
@ -179,8 +179,7 @@ impl RocksDB { |
|
|
|
rocksdb_ffi::rocksdb_delete(self.inner, writeopts, key.as_ptr(), |
|
|
|
rocksdb_ffi::rocksdb_delete(self.inner, writeopts, key.as_ptr(), |
|
|
|
key.len() as size_t, err); |
|
|
|
key.len() as size_t, err); |
|
|
|
if !err.is_null() { |
|
|
|
if !err.is_null() { |
|
|
|
let cs = from_c_str(err as *const i8); |
|
|
|
return Err(error_message(err)); |
|
|
|
return Err(cs); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return Ok(()) |
|
|
|
return Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|