From a871a8d29d813433cbe38fda210f06675257f2a3 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 30 Oct 2014 17:00:02 -0700 Subject: [PATCH] rgw: send x-amz-version-id and x-amz-delete_marker header fields send these fields on obj delete as defined by the api. This required adding an index read so that we can identify whether an instance is actually a delete marker. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_bucket.cc | 2 +- src/rgw/rgw_op.cc | 23 ++++++++++----- src/rgw/rgw_op.h | 4 ++- src/rgw/rgw_rados.cc | 65 +++++++++++++++++++++++++++++++++--------- src/rgw/rgw_rados.h | 10 ++++++- src/rgw/rgw_rest_s3.cc | 6 ++++ 6 files changed, 87 insertions(+), 23 deletions(-) diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 6971d89cf9269..2d7358032bcc9 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -348,7 +348,7 @@ int rgw_remove_object(RGWRados *store, const string& bucket_owner, rgw_bucket& b rgw_obj obj(bucket, key); - int ret = store->delete_obj(rctx, bucket_owner, obj, use_versioning, NULL); + int ret = store->delete_obj(rctx, bucket_owner, obj, use_versioning); return ret; } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 5ef4df1e35b4d..89672c5d91e3b 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2108,9 +2108,18 @@ void RGWDeleteObj::execute() obj_ctx->set_atomic(obj); - ACLOwner& obj_owner = s->owner; + RGWRados::Object del_target(store, *obj_ctx, obj); + RGWRados::Object::Delete del_op(&del_target); - ret = store->delete_obj(*obj_ctx, s->bucket_owner.get_id(), obj, s->bucket_info.versioning_status(), &obj_owner); + del_op.params.bucket_owner = s->bucket_owner.get_id(); + del_op.params.versioning_status = s->bucket_info.versioning_status(); + del_op.params.obj_owner = s->owner; + + ret = del_op.delete_obj(); + if (ret >= 0) { + delete_marker = del_op.result.delete_marker; + version_id = del_op.result.version_id; + } } } @@ -2971,7 +2980,7 @@ void RGWCompleteMultipart::execute() } // remove the upload obj - int r = store->delete_obj(*(RGWObjectCtx *)s->obj_ctx, s->bucket_owner.get_id(), meta_obj, 0, NULL); + int r = store->delete_obj(*(RGWObjectCtx *)s->obj_ctx, s->bucket_owner.get_id(), meta_obj, 0); if (r < 0) { ldout(store->ctx(), 0) << "WARNING: failed to remove object " << meta_obj << dendl; } @@ -3031,7 +3040,7 @@ void RGWAbortMultipart::execute() string oid = mp.get_part(obj_iter->second.num); rgw_obj obj; obj.init_ns(s->bucket, oid, mp_ns); - ret = store->delete_obj(*obj_ctx, owner, obj, 0, NULL); + ret = store->delete_obj(*obj_ctx, owner, obj, 0); if (ret < 0 && ret != -ENOENT) return; } else { @@ -3039,7 +3048,7 @@ void RGWAbortMultipart::execute() RGWObjManifest::obj_iterator oiter; for (oiter = manifest.obj_begin(); oiter != manifest.obj_end(); ++oiter) { rgw_obj loc = oiter.get_location(); - ret = store->delete_obj(*obj_ctx, owner, loc, 0, NULL); + ret = store->delete_obj(*obj_ctx, owner, loc, 0); if (ret < 0 && ret != -ENOENT) return; } @@ -3050,7 +3059,7 @@ void RGWAbortMultipart::execute() // and also remove the metadata obj meta_obj.init_ns(s->bucket, meta_oid, mp_ns); meta_obj.set_in_extra_data(true); - ret = store->delete_obj(*obj_ctx, owner, meta_obj, 0, NULL); + ret = store->delete_obj(*obj_ctx, owner, meta_obj, 0); if (ret == -ENOENT) { ret = -ERR_NO_SUCH_BUCKET; } @@ -3212,7 +3221,7 @@ void RGWDeleteMultiObj::execute() rgw_obj obj(bucket,(*iter)); obj_ctx->set_atomic(obj); - ret = store->delete_obj(*obj_ctx, s->bucket_owner.get_id(), obj, s->bucket_info.versioning_status(), NULL); + ret = store->delete_obj(*obj_ctx, s->bucket_owner.get_id(), obj, s->bucket_info.versioning_status()); if (ret == -ENOENT) { ret = 0; } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 7b8ccd7fa93c9..f353adbee3195 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -541,9 +541,11 @@ public: class RGWDeleteObj : public RGWOp { protected: int ret; + bool delete_marker; + string version_id; public: - RGWDeleteObj() : ret(0) {} + RGWDeleteObj() : ret(0), delete_marker(false) {} int verify_permission(); void pre_exec(); diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 0b1d772519a82..9cd9bb5b94d34 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -897,7 +897,7 @@ RGWPutObjProcessor_Aio::~RGWPutObjProcessor_Aio() list::iterator iter; for (iter = written_objs.begin(); iter != written_objs.end(); ++iter) { rgw_obj& obj = *iter; - int r = store->delete_obj(obj_ctx, bucket_owner, obj, false, NULL); + int r = store->delete_obj(obj_ctx, bucket_owner, obj, false); if (r < 0 && r != -ENOENT) { ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl; } @@ -3923,12 +3923,16 @@ int RGWRados::Object::Delete::delete_obj() rgw_obj& obj = target->get_obj(); if (params.versioning_status & BUCKET_VERSIONED) { - if (obj.get_instance().empty()) { + const string& instance = obj.get_instance(); + if (instance.empty()) { rgw_obj marker = obj; if ((params.versioning_status & BUCKET_VERSIONS_SUSPENDED) == 0) { store->gen_rand_obj_instance_name(&marker); } + result.version_id = marker.get_instance(); + result.delete_marker = true; + struct rgw_bucket_dir_entry_meta meta; meta.owner = params.obj_owner.get_id(); @@ -3940,10 +3944,20 @@ int RGWRados::Object::Delete::delete_obj() return r; } } else { - int r = store->unlink_obj_instance(target->get_ctx(), params.bucket_owner, obj); + rgw_bucket_dir_entry dirent; + int r = store->bi_get_instance(obj, &dirent); + if (r < 0 && r != -ENOENT) { + return r; + } + bool exists = (r == 0); + if (exists) { + result.delete_marker = dirent.is_delete_marker(); + } + r = store->unlink_obj_instance(target->get_ctx(), params.bucket_owner, obj); if (r < 0) { return r; } + result.version_id = instance; } return 0; @@ -3960,14 +3974,14 @@ int RGWRados::Object::Delete::delete_obj() return r; } - ObjectWriteOperation op; - - r = target->prepare_atomic_modification(op, false, NULL); + RGWObjState *state; + r = target->get_state(&state, false); if (r < 0) return r; - RGWObjState *state; - r = target->get_state(&state, false); + ObjectWriteOperation op; + + r = target->prepare_atomic_modification(op, false, NULL); if (r < 0) return r; @@ -4021,16 +4035,13 @@ int RGWRados::Object::Delete::delete_obj() return 0; } -int RGWRados::delete_obj(RGWObjectCtx& obj_ctx, const string& bucket_owner, rgw_obj& obj, int versioning_status, ACLOwner *obj_owner) +int RGWRados::delete_obj(RGWObjectCtx& obj_ctx, const string& bucket_owner, rgw_obj& obj, int versioning_status) { RGWRados::Object del_target(this, obj_ctx, obj); RGWRados::Object::Delete del_op(&del_target); del_op.params.bucket_owner = bucket_owner; del_op.params.versioning_status = versioning_status; - if (obj_owner) { - del_op.params.obj_owner = *obj_owner; - } return del_op.delete_obj(); } @@ -5684,7 +5695,7 @@ int RGWRados::apply_olh_log(RGWObjectCtx& obj_ctx, const string& bucket_owner, r cls_rgw_obj_key& key = *liter; rgw_obj obj_instance(bucket, key.name); obj_instance.set_instance(key.instance); - int ret = delete_obj(obj_ctx, bucket_owner, obj_instance, 0, NULL); + int ret = delete_obj(obj_ctx, bucket_owner, obj_instance, 0); if (ret < 0 && ret != -ENOENT) { ldout(cct, 0) << "ERROR: delete_obj() returned " << ret << " obj_instance=" << obj_instance << dendl; return ret; @@ -6589,6 +6600,34 @@ int RGWRados::trim_bi_log_entries(rgw_bucket& bucket, string& start_marker, stri return 0; } +int RGWRados::bi_get_instance(rgw_obj& obj, rgw_bucket_dir_entry *dirent) +{ + rgw_bucket bucket; + rgw_rados_ref ref; + int r = get_obj_ref(obj, &ref, &bucket); + if (r < 0) { + return r; + } + + rgw_cls_bi_entry bi_entry; + r = bi_get(bucket, obj, InstanceIdx, &bi_entry); + if (r < 0 && r != -ENOENT) { + ldout(cct, 0) << "ERROR: bi_get() returned r=" << r << dendl; + } + if (r < 0) { + return r; + } + bufferlist::iterator iter = bi_entry.data.begin(); + try { + ::decode(*dirent, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: failed to decode bi_entry()" << dendl; + return -EIO; + } + + return 0; +} + int RGWRados::bi_get(rgw_bucket& bucket, rgw_obj& obj, BIIndexType index_type, rgw_cls_bi_entry *entry) { librados::IoCtx index_ctx; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index aed74313e7376..2763e506cac6c 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1457,6 +1457,13 @@ public: DeleteParams() : versioning_status(0) {} } params; + + struct DeleteResult { + bool delete_marker; + string version_id; + + DeleteResult() : delete_marker(false) {} + } result; Delete(RGWRados::Object *_target) : target(_target) {} @@ -1603,7 +1610,7 @@ public: int bucket_suspended(rgw_bucket& bucket, bool *suspended); /** Delete an object.*/ - virtual int delete_obj(RGWObjectCtx& obj_ctx, const string& bucket_owner, rgw_obj& src_obj, int versioning_status, ACLOwner *obj_owner); + virtual int delete_obj(RGWObjectCtx& obj_ctx, const string& bucket_owner, rgw_obj& src_obj, int versioning_status); /* Delete a system object */ virtual int delete_system_obj(rgw_obj& src_obj, RGWObjVersionTracker *objv_tracker = NULL); @@ -1770,6 +1777,7 @@ public: int list_bi_log_entries(rgw_bucket& bucket, string& marker, uint32_t max, std::list& result, bool *truncated); int trim_bi_log_entries(rgw_bucket& bucket, string& marker, string& end_marker); + int bi_get_instance(rgw_obj& obj, rgw_bucket_dir_entry *dirent); int bi_get(rgw_bucket& bucket, rgw_obj& obj, BIIndexType index_type, rgw_cls_bi_entry *entry); int bi_put(rgw_bucket& bucket, rgw_cls_bi_entry& entry); int bi_list(rgw_bucket& bucket, const string& obj_name, const string& marker, uint32_t max, diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index bb3835baa4b86..2fea0e6efaa25 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1367,6 +1367,12 @@ void RGWDeleteObj_ObjStore_S3::send_response() set_req_state_err(s, r); dump_errno(s); + if (!version_id.empty()) { + dump_string_header(s, "x-amz-version-id", version_id.c_str()); + } + if (delete_marker) { + dump_string_header(s, "x-amz-delete-marker", "true"); + } end_header(s, this); } -- 2.39.5