|
|
@ -67,16 +67,18 @@ pub enum DBRecoveryMode { |
|
|
|
/// Making an atomic commit of several writes:
|
|
|
|
/// Making an atomic commit of several writes:
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
/// use rocksdb::{DB, WriteBatch};
|
|
|
|
/// use rocksdb::{DB, Options, WriteBatch};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let db = DB::open_default("path/for/rocksdb/storage1").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage1";
|
|
|
|
/// {
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut batch = WriteBatch::default();
|
|
|
|
/// let mut batch = WriteBatch::default();
|
|
|
|
/// batch.put(b"my key", b"my value");
|
|
|
|
/// batch.put(b"my key", b"my value");
|
|
|
|
/// batch.put(b"key2", b"value2");
|
|
|
|
/// batch.put(b"key2", b"value2");
|
|
|
|
/// batch.put(b"key3", b"value3");
|
|
|
|
/// batch.put(b"key3", b"value3");
|
|
|
|
/// db.write(batch); // Atomically commits the batch
|
|
|
|
/// db.write(batch); // Atomically commits the batch
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub struct WriteBatch { |
|
|
|
pub struct WriteBatch { |
|
|
|
inner: *mut ffi::rocksdb_writebatch_t, |
|
|
|
inner: *mut ffi::rocksdb_writebatch_t, |
|
|
@ -89,11 +91,15 @@ pub struct ReadOptions { |
|
|
|
/// A consistent view of the database at the point of creation.
|
|
|
|
/// A consistent view of the database at the point of creation.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
/// use rocksdb::{DB, IteratorMode};
|
|
|
|
/// use rocksdb::{DB, IteratorMode, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let db = DB::open_default("path/for/rocksdb/storage3").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage3";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but closed when goes out of scope
|
|
|
|
/// let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but closed when goes out of scope
|
|
|
|
/// let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot
|
|
|
|
/// let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
///
|
|
|
|
pub struct Snapshot<'a> { |
|
|
|
pub struct Snapshot<'a> { |
|
|
@ -110,9 +116,11 @@ pub struct Snapshot<'a> { |
|
|
|
/// widely recognised Rust idioms.
|
|
|
|
/// widely recognised Rust idioms.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
/// use rocksdb::DB;
|
|
|
|
/// use rocksdb::{DB, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage4").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage4";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Forwards iteration
|
|
|
|
/// // Forwards iteration
|
|
|
@ -144,6 +152,8 @@ pub struct Snapshot<'a> { |
|
|
|
/// println!("Saw {:?} {:?}", iter.key(), iter.value());
|
|
|
|
/// println!("Saw {:?} {:?}", iter.key(), iter.value());
|
|
|
|
/// iter.prev();
|
|
|
|
/// iter.prev();
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub struct DBRawIterator { |
|
|
|
pub struct DBRawIterator { |
|
|
|
inner: *mut ffi::rocksdb_iterator_t, |
|
|
|
inner: *mut ffi::rocksdb_iterator_t, |
|
|
@ -153,9 +163,11 @@ pub struct DBRawIterator { |
|
|
|
/// ranges and direction.
|
|
|
|
/// ranges and direction.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
/// use rocksdb::{DB, Direction, IteratorMode};
|
|
|
|
/// use rocksdb::{DB, Direction, IteratorMode, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage2").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage2";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.iterator(IteratorMode::Start); // Always iterates forward
|
|
|
|
/// let mut iter = db.iterator(IteratorMode::Start); // Always iterates forward
|
|
|
|
/// for (key, value) in iter {
|
|
|
|
/// for (key, value) in iter {
|
|
|
|
/// println!("Saw {:?} {:?}", key, value);
|
|
|
|
/// println!("Saw {:?} {:?}", key, value);
|
|
|
@ -175,6 +187,8 @@ pub struct DBRawIterator { |
|
|
|
/// for (key, value) in iter {
|
|
|
|
/// for (key, value) in iter {
|
|
|
|
/// println!("Saw {:?} {:?}", key, value);
|
|
|
|
/// println!("Saw {:?} {:?}", key, value);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub struct DBIterator { |
|
|
|
pub struct DBIterator { |
|
|
|
raw: DBRawIterator, |
|
|
|
raw: DBRawIterator, |
|
|
@ -228,23 +242,22 @@ impl DBRawIterator { |
|
|
|
/// # Examples
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// ```rust
|
|
|
|
/// use rocksdb::DB;
|
|
|
|
/// use rocksdb::{DB, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage5").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage5";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Iterate all keys from the start in lexicographic order
|
|
|
|
/// // Iterate all keys from the start in lexicographic order
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek_to_first();
|
|
|
|
/// iter.seek_to_first();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// while iter.valid() {
|
|
|
|
/// while iter.valid() {
|
|
|
|
/// println!("{:?} {:?}", iter.key(), iter.value());
|
|
|
|
/// println!("{:?} {:?}", iter.key(), iter.value());
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.next();
|
|
|
|
/// iter.next();
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Read just the first key
|
|
|
|
/// // Read just the first key
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek_to_first();
|
|
|
|
/// iter.seek_to_first();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// if iter.valid() {
|
|
|
|
/// if iter.valid() {
|
|
|
@ -252,6 +265,8 @@ impl DBRawIterator { |
|
|
|
/// } else {
|
|
|
|
/// } else {
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub fn seek_to_first(&mut self) { |
|
|
|
pub fn seek_to_first(&mut self) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -264,23 +279,22 @@ impl DBRawIterator { |
|
|
|
/// # Examples
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// ```rust
|
|
|
|
/// use rocksdb::DB;
|
|
|
|
/// use rocksdb::{DB, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage6").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage6";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Iterate all keys from the end in reverse lexicographic order
|
|
|
|
/// // Iterate all keys from the end in reverse lexicographic order
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek_to_last();
|
|
|
|
/// iter.seek_to_last();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// while iter.valid() {
|
|
|
|
/// while iter.valid() {
|
|
|
|
/// println!("{:?} {:?}", iter.key(), iter.value());
|
|
|
|
/// println!("{:?} {:?}", iter.key(), iter.value());
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.prev();
|
|
|
|
/// iter.prev();
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Read just the last key
|
|
|
|
/// // Read just the last key
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek_to_last();
|
|
|
|
/// iter.seek_to_last();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// if iter.valid() {
|
|
|
|
/// if iter.valid() {
|
|
|
@ -288,6 +302,8 @@ impl DBRawIterator { |
|
|
|
/// } else {
|
|
|
|
/// } else {
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub fn seek_to_last(&mut self) { |
|
|
|
pub fn seek_to_last(&mut self) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -303,13 +319,14 @@ impl DBRawIterator { |
|
|
|
/// # Examples
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// ```rust
|
|
|
|
/// use rocksdb::DB;
|
|
|
|
/// use rocksdb::{DB, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage7").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage7";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Read the first key that starts with 'a'
|
|
|
|
/// // Read the first key that starts with 'a'
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek(b"a");
|
|
|
|
/// iter.seek(b"a");
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// if iter.valid() {
|
|
|
|
/// if iter.valid() {
|
|
|
@ -317,6 +334,8 @@ impl DBRawIterator { |
|
|
|
/// } else {
|
|
|
|
/// } else {
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
/// ```
|
|
|
|
/// ```
|
|
|
|
pub fn seek(&mut self, key: &[u8]) { |
|
|
|
pub fn seek(&mut self, key: &[u8]) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -337,13 +356,14 @@ impl DBRawIterator { |
|
|
|
/// # Examples
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// ```rust
|
|
|
|
/// use rocksdb::DB;
|
|
|
|
/// use rocksdb::{DB, Options};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// let mut db = DB::open_default("path/for/rocksdb/storage8").unwrap();
|
|
|
|
/// let path = "_path_for_rocksdb_storage8";
|
|
|
|
|
|
|
|
/// {
|
|
|
|
|
|
|
|
/// let db = DB::open_default(path).unwrap();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
/// let mut iter = db.raw_iterator();
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// // Read the last key that starts with 'a'
|
|
|
|
/// // Read the last key that starts with 'a'
|
|
|
|
///
|
|
|
|
|
|
|
|
/// iter.seek_for_prev(b"b");
|
|
|
|
/// iter.seek_for_prev(b"b");
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// if iter.valid() {
|
|
|
|
/// if iter.valid() {
|
|
|
@ -351,6 +371,9 @@ impl DBRawIterator { |
|
|
|
/// } else {
|
|
|
|
/// } else {
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// // There are no keys in the database
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
/// let _ = DB::destroy(&Options::default(), path);
|
|
|
|
|
|
|
|
/// ```
|
|
|
|
pub fn seek_for_prev(&mut self, key: &[u8]) { |
|
|
|
pub fn seek_for_prev(&mut self, key: &[u8]) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
ffi::rocksdb_iter_seek_for_prev( |
|
|
|
ffi::rocksdb_iter_seek_for_prev( |
|
|
@ -640,9 +663,7 @@ impl DB { |
|
|
|
|
|
|
|
|
|
|
|
if let Err(e) = fs::create_dir_all(&path) { |
|
|
|
if let Err(e) = fs::create_dir_all(&path) { |
|
|
|
return Err(Error::new(format!( |
|
|
|
return Err(Error::new(format!( |
|
|
|
"Failed to create RocksDB\ |
|
|
|
"Failed to create RocksDB directory: `{:?}`.", e |
|
|
|
directory: `{:?}`.", |
|
|
|
|
|
|
|
e |
|
|
|
|
|
|
|
))); |
|
|
|
))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -719,17 +740,7 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn list_cf<P: AsRef<Path>>(opts: &Options, path: P) -> Result<Vec<String>, Error> { |
|
|
|
pub fn list_cf<P: AsRef<Path>>(opts: &Options, path: P) -> Result<Vec<String>, Error> { |
|
|
|
let cpath = match CString::new(path.as_ref().to_string_lossy().as_bytes()) { |
|
|
|
let cpath = to_cpath(path)?; |
|
|
|
Ok(c) => c, |
|
|
|
|
|
|
|
Err(_) => { |
|
|
|
|
|
|
|
return Err(Error::new( |
|
|
|
|
|
|
|
"Failed to convert path to CString \ |
|
|
|
|
|
|
|
when opening DB." |
|
|
|
|
|
|
|
.to_owned(), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut length = 0; |
|
|
|
let mut length = 0; |
|
|
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -749,7 +760,7 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn destroy<P: AsRef<Path>>(opts: &Options, path: P) -> Result<(), Error> { |
|
|
|
pub fn destroy<P: AsRef<Path>>(opts: &Options, path: P) -> Result<(), Error> { |
|
|
|
let cpath = CString::new(path.as_ref().to_string_lossy().as_bytes()).unwrap(); |
|
|
|
let cpath = to_cpath(path)?; |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
ffi_try!(ffi::rocksdb_destroy_db(opts.inner, cpath.as_ptr(),)); |
|
|
|
ffi_try!(ffi::rocksdb_destroy_db(opts.inner, cpath.as_ptr(),)); |
|
|
|
} |
|
|
|
} |
|
|
@ -757,7 +768,7 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn repair<P: AsRef<Path>>(opts: Options, path: P) -> Result<(), Error> { |
|
|
|
pub fn repair<P: AsRef<Path>>(opts: Options, path: P) -> Result<(), Error> { |
|
|
|
let cpath = CString::new(path.as_ref().to_string_lossy().as_bytes()).unwrap(); |
|
|
|
let cpath = to_cpath(path)?; |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
ffi_try!(ffi::rocksdb_repair_db(opts.inner, cpath.as_ptr(),)); |
|
|
|
ffi_try!(ffi::rocksdb_repair_db(opts.inner, cpath.as_ptr(),)); |
|
|
|
} |
|
|
|
} |
|
|
@ -1403,6 +1414,15 @@ impl DBVector { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn to_cpath<P: AsRef<Path>>(path: P) -> Result<CString, Error> { |
|
|
|
|
|
|
|
match CString::new(path.as_ref().to_string_lossy().as_bytes()) { |
|
|
|
|
|
|
|
Ok(c) => Ok(c), |
|
|
|
|
|
|
|
Err(_) => Err(Error::new( |
|
|
|
|
|
|
|
"Failed to convert path to CString when opening DB.".to_owned(), |
|
|
|
|
|
|
|
)), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
#[test] |
|
|
|
fn test_db_vector() { |
|
|
|
fn test_db_vector() { |
|
|
|
use std::mem; |
|
|
|
use std::mem; |
|
|
@ -1433,6 +1453,7 @@ fn external() { |
|
|
|
#[test] |
|
|
|
#[test] |
|
|
|
fn errors_do_stuff() { |
|
|
|
fn errors_do_stuff() { |
|
|
|
let path = "_rust_rocksdb_error"; |
|
|
|
let path = "_rust_rocksdb_error"; |
|
|
|
|
|
|
|
{ |
|
|
|
let _db = DB::open_default(path).unwrap(); |
|
|
|
let _db = DB::open_default(path).unwrap(); |
|
|
|
let opts = Options::default(); |
|
|
|
let opts = Options::default(); |
|
|
|
// The DB will still be open when we try to destroy it and the lock should fail.
|
|
|
|
// The DB will still be open when we try to destroy it and the lock should fail.
|
|
|
@ -1444,6 +1465,10 @@ fn errors_do_stuff() { |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(_) => panic!("should fail"), |
|
|
|
Ok(_) => panic!("should fail"), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let opts = Options::default(); |
|
|
|
|
|
|
|
let result = DB::destroy(&opts, path); |
|
|
|
|
|
|
|
assert!(result.is_ok()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
#[test] |
|
|
@ -1570,4 +1595,5 @@ fn set_option_test() { |
|
|
|
]; |
|
|
|
]; |
|
|
|
db.set_options(&multiple_options).unwrap(); |
|
|
|
db.set_options(&multiple_options).unwrap(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
assert!(DB::destroy(&Options::default(), path).is_ok()); |
|
|
|
} |
|
|
|
} |
|
|
|