Added last access time to cache.
This commit is contained in:
		@@ -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());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user