From f0f8e7455eef85f1a28057e23e4c286f680d5f73 Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Wed, 21 Dec 2022 10:27:16 -0500 Subject: [PATCH] Added last access time to cache. --- src/morethantext/mod.rs | 84 +++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/src/morethantext/mod.rs b/src/morethantext/mod.rs index d8023e3..5a2ccf7 100644 --- a/src/morethantext/mod.rs +++ b/src/morethantext/mod.rs @@ -7,19 +7,19 @@ use async_std::{ }; use error::DBError; 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"; #[derive(Clone)] -enum CacheEntry { +enum CacheType { Raw(String), } -impl CacheEntry { +impl CacheType { fn entry_type(&self) -> String { 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(); output.push(0); 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; } - fn from_bytes(data: Vec) -> CacheEntry { + fn from_bytes(data: Vec) -> CacheType { let mut data_iter = data.iter(); let mut holder: u8 = *data_iter.next().unwrap(); while holder != 0 { @@ -42,15 +42,36 @@ impl CacheEntry { for letter in data_iter { 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - CacheEntry::Raw(s) => write!(f, "{}", s), - } + write!(f, "{}", self.data) } } @@ -79,7 +100,7 @@ impl MoreThanText { }) } - async fn add_entry(&self, entry: CacheEntry) -> Result { + async fn add_entry(&self, entry: CacheType) -> Result { let mut id: String = "".to_string(); let mut dup = true; while dup { @@ -95,7 +116,8 @@ impl MoreThanText { } }; let mut cache = self.cache.lock().await; - cache.insert(id.clone(), entry); + let data = CacheEntry::new(entry); + cache.insert(id.clone(), data); Ok(id) } @@ -104,13 +126,16 @@ impl MoreThanText { match cache.get(id) { Some(id) => Ok(id.clone()), 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")), }, } } - 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 { Ok(_) => (), Err(err) => return Err(err), @@ -124,7 +149,8 @@ impl MoreThanText { } } 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(()) } } @@ -208,8 +234,8 @@ mod cache { #[async_std::test] async fn entry_ids_are_random() { let mtt = MTT::new().await; - let data1 = CacheEntry::Raw("one".to_string()); - let data2 = CacheEntry::Raw("two".to_string()); + let data1 = CacheType::Raw("one".to_string()); + let data2 = CacheType::Raw("two".to_string()); let id1 = mtt.db.add_entry(data1).await.unwrap(); let id2 = mtt.db.add_entry(data2).await.unwrap(); assert_ne!(id1, id2, "Ids should be unique.") @@ -219,7 +245,7 @@ mod cache { async fn store_cache() { let mtt = MTT::new().await; 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 output = mtt.db.get_entry(&id).await.unwrap(); assert_eq!(output.to_string(), data); @@ -233,7 +259,7 @@ mod cache { async fn retrieve_from_disk() { let mtt = MTT::new().await; 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()) .await .unwrap(); @@ -246,7 +272,7 @@ mod cache { let mtt = MTT::new().await; let msg = "could not write to file"; 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."), Err(err) => { assert_eq!(err.to_string(), "data write"); @@ -271,11 +297,11 @@ mod cache { let mtt = MTT::new().await; let id = mtt .db - .add_entry(CacheEntry::Raw("same".to_string())) + .add_entry(CacheType::Raw("same".to_string())) .await .unwrap(); 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(); let output = mtt.db.get_entry(&id).await.unwrap(); assert_eq!(output.to_string(), expected); @@ -288,7 +314,7 @@ mod cache { let mtt = MTT::new().await; match mtt .db - .update_entry("wilma", CacheEntry::Raw("wrong".to_string())) + .update_entry("wilma", CacheType::Raw("wrong".to_string())) .await { Ok(_) => assert!(false, "Bad id should raise an error."), @@ -302,13 +328,13 @@ mod cache { let msg = "could not write to file"; let id = mtt .db - .add_entry(CacheEntry::Raw("fleeting".to_string())) + .add_entry(CacheType::Raw("fleeting".to_string())) .await .unwrap(); mtt.create_io_error().await; match mtt .db - .update_entry(&id, CacheEntry::Raw("failure".to_string())) + .update_entry(&id, CacheType::Raw("failure".to_string())) .await { Ok(_) => assert!(false, "This should produce a write failure."), @@ -328,14 +354,14 @@ mod cache_entry { #[test] 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"); } #[test] fn raw_get_bytes() { 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(); expected.push(0); expected.append(&mut data.as_bytes().to_vec()); @@ -345,9 +371,9 @@ mod cache_entry { #[test] 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 output = CacheEntry::from_bytes(data); + let output = CacheType::from_bytes(data); assert_eq!(output.to_string(), holder.to_string()); } }