changeset 214:76e4eb726d60

table_reader: Improve API for working with more diverse key types.
author Lewin Bormann <lbo@spheniscida.de>
date Thu, 07 Sep 2017 21:38:47 +0200
parents d8f019641597
children b50ee2e407ba
files src/table_cache.rs src/table_reader.rs
diffstat 2 files changed, 22 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/table_cache.rs	Thu Sep 07 21:38:30 2017 +0200
+++ b/src/table_cache.rs	Thu Sep 07 21:38:47 2017 +0200
@@ -45,13 +45,12 @@
         }
     }
 
-    pub fn get<'a>(&mut self, file_num: u64, key: InternalKey<'a>) -> Result<Option<Vec<u8>>> {
+    pub fn get<'a>(&mut self,
+                   file_num: u64,
+                   key: InternalKey<'a>)
+                   -> Result<Option<(Vec<u8>, Vec<u8>)>> {
         let tbl = self.get_table(file_num)?;
-        if let Some(r) = tbl.get(key) {
-            Ok(Some(r))
-        } else {
-            Ok(None)
-        }
+        Ok(tbl.get(key))
     }
 
     /// Return a table from cache, or open the backing file, then cache and return it.
--- a/src/table_reader.rs	Thu Sep 07 21:38:30 2017 +0200
+++ b/src/table_reader.rs	Thu Sep 07 21:38:47 2017 +0200
@@ -193,10 +193,15 @@
         iter
     }
 
-    /// Retrieve value from table. This function uses the attached filters, so is better suited if
-    /// you frequently look for non-existing values (as it will detect the non-existence of an
-    /// entry in a block without having to load the block).
-    pub fn get<'a>(&self, key: InternalKey<'a>) -> Option<Vec<u8>> {
+    /// Retrieve next-biggest entry for key from table. This function uses the attached filters, so
+    /// is better suited if you frequently look for non-existing values (as it will detect the
+    /// non-existence of an entry in a block without having to load the block).
+    ///
+    /// The caller must check if the returned key is acceptable, as it may not be an exact match
+    /// for key. This is done this way because some key types, like internal keys, will not result
+    /// in an exact match; it depends on other comparators than the one that the table reader knows
+    /// whether a match is acceptable.
+    pub fn get<'a>(&self, key: InternalKey<'a>) -> Option<(Vec<u8>, Vec<u8>)> {
         let mut index_iter = self.indexblock.iter();
         index_iter.seek(key);
 
@@ -231,8 +236,8 @@
         // Go to entry and check if it's the wanted entry.
         iter.seek(key);
         if let Some((k, v)) = current_key_val(&iter) {
-            if self.opt.cmp.cmp(key, &k) == Ordering::Equal {
-                Some(v)
+            if self.opt.cmp.cmp(&k, key) >= Ordering::Equal {
+                Some((k, v))
             } else {
                 None
             }
@@ -449,7 +454,7 @@
         opt.block_size = 32;
         opt.filter_policy = BloomPolicy::new(4);
 
-        let mut i = 0 as u64;
+        let mut i = 1 as u64;
         let data: Vec<(Vec<u8>, &'static str)> = build_data()
             .into_iter()
             .map(|(k, v)| {
@@ -519,19 +524,16 @@
 
         // Go forward again, to last entry.
         while let Some((key, _)) = iter.next() {
-            println!("{:?}", key);
             if key.as_slice() == "zzz".as_bytes() {
                 break;
             }
         }
 
         assert!(iter.valid());
-        println!("{:?}", current_key_val(&iter));
         // backwards count
         let mut j = 0;
 
         while iter.prev() {
-            println!("{:?}", current_key_val(&iter));
             if let Some((k, v)) = current_key_val(&iter) {
                 j += 1;
                 assert_eq!((data[data.len() - 1 - j].0.as_bytes(),
@@ -666,15 +668,17 @@
         let mut _iter = table.iter();
         // Test that all of the table's entries are reachable via get()
         for (k, v) in LdbIteratorIter::wrap(&mut _iter) {
-            assert_eq!(table2.get(&k), Some(v));
+            assert_eq!(table2.get(&k), Some((k, v)));
         }
 
         assert_eq!(table.opt.block_cache.lock().unwrap().count(), 3);
 
+        // test that filters work and don't return anything at all.
         assert!(table.get("aaa".as_bytes()).is_none());
         assert!(table.get("aaaa".as_bytes()).is_none());
         assert!(table.get("aa".as_bytes()).is_none());
         assert!(table.get("abcd".as_bytes()).is_none());
+        assert!(table.get("abb".as_bytes()).is_none());
         assert!(table.get("zzy".as_bytes()).is_none());
         assert!(table.get("zz1".as_bytes()).is_none());
         assert!(table.get("zz{".as_bytes()).is_none());
@@ -700,6 +704,8 @@
             assert_eq!(k.len(), 3 + 8);
         }
 
+        assert!(table.get(LookupKey::new("abc".as_bytes(), 1000).internal_key()).is_some());
+
         let mut iter = table.iter();
 
         loop {
@@ -719,7 +725,6 @@
     #[test]
     fn test_table_reader_checksum() {
         let (mut src, size) = build_table(build_data());
-        println!("{}", size);
 
         src[10] += 1;