changeset 74:f05cafb37230

Update LdbIterator interface and adapt implementors
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 17 Jul 2016 16:36:56 +0200
parents 416a07a89e9d
children 94ea2222178f
files src/block.rs src/memtable.rs src/skipmap.rs src/types.rs
diffstat 4 files changed, 72 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/src/block.rs	Fri Jul 15 20:21:26 2016 +0200
+++ b/src/block.rs	Sun Jul 17 16:36:56 2016 +0200
@@ -137,7 +137,7 @@
     }
 }
 
-impl<'a, C: 'a + Comparator> LdbIterator<'a> for BlockIter<'a, C> {
+impl<'a, C: 'a + Comparator> LdbIterator for BlockIter<'a, C> {
     fn reset(&mut self) {
         self.offset = 0;
         self.current_restart_ix = 0;
@@ -215,9 +215,12 @@
         !self.key.is_empty() && self.val_offset > 0 && self.val_offset < self.block.restarts_off
     }
 
-    fn current(&self) -> Self::Item {
-        assert!(self.valid());
-        (self.key.clone(), &self.block.data[self.val_offset..self.offset])
+    fn current(&self) -> Option<Self::Item> {
+        if self.valid() {
+            Some((self.key.clone(), &self.block.data[self.val_offset..self.offset]))
+        } else {
+            None
+        }
     }
 }
 
@@ -426,7 +429,7 @@
         block_iter.prev();
         assert!(block_iter.valid());
         assert_eq!(block_iter.current(),
-                   ("key1".as_bytes().to_vec(), "value1".as_bytes()));
+                   Some(("key1".as_bytes().to_vec(), "value1".as_bytes())));
         block_iter.prev();
         assert!(!block_iter.valid());
     }
@@ -451,11 +454,11 @@
         iter.seek(&"prefix_key2".as_bytes());
         assert!(iter.valid());
         assert_eq!(iter.current(),
-                   ("prefix_key2".as_bytes().to_vec(), "value".as_bytes()));
+                   Some(("prefix_key2".as_bytes().to_vec(), "value".as_bytes())));
 
         iter.seek(&"key1".as_bytes());
         assert!(iter.valid());
         assert_eq!(iter.current(),
-                   ("key1".as_bytes().to_vec(), "value1".as_bytes()));
+                   Some(("key1".as_bytes().to_vec(), "value1".as_bytes())));
     }
 }
--- a/src/memtable.rs	Fri Jul 15 20:21:26 2016 +0200
+++ b/src/memtable.rs	Sun Jul 17 16:36:56 2016 +0200
@@ -144,8 +144,8 @@
         let mut iter = self.map.iter();
         iter.seek(key.memtable_key());
 
-        if iter.valid() {
-            let foundkey = iter.current().0;
+        if let Some(e) = iter.current() {
+            let foundkey = e.0;
             let (lkeylen, lkeyoff, _, _, _) = Self::parse_memtable_key(key.memtable_key());
             let (fkeylen, fkeyoff, tag, vallen, valoff) = Self::parse_memtable_key(foundkey);
 
@@ -196,7 +196,7 @@
     }
 }
 
-impl<'a, C: 'a + Comparator> LdbIterator<'a> for MemtableIterator<'a, C> {
+impl<'a, C: 'a + Comparator> LdbIterator for MemtableIterator<'a, C> {
     fn reset(&mut self) {
         self.skipmapiter.reset();
     }
@@ -220,14 +220,20 @@
     fn valid(&self) -> bool {
         self.skipmapiter.valid()
     }
-    fn current(&'a self) -> Self::Item {
-        assert!(self.valid());
+    fn current(&self) -> Option<Self::Item> {
+        if !self.valid() {
+            return None;
+        }
 
-        let (foundkey, _): (&'a [u8], &'a [u8]) = self.skipmapiter.current();
-        let (keylen, keyoff, tag, vallen, valoff) = MemTable::<C>::parse_memtable_key(foundkey);
+        if let Some((foundkey, _)) = self.skipmapiter.current() {
+            let (keylen, keyoff, tag, vallen, valoff) = MemTable::<C>::parse_memtable_key(foundkey);
 
-        if tag & 0xff == ValueType::TypeValue as u64 {
-            return (&foundkey[keyoff..keyoff + keylen], &foundkey[valoff..valoff + vallen]);
+            if tag & 0xff == ValueType::TypeValue as u64 {
+                return Some((&foundkey[keyoff..keyoff + keylen],
+                             &foundkey[valoff..valoff + vallen]));
+            } else {
+                panic!("should not happen");
+            }
         } else {
             panic!("should not happen");
         }
@@ -324,12 +330,12 @@
 
         iter.next();
         assert!(iter.valid());
-        assert_eq!(iter.current().0, vec![97, 98, 99].as_slice());
-        assert_eq!(iter.current().1, vec![49, 50, 51].as_slice());
+        assert_eq!(iter.current().unwrap().0, vec![97, 98, 99].as_slice());
+        assert_eq!(iter.current().unwrap().1, vec![49, 50, 51].as_slice());
 
         iter.seek("abf".as_bytes());
-        assert_eq!(iter.current().0, vec![97, 98, 102].as_slice());
-        assert_eq!(iter.current().1, vec![49, 50, 54].as_slice());
+        assert_eq!(iter.current().unwrap().0, vec![97, 98, 102].as_slice());
+        assert_eq!(iter.current().unwrap().1, vec![49, 50, 54].as_slice());
     }
 
     #[test]
@@ -339,15 +345,15 @@
 
         iter.next();
         assert!(iter.valid());
-        assert_eq!(iter.current().0, vec![97, 98, 99].as_slice());
+        assert_eq!(iter.current().unwrap().0, vec![97, 98, 99].as_slice());
 
         iter.next();
         assert!(iter.valid());
-        assert_eq!(iter.current().0, vec![97, 98, 100].as_slice());
+        assert_eq!(iter.current().unwrap().0, vec![97, 98, 100].as_slice());
 
         iter.prev();
         assert!(iter.valid());
-        assert_eq!(iter.current().0, vec![97, 98, 99].as_slice());
+        assert_eq!(iter.current().unwrap().0, vec![97, 98, 99].as_slice());
 
         iter.prev();
         assert!(!iter.valid());
--- a/src/skipmap.rs	Fri Jul 15 20:21:26 2016 +0200
+++ b/src/skipmap.rs	Sun Jul 17 16:36:56 2016 +0200
@@ -260,7 +260,7 @@
     }
 }
 
-impl<'a, C: Comparator> LdbIterator<'a> for SkipMapIter<'a, C> {
+impl<'a, C: Comparator> LdbIterator for SkipMapIter<'a, C> {
     fn reset(&mut self) {
         let new = self.map.iter();
         self.current = new.current;
@@ -272,17 +272,24 @@
     fn valid(&self) -> bool {
         unsafe { !(*self.current).key.is_empty() }
     }
-    fn current(&'a self) -> Self::Item {
-        assert!(self.valid());
-        unsafe { (&(*self.current).key, &(*self.current).value) }
+    fn current(&self) -> Option<Self::Item> {
+        if self.valid() {
+            Some(unsafe { (&(*self.current).key, &(*self.current).value) })
+        } else {
+            None
+        }
     }
     fn prev(&mut self) -> Option<Self::Item> {
         // Going after the original implementation here; we just seek to the node before current().
-        let prev = self.map.get_next_smaller(self.current().0);
-        self.current = unsafe { transmute_copy(&prev) };
+        if let Some(current) = self.current() {
+            let prev = self.map.get_next_smaller(current.0);
+            self.current = unsafe { transmute_copy(&prev) };
 
-        if !prev.key.is_empty() {
-            Some(unsafe { (&(*self.current).key, &(*self.current).value) })
+            if !prev.key.is_empty() {
+                Some(unsafe { (&(*self.current).key, &(*self.current).value) })
+            } else {
+                None
+            }
         } else {
             None
         }
@@ -290,11 +297,11 @@
 }
 
 #[cfg(test)]
-mod tests {
+pub mod tests {
     use super::*;
     use types::*;
 
-    fn make_skipmap() -> SkipMap<StandardComparator> {
+    pub fn make_skipmap() -> SkipMap<StandardComparator> {
         let mut skm = SkipMap::new();
         let keys = vec!["aba", "abb", "abc", "abd", "abe", "abf", "abg", "abh", "abi", "abj",
                         "abk", "abl", "abm", "abn", "abo", "abp", "abq", "abr", "abs", "abt",
@@ -397,10 +404,12 @@
         iter.next();
         assert!(iter.valid());
         iter.seek(&"abz".as_bytes().to_vec());
-        assert_eq!(iter.current(), ("abz".as_bytes(), "def".as_bytes()));
+        assert_eq!(iter.current().unwrap(),
+                   ("abz".as_bytes(), "def".as_bytes()));
         // go back to beginning
         iter.seek(&"aba".as_bytes().to_vec());
-        assert_eq!(iter.current(), ("aba".as_bytes(), "def".as_bytes()));
+        assert_eq!(iter.current().unwrap(),
+                   ("aba".as_bytes(), "def".as_bytes()));
 
         iter.seek(&"".as_bytes().to_vec());
         assert!(iter.valid());
@@ -426,6 +435,7 @@
         assert!(!iter.valid());
         iter.seek(&"abc".as_bytes());
         iter.prev();
-        assert_eq!(iter.current(), ("abb".as_bytes(), "def".as_bytes()));
+        assert_eq!(iter.current().unwrap(),
+                   ("abb".as_bytes(), "def".as_bytes()));
     }
 }
--- a/src/types.rs	Fri Jul 15 20:21:26 2016 +0200
+++ b/src/types.rs	Sun Jul 17 16:36:56 2016 +0200
@@ -1,4 +1,5 @@
 use std::cmp::Ordering;
+use std::default::Default;
 
 pub enum ValueType {
     TypeDeletion = 0,
@@ -20,11 +21,11 @@
 
 /// Trait used to influence how SkipMap determines the order of elements. Use StandardComparator
 /// for the normal implementation using numerical comparison.
-pub trait Comparator: Copy {
+pub trait Comparator: Copy + Default {
     fn cmp(&[u8], &[u8]) -> Ordering;
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
 pub struct StandardComparator;
 
 impl Comparator for StandardComparator {
@@ -42,7 +43,7 @@
 /// This works because the iterators used are stateful and keep the last returned element.
 ///
 /// Note: Implementing types are expected to hold `!valid()` before the first call to `next()`.
-pub trait LdbIterator<'a>: Iterator {
+pub trait LdbIterator: Iterator {
     // We're emulating LevelDB's Slice type here using actual slices with the lifetime of the
     // iterator. The lifetime of the iterator is usually the one of the backing storage (Block,
     // MemTable, SkipMap...)
@@ -50,12 +51,22 @@
 
     /// Seek the iterator to `key` or the next bigger key.
     fn seek(&mut self, key: &[u8]);
-    /// Resets the iterator to be `!valid()` again
+    /// Resets the iterator to be `!valid()` again (before first element)
     fn reset(&mut self);
     /// Returns true if `current()` would return a valid item.
     fn valid(&self) -> bool;
-    /// Return the current item. Panics if `!valid()`.
-    fn current(&'a self) -> Self::Item;
+    /// Return the current item.
+    fn current(&self) -> Option<Self::Item>;
     /// Go to the previous item.
     fn prev(&mut self) -> Option<Self::Item>;
+
+    /// You should override this with a more efficient solution.
+    fn seek_to_last(&mut self) {
+        while let Some(_) = self.next() {
+        }
+    }
+    fn seek_to_first(&mut self) {
+        self.reset();
+        self.next();
+    }
 }