garbage collection
This commit is contained in:
parent
19e1f63909
commit
7fa0fd2440
@ -21,6 +21,7 @@ use std::path::{PathBuf};
|
||||
|
||||
const CURRENT_DECLARED_VERSION: u64 = 3;
|
||||
const MAX_KEY_FILE_LEN: u64 = 1024 * 80;
|
||||
const MAX_CACHE_USAGE_TRACK: usize = 128;
|
||||
|
||||
/// Cipher type (currently only aes-128-ctr)
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
@ -461,6 +462,7 @@ impl KeyDirectory {
|
||||
/// warns if any error occured during the key loading
|
||||
pub fn get(&mut self, id: &Uuid) -> Option<&KeyFileContent> {
|
||||
let path = self.key_path(id);
|
||||
self.cache_usage.push_back(id.clone());
|
||||
Some(self.cache.entry(id.to_owned()).or_insert(
|
||||
match KeyDirectory::load_key(&path) {
|
||||
Ok(loaded_key) => loaded_key,
|
||||
@ -477,6 +479,33 @@ impl KeyDirectory {
|
||||
&self.path
|
||||
}
|
||||
|
||||
/// removes keys that never been requested during last `MAX_USAGE_TRACK` times
|
||||
pub fn collect_garbage(&mut self) {
|
||||
let total_usages = self.cache_usage.len();
|
||||
let untracked_usages = max(total_usages as i64 - MAX_CACHE_USAGE_TRACK as i64, 0) as usize;
|
||||
if untracked_usages > 0 {
|
||||
self.cache_usage.drain(..untracked_usages);
|
||||
}
|
||||
|
||||
if self.cache.len() <= MAX_CACHE_USAGE_TRACK { return; }
|
||||
|
||||
let uniqs: HashSet<&Uuid> = self.cache_usage.iter().collect();
|
||||
let mut removes = HashSet::new();
|
||||
|
||||
for key in self.cache.keys() {
|
||||
if !uniqs.contains(key) {
|
||||
removes.insert(key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for removed_key in removes { self.cache.remove(&removed_key); }
|
||||
}
|
||||
|
||||
/// reports how much keys is currently cached
|
||||
pub fn cache_size(&self) -> usize {
|
||||
self.cache.len()
|
||||
}
|
||||
|
||||
fn key_path(&self, id: &Uuid) -> PathBuf {
|
||||
let mut path = PathBuf::new();
|
||||
path.push(self.path.clone());
|
||||
@ -748,7 +777,7 @@ mod file_tests {
|
||||
|
||||
#[cfg(test)]
|
||||
mod directory_tests {
|
||||
use super::{KeyDirectory, new_uuid, uuid_to_string, KeyFileContent, KeyFileCrypto};
|
||||
use super::{KeyDirectory, new_uuid, uuid_to_string, KeyFileContent, KeyFileCrypto, MAX_CACHE_USAGE_TRACK};
|
||||
use common::*;
|
||||
use tests::helpers::*;
|
||||
|
||||
@ -775,6 +804,47 @@ mod directory_tests {
|
||||
|
||||
assert_eq!(key.id, uuid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn caches_keys() {
|
||||
let temp_path = RandomTempPath::create_dir();
|
||||
let mut directory = KeyDirectory::new(&temp_path.as_path());
|
||||
|
||||
let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap();
|
||||
let mut keys = Vec::new();
|
||||
for _ in 0..1000 {
|
||||
let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), U128::zero(), H256::random(), 32, 32));
|
||||
keys.push(directory.save(key).unwrap());
|
||||
}
|
||||
|
||||
for key_id in keys {
|
||||
directory.get(&key_id).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(1000, directory.cache_size())
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collects_garbage() {
|
||||
let temp_path = RandomTempPath::create_dir();
|
||||
let mut directory = KeyDirectory::new(&temp_path.as_path());
|
||||
|
||||
let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap();
|
||||
let mut keys = Vec::new();
|
||||
for _ in 0..1000 {
|
||||
let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), U128::zero(), H256::random(), 32, 32));
|
||||
keys.push(directory.save(key).unwrap());
|
||||
}
|
||||
|
||||
for key_id in keys {
|
||||
directory.get(&key_id).unwrap();
|
||||
}
|
||||
|
||||
directory.collect_garbage();
|
||||
// since all keys are different, should be exactly MAX_CACHE_USAGE_TRACK
|
||||
assert_eq!(MAX_CACHE_USAGE_TRACK, directory.cache_size())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user