DAV storage methods
This commit is contained in:
72
crates/groupware/src/file/hierarchy.rs
Normal file
72
crates/groupware/src/file/hierarchy.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::{Files, Server};
|
||||
use jmap_proto::types::collection::Collection;
|
||||
use percent_encoding::NON_ALPHANUMERIC;
|
||||
use trc::AddContext;
|
||||
use utils::bimap::IdBimap;
|
||||
|
||||
use crate::file::FileNode;
|
||||
|
||||
pub trait FileHierarchy: Sync + Send {
|
||||
fn fetch_file_hierarchy(
|
||||
&self,
|
||||
account_id: u32,
|
||||
) -> impl Future<Output = trc::Result<Arc<Files>>> + Send;
|
||||
}
|
||||
|
||||
impl FileHierarchy for Server {
|
||||
async fn fetch_file_hierarchy(&self, account_id: u32) -> trc::Result<Arc<Files>> {
|
||||
let change_id = self
|
||||
.store()
|
||||
.get_last_change_id(account_id, Collection::FileNode)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
if let Some(files) = self
|
||||
.inner
|
||||
.cache
|
||||
.files
|
||||
.get(&account_id)
|
||||
.filter(|x| x.modseq == change_id)
|
||||
{
|
||||
Ok(files)
|
||||
} else {
|
||||
let mut files = build_file_hierarchy(self, account_id).await?;
|
||||
files.modseq = change_id;
|
||||
let files = Arc::new(files);
|
||||
self.inner.cache.files.insert(account_id, files.clone());
|
||||
Ok(files)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn build_file_hierarchy(server: &Server, account_id: u32) -> trc::Result<Files> {
|
||||
let list = server
|
||||
.fetch_folders::<FileNode>(account_id, Collection::FileNode)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
.format(|_, name| {
|
||||
percent_encoding::utf8_percent_encode(name, NON_ALPHANUMERIC)
|
||||
.to_string()
|
||||
.into()
|
||||
});
|
||||
let mut files = Files {
|
||||
files: IdBimap::with_capacity(list.len()),
|
||||
size: std::mem::size_of::<Files>() as u64,
|
||||
modseq: None,
|
||||
};
|
||||
|
||||
for (id, name) in list.into_iterator() {
|
||||
files.size +=
|
||||
(std::mem::size_of::<u32>() + std::mem::size_of::<String>() + name.len()) as u64;
|
||||
files.files.insert(id, name);
|
||||
}
|
||||
|
||||
Ok(files)
|
||||
}
|
||||
@@ -14,8 +14,13 @@ use super::{ArchivedFileNode, FileNode};
|
||||
|
||||
impl IndexableObject for FileNode {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
let mut filters = Vec::with_capacity(5);
|
||||
filters.extend([
|
||||
let size = self.dead_properties.size() as u32
|
||||
+ self.display_name.as_ref().map_or(0, |n| n.len() as u32)
|
||||
+ self.name.len() as u32;
|
||||
|
||||
let mut values = Vec::with_capacity(6);
|
||||
|
||||
values.extend([
|
||||
IndexValue::Text {
|
||||
field: Property::Name.into(),
|
||||
value: self.name.to_lowercase().into(),
|
||||
@@ -28,16 +33,22 @@ impl IndexableObject for FileNode {
|
||||
]);
|
||||
|
||||
if let Some(file) = &self.file {
|
||||
filters.extend([
|
||||
let size = size + file.size;
|
||||
values.extend([
|
||||
IndexValue::Blob {
|
||||
value: file.blob_hash.clone(),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::Size.into(),
|
||||
value: file.size.into(),
|
||||
value: size.into(),
|
||||
},
|
||||
IndexValue::Quota { used: file.size },
|
||||
IndexValue::Quota { used: size },
|
||||
]);
|
||||
} else {
|
||||
values.push(IndexValue::Quota { used: size });
|
||||
}
|
||||
|
||||
filters.into_iter()
|
||||
values.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
pub mod hierarchy;
|
||||
pub mod index;
|
||||
|
||||
use dav_proto::schema::request::DeadProperty;
|
||||
use jmap_proto::types::value::AclGrant;
|
||||
use utils::BlobHash;
|
||||
|
||||
@@ -17,8 +19,10 @@ pub struct FileNode {
|
||||
pub name: String,
|
||||
pub display_name: Option<String>,
|
||||
pub file: Option<FileProperties>,
|
||||
pub created: u64,
|
||||
pub modified: u64,
|
||||
pub created: i64,
|
||||
pub modified: i64,
|
||||
pub change_id: u64,
|
||||
pub dead_properties: DeadProperty,
|
||||
pub acls: Vec<AclGrant>,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user