Skip to content

Commit

Permalink
feat: return Future in DavLockSystem (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuntara authored Jan 16, 2025
1 parent 610e407 commit 4f5092c
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/conditional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ where
false
} else {
match *ls {
Some(ref ls) => ls.check(p, None, true, false, vec![s]).is_ok(),
Some(ref ls) => ls.check(p, None, true, false, vec![s]).await.is_ok(),
None => false,
}
}
Expand Down
25 changes: 13 additions & 12 deletions src/fakels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//! `FakeLs` implements such a fake locksystem.
use std::time::{Duration, SystemTime};

use futures_util::{future, FutureExt};
use uuid::Uuid;
use xmltree::Element;

Expand Down Expand Up @@ -53,7 +54,7 @@ impl DavLockSystem for FakeLs {
timeout: Option<Duration>,
shared: bool,
deep: bool,
) -> Result<DavLock, DavLock> {
) -> LsFuture<Result<DavLock, DavLock>> {
let timeout = tm_limit(timeout);
let timeout_at = SystemTime::now() + timeout;

Expand All @@ -72,19 +73,19 @@ impl DavLockSystem for FakeLs {
deep,
};
debug!("lock {} created", &lock.token);
Ok(lock)
future::ready(Ok(lock)).boxed()
}

fn unlock(&self, _path: &DavPath, _token: &str) -> Result<(), ()> {
Ok(())
fn unlock(&self, _path: &DavPath, _token: &str) -> LsFuture<Result<(), ()>> {
future::ready(Ok(())).boxed()
}

fn refresh(
&self,
path: &DavPath,
token: &str,
timeout: Option<Duration>,
) -> Result<DavLock, ()> {
) -> LsFuture<Result<DavLock, ()>> {
debug!("refresh lock {}", token);
let v: Vec<&str> = token.split('/').collect();
let deep = v.len() > 1 && v[1] == "I";
Expand All @@ -103,7 +104,7 @@ impl DavLockSystem for FakeLs {
shared,
deep,
};
Ok(lock)
future::ready(Ok(lock)).boxed()
}

fn check(
Expand All @@ -113,15 +114,15 @@ impl DavLockSystem for FakeLs {
_ignore_principal: bool,
_deep: bool,
_submitted_tokens: Vec<&str>,
) -> Result<(), DavLock> {
Ok(())
) -> LsFuture<Result<(), DavLock>> {
future::ready(Ok(())).boxed()
}

fn discover(&self, _path: &DavPath) -> Vec<DavLock> {
Vec::new()
fn discover(&self, _path: &DavPath) -> LsFuture<Vec<DavLock>> {
future::ready(Vec::new()).boxed()
}

fn delete(&self, _path: &DavPath) -> Result<(), ()> {
Ok(())
fn delete(&self, _path: &DavPath) -> LsFuture<Result<(), ()>> {
future::ready(Ok(())).boxed()
}
}
9 changes: 6 additions & 3 deletions src/handle_copymove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,15 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
let principal = self.principal.as_deref();
if method == DavMethod::Move {
// for MOVE check if source path is locked
if let Err(_l) = locksystem.check(&path, principal, false, true, t.clone()) {
if let Err(_l) = locksystem
.check(&path, principal, false, true, t.clone())
.await
{
return Err(StatusCode::LOCKED.into());
}
}
// for MOVE and COPY check if destination is locked
if let Err(_l) = locksystem.check(&dest, principal, false, true, t) {
if let Err(_l) = locksystem.check(&dest, principal, false, true, t).await {
return Err(StatusCode::LOCKED.into());
}
}
Expand Down Expand Up @@ -293,7 +296,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
// move and if successful, remove locks at old location.
if self.do_move(&path, &dest, &mut multierror).await.is_ok() {
if let Some(ref locksystem) = self.ls {
locksystem.delete(&path).ok();
locksystem.delete(&path).await.ok();
}
let s = if exists {
StatusCode::NO_CONTENT
Expand Down
4 changes: 2 additions & 2 deletions src/handle_delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
if let Some(ref locksystem) = self.ls {
let t = tokens.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
let principal = self.principal.as_deref();
if let Err(_l) = locksystem.check(&path, principal, false, true, t) {
if let Err(_l) = locksystem.check(&path, principal, false, true, t).await {
return Err(DavError::Status(StatusCode::LOCKED));
}
}
Expand All @@ -174,7 +174,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
// Done. Now delete the path in the locksystem as well.
// Should really do this per resource, in case the delete partially fails. See TODO.pm
if let Some(ref locksystem) = self.ls {
locksystem.delete(&path).ok();
locksystem.delete(&path).await.ok();
}
let _ = multierror.add_status(&path, StatusCode::NO_CONTENT).await;
}
Expand Down
16 changes: 11 additions & 5 deletions src/handle_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
// try refresh
// FIXME: you can refresh a lock owned by someone else. is that OK?
let timeout = get_timeout(req, true, false);
let lock = match locksystem.refresh(&path, &tokens[0], timeout) {
let lock = match locksystem.refresh(&path, &tokens[0], timeout).await {
Ok(lock) => lock,
Err(_) => return Err(SC::PRECONDITION_FAILED.into()),
};
Expand Down Expand Up @@ -153,7 +153,10 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
// create lock
let timeout = get_timeout(req, false, shared);
let principal = self.principal.as_deref();
let lock = match locksystem.lock(&path, principal, owner.as_ref(), timeout, shared, deep) {
let lock = match locksystem
.lock(&path, principal, owner.as_ref(), timeout, shared, deep)
.await
{
Ok(lock) => lock,
Err(_) => return Err(SC::LOCKED.into()),
};
Expand Down Expand Up @@ -221,7 +224,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
self.fixpath(&mut res, &mut path, meta);
}

match locksystem.unlock(&path, token) {
match locksystem.unlock(&path, token).await {
Ok(_) => {
*res.status_mut() = SC::NO_CONTENT;
Ok(res)
Expand All @@ -231,7 +234,10 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
}
}

pub(crate) fn list_lockdiscovery(ls: Option<&Box<dyn DavLockSystem>>, path: &DavPath) -> Element {
pub(crate) async fn list_lockdiscovery(
ls: Option<&Box<dyn DavLockSystem>>,
path: &DavPath,
) -> Element {
let mut elem = Element::new2("D:lockdiscovery");

// must have a locksystem or bail
Expand All @@ -241,7 +247,7 @@ pub(crate) fn list_lockdiscovery(ls: Option<&Box<dyn DavLockSystem>>, path: &Dav
};

// list the locks.
let locks = locksystem.discover(path);
let locks = locksystem.discover(path).await;
for lock in &locks {
elem.push_element(build_lock_prop(lock, false));
}
Expand Down
2 changes: 1 addition & 1 deletion src/handle_mkcol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
if let Some(ref locksystem) = self.ls {
let t = tokens.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
let principal = self.principal.as_deref();
if let Err(_l) = locksystem.check(&path, principal, false, false, t) {
if let Err(_l) = locksystem.check(&path, principal, false, false, t).await {
return Err(DavError::Status(StatusCode::LOCKED));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/handle_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
if let Some(ref locksystem) = self.ls {
let t = tokens.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
let principal = self.principal.as_deref();
if let Err(_l) = locksystem.check(&path, principal, false, false, t) {
if let Err(_l) = locksystem.check(&path, principal, false, false, t).await {
return Err(StatusCode::LOCKED.into());
}
}
Expand Down Expand Up @@ -756,7 +756,7 @@ impl<C: Clone + Send + Sync + 'static> PropWriter<C> {
"lockdiscovery" => {
return Ok(StatusElement {
status: StatusCode::OK,
element: list_lockdiscovery(self.ls.as_ref(), path),
element: list_lockdiscovery(self.ls.as_ref(), path).await,
});
}
"quota-available-bytes" => {
Expand Down
2 changes: 1 addition & 1 deletion src/handle_put.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
if let Some(ref locksystem) = self.ls {
let t = tokens.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
let principal = self.principal.as_deref();
if let Err(_l) = locksystem.check(&path, principal, false, false, t) {
if let Err(_l) = locksystem.check(&path, principal, false, false, t).await {
return Err(DavError::StatusClose(SC::LOCKED));
}
}
Expand Down
16 changes: 10 additions & 6 deletions src/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
//!
use crate::davpath::DavPath;
use std::fmt::Debug;
use std::pin::Pin;
use std::time::{Duration, SystemTime};

use dyn_clone::{clone_trait_object, DynClone};
use futures_util::Future;
use xmltree::Element;

/// Type of the locks returned by DavLockSystem methods.
Expand All @@ -35,6 +37,8 @@ pub struct DavLock {
pub deep: bool,
}

pub type LsFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// The trait that defines a locksystem.
pub trait DavLockSystem: Debug + Send + Sync + DynClone {
/// Lock a node. Returns `Ok(new_lock)` if succeeded,
Expand All @@ -47,19 +51,19 @@ pub trait DavLockSystem: Debug + Send + Sync + DynClone {
timeout: Option<Duration>,
shared: bool,
deep: bool,
) -> Result<DavLock, DavLock>;
) -> LsFuture<Result<DavLock, DavLock>>;

/// Unlock a node. Returns `Ok(())` if succeeded, `Err (())` if failed
/// (because lock doesn't exist)
fn unlock(&self, path: &DavPath, token: &str) -> Result<(), ()>;
fn unlock(&self, path: &DavPath, token: &str) -> LsFuture<Result<(), ()>>;

/// Refresh lock. Returns updated lock if succeeded.
fn refresh(
&self,
path: &DavPath,
token: &str,
timeout: Option<Duration>,
) -> Result<DavLock, ()>;
) -> LsFuture<Result<DavLock, ()>>;

/// Check if node is locked and if so, if we own all the locks.
/// If not, returns as Err one conflicting lock.
Expand All @@ -70,13 +74,13 @@ pub trait DavLockSystem: Debug + Send + Sync + DynClone {
ignore_principal: bool,
deep: bool,
submitted_tokens: Vec<&str>,
) -> Result<(), DavLock>;
) -> LsFuture<Result<(), DavLock>>;

/// Find and return all locks that cover a given path.
fn discover(&self, path: &DavPath) -> Vec<DavLock>;
fn discover(&self, path: &DavPath) -> LsFuture<Vec<DavLock>>;

/// Delete all locks at this path and below (after MOVE or DELETE)
fn delete(&self, path: &DavPath) -> Result<(), ()>;
fn delete(&self, path: &DavPath) -> LsFuture<Result<(), ()>>;
}

clone_trait_object! {DavLockSystem}
Loading

0 comments on commit 4f5092c

Please sign in to comment.