Mercurial > lbo > hg > leveldb-rs
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); + } }