return object->delete_object(dpp, &rctx, null_yield);
}
-int rgw_remove_bucket_bypass_gc(rgw::sal::Store* store, rgw::sal::Bucket* bucket,
- int concurrent_max, bool keep_index_consistent,
- optional_yield y,
- const DoutPrefixProvider *dpp)
-{
- int ret;
- map<RGWObjCategory, RGWStorageStats> stats;
- map<string, bool> common_prefixes;
- RGWObjectCtx obj_ctx(store);
- CephContext *cct = store->ctx();
-
- string bucket_ver, master_ver;
-
- ret = bucket->get_bucket_info(dpp, null_yield);
- if (ret < 0)
- return ret;
-
- ret = bucket->get_bucket_stats(dpp, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, NULL);
- if (ret < 0)
- return ret;
-
- string prefix, delimiter;
-
- ret = abort_bucket_multiparts(dpp, store, cct, bucket, prefix, delimiter);
- if (ret < 0) {
- return ret;
- }
-
- rgw::sal::Bucket::ListParams params;
- rgw::sal::Bucket::ListResults results;
-
- params.list_versions = true;
- params.allow_unordered = true;
-
- std::unique_ptr<rgw::sal::Completions> handles = store->get_completions();
-
- int max_aio = concurrent_max;
- results.is_truncated = true;
-
- while (results.is_truncated) {
- ret = bucket->list(dpp, params, listing_max_entries, results, null_yield);
- if (ret < 0)
- return ret;
-
- std::vector<rgw_bucket_dir_entry>::iterator it = results.objs.begin();
- for (; it != results.objs.end(); ++it) {
- RGWObjState *astate = NULL;
- std::unique_ptr<rgw::sal::Object> obj = bucket->get_object((*it).key);
-
- ret = obj->get_obj_state(dpp, &obj_ctx, &astate, y, false);
- if (ret == -ENOENT) {
- ldpp_dout(dpp, 1) << "WARNING: cannot find obj state for obj " << obj << dendl;
- continue;
- }
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: get obj state returned with error " << ret << dendl;
- return ret;
- }
-
- if (astate->manifest) {
- RGWObjManifest& manifest = *astate->manifest;
- RGWObjManifest::obj_iterator miter = manifest.obj_begin(dpp);
- std::unique_ptr<rgw::sal::Object> head_obj = bucket->get_object(manifest.get_obj().key);
- rgw_raw_obj raw_head_obj;
- head_obj->get_raw_obj(&raw_head_obj);
-
- for (; miter != manifest.obj_end(dpp) && max_aio--; ++miter) {
- if (!max_aio) {
- ret = handles->drain();
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
- return ret;
- }
- max_aio = concurrent_max;
- }
-
- rgw_raw_obj last_obj = miter.get_location().get_raw_obj(store);
- if (last_obj == raw_head_obj) {
- // have the head obj deleted at the end
- continue;
- }
-
- ret = store->delete_raw_obj_aio(dpp, last_obj, handles.get());
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
- return ret;
- }
- } // for all shadow objs
-
- ret = head_obj->delete_obj_aio(dpp, astate, handles.get(), keep_index_consistent, null_yield);
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
- return ret;
- }
- }
-
- if (!max_aio) {
- ret = handles->drain();
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
- return ret;
- }
- max_aio = concurrent_max;
- }
- obj_ctx.invalidate(obj->get_obj());
- } // for all RGW objects
- }
-
- ret = handles->drain();
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
- return ret;
- }
-
- bucket->sync_user_stats(dpp, y);
- if (ret < 0) {
- ldpp_dout(dpp, 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
- }
-
- RGWObjVersionTracker objv_tracker;
-
- // this function can only be run if caller wanted children to be
- // deleted, so we can ignore the check for children as any that
- // remain are detritus from a prior bug
- ret = bucket->remove_bucket(dpp, true, std::string(), std::string(), false, nullptr, y);
- if (ret < 0) {
- ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " << bucket << dendl;
- return ret;
- }
-
- return ret;
-}
-
static void set_err_msg(std::string *sink, std::string msg)
{
if (sink && !msg.empty())
return ret;
if (bypass_gc)
- ret = rgw_remove_bucket_bypass_gc(store, bucket.get(), op_state.get_max_aio(), keep_index_consistent, y, dpp);
+ ret = bucket->remove_bucket_bypass_gc(op_state.get_max_aio(), keep_index_consistent, y, dpp);
else
ret = bucket->remove_bucket(dpp, op_state.will_delete_children(), string(), string(),
false, nullptr, y);
};
extern int rgw_remove_object(const DoutPrefixProvider *dpp, rgw::sal::Store* store, rgw::sal::Bucket* bucket, rgw_obj_key& key);
-extern int rgw_remove_bucket_bypass_gc(rgw::sal::Store* store, rgw::sal::Bucket* bucket, int concurrent_max, optional_yield y);
extern int rgw_object_get_attr(rgw::sal::Store* store, rgw::sal::Object* obj,
const char* attr_name, bufferlist& out_bl,
virtual Attrs& get_attrs(void) { return attrs; }
virtual int set_attrs(Attrs a) { attrs = a; return 0; }
virtual int remove_bucket(const DoutPrefixProvider* dpp, bool delete_children, std::string prefix, std::string delimiter, bool forward_to_master, req_info* req_info, optional_yield y) = 0;
+ virtual int remove_bucket_bypass_gc(int concurrent_max, bool
+ keep_index_consistent,
+ optional_yield y, const
+ DoutPrefixProvider *dpp) = 0;
virtual RGWAccessControlPolicy& get_acl(void) = 0;
virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl, optional_yield y) = 0;
virtual int get_bucket_info(const DoutPrefixProvider* dpp, optional_yield y) = 0;
virtual bool is_expired() = 0;
virtual void gen_rand_obj_instance_name() = 0;
virtual void raw_obj_to_obj(const rgw_raw_obj& raw_obj) = 0;
- virtual void get_raw_obj(rgw_raw_obj* raw_obj) = 0;
virtual MPSerializer* get_serializer(const DoutPrefixProvider *dpp, const std::string& lock_name) = 0;
virtual int transition(RGWObjectCtx& rctx,
Bucket* bucket,
namespace rgw::sal {
-RadosObject::~RadosObject() {}
+// default number of entries to list with each bucket listing call
+// (use marker to bridge between calls)
+static constexpr size_t listing_max_entries = 1000;
static int decode_policy(CephContext* cct,
bufferlist& bl,
return ret;
}
+int RadosBucket::remove_bucket_bypass_gc(int concurrent_max, bool
+ keep_index_consistent,
+ optional_yield y, const
+ DoutPrefixProvider *dpp)
+{
+ int ret;
+ map<RGWObjCategory, RGWStorageStats> stats;
+ map<string, bool> common_prefixes;
+ RGWObjectCtx obj_ctx(store);
+ CephContext *cct = store->ctx();
+
+ string bucket_ver, master_ver;
+
+ ret = get_bucket_info(dpp, null_yield);
+ if (ret < 0)
+ return ret;
+
+ ret = get_bucket_stats(dpp, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, NULL);
+ if (ret < 0)
+ return ret;
+
+ string prefix, delimiter;
+
+ ret = abort_bucket_multiparts(dpp, store, cct, this, prefix, delimiter);
+ if (ret < 0) {
+ return ret;
+ }
+
+ rgw::sal::Bucket::ListParams params;
+ rgw::sal::Bucket::ListResults results;
+
+ params.list_versions = true;
+ params.allow_unordered = true;
+
+ std::unique_ptr<rgw::sal::Completions> handles = store->get_completions();
+
+ int max_aio = concurrent_max;
+ results.is_truncated = true;
+
+ while (results.is_truncated) {
+ ret = list(dpp, params, listing_max_entries, results, null_yield);
+ if (ret < 0)
+ return ret;
+
+ std::vector<rgw_bucket_dir_entry>::iterator it = results.objs.begin();
+ for (; it != results.objs.end(); ++it) {
+ RGWObjState *astate = NULL;
+ std::unique_ptr<rgw::sal::Object> obj = get_object((*it).key);
+
+ ret = obj->get_obj_state(dpp, &obj_ctx, &astate, y, false);
+ if (ret == -ENOENT) {
+ ldpp_dout(dpp, 1) << "WARNING: cannot find obj state for obj " << obj << dendl;
+ continue;
+ }
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: get obj state returned with error " << ret << dendl;
+ return ret;
+ }
+
+ if (astate->manifest) {
+ RGWObjManifest& manifest = *astate->manifest;
+ RGWObjManifest::obj_iterator miter = manifest.obj_begin(dpp);
+ std::unique_ptr<rgw::sal::Object> head_obj = get_object(manifest.get_obj().key);
+ rgw_raw_obj raw_head_obj;
+ dynamic_cast<RadosObject*>(head_obj.get())->get_raw_obj(&raw_head_obj);
+
+ for (; miter != manifest.obj_end(dpp) && max_aio--; ++miter) {
+ if (!max_aio) {
+ ret = handles->drain();
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
+ return ret;
+ }
+ max_aio = concurrent_max;
+ }
+
+ rgw_raw_obj last_obj = miter.get_location().get_raw_obj(store);
+ if (last_obj == raw_head_obj) {
+ // have the head obj deleted at the end
+ continue;
+ }
+
+ ret = store->delete_raw_obj_aio(dpp, last_obj, handles.get());
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
+ return ret;
+ }
+ } // for all shadow objs
+
+ ret = head_obj->delete_obj_aio(dpp, astate, handles.get(), keep_index_consistent, null_yield);
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
+ return ret;
+ }
+ }
+
+ if (!max_aio) {
+ ret = handles->drain();
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
+ return ret;
+ }
+ max_aio = concurrent_max;
+ }
+ obj_ctx.invalidate(obj->get_obj());
+ } // for all RGW objects
+ }
+
+ ret = handles->drain();
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
+ return ret;
+ }
+
+ sync_user_stats(dpp, y);
+ if (ret < 0) {
+ ldpp_dout(dpp, 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
+ }
+
+ RGWObjVersionTracker objv_tracker;
+
+ // this function can only be run if caller wanted children to be
+ // deleted, so we can ignore the check for children as any that
+ // remain are detritus from a prior bug
+ ret = remove_bucket(dpp, true, std::string(), std::string(), false, nullptr, y);
+ if (ret < 0) {
+ ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " << this << dendl;
+ return ret;
+ }
+
+ return ret;
+}
+
int RadosBucket::get_bucket_info(const DoutPrefixProvider* dpp, optional_yield y)
{
auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
return 0;
}
+RadosObject::~RadosObject() {}
+
int RadosObject::get_obj_state(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, RGWObjState **state, optional_yield y, bool follow_olh)
{
return store->getRados()->get_obj_state(dpp, rctx, bucket->get_info(), get_obj(), state, follow_olh, y);
std::optional<rgw_raw_obj> raw_head;
if (!rgw::sal::Object::empty(head_obj.get())) {
raw_head.emplace();
- head_obj->get_raw_obj(&*raw_head);
+ dynamic_cast<RadosObject*>(head_obj.get())->get_raw_obj(&*raw_head);
}
/**
virtual bool is_expired() override;
virtual void gen_rand_obj_instance_name() override;
virtual void raw_obj_to_obj(const rgw_raw_obj& raw_obj) override;
- virtual void get_raw_obj(rgw_raw_obj* raw_obj) override;
+ void get_raw_obj(rgw_raw_obj* raw_obj);
virtual std::unique_ptr<Object> clone() override {
return std::unique_ptr<Object>(new RadosObject(*this));
}
virtual int list(const DoutPrefixProvider* dpp, ListParams&, int, ListResults&, optional_yield y) override;
Object* create_object(const rgw_obj_key& key /* Attributes */) override;
virtual int remove_bucket(const DoutPrefixProvider* dpp, bool delete_children, std::string prefix, std::string delimiter, bool forward_to_master, req_info* req_info, optional_yield y) override;
+ virtual int remove_bucket_bypass_gc(int concurrent_max, bool
+ keep_index_consistent,
+ optional_yield y, const
+ DoutPrefixProvider *dpp) override;
virtual RGWAccessControlPolicy& get_acl(void) override { return acls; }
virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl, optional_yield y) override;
virtual int get_bucket_info(const DoutPrefixProvider* dpp, optional_yield y) override;