From 2ffbd4934b11336402fc39554fe4999a3d9eb269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Mon, 15 Mar 2021 22:32:04 +0100 Subject: [PATCH] refer to types via address, not identifier also rework invariant entries, add addressable trait --- Cargo.lock | 5 +++-- Cargo.toml | 1 + src/database.rs | 50 +++++++++++++++++++++++++++++++++-------------- src/filesystem.rs | 34 +++++++++++++++++++------------- src/main.rs | 2 ++ src/routes.rs | 4 ++-- 6 files changed, 63 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd776ba..90e18a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1444,9 +1444,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.5.2" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" [[package]] name = "opaque-debug" @@ -2261,6 +2261,7 @@ dependencies = [ "env_logger", "filebuffer", "futures-util", + "lazy_static", "lexpr", "libsqlite3-sys", "log", diff --git a/Cargo.toml b/Cargo.toml index 1d62029..958b1f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ thiserror = "1.0" rayon = "1.4.0" futures-util = "~0.3.12" +lazy_static = "1.4.0" diesel = { version = "1.4", features = ["sqlite", "r2d2", "chrono", "serde_json"] } diesel_migrations = "1.4" diff --git a/src/database.rs b/src/database.rs index 47b72f2..ffe761c 100644 --- a/src/database.rs +++ b/src/database.rs @@ -36,6 +36,12 @@ pub struct Entry { pub value: EntryValue, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InvariantEntry { + pub attribute: String, + pub value: EntryValue, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "t", content = "c")] pub enum EntryValue { @@ -69,6 +75,22 @@ impl TryFrom<&Entry> for models::Entry { } } +impl TryFrom<&InvariantEntry> for Entry { + type Error = anyhow::Error; + + fn try_from(invariant: &InvariantEntry) -> Result { + let mut entity = Cursor::new(vec![0u8; 0]); + entity.write_all(invariant.attribute.as_bytes())?; + entity.write_all(invariant.value.to_string()?.as_bytes())?; + + Ok(Entry { + entity: Address::Hash(Hash(entity.into_inner())), + attribute: invariant.attribute.clone(), + value: invariant.value.clone(), + }) + } +} + impl std::fmt::Display for Entry { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} | {} | {}", self.entity, self.attribute, self.value) @@ -85,12 +107,21 @@ impl Hashable for Entry { } } -impl Entry { - pub fn address(&self) -> Result
{ +impl Hashable for InvariantEntry { + fn hash(&self) -> Result { + Entry::try_from(self)?.hash() + } +} + +pub trait Addressable: Hashable { + fn address(&self) -> Result
{ Ok(Address::Hash(self.hash()?)) } } +impl Addressable for Entry {} +impl Addressable for InvariantEntry {} + impl EntryValue { pub fn to_string(&self) -> Result { let (type_char, content) = match self { @@ -618,20 +649,9 @@ pub fn insert_entry>( pub fn ensure_invariant>( connection: &C, - attribute: String, - value: EntryValue, + invariant: &InvariantEntry, ) -> Result
{ - let mut entity = Cursor::new(vec![0u8; 0]); - entity.write_all(attribute.as_bytes())?; - entity.write_all(value.to_string()?.as_bytes())?; - - let entry = Entry { - entity: Address::Hash(Hash(entity.into_inner())), - attribute, - value, - }; - - insert_entry(connection, entry) + insert_entry(connection, Entry::try_from(invariant)?) } #[derive(Debug)] diff --git a/src/filesystem.rs b/src/filesystem.rs index eb18db3..e67eec3 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -1,8 +1,8 @@ use crate::addressing::Address; use crate::database::{ bulk_retrieve_objects, ensure_invariant, file_set_valid, insert_entry, insert_file, query, - retrieve_all_files, DbPool, Entry, EntryQuery, EntryValue, Query, QueryComponent, QueryPart, - DATABASE_FILENAME, IS_TYPE_ATTR, TYPE_ATTR, TYPE_HAS_ATTR, + retrieve_all_files, Addressable, DbPool, Entry, EntryQuery, EntryValue, InvariantEntry, Query, + QueryComponent, QueryPart, DATABASE_FILENAME, IS_TYPE_ATTR, TYPE_ATTR, TYPE_HAS_ATTR, }; use crate::hash::Hashable; use crate::jobs::{Job, JobContainer, JobId}; @@ -25,10 +25,24 @@ use walkdir::WalkDir; const DIR_TYPE: &str = "FS_DIR"; const DIR_KEY: &str = "DIR"; const DIR_HAS_KEY: &str = "DIR_HAS"; +lazy_static! { + static ref DIR_TYPE_INVARIANT: InvariantEntry = InvariantEntry { + attribute: String::from(TYPE_ATTR), + value: EntryValue::Value(Value::from(DIR_TYPE)), + }; + static ref DIR_TYPE_ADDR: Address = DIR_TYPE_INVARIANT.address().unwrap(); +} const FILE_TYPE: &str = "FS_FILE"; const FILE_IDENTITY_KEY: &str = "FILE_IS"; const FILENAME_KEY: &str = "FILE_NAME"; +lazy_static! { + static ref FILE_TYPE_INVARIANT: InvariantEntry = InvariantEntry { + attribute: String::from(TYPE_ATTR), + value: EntryValue::Value(Value::from(FILE_TYPE)), + }; + static ref FILE_TYPE_ADDR: Address = FILE_TYPE_INVARIANT.address().unwrap(); +} #[derive(Debug, Clone, PartialEq)] pub struct UDirectory { @@ -240,7 +254,7 @@ pub fn fetch_or_create_dir>( let type_entry = Entry { entity: new_directory_address.clone(), attribute: String::from(IS_TYPE_ATTR), - value: EntryValue::Value(Value::from(DIR_TYPE)), + value: EntryValue::Address(DIR_TYPE_ADDR.clone()), }; insert_entry(connection, type_entry)?; @@ -330,11 +344,7 @@ fn _rescan_vault>( let start = Instant::now(); // Initialize types, etc... - let file_type = ensure_invariant( - &pool.get()?, - String::from(TYPE_ATTR), - EntryValue::Value(Value::from(FILE_TYPE)), - )?; + let file_type = ensure_invariant(&pool.get()?, &FILE_TYPE_INVARIANT)?; for attr in &[FILE_IDENTITY_KEY, FILENAME_KEY] { insert_entry( &pool.get()?, @@ -346,11 +356,7 @@ fn _rescan_vault>( )?; } - let dir_type = ensure_invariant( - &pool.get()?, - String::from(TYPE_ATTR), - EntryValue::Value(Value::from(DIR_TYPE)), - )?; + let dir_type = ensure_invariant(&pool.get()?, &DIR_TYPE_INVARIANT)?; insert_entry( &pool.get()?, Entry { @@ -501,7 +507,7 @@ fn _process_directory_entry>( let type_entry = Entry { entity: file_address.clone(), attribute: String::from(IS_TYPE_ATTR), - value: EntryValue::Value(Value::from(FILE_TYPE)), + value: EntryValue::Address(FILE_TYPE_ADDR.clone()), }; insert_entry(&connection, type_entry)?; diff --git a/src/main.rs b/src/main.rs index e0555be..ef6a0bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,8 @@ extern crate diesel; #[macro_use] extern crate diesel_migrations; +#[macro_use] +extern crate lazy_static; use std::env; use std::net::SocketAddr; diff --git a/src/routes.rs b/src/routes.rs index 1b89da4..74775f4 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,7 +1,7 @@ use crate::addressing::Address; use crate::database::{ - get_latest_files, insert_entry, query, remove_object, retrieve_file, retrieve_object, DbPool, - Entry, Query, + get_latest_files, insert_entry, query, remove_object, retrieve_file, retrieve_object, + Addressable, DbPool, Entry, Query, }; use crate::filesystem::{list_directory, UPath}; use crate::hash::{decode, encode};