DAV storage methods
This commit is contained in:
@@ -254,3 +254,25 @@ impl CredentialsUsername for Credentials<String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsTenantId {
|
||||
fn tenant_id(&self) -> Option<u32>;
|
||||
}
|
||||
|
||||
impl AsTenantId for Option<u32> {
|
||||
fn tenant_id(&self) -> Option<u32> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsTenantId for AccessToken {
|
||||
fn tenant_id(&self) -> Option<u32> {
|
||||
self.tenant.map(|t| t.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsTenantId for ResourceToken {
|
||||
fn tenant_id(&self) -> Option<u32> {
|
||||
self.tenant.map(|t| t.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,22 @@ use utils::config::Config;
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct DavConfig {
|
||||
pub max_request_size: usize,
|
||||
pub dead_property_size: Option<usize>,
|
||||
pub live_property_size: usize,
|
||||
}
|
||||
|
||||
impl DavConfig {
|
||||
pub fn parse(config: &mut Config) -> Self {
|
||||
DavConfig {
|
||||
max_request_size: config
|
||||
.property("dav.limits.request-size")
|
||||
.property("dav.limits.size.request")
|
||||
.unwrap_or(25 * 1024 * 1024),
|
||||
dead_property_size: config
|
||||
.property_or_default::<Option<usize>>("dav.limits.size.dead-property", "1024")
|
||||
.unwrap_or(Some(1024)),
|
||||
live_property_size: config
|
||||
.property("dav.limits.size.live-property")
|
||||
.unwrap_or(250),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,12 @@ impl Caches {
|
||||
MB_10,
|
||||
(std::mem::size_of::<Threads>() + (500 * std::mem::size_of::<u64>())) as u64,
|
||||
),
|
||||
files: Cache::from_config(
|
||||
config,
|
||||
"file",
|
||||
MB_10,
|
||||
(std::mem::size_of::<Threads>() + (500 * std::mem::size_of::<u64>())) as u64,
|
||||
),
|
||||
bayes: CacheWithTtl::from_config(
|
||||
config,
|
||||
"bayes",
|
||||
|
||||
@@ -45,6 +45,7 @@ use rustls::sign::CertifiedKey;
|
||||
use tokio::sync::{Notify, Semaphore, mpsc};
|
||||
use tokio_rustls::TlsConnector;
|
||||
use utils::{
|
||||
bimap::IdBimap,
|
||||
cache::{Cache, CacheItemWeight, CacheWithTtl},
|
||||
snowflake::SnowflakeIdGenerator,
|
||||
};
|
||||
@@ -143,6 +144,7 @@ pub struct Caches {
|
||||
pub account: Cache<AccountId, Arc<Account>>,
|
||||
pub mailbox: Cache<MailboxId, Arc<MailboxState>>,
|
||||
pub threads: Cache<u32, Arc<Threads>>,
|
||||
pub files: Cache<u32, Arc<Files>>,
|
||||
|
||||
pub bayes: CacheWithTtl<TokenHash, Weights>,
|
||||
|
||||
@@ -244,6 +246,15 @@ pub struct Threads {
|
||||
pub modseq: Option<u64>,
|
||||
}
|
||||
|
||||
pub struct NameWrapper(pub String);
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Files {
|
||||
pub files: IdBimap,
|
||||
pub size: u64,
|
||||
pub modseq: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Core {
|
||||
pub storage: Storage,
|
||||
@@ -297,6 +308,12 @@ impl CacheItemWeight for HttpAuthCache {
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheItemWeight for Files {
|
||||
fn weight(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl MailboxState {
|
||||
pub fn calculate_weight(&self) -> u64 {
|
||||
std::mem::size_of::<MailboxState>() as u64
|
||||
@@ -412,6 +429,7 @@ impl Default for Caches {
|
||||
account: Cache::new(1024, 10 * 1024 * 1024),
|
||||
mailbox: Cache::new(1024, 10 * 1024 * 1024),
|
||||
threads: Cache::new(1024, 10 * 1024 * 1024),
|
||||
files: Cache::new(1024, 10 * 1024 * 1024),
|
||||
bayes: CacheWithTtl::new(1024, 10 * 1024 * 1024),
|
||||
dns_rbl: CacheWithTtl::new(1024, 10 * 1024 * 1024),
|
||||
dns_txt: CacheWithTtl::new(1024, 10 * 1024 * 1024),
|
||||
|
||||
@@ -142,6 +142,14 @@ impl Server {
|
||||
}
|
||||
|
||||
impl ExpandedFolders {
|
||||
pub fn len(&self) -> usize {
|
||||
self.names.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.names.is_empty()
|
||||
}
|
||||
|
||||
pub fn format<T>(mut self, formatter: T) -> Self
|
||||
where
|
||||
T: Fn(u32, &str) -> Option<String>,
|
||||
|
||||
@@ -9,10 +9,13 @@ use std::{borrow::Cow, collections::HashSet, fmt::Debug};
|
||||
use store::{
|
||||
Serialize, SerializeInfallible,
|
||||
write::{
|
||||
Archiver, BatchBuilder, BitmapClass, DirectoryClass, IntoOperations, Operation, ValueOp,
|
||||
assert::HashedValue,
|
||||
Archiver, BatchBuilder, BitmapClass, BlobOp, DirectoryClass, IntoOperations, Operation,
|
||||
ValueOp, assert::HashedValue,
|
||||
},
|
||||
};
|
||||
use utils::BlobHash;
|
||||
|
||||
use crate::auth::AsTenantId;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum IndexValue<'x> {
|
||||
@@ -21,6 +24,7 @@ pub enum IndexValue<'x> {
|
||||
U64 { field: u8, value: Option<u64> },
|
||||
U32List { field: u8, value: &'x [u32] },
|
||||
Tag { field: u8, is_set: bool },
|
||||
Blob { value: BlobHash },
|
||||
Quota { used: u32 },
|
||||
Acl { value: &'x [AclGrant] },
|
||||
}
|
||||
@@ -91,14 +95,10 @@ impl<T: IndexableObject> ObjectIndexBuilder<T> {
|
||||
self.current.as_ref()
|
||||
}
|
||||
|
||||
pub fn with_tenant_id(mut self, tenant_id: Option<u32>) -> Self {
|
||||
self.tenant_id = tenant_id;
|
||||
pub fn with_tenant_id(mut self, tenant: &impl AsTenantId) -> Self {
|
||||
self.tenant_id = tenant.tenant_id();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_tenant_id(&mut self, tenant_id: u32) {
|
||||
self.tenant_id = tenant_id.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IndexableObject> IntoOperations for ObjectIndexBuilder<T> {
|
||||
@@ -182,6 +182,13 @@ fn build_batch<T: IndexableObject>(
|
||||
});
|
||||
}
|
||||
}
|
||||
IndexValue::Blob { value } => {
|
||||
if set {
|
||||
batch.set(BlobOp::Link { hash: value }, vec![]);
|
||||
} else {
|
||||
batch.clear(BlobOp::Link { hash: value });
|
||||
}
|
||||
}
|
||||
IndexValue::Acl { value } => {
|
||||
for item in value {
|
||||
batch.ops.push(Operation::acl(
|
||||
@@ -354,6 +361,10 @@ fn merge_batch<T: IndexableObject>(
|
||||
});
|
||||
}
|
||||
}
|
||||
(IndexValue::Blob { value: old_hash }, IndexValue::Blob { value: new_hash }) => {
|
||||
batch.clear(BlobOp::Link { hash: old_hash });
|
||||
batch.set(BlobOp::Link { hash: new_hash }, vec![]);
|
||||
}
|
||||
(IndexValue::Acl { value: old_acl }, IndexValue::Acl { value: new_acl }) => {
|
||||
match (!old_acl.is_empty(), !new_acl.is_empty()) {
|
||||
(true, true) => {
|
||||
|
||||
Reference in New Issue
Block a user