Commit 32e68054 authored by Jay's avatar Jay

make iterator don't copy (#9)

parent 468aaa4a
...@@ -25,9 +25,9 @@ pub mod rocksdb_options; ...@@ -25,9 +25,9 @@ pub mod rocksdb_options;
pub mod merge_operator; pub mod merge_operator;
pub mod comparator; pub mod comparator;
pub use librocksdb_sys::{DBCompactionStyle, DBComparator, new_bloom_filter, pub use librocksdb_sys::{DBCompactionStyle, DBComparator, DBCompressionType,
self as rocksdb_ffi, DBCompressionType}; new_bloom_filter, self as rocksdb_ffi};
pub use rocksdb::{DB, DBIterator, DBVector, Direction, IteratorMode, Writable, pub use rocksdb::{DB, DBIterator, DBVector, Direction, IteratorMode, Kv,
WriteBatch}; Writable, WriteBatch};
pub use rocksdb_options::{BlockBasedOptions, Options, WriteOptions}; pub use rocksdb_options::{BlockBasedOptions, Options, WriteOptions};
pub use merge_operator::MergeOperands; pub use merge_operator::MergeOperands;
...@@ -48,7 +48,10 @@ pub struct Snapshot<'a> { ...@@ -48,7 +48,10 @@ pub struct Snapshot<'a> {
inner: rocksdb_ffi::DBSnapshot, inner: rocksdb_ffi::DBSnapshot,
} }
pub struct DBIterator { // We need to find a better way to add a lifetime in here.
#[allow(dead_code)]
pub struct DBIterator<'a> {
db: &'a DB,
inner: rocksdb_ffi::DBIterator, inner: rocksdb_ffi::DBIterator,
direction: Direction, direction: Direction,
just_seeked: bool, just_seeked: bool,
...@@ -59,13 +62,12 @@ pub enum Direction { ...@@ -59,13 +62,12 @@ pub enum Direction {
Reverse, Reverse,
} }
// TODO: should we use Vec<u8> instead? pub type Kv<'a> = (&'a [u8], &'a [u8]);
pub type Kv = (Box<[u8]>, Box<[u8]>);
impl Iterator for DBIterator { impl<'a> Iterator for DBIterator<'a> {
type Item = Kv; type Item = Kv<'a>;
fn next(&mut self) -> Option<Kv> { fn next(&mut self) -> Option<Kv<'a>> {
let native_iter = self.inner; let native_iter = self.inner;
if self.just_seeked { if self.just_seeked {
self.just_seeked = false; self.just_seeked = false;
...@@ -97,8 +99,7 @@ impl Iterator for DBIterator { ...@@ -97,8 +99,7 @@ impl Iterator for DBIterator {
slice::from_raw_parts(val_ptr, val_len as usize) slice::from_raw_parts(val_ptr, val_len as usize)
}; };
Some((key.to_vec().into_boxed_slice(), Some((key, val))
val.to_vec().into_boxed_slice()))
} else { } else {
None None
} }
...@@ -112,13 +113,17 @@ pub enum IteratorMode<'a> { ...@@ -112,13 +113,17 @@ pub enum IteratorMode<'a> {
} }
impl DBIterator { impl<'a> DBIterator<'a> {
fn new(db: &DB, readopts: &ReadOptions, mode: IteratorMode) -> DBIterator { fn new(db: &'a DB,
readopts: &ReadOptions,
mode: IteratorMode)
-> DBIterator<'a> {
unsafe { unsafe {
let iterator = rocksdb_ffi::rocksdb_create_iterator(db.inner, let iterator = rocksdb_ffi::rocksdb_create_iterator(db.inner,
readopts.inner); readopts.inner);
let mut rv = DBIterator { let mut rv = DBIterator {
db: db,
inner: iterator, inner: iterator,
direction: Direction::Forward, // blown away by set_mode() direction: Direction::Forward, // blown away by set_mode()
just_seeked: false, just_seeked: false,
...@@ -156,11 +161,11 @@ impl DBIterator { ...@@ -156,11 +161,11 @@ impl DBIterator {
unsafe { rocksdb_ffi::rocksdb_iter_valid(self.inner) } unsafe { rocksdb_ffi::rocksdb_iter_valid(self.inner) }
} }
fn new_cf(db: &DB, fn new_cf(db: &'a DB,
cf_handle: DBCFHandle, cf_handle: DBCFHandle,
readopts: &ReadOptions, readopts: &ReadOptions,
mode: IteratorMode) mode: IteratorMode)
-> Result<DBIterator, String> { -> Result<DBIterator<'a>, String> {
unsafe { unsafe {
let iterator = let iterator =
rocksdb_ffi::rocksdb_create_iterator_cf(db.inner, rocksdb_ffi::rocksdb_create_iterator_cf(db.inner,
...@@ -168,6 +173,7 @@ impl DBIterator { ...@@ -168,6 +173,7 @@ impl DBIterator {
cf_handle); cf_handle);
let mut rv = DBIterator { let mut rv = DBIterator {
db: db,
inner: iterator, inner: iterator,
direction: Direction::Forward, // blown away by set_mode() direction: Direction::Forward, // blown away by set_mode()
just_seeked: false, just_seeked: false,
...@@ -180,7 +186,7 @@ impl DBIterator { ...@@ -180,7 +186,7 @@ impl DBIterator {
} }
} }
impl Drop for DBIterator { impl<'a> Drop for DBIterator<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
rocksdb_ffi::rocksdb_iter_destroy(self.inner); rocksdb_ffi::rocksdb_iter_destroy(self.inner);
......
use rocksdb::{DB, Direction, IteratorMode, Writable}; use rocksdb::{DB, Direction, IteratorMode, Writable, Kv};
use tempdir::TempDir; use tempdir::TempDir;
fn cba(input: &Box<[u8]>) -> Box<[u8]> { fn collect<'a, T: Iterator<Item=Kv<'a>>>(iter: T) -> Vec<(Vec<u8>, Vec<u8>)> {
input.iter().cloned().collect::<Vec<_>>().into_boxed_slice() iter.map(|(k, v)| (k.to_vec(), v.to_vec())).collect()
} }
#[test] #[test]
pub fn test_iterator() { pub fn test_iterator() {
let path = TempDir::new("_rust_rocksdb_iteratortest").expect(""); let path = TempDir::new("_rust_rocksdb_iteratortest").expect("");
let k1: Box<[u8]> = b"k1".to_vec().into_boxed_slice(); let k1 = b"k1";
let k2: Box<[u8]> = b"k2".to_vec().into_boxed_slice(); let k2 = b"k2";
let k3: Box<[u8]> = b"k3".to_vec().into_boxed_slice(); let k3 = b"k3";
let k4: Box<[u8]> = b"k4".to_vec().into_boxed_slice(); let k4 = b"k4";
let v1: Box<[u8]> = b"v1111".to_vec().into_boxed_slice(); let v1 = b"v1111";
let v2: Box<[u8]> = b"v2222".to_vec().into_boxed_slice(); let v2 = b"v2222";
let v3: Box<[u8]> = b"v3333".to_vec().into_boxed_slice(); let v3 = b"v3333";
let v4: Box<[u8]> = b"v4444".to_vec().into_boxed_slice(); let v4 = b"v4444";
let db = DB::open_default(path.path().to_str().unwrap()).unwrap(); let db = DB::open_default(path.path().to_str().unwrap()).unwrap();
let p = db.put(&*k1, &*v1); let p = db.put(k1, v1);
assert!(p.is_ok()); assert!(p.is_ok());
let p = db.put(&*k2, &*v2); let p = db.put(k2, v2);
assert!(p.is_ok()); assert!(p.is_ok());
let p = db.put(&*k3, &*v3); let p = db.put(k3, v3);
assert!(p.is_ok()); assert!(p.is_ok());
let expected = vec![(cba(&k1), cba(&v1)), let expected = vec![(k1.to_vec(), v1.to_vec()),
(cba(&k2), cba(&v2)), (k2.to_vec(), v2.to_vec()),
(cba(&k3), cba(&v3))]; (k3.to_vec(), v3.to_vec())];
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
// Test that it's idempotent // Test that it's idempotent
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
// Test it in reverse a few times // Test it in reverse a few times
let iterator1 = db.iterator(IteratorMode::End); let iterator1 = db.iterator(IteratorMode::End);
let mut tmp_vec = iterator1.collect::<Vec<_>>(); let mut tmp_vec = collect(iterator1);
tmp_vec.reverse(); tmp_vec.reverse();
assert_eq!(tmp_vec, expected); assert_eq!(tmp_vec, expected);
let iterator1 = db.iterator(IteratorMode::End); let iterator1 = db.iterator(IteratorMode::End);
let mut tmp_vec = iterator1.collect::<Vec<_>>(); let mut tmp_vec = collect(iterator1);
tmp_vec.reverse(); tmp_vec.reverse();
assert_eq!(tmp_vec, expected); assert_eq!(tmp_vec, expected);
let iterator1 = db.iterator(IteratorMode::End); let iterator1 = db.iterator(IteratorMode::End);
let mut tmp_vec = iterator1.collect::<Vec<_>>(); let mut tmp_vec = collect(iterator1);
tmp_vec.reverse(); tmp_vec.reverse();
assert_eq!(tmp_vec, expected); assert_eq!(tmp_vec, expected);
let iterator1 = db.iterator(IteratorMode::End); let iterator1 = db.iterator(IteratorMode::End);
let mut tmp_vec = iterator1.collect::<Vec<_>>(); let mut tmp_vec = collect(iterator1);
tmp_vec.reverse(); tmp_vec.reverse();
assert_eq!(tmp_vec, expected); assert_eq!(tmp_vec, expected);
let iterator1 = db.iterator(IteratorMode::End); let iterator1 = db.iterator(IteratorMode::End);
let mut tmp_vec = iterator1.collect::<Vec<_>>(); let mut tmp_vec = collect(iterator1);
tmp_vec.reverse(); tmp_vec.reverse();
assert_eq!(tmp_vec, expected); assert_eq!(tmp_vec, expected);
// Try it forward again // Try it forward again
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let old_iterator = db.iterator(IteratorMode::Start); let old_iterator = db.iterator(IteratorMode::Start);
let p = db.put(&*k4, &*v4); let p = db.put(&*k4, &*v4);
assert!(p.is_ok()); assert!(p.is_ok());
let expected2 = vec![(cba(&k1), cba(&v1)), let expected2 = vec![(k1.to_vec(), v1.to_vec()),
(cba(&k2), cba(&v2)), (k2.to_vec(), v2.to_vec()),
(cba(&k3), cba(&v3)), (k3.to_vec(), v3.to_vec()),
(cba(&k4), cba(&v4))]; (k4.to_vec(), v4.to_vec())];
assert_eq!(old_iterator.collect::<Vec<_>>(), expected); assert_eq!(collect(old_iterator), expected);
let iterator1 = db.iterator(IteratorMode::Start); let iterator1 = db.iterator(IteratorMode::Start);
assert_eq!(iterator1.collect::<Vec<_>>(), expected2); assert_eq!(collect(iterator1), expected2);
let iterator1 = db.iterator(IteratorMode::From(b"k2", let iterator1 = db.iterator(IteratorMode::From(b"k2",
Direction::Forward)); Direction::Forward));
let expected = vec![(cba(&k2), cba(&v2)), let expected = vec![(k2.to_vec(), v2.to_vec()),
(cba(&k3), cba(&v3)), (k3.to_vec(), v3.to_vec()),
(cba(&k4), cba(&v4))]; (k4.to_vec(), v4.to_vec())];
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let iterator1 = db.iterator(IteratorMode::From(b"k2", let iterator1 = db.iterator(IteratorMode::From(b"k2",
Direction::Reverse)); Direction::Reverse));
let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))]; let expected = vec![(k2.to_vec(), v2.to_vec()), (k1.to_vec(), v1.to_vec())];
assert_eq!(iterator1.collect::<Vec<_>>(), expected); assert_eq!(collect(iterator1), expected);
let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward)); let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward));
assert!(iterator1.valid()); assert!(iterator1.valid());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment