refer to types via address, not identifier

also rework invariant entries, add addressable trait
feat/vaults
Tomáš Mládek 2021-03-15 22:32:04 +01:00
parent 2c5a824d4a
commit 2ffbd4934b
6 changed files with 63 additions and 33 deletions

5
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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<Self, Self::Error> {
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<Address> {
impl Hashable for InvariantEntry {
fn hash(&self) -> Result<Hash> {
Entry::try_from(self)?.hash()
}
}
pub trait Addressable: Hashable {
fn address(&self) -> Result<Address> {
Ok(Address::Hash(self.hash()?))
}
}
impl Addressable for Entry {}
impl Addressable for InvariantEntry {}
impl EntryValue {
pub fn to_string(&self) -> Result<String> {
let (type_char, content) = match self {
@ -618,20 +649,9 @@ pub fn insert_entry<C: Connection<Backend = Sqlite>>(
pub fn ensure_invariant<C: Connection<Backend = Sqlite>>(
connection: &C,
attribute: String,
value: EntryValue,
invariant: &InvariantEntry,
) -> Result<Address> {
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)]

View File

@ -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<C: Connection<Backend = Sqlite>>(
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<T: AsRef<Path>>(
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<T: AsRef<Path>>(
)?;
}
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<P: AsRef<Path>>(
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)?;

View File

@ -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;

View File

@ -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};