added Entry update function.
This commit is contained in:
		@@ -1,10 +1,12 @@
 | 
				
			|||||||
use super::{DBError, FileData, SessionData, Store};
 | 
					use super::{DBError, FileData, SessionData, Store};
 | 
				
			||||||
use async_std::{fs::{read, write}, path::Path};
 | 
					use async_std::{
 | 
				
			||||||
 | 
					    fs::{read, remove_file, write},
 | 
				
			||||||
 | 
					    path::Path,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
 | 
					use rand::{distributions::Alphanumeric, thread_rng, Rng};
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    cell::Cell,
 | 
					    cell::Cell,
 | 
				
			||||||
    slice,
 | 
					    slice, str,
 | 
				
			||||||
    str,
 | 
					 | 
				
			||||||
    time::{Duration, Instant},
 | 
					    time::{Duration, Instant},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,7 +52,7 @@ impl FileData<Self> for DataType {
 | 
				
			|||||||
                output.append(&mut "DBMap".as_bytes().to_vec());
 | 
					                output.append(&mut "DBMap".as_bytes().to_vec());
 | 
				
			||||||
                output.push(0);
 | 
					                output.push(0);
 | 
				
			||||||
                output.append(&mut store.to_bytes());
 | 
					                output.append(&mut store.to_bytes());
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        output
 | 
					        output
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -73,11 +75,9 @@ impl FileData<Self> for DataType {
 | 
				
			|||||||
            Err(_) => return Err(DBError::new("file corruption")),
 | 
					            Err(_) => return Err(DBError::new("file corruption")),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        match header {
 | 
					        match header {
 | 
				
			||||||
            "DBMap" => {
 | 
					            "DBMap" => match Store::from_bytes(data) {
 | 
				
			||||||
                match Store::from_bytes(data) {
 | 
					                Ok(store) => Ok(DataType::DBMap(store)),
 | 
				
			||||||
                    Ok(store) => Ok(DataType::DBMap(store)),
 | 
					                Err(err) => Err(err),
 | 
				
			||||||
                    Err(err) => Err(err),
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            _ => Err(DBError::new("file corruption")),
 | 
					            _ => Err(DBError::new("file corruption")),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -120,6 +120,21 @@ impl Entry {
 | 
				
			|||||||
        self.last_used.set(Instant::now());
 | 
					        self.last_used.set(Instant::now());
 | 
				
			||||||
        Ok(self.data.clone())
 | 
					        Ok(self.data.clone())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn update(&mut self, data: DataType) -> Result<(), DBError> {
 | 
				
			||||||
 | 
					        self.last_used.set(Instant::now());
 | 
				
			||||||
 | 
					        let filepath = Path::new(&self.filename);
 | 
				
			||||||
 | 
					        match write(filepath, data.to_bytes()).await {
 | 
				
			||||||
 | 
					            Ok(_) => (),
 | 
				
			||||||
 | 
					            Err(err) => {
 | 
				
			||||||
 | 
					                let mut error = DBError::new("write error");
 | 
				
			||||||
 | 
					                error.add_source(err);
 | 
				
			||||||
 | 
					                return Err(error);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        self.data = data;
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Cache;
 | 
					struct Cache;
 | 
				
			||||||
@@ -194,7 +209,10 @@ mod datatype_file {
 | 
				
			|||||||
        let data = dt_store.to_bytes();
 | 
					        let data = dt_store.to_bytes();
 | 
				
			||||||
        let mut feed = data.iter();
 | 
					        let mut feed = data.iter();
 | 
				
			||||||
        let output = DataType::from_bytes(&mut feed).unwrap();
 | 
					        let output = DataType::from_bytes(&mut feed).unwrap();
 | 
				
			||||||
        assert_eq!(dt_store.list(["database"].to_vec()).unwrap(), output.list(["database"].to_vec()).unwrap());
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            dt_store.list(["database"].to_vec()).unwrap(),
 | 
				
			||||||
 | 
					            output.list(["database"].to_vec()).unwrap()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
@@ -204,7 +222,10 @@ mod datatype_file {
 | 
				
			|||||||
        let data = dt_store.to_bytes();
 | 
					        let data = dt_store.to_bytes();
 | 
				
			||||||
        let mut feed = data.iter();
 | 
					        let mut feed = data.iter();
 | 
				
			||||||
        let output = DataType::from_bytes(&mut feed).unwrap();
 | 
					        let output = DataType::from_bytes(&mut feed).unwrap();
 | 
				
			||||||
        assert_eq!(dt_store.list(["database"].to_vec()).unwrap(), output.list(["database"].to_vec()).unwrap());
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            dt_store.list(["database"].to_vec()).unwrap(),
 | 
				
			||||||
 | 
					            output.list(["database"].to_vec()).unwrap()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
@@ -216,7 +237,7 @@ mod datatype_file {
 | 
				
			|||||||
            Err(err) => {
 | 
					            Err(err) => {
 | 
				
			||||||
                assert_eq!(err.to_string(), "file corruption");
 | 
					                assert_eq!(err.to_string(), "file corruption");
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -231,7 +252,7 @@ mod datatype_file {
 | 
				
			|||||||
            Err(err) => {
 | 
					            Err(err) => {
 | 
				
			||||||
                assert_eq!(err.to_string(), "file corruption");
 | 
					                assert_eq!(err.to_string(), "file corruption");
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -249,9 +270,16 @@ mod entry {
 | 
				
			|||||||
        let filepath = dir.path().join("count");
 | 
					        let filepath = dir.path().join("count");
 | 
				
			||||||
        let filename = filepath.to_str().unwrap();
 | 
					        let filename = filepath.to_str().unwrap();
 | 
				
			||||||
        let item = Entry::new(filename.to_string(), data).await.unwrap();
 | 
					        let item = Entry::new(filename.to_string(), data).await.unwrap();
 | 
				
			||||||
        assert!(Duration::from_secs(1) > item.elapsed(), "last_used should have been now.");
 | 
					        assert!(
 | 
				
			||||||
        item.last_used.set(Instant::now() - Duration::from_secs(500));
 | 
					            Duration::from_secs(1) > item.elapsed(),
 | 
				
			||||||
        assert!(Duration::from_secs(499) < item.elapsed(), "The duration should have increased.");
 | 
					            "last_used should have been now."
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        item.last_used
 | 
				
			||||||
 | 
					            .set(Instant::now() - Duration::from_secs(500));
 | 
				
			||||||
 | 
					        assert!(
 | 
				
			||||||
 | 
					            Duration::from_secs(499) < item.elapsed(),
 | 
				
			||||||
 | 
					            "The duration should have increased."
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[async_std::test]
 | 
					    #[async_std::test]
 | 
				
			||||||
@@ -264,7 +292,10 @@ mod entry {
 | 
				
			|||||||
        let item = Entry::new(filename.to_string(), data.clone())
 | 
					        let item = Entry::new(filename.to_string(), data.clone())
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
        assert!(Duration::from_secs(1) > item.elapsed(), "last_used should have been now.");
 | 
					        assert!(
 | 
				
			||||||
 | 
					            Duration::from_secs(1) > item.elapsed(),
 | 
				
			||||||
 | 
					            "last_used should have been now."
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        let output = item.get().await.unwrap();
 | 
					        let output = item.get().await.unwrap();
 | 
				
			||||||
        assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
            data.list(["database"].to_vec()).unwrap(),
 | 
					            data.list(["database"].to_vec()).unwrap(),
 | 
				
			||||||
@@ -286,7 +317,11 @@ mod entry {
 | 
				
			|||||||
            Err(err) => {
 | 
					            Err(err) => {
 | 
				
			||||||
                assert_eq!(err.to_string(), "failed to write");
 | 
					                assert_eq!(err.to_string(), "failed to write");
 | 
				
			||||||
                assert!(err.source().is_some(), "Must include the source error.");
 | 
					                assert!(err.source().is_some(), "Must include the source error.");
 | 
				
			||||||
                assert!(err.source().unwrap().to_string().contains("could not write to file"));
 | 
					                assert!(err
 | 
				
			||||||
 | 
					                    .source()
 | 
				
			||||||
 | 
					                    .unwrap()
 | 
				
			||||||
 | 
					                    .to_string()
 | 
				
			||||||
 | 
					                    .contains("could not write to file"));
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -320,9 +355,64 @@ mod entry {
 | 
				
			|||||||
        let filepath = dir.path().join("holder");
 | 
					        let filepath = dir.path().join("holder");
 | 
				
			||||||
        let filename = filepath.to_str().unwrap();
 | 
					        let filename = filepath.to_str().unwrap();
 | 
				
			||||||
        let item = Entry::new(filename.to_string(), data).await.unwrap();
 | 
					        let item = Entry::new(filename.to_string(), data).await.unwrap();
 | 
				
			||||||
        item.last_used.set(Instant::now() - Duration::from_secs(300));
 | 
					        item.last_used
 | 
				
			||||||
 | 
					            .set(Instant::now() - Duration::from_secs(300));
 | 
				
			||||||
        item.get().await.unwrap();
 | 
					        item.get().await.unwrap();
 | 
				
			||||||
        assert!(Duration::from_secs(1) > item.elapsed(), "last_used should have been reset.");
 | 
					        assert!(
 | 
				
			||||||
 | 
					            Duration::from_secs(1) > item.elapsed(),
 | 
				
			||||||
 | 
					            "last_used should have been reset."
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[async_std::test]
 | 
				
			||||||
 | 
					    async fn update_entry() {
 | 
				
			||||||
 | 
					        let dir = tempdir().unwrap();
 | 
				
			||||||
 | 
					        let mut data = DataType::new("store").unwrap();
 | 
				
			||||||
 | 
					        let filepath = dir.path().join("changing");
 | 
				
			||||||
 | 
					        let filename = filepath.to_str().unwrap();
 | 
				
			||||||
 | 
					        let mut item = Entry::new(filename.to_string(), data.clone())
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        item.last_used
 | 
				
			||||||
 | 
					            .set(Instant::now() - Duration::from_secs(500));
 | 
				
			||||||
 | 
					        data.add("database", "new", "stuff").unwrap();
 | 
				
			||||||
 | 
					        item.update(data.clone()).await.unwrap();
 | 
				
			||||||
 | 
					        assert!(
 | 
				
			||||||
 | 
					            Duration::from_secs(1) > item.elapsed(),
 | 
				
			||||||
 | 
					            "last_used should have been reset."
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let output = item.get().await.unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            data.list(["database"].to_vec()).unwrap(),
 | 
				
			||||||
 | 
					            output.list(["database"].to_vec()).unwrap()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let content = read(&filepath).await.unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(content, data.to_bytes());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[async_std::test]
 | 
				
			||||||
 | 
					    async fn update_write_errors() -> Result<(), DBError> {
 | 
				
			||||||
 | 
					        let dir = tempdir().unwrap();
 | 
				
			||||||
 | 
					        let data = DataType::new("store").unwrap();
 | 
				
			||||||
 | 
					        let filepath = dir.path().join("changing");
 | 
				
			||||||
 | 
					        let filename = filepath.to_str().unwrap();
 | 
				
			||||||
 | 
					        let mut item = Entry::new(filename.to_string(), data.clone())
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        drop(dir);
 | 
				
			||||||
 | 
					        match item.update(data).await {
 | 
				
			||||||
 | 
					            Ok(_) => Err(DBError::new("file writes should return an error")),
 | 
				
			||||||
 | 
					            Err(err) => {
 | 
				
			||||||
 | 
					                assert_eq!(err.to_string(), "write error");
 | 
				
			||||||
 | 
					                assert!(err.source().is_some(), "Must include the source error.");
 | 
				
			||||||
 | 
					                assert!(err
 | 
				
			||||||
 | 
					                    .source()
 | 
				
			||||||
 | 
					                    .unwrap()
 | 
				
			||||||
 | 
					                    .to_string()
 | 
				
			||||||
 | 
					                    .contains("could not write to file"));
 | 
				
			||||||
 | 
					                Ok(())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user