Added last access time to cache.
This commit is contained in:
parent
3164da0f4c
commit
f0f8e7455e
@ -7,19 +7,19 @@ use async_std::{
|
|||||||
};
|
};
|
||||||
use error::DBError;
|
use error::DBError;
|
||||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||||
use std::{collections::HashMap, fmt, str};
|
use std::{collections::HashMap, fmt, str, time::Instant};
|
||||||
|
|
||||||
const DATA: &str = "data";
|
const DATA: &str = "data";
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum CacheEntry {
|
enum CacheType {
|
||||||
Raw(String),
|
Raw(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheEntry {
|
impl CacheType {
|
||||||
fn entry_type(&self) -> String {
|
fn entry_type(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
CacheEntry::Raw(_) => "Raw".to_string(),
|
CacheType::Raw(_) => "Raw".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,12 +27,12 @@ impl CacheEntry {
|
|||||||
let mut output = self.entry_type().into_bytes();
|
let mut output = self.entry_type().into_bytes();
|
||||||
output.push(0);
|
output.push(0);
|
||||||
match self {
|
match self {
|
||||||
CacheEntry::Raw(s) => output.append(&mut s.as_bytes().to_vec()),
|
CacheType::Raw(s) => output.append(&mut s.as_bytes().to_vec()),
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_bytes(data: Vec<u8>) -> CacheEntry {
|
fn from_bytes(data: Vec<u8>) -> CacheType {
|
||||||
let mut data_iter = data.iter();
|
let mut data_iter = data.iter();
|
||||||
let mut holder: u8 = *data_iter.next().unwrap();
|
let mut holder: u8 = *data_iter.next().unwrap();
|
||||||
while holder != 0 {
|
while holder != 0 {
|
||||||
@ -42,15 +42,36 @@ impl CacheEntry {
|
|||||||
for letter in data_iter {
|
for letter in data_iter {
|
||||||
output.push(letter.clone());
|
output.push(letter.clone());
|
||||||
}
|
}
|
||||||
CacheEntry::Raw(str::from_utf8(&output).unwrap().to_string())
|
CacheType::Raw(str::from_utf8(&output).unwrap().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CacheType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
CacheType::Raw(s) => write!(f, "{}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct CacheEntry {
|
||||||
|
data: CacheType,
|
||||||
|
last_used: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheEntry {
|
||||||
|
fn new(data: CacheType) -> Self {
|
||||||
|
Self {
|
||||||
|
data: data,
|
||||||
|
last_used: Instant::now(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for CacheEntry {
|
impl fmt::Display for CacheEntry {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
write!(f, "{}", self.data)
|
||||||
CacheEntry::Raw(s) => write!(f, "{}", s),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +100,7 @@ impl MoreThanText {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_entry(&self, entry: CacheEntry) -> Result<String, DBError> {
|
async fn add_entry(&self, entry: CacheType) -> Result<String, DBError> {
|
||||||
let mut id: String = "".to_string();
|
let mut id: String = "".to_string();
|
||||||
let mut dup = true;
|
let mut dup = true;
|
||||||
while dup {
|
while dup {
|
||||||
@ -95,7 +116,8 @@ impl MoreThanText {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut cache = self.cache.lock().await;
|
let mut cache = self.cache.lock().await;
|
||||||
cache.insert(id.clone(), entry);
|
let data = CacheEntry::new(entry);
|
||||||
|
cache.insert(id.clone(), data);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,13 +126,16 @@ impl MoreThanText {
|
|||||||
match cache.get(id) {
|
match cache.get(id) {
|
||||||
Some(id) => Ok(id.clone()),
|
Some(id) => Ok(id.clone()),
|
||||||
None => match read(Path::new(&self.dir).join(&id)).await {
|
None => match read(Path::new(&self.dir).join(&id)).await {
|
||||||
Ok(content) => Ok(CacheEntry::from_bytes(content)),
|
Ok(content) => {
|
||||||
|
let data = CacheType::from_bytes(content);
|
||||||
|
Ok(CacheEntry::new(data))
|
||||||
|
}
|
||||||
Err(_) => Err(DBError::new("cache entry not found")),
|
Err(_) => Err(DBError::new("cache entry not found")),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_entry(&self, id: &str, entry: CacheEntry) -> Result<(), DBError> {
|
async fn update_entry(&self, id: &str, entry: CacheType) -> Result<(), DBError> {
|
||||||
match self.get_entry(id).await {
|
match self.get_entry(id).await {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -124,7 +149,8 @@ impl MoreThanText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut cache = self.cache.lock().await;
|
let mut cache = self.cache.lock().await;
|
||||||
cache.insert(id.to_string(), entry);
|
let data = CacheEntry::new(entry);
|
||||||
|
cache.insert(id.to_string(), data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,8 +234,8 @@ mod cache {
|
|||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn entry_ids_are_random() {
|
async fn entry_ids_are_random() {
|
||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
let data1 = CacheEntry::Raw("one".to_string());
|
let data1 = CacheType::Raw("one".to_string());
|
||||||
let data2 = CacheEntry::Raw("two".to_string());
|
let data2 = CacheType::Raw("two".to_string());
|
||||||
let id1 = mtt.db.add_entry(data1).await.unwrap();
|
let id1 = mtt.db.add_entry(data1).await.unwrap();
|
||||||
let id2 = mtt.db.add_entry(data2).await.unwrap();
|
let id2 = mtt.db.add_entry(data2).await.unwrap();
|
||||||
assert_ne!(id1, id2, "Ids should be unique.")
|
assert_ne!(id1, id2, "Ids should be unique.")
|
||||||
@ -219,7 +245,7 @@ mod cache {
|
|||||||
async fn store_cache() {
|
async fn store_cache() {
|
||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
let data = "something";
|
let data = "something";
|
||||||
let expected = CacheEntry::Raw(data.to_string());
|
let expected = CacheType::Raw(data.to_string());
|
||||||
let id = mtt.db.add_entry(expected.clone()).await.unwrap();
|
let id = mtt.db.add_entry(expected.clone()).await.unwrap();
|
||||||
let output = mtt.db.get_entry(&id).await.unwrap();
|
let output = mtt.db.get_entry(&id).await.unwrap();
|
||||||
assert_eq!(output.to_string(), data);
|
assert_eq!(output.to_string(), data);
|
||||||
@ -233,7 +259,7 @@ mod cache {
|
|||||||
async fn retrieve_from_disk() {
|
async fn retrieve_from_disk() {
|
||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
let id = "someid";
|
let id = "someid";
|
||||||
let data = CacheEntry::Raw("stored".to_string());
|
let data = CacheType::Raw("stored".to_string());
|
||||||
write(mtt.dir.path().join(DATA).join(id), data.to_bytes())
|
write(mtt.dir.path().join(DATA).join(id), data.to_bytes())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -246,7 +272,7 @@ mod cache {
|
|||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
let msg = "could not write to file";
|
let msg = "could not write to file";
|
||||||
mtt.create_io_error().await;
|
mtt.create_io_error().await;
|
||||||
match mtt.db.add_entry(CacheEntry::Raw("fail".to_string())).await {
|
match mtt.db.add_entry(CacheType::Raw("fail".to_string())).await {
|
||||||
Ok(_) => assert!(false, "This test should fail."),
|
Ok(_) => assert!(false, "This test should fail."),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
assert_eq!(err.to_string(), "data write");
|
assert_eq!(err.to_string(), "data write");
|
||||||
@ -271,11 +297,11 @@ mod cache {
|
|||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
let id = mtt
|
let id = mtt
|
||||||
.db
|
.db
|
||||||
.add_entry(CacheEntry::Raw("same".to_string()))
|
.add_entry(CacheType::Raw("same".to_string()))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let expected = "different";
|
let expected = "different";
|
||||||
let expect = CacheEntry::Raw(expected.to_string());
|
let expect = CacheType::Raw(expected.to_string());
|
||||||
mtt.db.update_entry(&id, expect.clone()).await.unwrap();
|
mtt.db.update_entry(&id, expect.clone()).await.unwrap();
|
||||||
let output = mtt.db.get_entry(&id).await.unwrap();
|
let output = mtt.db.get_entry(&id).await.unwrap();
|
||||||
assert_eq!(output.to_string(), expected);
|
assert_eq!(output.to_string(), expected);
|
||||||
@ -288,7 +314,7 @@ mod cache {
|
|||||||
let mtt = MTT::new().await;
|
let mtt = MTT::new().await;
|
||||||
match mtt
|
match mtt
|
||||||
.db
|
.db
|
||||||
.update_entry("wilma", CacheEntry::Raw("wrong".to_string()))
|
.update_entry("wilma", CacheType::Raw("wrong".to_string()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => assert!(false, "Bad id should raise an error."),
|
Ok(_) => assert!(false, "Bad id should raise an error."),
|
||||||
@ -302,13 +328,13 @@ mod cache {
|
|||||||
let msg = "could not write to file";
|
let msg = "could not write to file";
|
||||||
let id = mtt
|
let id = mtt
|
||||||
.db
|
.db
|
||||||
.add_entry(CacheEntry::Raw("fleeting".to_string()))
|
.add_entry(CacheType::Raw("fleeting".to_string()))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
mtt.create_io_error().await;
|
mtt.create_io_error().await;
|
||||||
match mtt
|
match mtt
|
||||||
.db
|
.db
|
||||||
.update_entry(&id, CacheEntry::Raw("failure".to_string()))
|
.update_entry(&id, CacheType::Raw("failure".to_string()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => assert!(false, "This should produce a write failure."),
|
Ok(_) => assert!(false, "This should produce a write failure."),
|
||||||
@ -328,14 +354,14 @@ mod cache_entry {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn raw_get_type() {
|
fn raw_get_type() {
|
||||||
let holder = CacheEntry::Raw("nothing important".to_string());
|
let holder = CacheType::Raw("nothing important".to_string());
|
||||||
assert_eq!(holder.entry_type(), "Raw");
|
assert_eq!(holder.entry_type(), "Raw");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn raw_get_bytes() {
|
fn raw_get_bytes() {
|
||||||
let data = "addams";
|
let data = "addams";
|
||||||
let holder = CacheEntry::Raw(data.to_string());
|
let holder = CacheType::Raw(data.to_string());
|
||||||
let mut expected = holder.entry_type().into_bytes();
|
let mut expected = holder.entry_type().into_bytes();
|
||||||
expected.push(0);
|
expected.push(0);
|
||||||
expected.append(&mut data.as_bytes().to_vec());
|
expected.append(&mut data.as_bytes().to_vec());
|
||||||
@ -345,9 +371,9 @@ mod cache_entry {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn raw_from_bytes() {
|
fn raw_from_bytes() {
|
||||||
let holder = CacheEntry::Raw("stored item".to_string());
|
let holder = CacheType::Raw("stored item".to_string());
|
||||||
let data = holder.to_bytes();
|
let data = holder.to_bytes();
|
||||||
let output = CacheEntry::from_bytes(data);
|
let output = CacheType::from_bytes(data);
|
||||||
assert_eq!(output.to_string(), holder.to_string());
|
assert_eq!(output.to_string(), holder.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user