libblobd_direct/op/
delete_object.rs

1use super::OpError;
2use super::OpResult;
3use crate::ctx::Ctx;
4use crate::object::calc_object_layout;
5use crate::object::Object;
6use off64::usz;
7use std::sync::atomic::Ordering::Relaxed;
8use std::sync::Arc;
9use tinybuf::TinyBuf;
10
11pub(crate) async fn reap_object(ctx: &Ctx, obj: &Object) {
12  let tuple = ctx.tuples.delete_object(obj.id()).await;
13
14  let layout = calc_object_layout(&ctx.pages, obj.size);
15
16  {
17    let mut allocator = ctx.heap_allocator.lock();
18
19    for &page_dev_offset in obj.lpage_dev_offsets.iter() {
20      allocator.release(page_dev_offset, ctx.pages.lpage_size_pow2);
21    }
22    for (i, tail_page_size_pow2) in layout.tail_page_sizes_pow2 {
23      let page_dev_offset = obj.tail_page_dev_offsets[usz!(i)];
24      allocator.release(page_dev_offset, tail_page_size_pow2);
25    }
26    allocator.release(tuple.metadata_dev_offset, tuple.metadata_page_size_pow2);
27  };
28
29  ctx
30    .metrics
31    .0
32    .object_metadata_bytes
33    .fetch_sub(obj.metadata_size(), Relaxed);
34  ctx.metrics.0.object_data_bytes.fetch_sub(obj.size, Relaxed);
35}
36
37pub struct OpDeleteObjectInput {
38  pub key: TinyBuf,
39  // Only useful if versioning is enabled.
40  pub id: Option<u64>,
41}
42
43pub struct OpDeleteObjectOutput {}
44
45pub(crate) async fn op_delete_object(
46  ctx: Arc<Ctx>,
47  req: OpDeleteObjectInput,
48) -> OpResult<OpDeleteObjectOutput> {
49  let Some((_, obj)) = ctx.committed_objects.remove_if(&req.key, |_, o| req.id.is_none() || Some(o.id()) == req.id) else {
50    return Err(OpError::ObjectNotFound);
51  };
52
53  // We can reap the object now, as there should only be other readers (it's committed, so there shouldn't be any writers), and readers will double check the state after reading and discard the read if necessary (the object metadata still exists in memory due to Arc, so it's safe to check).
54  reap_object(&ctx, &obj).await;
55
56  ctx.metrics.0.delete_op_count.fetch_add(1, Relaxed);
57  ctx.metrics.0.committed_object_count.fetch_sub(1, Relaxed);
58
59  Ok(OpDeleteObjectOutput {})
60}