|
|
@ -19,8 +19,7 @@ use {ColumnFamily, ColumnFamilyDescriptor, Error, Options, WriteOptions, DB}; |
|
|
|
|
|
|
|
|
|
|
|
use libc::{self, c_char, c_int, c_uchar, c_void, size_t}; |
|
|
|
use libc::{self, c_char, c_int, c_uchar, c_void, size_t}; |
|
|
|
use std::collections::BTreeMap; |
|
|
|
use std::collections::BTreeMap; |
|
|
|
use std::ffi::CStr; |
|
|
|
use std::ffi::{CStr, CString}; |
|
|
|
use std::ffi::CString; |
|
|
|
|
|
|
|
use std::fmt; |
|
|
|
use std::fmt; |
|
|
|
use std::fs; |
|
|
|
use std::fs; |
|
|
|
use std::ops::Deref; |
|
|
|
use std::ops::Deref; |
|
|
@ -28,6 +27,7 @@ use std::path::Path; |
|
|
|
use std::ptr; |
|
|
|
use std::ptr; |
|
|
|
use std::slice; |
|
|
|
use std::slice; |
|
|
|
use std::str; |
|
|
|
use std::str; |
|
|
|
|
|
|
|
use std::sync::{Arc, RwLock}; |
|
|
|
|
|
|
|
|
|
|
|
pub fn new_bloom_filter(bits: c_int) -> *mut ffi::rocksdb_filterpolicy_t { |
|
|
|
pub fn new_bloom_filter(bits: c_int) -> *mut ffi::rocksdb_filterpolicy_t { |
|
|
|
unsafe { ffi::rocksdb_filterpolicy_create_bloom(bits) } |
|
|
|
unsafe { ffi::rocksdb_filterpolicy_create_bloom(bits) } |
|
|
@ -386,7 +386,7 @@ impl DBRawIterator { |
|
|
|
/// if the iterator's seek position is ever moved by any of the seek commands or the
|
|
|
|
/// if the iterator's seek position is ever moved by any of the seek commands or the
|
|
|
|
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
|
|
|
|
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
|
|
|
|
/// for something else or freed entirely.
|
|
|
|
/// for something else or freed entirely.
|
|
|
|
pub unsafe fn key_inner<'a>(&'a self) -> Option<&'a [u8]> { |
|
|
|
pub unsafe fn key_inner(&self) -> Option<&[u8]> { |
|
|
|
if self.valid() { |
|
|
|
if self.valid() { |
|
|
|
let mut key_len: size_t = 0; |
|
|
|
let mut key_len: size_t = 0; |
|
|
|
let key_len_ptr: *mut size_t = &mut key_len; |
|
|
|
let key_len_ptr: *mut size_t = &mut key_len; |
|
|
@ -410,7 +410,7 @@ impl DBRawIterator { |
|
|
|
/// if the iterator's seek position is ever moved by any of the seek commands or the
|
|
|
|
/// if the iterator's seek position is ever moved by any of the seek commands or the
|
|
|
|
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
|
|
|
|
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
|
|
|
|
/// for something else or freed entirely.
|
|
|
|
/// for something else or freed entirely.
|
|
|
|
pub unsafe fn value_inner<'a>(&'a self) -> Option<&'a [u8]> { |
|
|
|
pub unsafe fn value_inner(&self) -> Option<&[u8]> { |
|
|
|
if self.valid() { |
|
|
|
if self.valid() { |
|
|
|
let mut val_len: size_t = 0; |
|
|
|
let mut val_len: size_t = 0; |
|
|
|
let val_len_ptr: *mut size_t = &mut val_len; |
|
|
|
let val_len_ptr: *mut size_t = &mut val_len; |
|
|
@ -454,7 +454,7 @@ impl DBIterator { |
|
|
|
mode: IteratorMode, |
|
|
|
mode: IteratorMode, |
|
|
|
) -> Result<DBIterator, Error> { |
|
|
|
) -> Result<DBIterator, Error> { |
|
|
|
let mut rv = DBIterator { |
|
|
|
let mut rv = DBIterator { |
|
|
|
raw: try!(DBRawIterator::new_cf(db, cf_handle, readopts)), |
|
|
|
raw: DBRawIterator::new_cf(db, cf_handle, readopts)?, |
|
|
|
direction: Direction::Forward, // blown away by set_mode()
|
|
|
|
direction: Direction::Forward, // blown away by set_mode()
|
|
|
|
just_seeked: false, |
|
|
|
just_seeked: false, |
|
|
|
}; |
|
|
|
}; |
|
|
@ -647,7 +647,7 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let db: *mut ffi::rocksdb_t; |
|
|
|
let db: *mut ffi::rocksdb_t; |
|
|
|
let mut cf_map = BTreeMap::new(); |
|
|
|
let cf_map = Arc::new(RwLock::new(BTreeMap::new())); |
|
|
|
|
|
|
|
|
|
|
|
if cfs.len() == 0 { |
|
|
|
if cfs.len() == 0 { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -701,7 +701,9 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (n, h) in cfs_v.iter().zip(cfhandles) { |
|
|
|
for (n, h) in cfs_v.iter().zip(cfhandles) { |
|
|
|
cf_map.insert(n.name.clone(), ColumnFamily { inner: h }); |
|
|
|
cf_map.write() |
|
|
|
|
|
|
|
.map_err(|e| Error::new(e.to_string()))? |
|
|
|
|
|
|
|
.insert(n.name.clone(), ColumnFamily { inner: h }); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -856,7 +858,7 @@ impl DB { |
|
|
|
self.get_cf_opt(cf, key, &ReadOptions::default()) |
|
|
|
self.get_cf_opt(cf, key, &ReadOptions::default()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn create_cf(&mut self, name: &str, opts: &Options) -> Result<ColumnFamily, Error> { |
|
|
|
pub fn create_cf(&self, name: &str, opts: &Options) -> Result<ColumnFamily, Error> { |
|
|
|
let cname = match CString::new(name.as_bytes()) { |
|
|
|
let cname = match CString::new(name.as_bytes()) { |
|
|
|
Ok(c) => c, |
|
|
|
Ok(c) => c, |
|
|
|
Err(_) => { |
|
|
|
Err(_) => { |
|
|
@ -874,31 +876,30 @@ impl DB { |
|
|
|
cname.as_ptr(), |
|
|
|
cname.as_ptr(), |
|
|
|
)); |
|
|
|
)); |
|
|
|
let cf = ColumnFamily { inner: cf_handler }; |
|
|
|
let cf = ColumnFamily { inner: cf_handler }; |
|
|
|
self.cfs.insert(name.to_string(), cf); |
|
|
|
self.cfs.write().map_err(|e| Error::new(e.to_string()))? |
|
|
|
|
|
|
|
.insert(name.to_string(), cf); |
|
|
|
cf |
|
|
|
cf |
|
|
|
}; |
|
|
|
}; |
|
|
|
Ok(cf) |
|
|
|
Ok(cf) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn drop_cf(&mut self, name: &str) -> Result<(), Error> { |
|
|
|
pub fn drop_cf(&self, name: &str) -> Result<(), Error> { |
|
|
|
let cf = self.cfs.get(name); |
|
|
|
if let Some(cf) = self.cfs.write().map_err(|e| Error::new(e.to_string()))? |
|
|
|
if cf.is_none() { |
|
|
|
.remove(name) { |
|
|
|
return Err(Error::new( |
|
|
|
unsafe { |
|
|
|
format!("Invalid column family: {}", name).to_owned(), |
|
|
|
ffi_try!(ffi::rocksdb_drop_column_family(self.inner, cf.inner,)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
unsafe { |
|
|
|
} else { |
|
|
|
ffi_try!(ffi::rocksdb_drop_column_family( |
|
|
|
Err(Error::new( |
|
|
|
self.inner, |
|
|
|
format!("Invalid column family: {}", name).to_owned() |
|
|
|
cf.unwrap().inner, |
|
|
|
)) |
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Return the underlying column family handle.
|
|
|
|
/// Return the underlying column family handle.
|
|
|
|
pub fn cf_handle(&self, name: &str) -> Option<ColumnFamily> { |
|
|
|
pub fn cf_handle(&self, name: &str) -> Option<ColumnFamily> { |
|
|
|
self.cfs.get(name).cloned() |
|
|
|
self.cfs.read().ok()?.get(name).cloned() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn iterator(&self, mode: IteratorMode) -> DBIterator { |
|
|
|
pub fn iterator(&self, mode: IteratorMode) -> DBIterator { |
|
|
@ -915,7 +916,7 @@ impl DB { |
|
|
|
DBIterator::new(self, &opts, mode) |
|
|
|
DBIterator::new(self, &opts, mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn prefix_iterator<'a>(&self, prefix: &'a [u8]) -> DBIterator { |
|
|
|
pub fn prefix_iterator(&self, prefix: &[u8]) -> DBIterator { |
|
|
|
let mut opts = ReadOptions::default(); |
|
|
|
let mut opts = ReadOptions::default(); |
|
|
|
opts.set_prefix_same_as_start(true); |
|
|
|
opts.set_prefix_same_as_start(true); |
|
|
|
DBIterator::new(self, &opts, IteratorMode::From(prefix, Direction::Forward)) |
|
|
|
DBIterator::new(self, &opts, IteratorMode::From(prefix, Direction::Forward)) |
|
|
@ -940,10 +941,10 @@ impl DB { |
|
|
|
DBIterator::new_cf(self, cf_handle, &opts, mode) |
|
|
|
DBIterator::new_cf(self, cf_handle, &opts, mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn prefix_iterator_cf<'a>( |
|
|
|
pub fn prefix_iterator_cf( |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
cf_handle: ColumnFamily, |
|
|
|
cf_handle: ColumnFamily, |
|
|
|
prefix: &'a [u8], |
|
|
|
prefix: &[u8] |
|
|
|
) -> Result<DBIterator, Error> { |
|
|
|
) -> Result<DBIterator, Error> { |
|
|
|
let mut opts = ReadOptions::default(); |
|
|
|
let mut opts = ReadOptions::default(); |
|
|
|
opts.set_prefix_same_as_start(true); |
|
|
|
opts.set_prefix_same_as_start(true); |
|
|
@ -1241,8 +1242,10 @@ impl Drop for WriteBatch { |
|
|
|
impl Drop for DB { |
|
|
|
impl Drop for DB { |
|
|
|
fn drop(&mut self) { |
|
|
|
fn drop(&mut self) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
for cf in self.cfs.values() { |
|
|
|
if let Ok(cfs) = self.cfs.read() { |
|
|
|
ffi::rocksdb_column_family_handle_destroy(cf.inner); |
|
|
|
for cf in cfs.values() { |
|
|
|
|
|
|
|
ffi::rocksdb_column_family_handle_destroy(cf.inner); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
ffi::rocksdb_close(self.inner); |
|
|
|
ffi::rocksdb_close(self.inner); |
|
|
|
} |
|
|
|
} |
|
|
|