changeset 15:bc44456d88d3

Add some documentation to memtable/skipmap implementations.
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 11 Jun 2016 11:51:46 +0200
parents 1d7d9201099e
children 0e88ae259968
files src/memtable.rs src/skipmap.rs
diffstat 2 files changed, 32 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/memtable.rs	Fri Jun 10 21:16:14 2016 +0200
+++ b/src/memtable.rs	Sat Jun 11 11:51:46 2016 +0200
@@ -9,6 +9,8 @@
     key_offset: usize,
 }
 
+/// Encapsulates a user key + sequence number, which is used for lookups in the internal map
+/// implementation of a MemTable.
 impl LookupKey {
     #[allow(unused_assignments)]
     fn new(k: &Vec<u8>, s: SequenceNumber) -> LookupKey {
@@ -34,11 +36,9 @@
     fn memtable_key<'a>(&'a self) -> &'a Vec<u8> {
         return &self.key;
     }
-    fn user_key(&self) -> Vec<u8> {
-        return self.key[self.key_offset..].to_vec();
-    }
 }
 
+/// Provides Insert/Get/Iterate, based on the SkipMap implementation.
 pub struct MemTable<C: Comparator> {
     map: SkipMap<C>,
 }
@@ -61,6 +61,10 @@
         self.map.insert(Self::build_memtable_key(key, value, t, seq), Vec::new())
     }
 
+    /// A memtable key is a bytestring containing (keylen, key, tag, vallen, val). This function
+    /// builds such a key. It's called key because the underlying Map implementation will only be
+    /// concerned with keys; the value field is not used (instead, the value is encoded in the key,
+    /// and for lookups we just search for the next bigger entry).
     fn build_memtable_key(key: &Vec<u8>,
                           value: &Vec<u8>,
                           t: ValueType,
@@ -99,7 +103,9 @@
         buf
     }
 
-    // returns (keylen, key, tag, vallen, val)
+    /// Parses a memtable key and returns (keylen, key, tag, vallen, val).
+    /// If the key only contains (keylen, key, tag), the vallen and val return values will be
+    /// meaningless.
     fn parse_memtable_key(mkey: &Vec<u8>) -> (usize, Vec<u8>, u64, usize, Vec<u8>) {
         let (keylen, mut i): (usize, usize) = VarInt::decode_var(&mkey);
 
--- a/src/skipmap.rs	Fri Jun 10 21:16:14 2016 +0200
+++ b/src/skipmap.rs	Sat Jun 11 11:51:46 2016 +0200
@@ -8,6 +8,8 @@
 const MAX_HEIGHT: usize = 12;
 const BRANCHING_FACTOR: u32 = 4;
 
+/// Trait used to influence how SkipMap determines the order of elements. Use StandardComparator
+/// for the normal implementation using numerical comparison.
 pub trait Comparator {
     fn cmp(&Vec<u8>, &Vec<u8>) -> Ordering;
 }
@@ -20,14 +22,19 @@
     }
 }
 
+/// A node in a skipmap contains links to the next node and others that are further away (skips);
+/// `skips[0]` is the immediate element after, that is, the element contained in `next`.
 struct Node {
     skips: Vec<Option<*mut Node>>,
-    // skips[0] points to the element in next; next provides proper ownership
     next: Option<Box<Node>>,
     key: Vec<u8>,
     value: Vec<u8>,
 }
 
+/// Implements the backing store for a `MemTable`. The important methods are `insert()` and
+/// `contains()`; in order to get full key and value for an entry, use a `SkipMapIter` instance,
+/// `seek()` to the key to look up (this is as fast as any lookup in a skip map), and then call
+/// `current()`.
 pub struct SkipMap<C: Comparator> {
     head: Box<Node>,
     rand: StdRng,
@@ -86,7 +93,7 @@
         n.key.starts_with(&key)
     }
 
-    // Returns the node with key or the next smaller one
+    // Returns the node with key or the next greater one
     fn get_greater_or_equal<'a>(&'a self, key: &Vec<u8>) -> &'a Node {
         // Start at the highest skip link of the head node, and work down from there
         let mut current: *const Node = unsafe { transmute_copy(&self.head.as_ref()) };
@@ -344,5 +351,18 @@
         iter.seek(&"aba".as_bytes().to_vec());
         assert_eq!(iter.current(),
                    (&"aba".as_bytes().to_vec(), &"def".as_bytes().to_vec()));
+
+        iter.seek(&"".as_bytes().to_vec());
+        assert!(iter.valid());
+
+        loop {
+            if let Some(_) = iter.next() {
+
+            } else {
+                break;
+            }
+        }
+        assert_eq!(iter.next(), None);
+
     }
 }