diff --git a/src/disk/cache/mod.rs b/src/disk/cache.rs similarity index 80% rename from src/disk/cache/mod.rs rename to src/disk/cache.rs index d20e5ff988023dd55b5c82b457510eb1e4b9693c..351af7f8fc1e5797ae7e56dea63c09d3303518cb 100644 --- a/src/disk/cache/mod.rs +++ b/src/disk/cache.rs @@ -1,14 +1,10 @@ use std::{cmp, ptr}; +use std::collections::{BTreeMap, VecDeque}; use syscall::error::Result; use BLOCK_SIZE; use disk::Disk; -use self::lru_cache::LruCache; - -mod linked_hash_map; -mod lru_cache; - fn copy_memory(src: &[u8], dest: &mut [u8]) -> usize { let len = cmp::min(src.len(), dest.len()); unsafe { ptr::copy(src.as_ptr(), dest.as_mut_ptr(), len) }; @@ -17,15 +13,29 @@ fn copy_memory(src: &[u8], dest: &mut [u8]) -> usize { pub struct DiskCache<T> { inner: T, - cache: LruCache<u64, [u8; BLOCK_SIZE as usize]>, + cache: BTreeMap<u64, [u8; BLOCK_SIZE as usize]>, + order: VecDeque<u64>, + size: usize, } impl<T: Disk> DiskCache<T> { pub fn new(inner: T) -> Self { DiskCache { inner: inner, - cache: LruCache::new((256 * 1024 * 1024 / BLOCK_SIZE) as usize) // 256 MB cache + cache: BTreeMap::new(), + order: VecDeque::new(), + size: 65536, // 256 MB cache + } + } + + fn insert(&mut self, i: u64, data: [u8; BLOCK_SIZE as usize]) { + while self.order.len() >= self.size { + let removed = self.order.pop_front().unwrap(); + self.cache.remove(&removed); } + + self.cache.insert(i, data); + self.order.push_back(i); } } @@ -63,7 +73,7 @@ impl<T: Disk> Disk for DiskCache<T> { let mut cache_buf = [0; BLOCK_SIZE as usize]; read += copy_memory(buffer_slice, &mut cache_buf); - self.cache.insert(block_i, cache_buf); + self.insert(block_i, cache_buf); } } @@ -85,7 +95,7 @@ impl<T: Disk> Disk for DiskCache<T> { let mut cache_buf = [0; BLOCK_SIZE as usize]; written += copy_memory(buffer_slice, &mut cache_buf); - self.cache.insert(block_i, cache_buf); + self.insert(block_i, cache_buf); } Ok(written) diff --git a/src/disk/cache/linked_hash_map.rs b/src/disk/cache/linked_hash_map.rs deleted file mode 100644 index cc8f62064611431ac567fa8fb2e8177f1313fd53..0000000000000000000000000000000000000000 --- a/src/disk/cache/linked_hash_map.rs +++ /dev/null @@ -1,732 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A HashMap wrapper that holds key-value pairs in insertion order. - -#![forbid(missing_docs)] -#![cfg_attr(feature = "nightly", feature(hashmap_public_hasher))] -#![cfg_attr(all(feature = "nightly", test), feature(test))] - -use std::borrow::Borrow; -use std::cmp::Ordering; -use std::collections::hash_map::{self, HashMap}; -use std::fmt; -use std::hash::{BuildHasher, Hash, Hasher}; -use std::iter; -use std::marker; -use std::mem; -use std::ops::{Index, IndexMut}; -use std::ptr; - -struct KeyRef<K> { k: *const K } - -struct LinkedHashMapEntry<K, V> { - next: *mut LinkedHashMapEntry<K, V>, - prev: *mut LinkedHashMapEntry<K, V>, - key: K, - value: V, -} - -/// A linked hash map. -pub struct LinkedHashMap<K, V, S = hash_map::RandomState> { - map: HashMap<KeyRef<K>, Box<LinkedHashMapEntry<K, V>>, S>, - head: *mut LinkedHashMapEntry<K, V>, - free: *mut LinkedHashMapEntry<K, V>, -} - -impl<K: Hash> Hash for KeyRef<K> { - fn hash<H: Hasher>(&self, state: &mut H) { - unsafe { (*self.k).hash(state) } - } -} - -impl<K: PartialEq> PartialEq for KeyRef<K> { - fn eq(&self, other: &Self) -> bool { - unsafe{ (*self.k).eq(&*other.k) } - } -} - -impl<K: Eq> Eq for KeyRef<K> {} - -// This type exists only to support borrowing `KeyRef`s, which cannot be borrowed to `Q` directly -// due to conflicting implementations of `Borrow`. The layout of `&Qey<Q>` must be identical to -// `&Q` in order to support transmuting in the `Qey::from_ref` method. -#[derive(Hash, PartialEq, Eq)] -struct Qey<Q: ?Sized>(Q); - -impl<Q: ?Sized> Qey<Q> { - fn from_ref(q: &Q) -> &Self { unsafe { mem::transmute(q) } } -} - -impl<K, Q: ?Sized> Borrow<Qey<Q>> for KeyRef<K> where K: Borrow<Q> { - fn borrow(&self) -> &Qey<Q> { - Qey::from_ref(unsafe { (*self.k).borrow() }) - } -} - -impl<K, V> LinkedHashMapEntry<K, V> { - fn new(k: K, v: V) -> Self { - LinkedHashMapEntry { - key: k, - value: v, - next: ptr::null_mut(), - prev: ptr::null_mut(), - } - } -} - -unsafe fn drop_empty_entry_box<K, V>(the_box: *mut LinkedHashMapEntry<K, V>) { - // Prevent compiler from trying to drop the un-initialized key and values in the node. - let LinkedHashMapEntry { key, value, .. } = *Box::from_raw(the_box); - mem::forget(key); - mem::forget(value); -} - -impl<K: Hash + Eq, V> LinkedHashMap<K, V> { - /// Creates a linked hash map. - pub fn new() -> Self { Self::with_map(HashMap::new()) } - - /// Creates an empty linked hash map with the given initial capacity. - pub fn with_capacity(capacity: usize) -> Self { - Self::with_map(HashMap::with_capacity(capacity)) - } -} - -impl<K, V, S> LinkedHashMap<K, V, S> { - fn clear_free_list(&mut self) { - unsafe { - let mut free = self.free; - while ! free.is_null() { - let next_free = (*free).next; - drop_empty_entry_box(free); - free = next_free; - } - self.free = ptr::null_mut(); - } - } -} - -impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> { - fn with_map(map: HashMap<KeyRef<K>, Box<LinkedHashMapEntry<K, V>>, S>) -> Self { - LinkedHashMap { - map: map, - head: ptr::null_mut(), - free: ptr::null_mut(), - } - } - - /// Creates an empty linked hash map with the given initial hash state. - pub fn with_hash_state(hash_state: S) -> Self { - Self::with_map(HashMap::with_hasher(hash_state)) - } - - /// Creates an empty linked hash map with the given initial capacity and hash state. - pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S) -> Self { - Self::with_map(HashMap::with_capacity_and_hasher(capacity, hash_state)) - } - - /// Reserves capacity for at least `additional` more elements to be inserted into the map. The - /// map may reserve more space to avoid frequent allocations. - /// - /// # Panics - /// - /// Panics if the new allocation size overflows `usize.` - pub fn reserve(&mut self, additional: usize) { self.map.reserve(additional); } - - /// Shrinks the capacity of the map as much as possible. It will drop down as much as possible - /// while maintaining the internal rules and possibly leaving some space in accordance with the - /// resize policy. - pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit(); - self.clear_free_list(); - } - - /// Inserts a key-value pair into the map. If the key already existed, the old value is - /// returned. - pub fn insert(&mut self, k: K, v: V) -> Option<V> { - if self.head.is_null() { - // allocate the guard node if not present - unsafe { - self.head = Box::into_raw(Box::new(mem::uninitialized())); - (*self.head).next = self.head; - (*self.head).prev = self.head; - } - } - let (node_ptr, node_opt, old_val) = match self.map.get_mut(&KeyRef{k: &k}) { - Some(node) => { - let old_val = mem::replace(&mut node.value, v); - let node_ptr: *mut LinkedHashMapEntry<K, V> = &mut **node; - (node_ptr, None, Some(old_val)) - } - None => { - let mut node = if self.free.is_null() { - Box::new(LinkedHashMapEntry::new(k, v)) - } else { - // use a recycled box - unsafe { - let free = self.free; - self.free = (*free).next; - ptr::write(free, LinkedHashMapEntry::new(k, v)); - Box::from_raw(free) - } - }; - let node_ptr: *mut LinkedHashMapEntry<K, V> = &mut *node; - (node_ptr, Some(node), None) - } - }; - match node_opt { - None => { - // Existing node, just update LRU position - self.detach(node_ptr); - self.attach(node_ptr); - } - Some(node) => { - let keyref = unsafe { &(*node_ptr).key }; - self.map.insert(KeyRef{k: keyref}, node); - self.attach(node_ptr); - } - } - old_val - } - - /// Checks if the map contains the given key. - pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool where K: Borrow<Q>, Q: Eq + Hash { - self.map.contains_key(Qey::from_ref(k)) - } - - /// Returns the value corresponding to the key in the map. - pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Eq + Hash { - self.map.get(Qey::from_ref(k)).map(|e| &e.value) - } - - /// Returns the mutable reference corresponding to the key in the map. - pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash { - self.map.get_mut(Qey::from_ref(k)).map(|e| &mut e.value) - } - - /// Returns the value corresponding to the key in the map. - /// - /// If value is found, it is moved to the end of the list. - /// This operation can be used in implemenation of LRU cache. - pub fn get_refresh<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash { - let (value, node_ptr_opt) = match self.map.get_mut(Qey::from_ref(k)) { - None => (None, None), - Some(node) => { - let node_ptr: *mut LinkedHashMapEntry<K, V> = &mut **node; - (Some(unsafe { &mut(*node_ptr).value }), Some(node_ptr)) - } - }; - if let Some(node_ptr) = node_ptr_opt { - self.detach(node_ptr); - self.attach(node_ptr); - } - return value; - } - - /// Removes and returns the value corresponding to the key from the map. - pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Eq + Hash { - let removed = self.map.remove(Qey::from_ref(k)); - removed.map(|mut node| { - let node_ptr: *mut LinkedHashMapEntry<K,V> = &mut *node; - self.detach(node_ptr); - unsafe { - // add to free list - (*node_ptr).next = self.free; - self.free = node_ptr; - // forget the box but drop the key and return the value - mem::forget(node); - drop(ptr::read(&(*node_ptr).key)); - ptr::read(&(*node_ptr).value) - } - }) - } - - /// Returns the maximum number of key-value pairs the map can hold without reallocating. - pub fn capacity(&self) -> usize { - self.map.capacity() - } - - /// Removes the first entry. - /// - /// Can be used in implementation of LRU cache. - #[inline] - pub fn pop_front(&mut self) -> Option<(K, V)> { - if self.len() > 0 { - let lru = unsafe { (*self.head).prev }; - self.detach(lru); - return self.map - .remove(&KeyRef{k: unsafe { &(*lru).key }}) - .map(|e| { let e = *e; (e.key, e.value) }) - } - None - } - - /// Gets the first entry. - #[inline] - pub fn front(&self) -> Option<(&K, &V)> { - if self.len() > 0 { - let lru = unsafe { (*self.head).prev }; - return self.map.get(&KeyRef{k: unsafe { &(*lru).key }}) - .map(|e| (&e.key, &e.value)) - } - None - } - - /// Removes the last entry. - #[inline] - pub fn pop_back(&mut self) -> Option<(K, V)> { - if self.len() > 0 { - let mru = unsafe { (*self.head).next }; - self.detach(mru); - return self.map - .remove(&KeyRef{k: unsafe { &(*mru).key }}) - .map(|e| { let e = *e; (e.key, e.value) }) - } - None - } - - /// Gets the last entry. - #[inline] - pub fn back(&mut self) -> Option<(&K, &V)> { - if self.len() > 0 { - let mru = unsafe { (*self.head).next }; - return self.map.get(&KeyRef{k: unsafe { &(*mru).key }}) - .map(|e| (&e.key, &e.value)) - } - None - } - - /// Returns the number of key-value pairs in the map. - pub fn len(&self) -> usize { self.map.len() } - - /// Returns whether the map is currently empty. - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the map of all key-value pairs. - pub fn clear(&mut self) { - self.map.clear(); - // update the guard node if present - if ! self.head.is_null() { - unsafe { - (*self.head).prev = self.head; - (*self.head).next = self.head; - } - } - } - - /// Returns a double-ended iterator visiting all key-value pairs in order of insertion. - /// Iterator element type is `(&'a K, &'a V)` - pub fn iter(&self) -> Iter<K, V> { - let head = if ! self.head.is_null() { - unsafe { (*self.head).prev } - } else { - ptr::null_mut() - }; - Iter { - head: head, - tail: self.head, - remaining: self.len(), - marker: marker::PhantomData, - } - } - - /// Returns a double-ended iterator visiting all key-value pairs in order of insertion. - /// Iterator element type is `(&'a K, &'a mut V)` - pub fn iter_mut(&mut self) -> IterMut<K, V> { - let head = if ! self.head.is_null() { - unsafe { (*self.head).prev } - } else { - ptr::null_mut() - }; - IterMut { - head: head, - tail: self.head, - remaining: self.len(), - marker: marker::PhantomData, - } - } - - /// Returns a double-ended iterator visiting all key in order of insertion. - pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { - fn first<A, B>((a, _): (A, B)) -> A { a } - let first: fn((&'a K, &'a V)) -> &'a K = first; // coerce to fn ptr - - Keys { inner: self.iter().map(first) } - } - - /// Returns a double-ended iterator visiting all values in order of insertion. - pub fn values<'a>(&'a self) -> Values<'a, K, V> { - fn second<A, B>((_, b): (A, B)) -> B { b } - let second: fn((&'a K, &'a V)) -> &'a V = second; // coerce to fn ptr - - Values { inner: self.iter().map(second) } - } -} - -impl<'a, K, V, S, Q: ?Sized> Index<&'a Q> for LinkedHashMap<K, V, S> - where K: Hash + Eq + Borrow<Q>, S: BuildHasher, Q: Eq + Hash -{ - type Output = V; - - fn index(&self, index: &'a Q) -> &V { - self.get(index).expect("no entry found for key") - } -} - -impl<'a, K, V, S, Q: ?Sized> IndexMut<&'a Q> for LinkedHashMap<K, V, S> - where K: Hash + Eq + Borrow<Q>, S: BuildHasher, Q: Eq + Hash -{ - fn index_mut(&mut self, index: &'a Q) -> &mut V { - self.get_mut(index).expect("no entry found for key") - } -} - -impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> { - #[inline] - fn detach(&mut self, node: *mut LinkedHashMapEntry<K, V>) { - unsafe { - (*(*node).prev).next = (*node).next; - (*(*node).next).prev = (*node).prev; - } - } - - #[inline] - fn attach(&mut self, node: *mut LinkedHashMapEntry<K, V>) { - unsafe { - (*node).next = (*self.head).next; - (*node).prev = self.head; - (*self.head).next = node; - (*(*node).next).prev = node; - } - } -} - -#[cfg(not(feature = "nightly"))] -impl<K: Hash + Eq + Clone, V: Clone> Clone for LinkedHashMap<K, V> { - fn clone(&self) -> Self { - self.iter().map(|(k, v)| (k.clone(), v.clone())).collect() - } -} - -#[cfg(feature = "nightly")] -impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher + Clone> Clone for LinkedHashMap<K, V, S> { - fn clone(&self) -> Self { - let mut map = Self::with_hash_state(self.map.hasher().clone()); - map.extend(self.iter().map(|(k, v)| (k.clone(), v.clone()))); - map - } -} - -impl<K: Hash + Eq, V, S: BuildHasher + Default> Default for LinkedHashMap<K, V, S> { - fn default() -> Self { LinkedHashMap::with_hash_state(Default::default()) } -} - -impl<K: Hash + Eq, V, S: BuildHasher> Extend<(K, V)> for LinkedHashMap<K, V, S> { - fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -impl<'a, K, V, S> Extend<(&'a K, &'a V)> for LinkedHashMap<K, V, S> - where K: 'a + Hash + Eq + Copy, V: 'a + Copy, S: BuildHasher, -{ - fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) { - for (&k, &v) in iter { - self.insert(k, v); - } - } -} - -impl<K: Hash + Eq, V, S: BuildHasher + Default> iter::FromIterator<(K, V)> for LinkedHashMap<K, V, S> { - fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self { - let iter = iter.into_iter(); - let mut map = Self::with_capacity_and_hash_state(iter.size_hint().0, Default::default()); - map.extend(iter); - map - } -} - -impl<A: fmt::Debug + Hash + Eq, B: fmt::Debug, S: BuildHasher> fmt::Debug for LinkedHashMap<A, B, S> { - /// Returns a string that lists the key-value pairs in insertion order. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_map().entries(self).finish() - } -} - -impl<K: Hash + Eq, V: PartialEq, S: BuildHasher> PartialEq for LinkedHashMap<K, V, S> { - fn eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.iter().eq(other) - } - - fn ne(&self, other: &Self) -> bool { - self.len() != other.len() || self.iter().ne(other) - } -} - -impl<K: Hash + Eq, V: Eq, S: BuildHasher> Eq for LinkedHashMap<K, V, S> {} - -impl<K: Hash + Eq + PartialOrd, V: PartialOrd, S: BuildHasher> PartialOrd for LinkedHashMap<K, V, S> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.iter().partial_cmp(other) - } - - fn lt(&self, other: &Self) -> bool { - self.iter().lt(other) - } - - fn le(&self, other: &Self) -> bool { - self.iter().le(other) - } - - fn ge(&self, other: &Self) -> bool { - self.iter().ge(other) - } - - fn gt(&self, other: &Self) -> bool { - self.iter().gt(other) - } -} - -impl<K: Hash + Eq + Ord, V: Ord, S: BuildHasher> Ord for LinkedHashMap<K, V, S> { - fn cmp(&self, other: &Self) -> Ordering { - self.iter().cmp(other) - } -} - -impl<K: Hash + Eq, V: Hash, S: BuildHasher> Hash for LinkedHashMap<K, V, S> { - fn hash<H: Hasher>(&self, h: &mut H) { for e in self.iter() { e.hash(h); } } -} - -unsafe impl<K: Send, V: Send, S: Send> Send for LinkedHashMap<K, V, S> {} - -unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {} - -impl<K, V, S> Drop for LinkedHashMap<K, V, S> { - fn drop(&mut self) { - unsafe { - if ! self.head.is_null() { - drop_empty_entry_box(self.head); - } - self.clear_free_list(); - } - } -} - -/// An insertion-order iterator over a `LinkedHashMap`'s entries, with immutable references to the -/// values. -pub struct Iter<'a, K: 'a, V: 'a> { - head: *const LinkedHashMapEntry<K, V>, - tail: *const LinkedHashMapEntry<K, V>, - remaining: usize, - marker: marker::PhantomData<(&'a K, &'a V)>, -} - -/// An insertion-order iterator over a `LinkedHashMap`'s entries, with mutable references to the -/// values. -pub struct IterMut<'a, K: 'a, V: 'a> { - head: *mut LinkedHashMapEntry<K, V>, - tail: *mut LinkedHashMapEntry<K, V>, - remaining: usize, - marker: marker::PhantomData<(&'a K, &'a mut V)>, -} - -unsafe impl<'a, K, V> Send for Iter<'a, K, V> where K: Send, V: Send {} - -unsafe impl<'a, K, V> Send for IterMut<'a, K, V> where K: Send, V: Send {} - -unsafe impl<'a, K, V> Sync for Iter<'a, K, V> where K: Sync, V: Sync {} - -unsafe impl<'a, K, V> Sync for IterMut<'a, K, V> where K: Sync, V: Sync {} - -impl<'a, K, V> Clone for Iter<'a, K, V> { - fn clone(&self) -> Self { Iter { ..*self } } -} - -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option<(&'a K, &'a V)> { - if self.head == self.tail { - None - } else { - self.remaining -= 1; - unsafe { - let r = Some((&(*self.head).key, &(*self.head).value)); - self.head = (*self.head).prev; - r - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.remaining, Some(self.remaining)) - } -} - -impl<'a, K, V> Iterator for IterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - if self.head == self.tail { - None - } else { - self.remaining -= 1; - unsafe { - let r = Some((&(*self.head).key, &mut (*self.head).value)); - self.head = (*self.head).prev; - r - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.remaining, Some(self.remaining)) - } -} - -impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { - fn next_back(&mut self) -> Option<(&'a K, &'a V)> { - if self.head == self.tail { - None - } else { - self.remaining -= 1; - unsafe { - self.tail = (*self.tail).next; - let r = Some((&(*self.tail).key, &(*self.tail).value)); - r - } - } - } -} - -impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { - fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { - if self.head == self.tail { - None - } else { - self.remaining -= 1; - unsafe { - self.tail = (*self.tail).next; - let r = Some((&(*self.tail).key, &mut (*self.tail).value)); - r - } - } - } -} - -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { - fn len(&self) -> usize { self.remaining } -} - -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { - fn len(&self) -> usize { self.remaining } -} - -/// An insertion-order iterator over a `LinkedHashMap`'s keys. -pub struct Keys<'a, K: 'a, V: 'a> { - inner: iter::Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> -} - -impl<'a, K, V> Clone for Keys<'a, K, V> { - fn clone(&self) -> Self { Keys { inner: self.inner.clone() } } -} - -impl<'a, K, V> Iterator for Keys<'a, K, V> { - type Item = &'a K; - - #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } -} - -impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { - #[inline] fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() } -} - -impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { - fn len(&self) -> usize { self.inner.len() } -} - -/// An insertion-order iterator over a `LinkedHashMap`'s values. -pub struct Values<'a, K: 'a, V: 'a> { - inner: iter::Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> -} - -impl<'a, K, V> Clone for Values<'a, K, V> { - fn clone(&self) -> Self { Values { inner: self.inner.clone() } } -} - -impl<'a, K, V> Iterator for Values<'a, K, V> { - type Item = &'a V; - - #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } -} - -impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { - #[inline] fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() } -} - -impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { - fn len(&self) -> usize { self.inner.len() } -} - -impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a LinkedHashMap<K, V, S> { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - fn into_iter(self) -> Iter<'a, K, V> { self.iter() } -} - -impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a mut LinkedHashMap<K, V, S> { - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() } -} - -#[cfg(all(feature = "nightly", test))] -mod bench { - extern crate test; - - use super::LinkedHashMap; - - #[bench] - fn not_recycled_cycling(b: &mut test::Bencher) { - let mut hash_map = LinkedHashMap::with_capacity(1000); - for i in 0usize..1000 { - hash_map.insert(i, i); - } - b.iter(|| { - for i in 0usize..1000 { - hash_map.remove(&i); - } - hash_map.clear_free_list(); - for i in 0usize..1000 { - hash_map.insert(i, i); - } - }) - } - - #[bench] - fn recycled_cycling(b: &mut test::Bencher) { - let mut hash_map = LinkedHashMap::with_capacity(1000); - for i in 0usize..1000 { - hash_map.insert(i, i); - } - b.iter(|| { - for i in 0usize..1000 { - hash_map.remove(&i); - } - for i in 0usize..1000 { - hash_map.insert(i, i); - } - }) - } -} diff --git a/src/disk/cache/lru_cache.rs b/src/disk/cache/lru_cache.rs deleted file mode 100644 index b5ea5e996568af82056303028f2c05bdc4559571..0000000000000000000000000000000000000000 --- a/src/disk/cache/lru_cache.rs +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A cache that holds a limited number of key-value pairs. When the -//! capacity of the cache is exceeded, the least-recently-used -//! (where "used" means a look-up or putting the pair into the cache) -//! pair is automatically removed. - -use std::collections::hash_map::RandomState; -use std::fmt; -use std::hash::{Hash, BuildHasher}; -use std::borrow::Borrow; - -use super::linked_hash_map::{self, LinkedHashMap}; - -// FIXME(conventions): implement indexing? - -/// An LRU cache. -pub struct LruCache<K, V, S = RandomState> where K: Eq + Hash, S: BuildHasher { - map: LinkedHashMap<K, V, S>, - max_size: usize, -} - -impl<K: Hash + Eq, V> LruCache<K, V> { - /// Creates an empty cache that can hold at most `capacity` items. - pub fn new(capacity: usize) -> LruCache<K, V> { - LruCache { - map: LinkedHashMap::new(), - max_size: capacity, - } - } -} - -impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher { - /// Creates an empty cache that can hold at most `capacity` items with the given hash state. - pub fn with_hash_state(capacity: usize, hash_state: S) -> LruCache<K, V, S> { - LruCache { map: LinkedHashMap::with_hash_state(hash_state), max_size: capacity } - } - - /// Checks if the map contains the given key. - pub fn contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool - where K: Borrow<Q>, - Q: Hash + Eq - { - self.get_mut(key).is_some() - } - - /// Inserts a key-value pair into the cache. If the key already existed, the old value is - /// returned. - pub fn insert(&mut self, k: K, v: V) -> Option<V> { - let old_val = self.map.insert(k, v); - if self.len() > self.capacity() { - self.remove_lru(); - } - old_val - } - - /// Returns a mutable reference to the value corresponding to the given key in the cache, if - /// any. - pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> - where K: Borrow<Q>, - Q: Hash + Eq - { - self.map.get_refresh(k) - } - - /// Removes the given key from the cache and returns its corresponding value. - pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> - where K: Borrow<Q>, - Q: Hash + Eq - { - self.map.remove(k) - } - - /// Returns the maximum number of key-value pairs the cache can hold. - pub fn capacity(&self) -> usize { - self.max_size - } - - /// Sets the number of key-value pairs the cache can hold. Removes - /// least-recently-used key-value pairs if necessary. - pub fn set_capacity(&mut self, capacity: usize) { - for _ in capacity..self.len() { - self.remove_lru(); - } - self.max_size = capacity; - } - - #[inline] - fn remove_lru(&mut self) -> Option<(K, V)> { - self.map.pop_front() - } - - /// Returns the number of key-value pairs in the cache. - pub fn len(&self) -> usize { self.map.len() } - - /// Returns `true` if the cache contains no key-value pairs. - pub fn is_empty(&self) -> bool { self.map.is_empty() } - - /// Removes all key-value pairs from the cache. - pub fn clear(&mut self) { self.map.clear(); } - - /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order. - /// - /// Accessing the cache through the iterator does _not_ affect the cache's LRU state. - pub fn iter(&self) -> Iter<K, V> { Iter(self.map.iter()) } - - /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order, - /// with mutable references to the values. - /// - /// Accessing the cache through the iterator does _not_ affect the cache's LRU state. - pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) } -} - -impl<K: Hash + Eq, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> { - fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -impl<A: fmt::Debug + Hash + Eq, B: fmt::Debug, S: BuildHasher> fmt::Debug for LruCache<A, B, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_map().entries(self.iter().rev()).finish() - } -} - -impl<'a, K, V, S> IntoIterator for &'a LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - fn into_iter(self) -> Iter<'a, K, V> { self.iter() } -} - -impl<'a, K, V, S> IntoIterator for &'a mut LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher { - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() } -} - -impl<K, V> Clone for LruCache<K, V> where K: Clone + Eq + Hash, V: Clone { - fn clone(&self) -> LruCache<K, V> { LruCache { map: self.map.clone(), ..*self } } -} - -/// An iterator over a cache's key-value pairs in least- to most-recently-used order. -/// -/// Accessing a cache through the iterator does _not_ affect the cache's LRU state. -pub struct Iter<'a, K: 'a, V: 'a>(linked_hash_map::Iter<'a, K, V>); - -impl<'a, K, V> Clone for Iter<'a, K, V> { - fn clone(&self) -> Iter<'a, K, V> { Iter(self.0.clone()) } -} - -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - fn next(&mut self) -> Option<(&'a K, &'a V)> { self.0.next() } - fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } -} - -impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { - fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.0.next_back() } -} - -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { - fn len(&self) -> usize { self.0.len() } -} - -/// An iterator over a cache's key-value pairs in least- to most-recently-used order with mutable -/// references to the values. -/// -/// Accessing a cache through the iterator does _not_ affect the cache's LRU state. -pub struct IterMut<'a, K: 'a, V: 'a>(linked_hash_map::IterMut<'a, K, V>); - -impl<'a, K, V> Iterator for IterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next() } - fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } -} - -impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { - fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next_back() } -} - -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { - fn len(&self) -> usize { self.0.len() } -} - -#[cfg(test)] -mod tests { - use super::LruCache; - - #[test] - fn test_put_and_get() { - let mut cache = LruCache::new(2); - cache.insert(1, 10); - cache.insert(2, 20); - assert_eq!(cache.get_mut(&1), Some(&mut 10)); - assert_eq!(cache.get_mut(&2), Some(&mut 20)); - assert_eq!(cache.len(), 2); - } - - #[test] - fn test_put_update() { - let mut cache = LruCache::new(1); - cache.insert("1", 10); - cache.insert("1", 19); - assert_eq!(cache.get_mut("1"), Some(&mut 19)); - assert_eq!(cache.len(), 1); - } - - #[test] - fn test_contains_key() { - let mut cache = LruCache::new(1); - cache.insert("1", 10); - assert_eq!(cache.contains_key("1"), true); - } - - #[test] - fn test_expire_lru() { - let mut cache = LruCache::new(2); - cache.insert("foo1", "bar1"); - cache.insert("foo2", "bar2"); - cache.insert("foo3", "bar3"); - assert!(cache.get_mut("foo1").is_none()); - cache.insert("foo2", "bar2update"); - cache.insert("foo4", "bar4"); - assert!(cache.get_mut("foo3").is_none()); - } - - #[test] - fn test_pop() { - let mut cache = LruCache::new(2); - cache.insert(1, 10); - cache.insert(2, 20); - assert_eq!(cache.len(), 2); - let opt1 = cache.remove(&1); - assert!(opt1.is_some()); - assert_eq!(opt1.unwrap(), 10); - assert!(cache.get_mut(&1).is_none()); - assert_eq!(cache.len(), 1); - } - - #[test] - fn test_change_capacity() { - let mut cache = LruCache::new(2); - assert_eq!(cache.capacity(), 2); - cache.insert(1, 10); - cache.insert(2, 20); - cache.set_capacity(1); - assert!(cache.get_mut(&1).is_none()); - assert_eq!(cache.capacity(), 1); - } - - #[test] - fn test_debug() { - let mut cache = LruCache::new(3); - cache.insert(1, 10); - cache.insert(2, 20); - cache.insert(3, 30); - assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}"); - cache.insert(2, 22); - assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}"); - cache.insert(6, 60); - assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}"); - cache.get_mut(&3); - assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}"); - cache.set_capacity(2); - assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}"); - } - - #[test] - fn test_remove() { - let mut cache = LruCache::new(3); - cache.insert(1, 10); - cache.insert(2, 20); - cache.insert(3, 30); - cache.insert(4, 40); - cache.insert(5, 50); - cache.remove(&3); - cache.remove(&4); - assert!(cache.get_mut(&3).is_none()); - assert!(cache.get_mut(&4).is_none()); - cache.insert(6, 60); - cache.insert(7, 70); - cache.insert(8, 80); - assert!(cache.get_mut(&5).is_none()); - assert_eq!(cache.get_mut(&6), Some(&mut 60)); - assert_eq!(cache.get_mut(&7), Some(&mut 70)); - assert_eq!(cache.get_mut(&8), Some(&mut 80)); - } - - #[test] - fn test_clear() { - let mut cache = LruCache::new(2); - cache.insert(1, 10); - cache.insert(2, 20); - cache.clear(); - assert!(cache.get_mut(&1).is_none()); - assert!(cache.get_mut(&2).is_none()); - assert_eq!(format!("{:?}", cache), "{}"); - } - - #[test] - fn test_iter() { - let mut cache = LruCache::new(3); - cache.insert(1, 10); - cache.insert(2, 20); - cache.insert(3, 30); - cache.insert(4, 40); - cache.insert(5, 50); - assert_eq!(cache.iter().collect::<Vec<_>>(), - [(&3, &30), (&4, &40), (&5, &50)]); - assert_eq!(cache.iter_mut().collect::<Vec<_>>(), - [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]); - assert_eq!(cache.iter().rev().collect::<Vec<_>>(), - [(&5, &50), (&4, &40), (&3, &30)]); - assert_eq!(cache.iter_mut().rev().collect::<Vec<_>>(), - [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]); - } -}