diff options
author | Alex Auvolat <alex@adnab.me> | 2023-10-20 13:55:34 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2023-10-20 13:56:35 +0200 |
commit | c82d91c6bccf307186332b6c5c6fc0b128b1b2b1 (patch) | |
tree | 5059701470a55c785d12306574b8041f90d9b59b /src/api/s3/delete.rs | |
parent | 8686cfd0b10a49048021102a08d637b0d4fe6a91 (diff) | |
download | garage-c82d91c6bccf307186332b6c5c6fc0b128b1b2b1.tar.gz garage-c82d91c6bccf307186332b6c5c6fc0b128b1b2b1.zip |
DeleteObject: always insert a deletion marker with a bigger timestamp than everything beforeincreasing-timestamps
Diffstat (limited to 'src/api/s3/delete.rs')
-rw-r--r-- | src/api/s3/delete.rs | 42 |
1 files changed, 19 insertions, 23 deletions
diff --git a/src/api/s3/delete.rs b/src/api/s3/delete.rs index b337155f..1c491eac 100644 --- a/src/api/s3/delete.rs +++ b/src/api/s3/delete.rs @@ -3,12 +3,12 @@ use std::sync::Arc; use hyper::{Body, Request, Response, StatusCode}; use garage_util::data::*; -use garage_util::time::*; use garage_model::garage::Garage; use garage_model::s3::object_table::*; use crate::s3::error::*; +use crate::s3::put::next_timestamp; use crate::s3::xml as s3_xml; use crate::signature::verify_signed_content; @@ -23,40 +23,36 @@ async fn handle_delete_internal( .await? .ok_or(Error::NoSuchKey)?; // No need to delete - let interesting_versions = object.versions().iter().filter(|v| { - !matches!( - v.state, - ObjectVersionState::Aborted - | ObjectVersionState::Complete(ObjectVersionData::DeleteMarker) - ) - }); - - let mut version_to_delete = None; - let mut timestamp = now_msec(); - for v in interesting_versions { - if v.timestamp + 1 > timestamp || version_to_delete.is_none() { - version_to_delete = Some(v.uuid); + let del_timestamp = next_timestamp(Some(&object)); + let del_uuid = gen_uuid(); + + let deleted_version = object + .versions() + .iter() + .rev() + .find(|v| !matches!(&v.state, ObjectVersionState::Aborted)) + .or_else(|| object.versions().iter().rev().next()); + let deleted_version = match deleted_version { + Some(dv) => dv.uuid, + None => { + warn!("Object has no versions: {:?}", object); + Uuid::from([0u8; 32]) } - timestamp = std::cmp::max(timestamp, v.timestamp + 1); - } - - let deleted_version = version_to_delete.ok_or(Error::NoSuchKey)?; - - let version_uuid = gen_uuid(); + }; let object = Object::new( bucket_id, key.into(), vec![ObjectVersion { - uuid: version_uuid, - timestamp, + uuid: del_uuid, + timestamp: del_timestamp, state: ObjectVersionState::Complete(ObjectVersionData::DeleteMarker), }], ); garage.object_table.insert(&object).await?; - Ok((deleted_version, version_uuid)) + Ok((deleted_version, del_uuid)) } pub async fn handle_delete( |