diff --git a/src/common/static_ptr.h b/src/common/static_ptr.h index 63fce43424013..542f1e9a67a42 100644 --- a/src/common/static_ptr.h +++ b/src/common/static_ptr.h @@ -33,7 +33,7 @@ namespace _mem { // of the same arguments (which is not true for function type erasure) // it's a pretty good one. enum class op { - copy, move, destroy, size + move, destroy, size }; template static std::size_t op_fun(op oper, void* p1, void* p2) @@ -41,15 +41,6 @@ static std::size_t op_fun(op oper, void* p1, void* p2) auto me = static_cast(p1); switch (oper) { - case op::copy: - // One conspicuous downside is that immovable/uncopyable functions - // kill compilation right here, even if nobody ever calls the move - // or copy methods. Working around this is a pain, since we'd need - // four operator functions and a top-level class to - // provide/withhold copy/move operations as appropriate. - new (p2) T(*me); - break; - case op::move: new (p2) T(std::move(*me)); break; @@ -137,12 +128,6 @@ class static_ptr { // Set from another static pointer. // // Since the templated versions don't count for overriding the defaults - static_ptr(const static_ptr& rhs) - noexcept(std::is_nothrow_copy_constructible_v) : operate(rhs.operate) { - if (operate) { - operate(_mem::op::copy, &rhs.buf, &buf); - } - } static_ptr(static_ptr&& rhs) noexcept(std::is_nothrow_move_constructible_v) : operate(rhs.operate) { if (operate) { @@ -150,14 +135,6 @@ class static_ptr { } } - template - static_ptr(const static_ptr& rhs) - noexcept(std::is_nothrow_copy_constructible_v) : operate(rhs.operate) { - create_ward(); - if (operate) { - operate(_mem::op::copy, &rhs.buf, &buf); - } - } template static_ptr(static_ptr&& rhs) noexcept(std::is_nothrow_move_constructible_v) : operate(rhs.operate) { @@ -167,16 +144,6 @@ class static_ptr { } } - static_ptr& operator =(const static_ptr& rhs) - noexcept(std::is_nothrow_copy_constructible_v) { - reset(); - if (rhs) { - operate = rhs.operate; - operate(_mem::op::copy, - const_cast(static_cast(&rhs.buf)), &buf); - } - return *this; - } static_ptr& operator =(static_ptr&& rhs) noexcept(std::is_nothrow_move_constructible_v) { reset(); @@ -187,18 +154,6 @@ class static_ptr { return *this; } - template - static_ptr& operator =(const static_ptr& rhs) - noexcept(std::is_nothrow_copy_constructible_v) { - create_ward(); - reset(); - if (rhs) { - operate = rhs.operate; - operate(_mem::op::copy, - const_cast(static_cast(&rhs.buf)), &buf); - } - return *this; - } template static_ptr& operator =(static_ptr&& rhs) noexcept(std::is_nothrow_move_constructible_v) { @@ -300,20 +255,6 @@ class static_ptr { // nice idiom. Having to release and reconstruct is obnoxious. // template -static_ptr static_pointer_cast(const static_ptr& p) { - static_assert(Z >= S, - "Value too large."); - static_ptr r; - // Really, this is always true because static_cast either succeeds - // or fails to compile, but it prevents an unused variable warning - // and should be optimized out. - if (static_cast(p.get())) { - p.operate(_mem::op::copy, &p.buf, &r.buf); - r.operate = p.operate; - } - return r; -} -template static_ptr static_pointer_cast(static_ptr&& p) { static_assert(Z >= S, "Value too large."); @@ -329,17 +270,6 @@ static_ptr static_pointer_cast(static_ptr&& p) { // same behavior as dynamic_cast. // template -static_ptr dynamic_pointer_cast(const static_ptr& p) { - static_assert(Z >= S, - "Value too large."); - static_ptr r; - if (dynamic_cast(p.get())) { - p.operate(_mem::op::copy, &p.buf, &r.buf); - r.operate = p.operate; - } - return r; -} -template static_ptr dynamic_pointer_cast(static_ptr&& p) { static_assert(Z >= S, "Value too large."); @@ -351,17 +281,6 @@ static_ptr dynamic_pointer_cast(static_ptr&& p) { return r; } -template -static_ptr const_pointer_cast(const static_ptr& p) { - static_assert(Z >= S, - "Value too large."); - static_ptr r; - if (const_cast(p.get())) { - p.operate(_mem::op::copy, &p.buf, &r.buf); - r.operate = p.operate; - } - return r; -} template static_ptr const_pointer_cast(static_ptr&& p) { static_assert(Z >= S, @@ -378,15 +297,6 @@ static_ptr const_pointer_cast(static_ptr&& p) { // where they might. It works, though! // template -static_ptr reinterpret_pointer_cast(const static_ptr& p) { - static_assert(Z >= S, - "Value too large."); - static_ptr r; - p.operate(_mem::op::copy, &p.buf, &r.buf); - r.operate = p.operate; - return r; -} -template static_ptr reinterpret_pointer_cast(static_ptr&& p) { static_assert(Z >= S, "Value too large."); @@ -404,17 +314,6 @@ static_ptr reinterpret_pointer_cast(static_ptr&& p) { // I follow cast semantics. Since this is a pointer-like type, it // returns a null value rather than throwing. template -static_ptr resize_pointer_cast(const static_ptr& p) { - static_assert(std::is_same_v, - "resize_pointer_cast only changes size, not type."); - static_ptr r; - if (Z >= p.operate(_mem::op::size, &p.buf, nullptr)) { - p.operate(_mem::op::copy, &p.buf, &r.buf); - r.operate = p.operate; - } - return r; -} -template static_ptr resize_pointer_cast(static_ptr&& p) { static_assert(std::is_same_v, "resize_pointer_cast only changes size, not type."); @@ -427,11 +326,19 @@ static_ptr resize_pointer_cast(static_ptr&& p) { } template -bool operator ==(static_ptr s, std::nullptr_t) { +bool operator ==(const static_ptr& s, std::nullptr_t) { + return !s; +} +template +bool operator ==(std::nullptr_t, const static_ptr& s) { + return !s; +} +template +bool operator ==(static_ptr& s, std::nullptr_t) { return !s; } template -bool operator ==(std::nullptr_t, static_ptr s) { +bool operator ==(std::nullptr_t, static_ptr& s) { return !s; } diff --git a/src/rgw/rgw_acl.h b/src/rgw/rgw_acl.h index 9e8a0e5dd49ef..06c79e744ce22 100644 --- a/src/rgw/rgw_acl.h +++ b/src/rgw/rgw_acl.h @@ -401,6 +401,7 @@ class ACLOwner string display_name; public: ACLOwner() {} + ACLOwner(const rgw_user& _id) : id(_id) {} ~ACLOwner() {} void encode(bufferlist& bl) const { diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index c85bf8564045b..6829fe97befce 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -7224,7 +7224,7 @@ int main(int argc, const char **argv) if (opt_cmd == OPT::LC_LIST) { formatter->open_array_section("lifecycle_list"); - vector bucket_lc_map; + vector bucket_lc_map; string marker; int index{0}; #define MAX_LC_LIST_ENTRIES 100 diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 9234a66630c65..f1fd131c10e4e 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -439,7 +439,7 @@ int rgw_remove_bucket_bypass_gc(rgw::sal::RGWRadosStore *store, rgw_bucket& buck max_aio = concurrent_max; } - rgw_raw_obj last_obj = miter.get_location().get_raw_obj(store->getRados()); + 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; @@ -1819,7 +1819,8 @@ static int fix_single_bucket_lc(rgw::sal::RGWRadosStore *store, return ret; } - return rgw::lc::fix_lc_shard_entry(store, bucket_info, bucket_attrs); + return rgw::lc::fix_lc_shard_entry(store, store->get_rgwlc()->get_lc(), bucket_info, + bucket_attrs); } static void format_lc_status(Formatter* formatter, diff --git a/src/rgw/rgw_cr_rados.cc b/src/rgw/rgw_cr_rados.cc index a269af767a3d1..38217e1854c40 100644 --- a/src/rgw/rgw_cr_rados.cc +++ b/src/rgw/rgw_cr_rados.cc @@ -635,7 +635,7 @@ int RGWAsyncFetchRemoteObj::_send_request() char buf[16]; snprintf(buf, sizeof(buf), ".%lld", (long long)store->getRados()->instance_id()); - map attrs; + rgw::sal::RGWAttrs attrs; rgw::sal::RGWRadosBucket bucket(store, src_bucket); rgw::sal::RGWRadosObject src_obj(store, key, &bucket); diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index ffa76b806d4ee..28c1e0e1abc02 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -1583,7 +1583,8 @@ namespace rgw { &state->dest_placement, state->bucket_owner.get_id(), *static_cast(state->obj_ctx), - state->object->get_obj(), olh_epoch, state->req_id, this, state->yield); + std::move(state->object->clone()), olh_epoch, state->req_id, + this, state->yield); op_ret = processor->prepare(state->yield); if (op_ret < 0) { diff --git a/src/rgw/rgw_lc.cc b/src/rgw/rgw_lc.cc index c49e8c7e728db..26471a74642d9 100644 --- a/src/rgw/rgw_lc.cc +++ b/src/rgw/rgw_lc.cc @@ -18,7 +18,6 @@ #include "common/containers.h" #include #include "include/random.h" -#include "cls/rgw/cls_rgw_client.h" #include "cls/lock/cls_lock_client.h" #include "rgw_perf_counters.h" #include "rgw_common.h" @@ -243,6 +242,7 @@ void *RGWLC::LCWorker::entry() { void RGWLC::initialize(CephContext *_cct, rgw::sal::RGWRadosStore *_store) { cct = _cct; store = _store; + sal_lc = std::move(store->get_lifecycle()); max_objs = cct->_conf->rgw_lc_max_objs; if (max_objs > HASH_PRIME) max_objs = HASH_PRIME; @@ -291,7 +291,7 @@ bool RGWLC::if_already_run_today(time_t start_date) return false; } -static inline std::ostream& operator<<(std::ostream &os, cls_rgw_lc_entry& ent) { +static inline std::ostream& operator<<(std::ostream &os, rgw::sal::Lifecycle::LCEntry& ent) { os << "getRados()->lc_pool_ctx, obj_names[index], - marker, MAX_LC_LIST_ENTRIES, entries); + int ret = sal_lc->list_entries(obj_names[index], marker, MAX_LC_LIST_ENTRIES, entries); if (ret < 0) return ret; for (auto& entry : entries) { entry.start_time = ceph_clock_now(); entry.status = lc_uninitial; // lc_uninitial? really? - ret = cls_rgw_lc_set_entry(store->getRados()->lc_pool_ctx, - obj_names[index], entry); + ret = sal_lc->set_entry(obj_names[index], entry); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::bucket_lc_prepare() failed to set entry on " @@ -370,17 +368,13 @@ static bool obj_has_expired(CephContext *cct, ceph::real_time mtime, int days, return (timediff >= cmp); } -static bool pass_object_lock_check(RGWRados *store, RGWBucketInfo& bucket_info, - rgw_obj& obj, RGWObjectCtx& ctx) +static bool pass_object_lock_check(rgw::sal::RGWStore* store, rgw::sal::RGWObject* obj, RGWObjectCtx& ctx) { - if (!bucket_info.obj_lock_enabled()) { + if (!obj->get_bucket()->get_info().obj_lock_enabled()) { return true; } - RGWRados::Object op_target(store, bucket_info, ctx, obj); - RGWRados::Object::Read read_op(&op_target); - map attrs; - read_op.params.attrs = &attrs; - int ret = read_op.prepare(null_yield); + std::unique_ptr read_op = obj->get_read_op(&ctx); + int ret = read_op->prepare(null_yield); if (ret < 0) { if (ret == -ENOENT) { return true; @@ -388,8 +382,8 @@ static bool pass_object_lock_check(RGWRados *store, RGWBucketInfo& bucket_info, return false; } } else { - auto iter = attrs.find(RGW_ATTR_OBJECT_RETENTION); - if (iter != attrs.end()) { + auto iter = obj->get_attrs().find(RGW_ATTR_OBJECT_RETENTION); + if (iter != obj->get_attrs().end()) { RGWObjectRetention retention; try { decode(retention, iter->second); @@ -403,8 +397,8 @@ static bool pass_object_lock_check(RGWRados *store, RGWBucketInfo& bucket_info, return false; } } - iter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD); - if (iter != attrs.end()) { + iter = obj->get_attrs().find(RGW_ATTR_OBJECT_LEGAL_HOLD); + if (iter != obj->get_attrs().end()) { RGWObjectLegalHold obj_legal_hold; try { decode(obj_legal_hold, iter->second); @@ -422,30 +416,26 @@ static bool pass_object_lock_check(RGWRados *store, RGWBucketInfo& bucket_info, } class LCObjsLister { - rgw::sal::RGWRadosStore *store; - RGWBucketInfo& bucket_info; - RGWRados::Bucket target; - RGWRados::Bucket::List list_op; - bool is_truncated{false}; - rgw_obj_key next_marker; + rgw::sal::RGWStore *store; + rgw::sal::RGWBucket* bucket; + rgw::sal::RGWBucket::ListParams list_params; + rgw::sal::RGWBucket::ListResults list_results; string prefix; - vector objs; vector::iterator obj_iter; rgw_bucket_dir_entry pre_obj; int64_t delay_ms; public: - LCObjsLister(rgw::sal::RGWRadosStore *_store, RGWBucketInfo& _bucket_info) : - store(_store), bucket_info(_bucket_info), - target(store->getRados(), bucket_info), list_op(&target) { - list_op.params.list_versions = bucket_info.versioned(); - list_op.params.allow_unordered = true; + LCObjsLister(rgw::sal::RGWStore *_store, rgw::sal::RGWBucket* _bucket) : + store(_store), bucket(_bucket) { + list_params.list_versions = bucket->versioned(); + list_params.allow_unordered = true; delay_ms = store->ctx()->_conf.get_val("rgw_lc_thread_delay"); } void set_prefix(const string& p) { prefix = p; - list_op.params.prefix = prefix; + list_params.prefix = prefix; } int init() { @@ -453,13 +443,12 @@ class LCObjsLister { } int fetch() { - int ret = list_op.list_objects( - 1000, &objs, NULL, &is_truncated, null_yield); + int ret = bucket->list(list_params, 1000, list_results, null_yield); if (ret < 0) { return ret; } - obj_iter = objs.begin(); + obj_iter = list_results.objs.begin(); return 0; } @@ -471,13 +460,13 @@ class LCObjsLister { bool get_obj(rgw_bucket_dir_entry **obj, std::function fetch_barrier = []() { /* nada */}) { - if (obj_iter == objs.end()) { - if (!is_truncated) { + if (obj_iter == list_results.objs.end()) { + if (!list_results.is_truncated) { delay(); return false; } else { fetch_barrier(); - list_op.params.marker = pre_obj.key; + list_params.marker = pre_obj.key; int ret = fetch(); if (ret < 0) { ldout(store->ctx(), 0) << "ERROR: list_op returned ret=" << ret @@ -489,7 +478,7 @@ class LCObjsLister { } /* returning address of entry in objs */ *obj = &(*obj_iter); - return obj_iter != objs.end(); + return obj_iter != list_results.objs.end(); } rgw_bucket_dir_entry get_prev_obj() { @@ -502,8 +491,8 @@ class LCObjsLister { } boost::optional next_key_name() { - if (obj_iter == objs.end() || - (obj_iter + 1) == objs.end()) { + if (obj_iter == list_results.objs.end() || + (obj_iter + 1) == list_results.objs.end()) { /* this should have been called after get_obj() was called, so this should * only happen if is_truncated is false */ return boost::none; @@ -521,12 +510,12 @@ struct op_env { lc_op op; rgw::sal::RGWRadosStore *store; LCWorker* worker; - RGWBucketInfo& bucket_info; + rgw::sal::RGWBucket* bucket; LCObjsLister& ol; op_env(lc_op& _op, rgw::sal::RGWRadosStore *_store, LCWorker* _worker, - RGWBucketInfo& _bucket_info, LCObjsLister& _ol) - : op(_op), store(_store), worker(_worker), bucket_info(_bucket_info), + rgw::sal::RGWBucket* _bucket, LCObjsLister& _ol) + : op(_op), store(_store), worker(_worker), bucket(_bucket), ol(_ol) {} }; /* op_env */ @@ -541,11 +530,11 @@ struct lc_op_ctx { ceph::real_time effective_mtime; rgw::sal::RGWRadosStore *store; - RGWBucketInfo& bucket_info; + rgw::sal::RGWBucket* bucket; lc_op& op; // ok--refers to expanded env.op LCObjsLister& ol; - rgw_obj obj; + std::unique_ptr obj; RGWObjectCtx rctx; const DoutPrefixProvider *dpp; WorkQ* wq; @@ -556,9 +545,11 @@ struct lc_op_ctx { const DoutPrefixProvider *dpp, WorkQ* wq) : cct(env.store->ctx()), env(env), o(o), next_key_name(next_key_name), effective_mtime(effective_mtime), - store(env.store), bucket_info(env.bucket_info), op(env.op), ol(env.ol), - obj(env.bucket_info.bucket, o.key), rctx(env.store), dpp(dpp), wq(wq) - {} + store(env.store), bucket(env.bucket), op(env.op), ol(env.ol), + rctx(env.store), dpp(dpp), wq(wq) + { + obj = bucket->get_object(o.key); + } bool next_has_same_name(const std::string& key_name) { return (next_key_name && key_name.compare( @@ -570,10 +561,12 @@ struct lc_op_ctx { static int remove_expired_obj(lc_op_ctx& oc, bool remove_indeed) { auto& store = oc.store; - auto& bucket_info = oc.bucket_info; + auto& bucket_info = oc.bucket->get_info(); auto& o = oc.o; auto obj_key = o.key; auto& meta = o.meta; + int ret; + std::string version_id; if (!remove_indeed) { obj_key.instance.clear(); @@ -581,20 +574,24 @@ static int remove_expired_obj(lc_op_ctx& oc, bool remove_indeed) obj_key.instance = "null"; } - rgw_obj obj(bucket_info.bucket, obj_key); + std::unique_ptr bucket; + std::unique_ptr obj; + + ret = store->get_bucket(nullptr, bucket_info, &bucket); + if (ret < 0) { + return ret; + } + + obj = bucket->get_object(obj_key); + ACLOwner obj_owner; obj_owner.set_id(rgw_user {meta.owner}); obj_owner.set_name(meta.owner_display_name); + ACLOwner bucket_owner; + bucket_owner.set_id(bucket_info.owner); - RGWRados::Object del_target(store->getRados(), bucket_info, oc.rctx, obj); - RGWRados::Object::Delete del_op(&del_target); - - del_op.params.bucket_owner = bucket_info.owner; - del_op.params.versioning_status = bucket_info.versioning_status(); - del_op.params.obj_owner = obj_owner; - del_op.params.unmod_since = meta.mtime; - - return del_op.delete_obj(null_yield); + return obj->delete_object(&oc.rctx, obj_owner, bucket_owner, meta.mtime, false, 0, + version_id, null_yield); } /* remove_expired_obj */ class LCOpAction { @@ -822,24 +819,23 @@ static inline bool worker_should_stop(time_t stop_at, bool once) return !once && stop_at < time(nullptr); } -int RGWLC::handle_multipart_expiration( - RGWRados::Bucket *target, const multimap& prefix_map, - LCWorker* worker, time_t stop_at, bool once) +int RGWLC::handle_multipart_expiration(rgw::sal::RGWBucket* target, + const multimap& prefix_map, + LCWorker* worker, time_t stop_at, bool once) { MultipartMetaFilter mp_filter; vector objs; - bool is_truncated; int ret; - RGWBucketInfo& bucket_info = target->get_bucket_info(); - RGWRados::Bucket::List list_op(target); + rgw::sal::RGWBucket::ListParams params; + rgw::sal::RGWBucket::ListResults results; auto delay_ms = cct->_conf.get_val("rgw_lc_thread_delay"); - list_op.params.list_versions = false; + params.list_versions = false; /* lifecycle processing does not depend on total order, so can * take advantage of unordered listing optimizations--such as * operating on one shard at a time */ - list_op.params.allow_unordered = true; - list_op.params.ns = RGW_OBJ_NS_MULTIPART; - list_op.params.filter = &mp_filter; + params.allow_unordered = true; + params.ns = RGW_OBJ_NS_MULTIPART; + params.filter = &mp_filter; auto pf = [&](RGWLC::LCWorker* wk, WorkQ* wq, WorkItem& wi) { auto wt = boost::get>(wi); @@ -851,7 +847,7 @@ int RGWLC::handle_multipart_expiration( return; } RGWObjectCtx rctx(store); - int ret = abort_multipart_upload(store, cct, &rctx, bucket_info, mp_obj); + int ret = abort_multipart_upload(store, cct, &rctx, target->get_info(), mp_obj); if (ret == 0) { if (perfcounter) { perfcounter->inc(l_rgw_lc_abort_mpu, 1); @@ -889,11 +885,10 @@ int RGWLC::handle_multipart_expiration( if (!prefix_iter->second.status || prefix_iter->second.mp_expiration <= 0) { continue; } - list_op.params.prefix = prefix_iter->first; + params.prefix = prefix_iter->first; do { objs.clear(); - list_op.params.marker = list_op.get_next_marker(); - ret = list_op.list_objects(1000, &objs, NULL, &is_truncated, null_yield); + ret = target->list(params, 1000, results, null_yield); if (ret < 0) { if (ret == (-ENOENT)) return 0; @@ -911,20 +906,18 @@ int RGWLC::handle_multipart_expiration( } /* for objs */ std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms)); - } while(is_truncated); + } while(results.is_truncated); } /* for prefix_map */ worker->workpool->drain(); return 0; } -static int read_obj_tags(RGWRados *store, RGWBucketInfo& bucket_info, - rgw_obj& obj, RGWObjectCtx& ctx, bufferlist& tags_bl) +static int read_obj_tags(rgw::sal::RGWObject* obj, RGWObjectCtx& ctx, bufferlist& tags_bl) { - RGWRados::Object op_target(store, bucket_info, ctx, obj); - RGWRados::Object::Read read_op(&op_target); + std::unique_ptr rop = obj->get_read_op(&ctx); - return read_op.get_attr(RGW_ATTR_TAGS, tags_bl, null_yield); + return rop->get_attr(RGW_ATTR_TAGS, tags_bl, null_yield); } static bool is_valid_op(const lc_op& op) @@ -968,8 +961,7 @@ static int check_tags(lc_op_ctx& oc, bool *skip) *skip = true; bufferlist tags_bl; - int ret = read_obj_tags(oc.store->getRados(), oc.bucket_info, oc.obj, - oc.rctx, tags_bl); + int ret = read_obj_tags(oc.obj.get(), oc.rctx, tags_bl); if (ret < 0) { if (ret != -ENODATA) { ldout(oc.cct, 5) << "ERROR: read_obj_tags returned r=" @@ -1084,20 +1076,20 @@ class LCOpAction_CurrentExpiration : public LCOpAction { r = remove_expired_obj(oc, true); if (r < 0) { ldout(oc.cct, 0) << "ERROR: current is-dm remove_expired_obj " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " " << cpp_strerror(r) << " " << oc.wq->thr_name() << dendl; return r; } ldout(oc.cct, 2) << "DELETED: current is-dm " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " " << oc.wq->thr_name() << dendl; } else { /* ! o.is_delete_marker() */ - r = remove_expired_obj(oc, !oc.bucket_info.versioned()); + r = remove_expired_obj(oc, !oc.bucket->versioned()); if (r < 0) { ldout(oc.cct, 0) << "ERROR: remove_expired_obj " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " " << cpp_strerror(r) << " " << oc.wq->thr_name() << dendl; return r; @@ -1105,7 +1097,7 @@ class LCOpAction_CurrentExpiration : public LCOpAction { if (perfcounter) { perfcounter->inc(l_rgw_lc_expire_current, 1); } - ldout(oc.cct, 2) << "DELETED:" << oc.bucket_info.bucket << ":" << o.key + ldout(oc.cct, 2) << "DELETED:" << oc.bucket << ":" << o.key << " " << oc.wq->thr_name() << dendl; } return 0; @@ -1136,8 +1128,7 @@ class LCOpAction_NonCurrentExpiration : public LCOpAction { << oc.wq->thr_name() << dendl; return is_expired && - pass_object_lock_check(oc.store->getRados(), - oc.bucket_info, oc.obj, oc.rctx); + pass_object_lock_check(oc.store, oc.obj.get(), oc.rctx); } int process(lc_op_ctx& oc) { @@ -1145,7 +1136,7 @@ class LCOpAction_NonCurrentExpiration : public LCOpAction { int r = remove_expired_obj(oc, true); if (r < 0) { ldout(oc.cct, 0) << "ERROR: remove_expired_obj (non-current expiration) " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " " << cpp_strerror(r) << " " << oc.wq->thr_name() << dendl; return r; @@ -1153,7 +1144,7 @@ class LCOpAction_NonCurrentExpiration : public LCOpAction { if (perfcounter) { perfcounter->inc(l_rgw_lc_expire_noncurrent, 1); } - ldout(oc.cct, 2) << "DELETED:" << oc.bucket_info.bucket << ":" << o.key + ldout(oc.cct, 2) << "DELETED:" << oc.bucket << ":" << o.key << " (non-current expiration) " << oc.wq->thr_name() << dendl; return 0; @@ -1189,7 +1180,7 @@ class LCOpAction_DMExpiration : public LCOpAction { int r = remove_expired_obj(oc, true); if (r < 0) { ldout(oc.cct, 0) << "ERROR: remove_expired_obj (delete marker expiration) " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " " << cpp_strerror(r) << " " << oc.wq->thr_name() << dendl; @@ -1198,7 +1189,7 @@ class LCOpAction_DMExpiration : public LCOpAction { if (perfcounter) { perfcounter->inc(l_rgw_lc_expire_dm, 1); } - ldout(oc.cct, 2) << "DELETED:" << oc.bucket_info.bucket << ":" << o.key + ldout(oc.cct, 2) << "DELETED:" << oc.bucket << ":" << o.key << " (delete marker expiration) " << oc.wq->thr_name() << dendl; return 0; @@ -1262,33 +1253,30 @@ class LCOpAction_Transition : public LCOpAction { auto& o = oc.o; rgw_placement_rule target_placement; - target_placement.inherit_from(oc.bucket_info.placement_rule); + target_placement.inherit_from(oc.bucket->get_placement_rule()); target_placement.storage_class = transition.storage_class; if (!oc.store->svc()->zone->get_zone_params(). valid_placement(target_placement)) { ldpp_dout(oc.dpp, 0) << "ERROR: non existent dest placement: " << target_placement - << " bucket="<< oc.bucket_info.bucket + << " bucket="<< oc.bucket << " rule_id=" << oc.op.id << " " << oc.wq->thr_name() << dendl; return -EINVAL; } - rgw::sal::RGWRadosBucket bucket(oc.store, oc.bucket_info); - rgw::sal::RGWRadosObject obj(oc.store, oc.obj.key, &bucket); - int r = oc.store->getRados()->transition_obj( - oc.rctx, &bucket, obj, target_placement, o.meta.mtime, - o.versioned_epoch, oc.dpp, null_yield); + int r = oc.obj->transition(oc.rctx, oc.bucket, target_placement, o.meta.mtime, + o.versioned_epoch, oc.dpp, null_yield); if (r < 0) { ldpp_dout(oc.dpp, 0) << "ERROR: failed to transition obj " - << oc.bucket_info.bucket << ":" << o.key + << oc.bucket << ":" << o.key << " -> " << transition.storage_class << " " << cpp_strerror(r) << " " << oc.wq->thr_name() << dendl; return r; } - ldpp_dout(oc.dpp, 2) << "TRANSITIONED:" << oc.bucket_info.bucket + ldpp_dout(oc.dpp, 2) << "TRANSITIONED:" << oc.bucket << ":" << o.key << " -> " << transition.storage_class << " " << oc.wq->thr_name() << dendl; @@ -1427,12 +1415,12 @@ int LCOpRule::process(rgw_bucket_dir_entry& o, int r = (*selected)->process(ctx); if (r < 0) { ldpp_dout(dpp, 0) << "ERROR: remove_expired_obj " - << env.bucket_info.bucket << ":" << o.key + << env.bucket << ":" << o.key << " " << cpp_strerror(r) << " " << wq->thr_name() << dendl; return r; } - ldpp_dout(dpp, 20) << "processed:" << env.bucket_info.bucket << ":" + ldpp_dout(dpp, 20) << "processed:" << env.bucket << ":" << o.key << " " << wq->thr_name() << dendl; } @@ -1444,8 +1432,7 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, time_t stop_at, bool once) { RGWLifecycleConfiguration config(cct); - RGWBucketInfo bucket_info; - map bucket_attrs; + std::unique_ptr bucket; string no_ns, list_versions; vector objs; vector result; @@ -1453,9 +1440,14 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, string bucket_tenant = result[0]; string bucket_name = result[1]; string bucket_marker = result[2]; - int ret = store->getRados()->get_bucket_info( - store->svc(), bucket_tenant, bucket_name, bucket_info, NULL, null_yield, - &bucket_attrs); + int ret = store->get_bucket(nullptr, bucket_tenant, bucket_name, &bucket, null_yield); + if (ret < 0) { + ldpp_dout(this, 0) << "LC:get_bucket for " << bucket_name + << " failed" << dendl; + return ret; + } + + ret = bucket->get_bucket_info(null_yield); if (ret < 0) { ldpp_dout(this, 0) << "LC:get_bucket_info for " << bucket_name << " failed" << dendl; @@ -1469,18 +1461,16 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, } ); - if (bucket_info.bucket.marker != bucket_marker) { + if (bucket->get_marker() != bucket_marker) { ldpp_dout(this, 1) << "LC: deleting stale entry found for bucket=" << bucket_tenant << ":" << bucket_name - << " cur_marker=" << bucket_info.bucket.marker + << " cur_marker=" << bucket->get_marker() << " orig_marker=" << bucket_marker << dendl; return -ENOENT; } - RGWRados::Bucket target(store->getRados(), bucket_info); - - map::iterator aiter = bucket_attrs.find(RGW_ATTR_LC); - if (aiter == bucket_attrs.end()) + map::iterator aiter = bucket->get_attrs().find(RGW_ATTR_LC); + if (aiter == bucket->get_attrs().end()) return 0; bufferlist::const_iterator iter{&aiter->second}; @@ -1541,7 +1531,7 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, pre_marker = next_marker; } - LCObjsLister ol(store, bucket_info); + LCObjsLister ol(store, bucket.get()); ol.set_prefix(prefix_iter->first); ret = ol.init(); @@ -1552,7 +1542,7 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, return ret; } - op_env oenv(op, store, worker, bucket_info, ol); + op_env oenv(op, store, worker, bucket.get(), ol); LCOpRule orule(oenv); orule.build(); // why can't ctor do it? rgw_bucket_dir_entry* o{nullptr}; @@ -1564,27 +1554,26 @@ int RGWLC::bucket_lc_process(string& shard_id, LCWorker* worker, worker->workpool->drain(); } - ret = handle_multipart_expiration(&target, prefix_map, worker, stop_at, once); + ret = handle_multipart_expiration(bucket.get(), prefix_map, worker, stop_at, once); return ret; } int RGWLC::bucket_lc_post(int index, int max_lock_sec, - cls_rgw_lc_entry& entry, int& result, + rgw::sal::Lifecycle::LCEntry& entry, int& result, LCWorker* worker) { utime_t lock_duration(cct->_conf->rgw_lc_lock_max_time, 0); - rados::cls::lock::Lock l(lc_index_lock_name); - l.set_cookie(cookie); - l.set_duration(lock_duration); + rgw::sal::LCSerializer* lock = sal_lc->get_serializer(lc_index_lock_name, + obj_names[index], + cookie); dout(5) << "RGWLC::bucket_lc_post(): POST " << entry << " index: " << index << " worker ix: " << worker->ix << dendl; do { - int ret = l.lock_exclusive( - &store->getRados()->lc_pool_ctx, obj_names[index]); + int ret = lock->try_lock(lock_duration, null_yield); if (ret == -EBUSY || ret == -EEXIST) { /* already locked by another lc processor */ ldpp_dout(this, 0) << "RGWLC::bucket_lc_post() failed to acquire lock on " @@ -1597,8 +1586,7 @@ int RGWLC::bucket_lc_post(int index, int max_lock_sec, ldpp_dout(this, 20) << "RGWLC::bucket_lc_post() lock " << obj_names[index] << dendl; if (result == -ENOENT) { - ret = cls_rgw_lc_rm_entry(store->getRados()->lc_pool_ctx, - obj_names[index], entry); + ret = sal_lc->rm_entry(obj_names[index], entry); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::bucket_lc_post() failed to remove entry " << obj_names[index] << dendl; @@ -1610,14 +1598,14 @@ int RGWLC::bucket_lc_post(int index, int max_lock_sec, entry.status = lc_complete; } - ret = cls_rgw_lc_set_entry(store->getRados()->lc_pool_ctx, - obj_names[index], entry); + ret = sal_lc->set_entry(obj_names[index], entry); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::process() failed to set entry on " << obj_names[index] << dendl; } clean: - l.unlock(&store->getRados()->lc_pool_ctx, obj_names[index]); + lock->unlock(); + delete lock; ldpp_dout(this, 20) << "RGWLC::bucket_lc_post() unlock " << obj_names[index] << dendl; return 0; @@ -1625,15 +1613,13 @@ int RGWLC::bucket_lc_post(int index, int max_lock_sec, } int RGWLC::list_lc_progress(string& marker, uint32_t max_entries, - vector& progress_map, + vector& progress_map, int& index) { progress_map.clear(); for(; index < max_objs; index++, marker="") { - vector entries; - int ret = - cls_rgw_lc_list(store->getRados()->lc_pool_ctx, obj_names[index], marker, - max_entries, entries); + vector entries; + int ret = sal_lc->list_entries(obj_names[index], marker, max_entries, entries); if (ret < 0) { if (ret == -ENOENT) { ldpp_dout(this, 10) << __func__ << "() ignoring unfound lc object=" @@ -1718,19 +1704,19 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, << "index: " << index << " worker ix: " << worker->ix << dendl; - rados::cls::lock::Lock l(lc_index_lock_name); + rgw::sal::LCSerializer* lock = sal_lc->get_serializer(lc_index_lock_name, + obj_names[index], + std::string()); do { utime_t now = ceph_clock_now(); //string = bucket_name:bucket_id, start_time, int = LC_BUCKET_STATUS - cls_rgw_lc_entry entry; + rgw::sal::Lifecycle::LCEntry entry; if (max_lock_secs <= 0) return -EAGAIN; utime_t time(max_lock_secs, 0); - l.set_duration(time); - int ret = l.lock_exclusive(&store->getRados()->lc_pool_ctx, - obj_names[index]); + int ret = lock->try_lock(time, null_yield); if (ret == -EBUSY || ret == -EEXIST) { /* already locked by another lc processor */ ldpp_dout(this, 0) << "RGWLC::process() failed to acquire lock on " @@ -1741,9 +1727,8 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, if (ret < 0) return 0; - cls_rgw_lc_obj_head head; - ret = cls_rgw_lc_get_head(store->getRados()->lc_pool_ctx, obj_names[index], - head); + rgw::sal::Lifecycle::LCHead head; + ret = sal_lc->get_head(obj_names[index], head); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::process() failed to get obj head " << obj_names[index] << ", ret=" << ret << dendl; @@ -1751,8 +1736,7 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, } if (! (cct->_conf->rgw_lc_lock_max_time == 9969)) { - ret = cls_rgw_lc_get_entry(store->getRados()->lc_pool_ctx, - obj_names[index], head.marker, entry); + ret = sal_lc->get_entry(obj_names[index], head.marker, entry); if (ret >= 0) { if (entry.status == lc_processing) { if (expired_session(entry.start_time)) { @@ -1784,8 +1768,7 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, } } - ret = cls_rgw_lc_get_next_entry(store->getRados()->lc_pool_ctx, - obj_names[index], head.marker, entry); + ret = sal_lc->get_next_entry(obj_names[index], head.marker, entry); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::process() failed to get obj entry " << obj_names[index] << dendl; @@ -1801,8 +1784,7 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, << dendl; entry.status = lc_processing; - ret = cls_rgw_lc_set_entry(store->getRados()->lc_pool_ctx, - obj_names[index], entry); + ret = sal_lc->set_entry(obj_names[index], entry); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::process() failed to set obj entry " << obj_names[index] << entry.bucket << entry.status << dendl; @@ -1810,8 +1792,7 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, } head.marker = entry.bucket; - ret = cls_rgw_lc_put_head(store->getRados()->lc_pool_ctx, - obj_names[index], head); + ret = sal_lc->put_head(obj_names[index], head); if (ret < 0) { ldpp_dout(this, 0) << "RGWLC::process() failed to put head " << obj_names[index] @@ -1823,7 +1804,8 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, << " index: " << index << " worker ix: " << worker->ix << dendl; - l.unlock(&store->getRados()->lc_pool_ctx, obj_names[index]); + lock->unlock(); + delete lock; ret = bucket_lc_process(entry.bucket, worker, thread_stop_at(), once); bucket_lc_post(index, max_lock_secs, entry, ret, worker); } while(1 && !once); @@ -1831,7 +1813,8 @@ int RGWLC::process(int index, int max_lock_secs, LCWorker* worker, return 0; exit: - l.unlock(&store->getRados()->lc_pool_ctx, obj_names[index]); + lock->unlock(); + delete lock; return 0; } @@ -1967,6 +1950,7 @@ static std::string get_lc_shard_name(const rgw_bucket& bucket){ template static int guard_lc_modify(rgw::sal::RGWRadosStore* store, + rgw::sal::Lifecycle* sal_lc, const rgw_bucket& bucket, const string& cookie, const F& f) { CephContext *cct = store->ctx(); @@ -1977,21 +1961,20 @@ static int guard_lc_modify(rgw::sal::RGWRadosStore* store, get_lc_oid(cct, shard_id, &oid); /* XXX it makes sense to take shard_id for a bucket_id? */ - cls_rgw_lc_entry entry; + rgw::sal::Lifecycle::LCEntry entry; entry.bucket = shard_id; entry.status = lc_uninitial; int max_lock_secs = cct->_conf->rgw_lc_lock_max_time; - rados::cls::lock::Lock l(lc_index_lock_name); + rgw::sal::LCSerializer* lock = sal_lc->get_serializer(lc_index_lock_name, + oid, + cookie); utime_t time(max_lock_secs, 0); - l.set_duration(time); - l.set_cookie(cookie); - librados::IoCtx *ctx = store->getRados()->get_lc_pool_ctx(); int ret; do { - ret = l.lock_exclusive(ctx, oid); + ret = lock->try_lock(time, null_yield); if (ret == -EBUSY || ret == -EEXIST) { ldout(cct, 0) << "RGWLC::RGWPutLC() failed to acquire lock on " << oid << ", sleep 5, try again" << dendl; @@ -2003,14 +1986,15 @@ static int guard_lc_modify(rgw::sal::RGWRadosStore* store, << oid << ", ret=" << ret << dendl; break; } - ret = f(ctx, oid, entry); + ret = f(sal_lc, oid, entry); if (ret < 0) { ldout(cct, 0) << "RGWLC::RGWPutLC() failed to set entry on " << oid << ", ret=" << ret << dendl; } break; } while(true); - l.unlock(ctx, oid); + lock->unlock(); + delete lock; return ret; } @@ -2033,10 +2017,10 @@ int RGWLC::set_bucket_config(RGWBucketInfo& bucket_info, rgw_bucket& bucket = bucket_info.bucket; - ret = guard_lc_modify(store, bucket, cookie, - [&](librados::IoCtx *ctx, const string& oid, - const cls_rgw_lc_entry& entry) { - return cls_rgw_lc_set_entry(*ctx, oid, entry); + ret = guard_lc_modify(store, sal_lc.get(), bucket, cookie, + [&](rgw::sal::Lifecycle* sal_lc, const string& oid, + const rgw::sal::Lifecycle::LCEntry& entry) { + return sal_lc->set_entry(oid, entry); }); return ret; @@ -2060,10 +2044,10 @@ int RGWLC::remove_bucket_config(RGWBucketInfo& bucket_info, } - ret = guard_lc_modify(store, bucket, cookie, - [&](librados::IoCtx *ctx, const string& oid, - const cls_rgw_lc_entry& entry) { - return cls_rgw_lc_rm_entry(*ctx, oid, entry); + ret = guard_lc_modify(store, sal_lc.get(), bucket, cookie, + [&](rgw::sal::Lifecycle* sal_lc, const string& oid, + const rgw::sal::Lifecycle::LCEntry& entry) { + return sal_lc->rm_entry(oid, entry); }); return ret; @@ -2078,6 +2062,7 @@ RGWLC::~RGWLC() namespace rgw::lc { int fix_lc_shard_entry(rgw::sal::RGWRadosStore* store, + rgw::sal::Lifecycle* sal_lc, const RGWBucketInfo& bucket_info, const map& battrs) { @@ -2090,20 +2075,18 @@ int fix_lc_shard_entry(rgw::sal::RGWRadosStore* store, std::string lc_oid; get_lc_oid(store->ctx(), shard_name, &lc_oid); - cls_rgw_lc_entry entry; + rgw::sal::Lifecycle::LCEntry entry; // There are multiple cases we need to encounter here // 1. entry exists and is already set to marker, happens in plain buckets & newly resharded buckets // 2. entry doesn't exist, which usually happens when reshard has happened prior to update and next LC process has already dropped the update // 3. entry exists matching the current bucket id which was after a reshard (needs to be updated to the marker) // We are not dropping the old marker here as that would be caught by the next LC process update - auto lc_pool_ctx = store->getRados()->get_lc_pool_ctx(); - int ret = cls_rgw_lc_get_entry(*lc_pool_ctx, - lc_oid, shard_name, entry); + int ret = sal_lc->get_entry(lc_oid, shard_name, entry); if (ret == 0) { ldout(store->ctx(), 5) << "Entry already exists, nothing to do" << dendl; return ret; // entry is already existing correctly set to marker } - ldout(store->ctx(), 5) << "cls_rgw_lc_get_entry errored ret code=" << ret << dendl; + ldout(store->ctx(), 5) << "lc_get_entry errored ret code=" << ret << dendl; if (ret == -ENOENT) { ldout(store->ctx(), 1) << "No entry for bucket=" << bucket_info.bucket.name << " creating " << dendl; @@ -2113,11 +2096,11 @@ int fix_lc_shard_entry(rgw::sal::RGWRadosStore* store, std::string cookie = cookie_buf; ret = guard_lc_modify( - store, bucket_info.bucket, cookie, - [&lc_pool_ctx, &lc_oid](librados::IoCtx* ctx, + store, sal_lc, bucket_info.bucket, cookie, + [&sal_lc, &lc_oid](rgw::sal::Lifecycle* slc, const string& oid, - const cls_rgw_lc_entry& entry) { - return cls_rgw_lc_set_entry(*lc_pool_ctx, lc_oid, entry); + const rgw::sal::Lifecycle::LCEntry& entry) { + return slc->set_entry(lc_oid, entry); }); } diff --git a/src/rgw/rgw_lc.h b/src/rgw/rgw_lc.h index b0e87efba76ce..8f231af6b6148 100644 --- a/src/rgw/rgw_lc.h +++ b/src/rgw/rgw_lc.h @@ -462,6 +462,7 @@ WRITE_CLASS_ENCODER(RGWLifecycleConfiguration) class RGWLC : public DoutPrefixProvider { CephContext *cct; rgw::sal::RGWRadosStore *store; + std::unique_ptr sal_lc; int max_objs{0}; string *obj_names{nullptr}; std::atomic down_flag = { false }; @@ -516,12 +517,12 @@ class RGWLC : public DoutPrefixProvider { bool expired_session(time_t started); time_t thread_stop_at(); int list_lc_progress(string& marker, uint32_t max_entries, - vector&, int& index); + vector&, int& index); int bucket_lc_prepare(int index, LCWorker* worker); int bucket_lc_process(string& shard_id, LCWorker* worker, time_t stop_at, bool once); int bucket_lc_post(int index, int max_lock_sec, - cls_rgw_lc_entry& entry, int& result, LCWorker* worker); + rgw::sal::Lifecycle::LCEntry& entry, int& result, LCWorker* worker); bool going_down(); void start_processor(); void stop_processor(); @@ -532,19 +533,22 @@ class RGWLC : public DoutPrefixProvider { const map& bucket_attrs); CephContext *get_cct() const override { return cct; } + rgw::sal::Lifecycle *get_lc() const { return sal_lc.get(); } unsigned get_subsys() const; std::ostream& gen_prefix(std::ostream& out) const; private: - int handle_multipart_expiration(RGWRados::Bucket *target, + int handle_multipart_expiration(rgw::sal::RGWBucket* target, const multimap& prefix_map, LCWorker* worker, time_t stop_at, bool once); }; namespace rgw::lc { -int fix_lc_shard_entry(rgw::sal::RGWRadosStore *store, const RGWBucketInfo& bucket_info, +int fix_lc_shard_entry(rgw::sal::RGWRadosStore *store, + rgw::sal::Lifecycle* sal_lc, + const RGWBucketInfo& bucket_info, const map& battrs); std::string s3_expiration_header( diff --git a/src/rgw/rgw_lc_s3.cc b/src/rgw/rgw_lc_s3.cc index cba2b00c0f86c..57a996f0cf821 100644 --- a/src/rgw/rgw_lc_s3.cc +++ b/src/rgw/rgw_lc_s3.cc @@ -313,7 +313,7 @@ void LCRule_S3::dump_xml(Formatter *f) const { } } -int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfiguration& dest) +int RGWLifecycleConfiguration_S3::rebuild(RGWLifecycleConfiguration& dest) { int ret = 0; multimap::iterator iter; diff --git a/src/rgw/rgw_lc_s3.h b/src/rgw/rgw_lc_s3.h index 0d6ffa93c93d7..5aa9c8e8c4961 100644 --- a/src/rgw/rgw_lc_s3.h +++ b/src/rgw/rgw_lc_s3.h @@ -95,7 +95,7 @@ class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(nullptr) {} void decode_xml(XMLObj *obj); - int rebuild(RGWRados *store, RGWLifecycleConfiguration& dest); + int rebuild(RGWLifecycleConfiguration& dest); void dump_xml(Formatter *f) const; }; diff --git a/src/rgw/rgw_multi.cc b/src/rgw/rgw_multi.cc index 873bb90f1d25e..79284591b40ee 100644 --- a/src/rgw/rgw_multi.cc +++ b/src/rgw/rgw_multi.cc @@ -243,7 +243,7 @@ int abort_multipart_upload(rgw::sal::RGWRadosStore *store, CephContext *cct, RGWObjManifest::obj_iterator oiter = obj_part.manifest.obj_begin(); if (oiter != obj_part.manifest.obj_end()) { rgw_obj head; - rgw_raw_obj raw_head = oiter.get_location().get_raw_obj(store->getRados()); + rgw_raw_obj raw_head = oiter.get_location().get_raw_obj(store); RGWSI_Tier_RADOS::raw_obj_to_obj(bucket_info.bucket, raw_head, &head); rgw_obj_index_key key; diff --git a/src/rgw/rgw_obj_manifest.h b/src/rgw/rgw_obj_manifest.h index 0a6dfa67d6e78..5423dea356483 100644 --- a/src/rgw/rgw_obj_manifest.h +++ b/src/rgw/rgw_obj_manifest.h @@ -17,6 +17,7 @@ #include "rgw_common.h" #include "rgw_compression_types.h" +#include "rgw_sal.h" class RGWSI_Zone; struct RGWZoneGroup; @@ -44,7 +45,7 @@ class rgw_obj_select { } rgw_raw_obj get_raw_obj(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params) const; - rgw_raw_obj get_raw_obj(RGWRados *store) const; + rgw_raw_obj get_raw_obj(rgw::sal::RGWStore* store) const; rgw_obj_select& operator=(const rgw_obj& rhs) { obj = rhs; @@ -548,7 +549,7 @@ class RGWObjManifest { int create_next(uint64_t ofs); rgw_raw_obj get_cur_obj(RGWZoneGroup& zonegroup, RGWZoneParams& zone_params) { return cur_obj.get_raw_obj(zonegroup, zone_params); } - rgw_raw_obj get_cur_obj(RGWRados *store) const { return cur_obj.get_raw_obj(store); } + rgw_raw_obj get_cur_obj(rgw::sal::RGWStore* store) const { return cur_obj.get_raw_obj(store); } /* total max size of current stripe (including head obj) */ uint64_t cur_stripe_max_size() const { diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index b7765c9deae1e..67c0d3227aad2 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -3371,7 +3371,6 @@ void RGWDeleteBucket::execute(optional_yield y) int RGWPutObj::init_processing(optional_yield y) { copy_source = url_decode(s->info.env->get("HTTP_X_AMZ_COPY_SOURCE", "")); copy_source_range = s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE"); - map src_attrs; size_t pos; int ret; @@ -3413,15 +3412,20 @@ int RGWPutObj::init_processing(optional_yield y) { return ret; } } - ret = store->getRados()->get_bucket_info(store->svc(), - copy_source_tenant_name, - copy_source_bucket_name, - copy_source_bucket_info, - NULL, s->yield, &src_attrs); + std::unique_ptr bucket; + ret = store->get_bucket(s->user.get(), copy_source_tenant_name, copy_source_bucket_name, + &bucket, s->yield); + if (ret < 0) { + ldpp_dout(this, 5) << __func__ << "(): get_bucket() returned ret=" << ret << dendl; + return ret; + } + + ret = bucket->get_bucket_info(s->yield); if (ret < 0) { ldpp_dout(this, 5) << __func__ << "(): get_bucket_info() returned ret=" << ret << dendl; return ret; } + copy_source_bucket_info = bucket->get_info(); /* handle x-amz-copy-source-range */ if (copy_source_range) { @@ -3790,12 +3794,7 @@ void RGWPutObj::execute(optional_yield y) /* Handle object versioning of Swift API. */ if (! multipart) { - op_ret = store->getRados()->swift_versioning_copy(obj_ctx, - s->bucket_owner.get_id(), - s->bucket.get(), - s->object.get(), - this, - s->yield); + op_ret = s->object->swift_versioning_copy(s->obj_ctx, this, s->yield); if (op_ret < 0) { return; } @@ -3837,7 +3836,7 @@ void RGWPutObj::execute(optional_yield y) ldpp_dout(this, 20) << "dest_placement for part=" << upload_info.dest_placement << dendl; processor.emplace( &*aio, store, s->bucket.get(), pdest_placement, - s->owner.get_id(), obj_ctx, s->object->get_obj(), + s->owner.get_id(), obj_ctx, std::move(s->object->clone()), multipart_upload_id, multipart_part_num, multipart_part_str, this, s->yield); } else if(append) { @@ -3848,7 +3847,7 @@ void RGWPutObj::execute(optional_yield y) pdest_placement = &s->dest_placement; processor.emplace( &*aio, store, s->bucket.get(), pdest_placement, s->bucket_owner.get_id(), - obj_ctx, s->object->get_obj(), + obj_ctx, std::move(s->object->clone()), s->req_id, position, &cur_accounted_size, this, s->yield); } else { if (s->bucket->versioning_enabled()) { @@ -3862,8 +3861,8 @@ void RGWPutObj::execute(optional_yield y) pdest_placement = &s->dest_placement; processor.emplace( &*aio, store, s->bucket.get(), pdest_placement, - s->bucket_owner.get_id(), obj_ctx, s->object->get_obj(), olh_epoch, - s->req_id, this, s->yield); + s->bucket_owner.get_id(), obj_ctx, std::move(s->object->clone()), + olh_epoch, s->req_id, this, s->yield); } op_ret = processor->prepare(s->yield); @@ -4201,7 +4200,7 @@ void RGWPostObj::execute(optional_yield y) &s->dest_placement, s->bucket_owner.get_id(), *static_cast(s->obj_ctx), - obj->get_obj(), 0, s->req_id, this, s->yield); + std::move(obj), 0, s->req_id, this, s->yield); op_ret = processor.prepare(s->yield); if (op_ret < 0) { return; @@ -4836,10 +4835,7 @@ void RGWDeleteObj::execute(optional_yield y) s->object->set_atomic(s->obj_ctx); bool ver_restored = false; - op_ret = store->getRados()->swift_versioning_restore(*obj_ctx, s->bucket_owner.get_id(), - s->bucket.get(), - s->object.get(), - ver_restored, this); + op_ret = s->object->swift_versioning_restore(s->obj_ctx, ver_restored, this); if (op_ret < 0) { return; } @@ -5157,15 +5153,14 @@ void RGWCopyObj::execute(optional_yield y) return; } - RGWObjectCtx& obj_ctx = *static_cast(s->obj_ctx); if ( ! version_id.empty()) { dest_object->set_instance(version_id); } else if (dest_bucket->versioning_enabled()) { dest_object->gen_rand_obj_instance_name(); } - src_object->set_atomic(&obj_ctx); - dest_object->set_atomic(&obj_ctx); + src_object->set_atomic(s->obj_ctx); + dest_object->set_atomic(s->obj_ctx); encode_delete_at_attr(delete_at, attrs); @@ -5189,16 +5184,12 @@ void RGWCopyObj::execute(optional_yield y) /* Handle object versioning of Swift API. In case of copying to remote this * should fail gently (op_ret == 0) as the dst_obj will not exist here. */ - op_ret = store->getRados()->swift_versioning_copy(obj_ctx, - dest_bucket->get_info().owner, - dest_bucket.get(), - dest_object.get(), - this, - s->yield); + op_ret = dest_object->swift_versioning_copy(s->obj_ctx, this, s->yield); if (op_ret < 0) { return; } + RGWObjectCtx& obj_ctx = *static_cast(s->obj_ctx); op_ret = src_object->copy_object(obj_ctx, s->user.get(), &s->info, @@ -5557,7 +5548,7 @@ void RGWPutLC::execute(optional_yield y) return; } - op_ret = config.rebuild(store->getRados(), new_config); + op_ret = config.rebuild(new_config); if (op_ret < 0) return; @@ -5575,7 +5566,7 @@ void RGWPutLC::execute(optional_yield y) return; } - op_ret = store->getRados()->get_lc()->set_bucket_config(s->bucket->get_info(), s->bucket_attrs, &new_config); + op_ret = store->get_rgwlc()->set_bucket_config(s->bucket->get_info(), s->bucket_attrs, &new_config); if (op_ret < 0) { return; } @@ -5591,7 +5582,7 @@ void RGWDeleteLC::execute(optional_yield y) return; } - op_ret = store->getRados()->get_lc()->remove_bucket_config(s->bucket->get_info(), s->bucket_attrs); + op_ret = store->get_rgwlc()->remove_bucket_config(s->bucket->get_info(), s->bucket_attrs); if (op_ret < 0) { return; } @@ -5823,8 +5814,7 @@ void RGWInitMultipart::pre_exec() void RGWInitMultipart::execute(optional_yield y) { bufferlist aclbl; - map attrs; - rgw_obj obj; + rgw::sal::RGWAttrs attrs; if (get_params(y) < 0) return; @@ -5857,6 +5847,7 @@ void RGWInitMultipart::execute(optional_yield y) do { char buf[33]; + std::unique_ptr obj; gen_rand_alphanumeric(s->cct, buf, sizeof(buf) - 1); upload_id = MULTIPART_UPLOAD_ID_PREFIX; /* v2 upload id */ upload_id.append(buf); @@ -5865,29 +5856,30 @@ void RGWInitMultipart::execute(optional_yield y) RGWMPObj mp(s->object->get_name(), upload_id); tmp_obj_name = mp.get_meta(); - obj.init_ns(s->bucket->get_key(), tmp_obj_name, mp_ns); + obj = s->bucket->get_object(rgw_obj_key(tmp_obj_name, string(), mp_ns)); // the meta object will be indexed with 0 size, we c - obj.set_in_extra_data(true); - obj.index_hash_source = s->object->get_name(); - - RGWRados::Object op_target(store->getRados(), s->bucket->get_info(), *static_cast(s->obj_ctx), obj); - op_target.set_versioning_disabled(true); /* no versioning for multipart meta */ + obj->set_in_extra_data(true); + obj->set_hash_source(s->object->get_name()); - RGWRados::Object::Write obj_op(&op_target); + std::unique_ptr obj_op = obj->get_write_op(s->obj_ctx); - obj_op.meta.owner = s->owner.get_id(); - obj_op.meta.category = RGWObjCategory::MultiMeta; - obj_op.meta.flags = PUT_OBJ_CREATE_EXCL; - obj_op.meta.mtime = &mtime; + obj_op->params.versioning_disabled = true; /* no versioning for multipart meta */ + obj_op->params.owner = s->owner; + obj_op->params.category = RGWObjCategory::MultiMeta; + obj_op->params.flags = PUT_OBJ_CREATE_EXCL; + obj_op->params.mtime = &mtime; + obj_op->params.attrs = &attrs; multipart_upload_info upload_info; upload_info.dest_placement = s->dest_placement; bufferlist bl; encode(upload_info, bl); - obj_op.meta.data = &bl; + obj_op->params.data = &bl; + + op_ret = obj_op->prepare(s->yield); - op_ret = obj_op.write_meta(bl.length(), 0, attrs, s->yield); + op_ret = obj_op->write_meta(bl.length(), 0, s->yield); } while (op_ret == -EEXIST); // send request to notification manager @@ -5944,14 +5936,14 @@ void RGWCompleteMultipart::execute(optional_yield y) string meta_oid; map obj_parts; map::iterator obj_iter; - map attrs; + rgw::sal::RGWAttrs attrs; off_t ofs = 0; MD5 hash; char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE]; char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; bufferlist etag_bl; std::unique_ptr meta_obj; - rgw_obj target_obj; + std::unique_ptr target_obj; RGWMPObj mp; RGWObjManifest manifest; uint64_t olh_epoch = 0; @@ -6026,18 +6018,12 @@ void RGWCompleteMultipart::execute(optional_yield y) /*take a cls lock on meta_obj to prevent racing completions (or retries) from deleting the parts*/ - rgw_pool meta_pool; - rgw_raw_obj raw_obj; int max_lock_secs_mp = s->cct->_conf.get_val("rgw_mp_lock_max_time"); utime_t dur(max_lock_secs_mp, 0); - store->getRados()->obj_to_raw((s->bucket->get_info()).placement_rule, meta_obj->get_obj(), &raw_obj); - store->getRados()->get_obj_data_pool((s->bucket->get_info()).placement_rule, - meta_obj->get_obj(), &meta_pool); - store->getRados()->open_pool_ctx(meta_pool, serializer.ioctx, true); - - op_ret = serializer.try_lock(raw_obj.oid, dur, y); + serializer = meta_obj->get_serializer("RGWCompleteMultipart"); + op_ret = serializer->try_lock(dur, y); if (op_ret < 0) { ldpp_dout(this, 0) << "failed to acquire lock" << dendl; op_ret = -ERR_INTERNAL_ERROR; @@ -6172,42 +6158,46 @@ void RGWCompleteMultipart::execute(optional_yield y) attrs[RGW_ATTR_COMPRESSION] = tmp; } - target_obj.init(s->bucket->get_key(), s->object->get_name()); + target_obj = s->bucket->get_object(rgw_obj_key(s->object->get_name())); if (versioned_object) { if (!version_id.empty()) { - target_obj.key.set_instance(version_id); + target_obj->set_instance(version_id); } else { - store->getRados()->gen_rand_obj_instance_name(&target_obj); - version_id = target_obj.key.get_instance(); + target_obj->gen_rand_obj_instance_name(); + version_id = target_obj->get_instance(); } } RGWObjectCtx& obj_ctx = *static_cast(s->obj_ctx); - obj_ctx.set_atomic(target_obj); + target_obj->set_atomic(&obj_ctx); + + std::unique_ptr obj_op = target_obj->get_write_op(&obj_ctx); - RGWRados::Object op_target(store->getRados(), s->bucket->get_info(), *static_cast(s->obj_ctx), target_obj); - RGWRados::Object::Write obj_op(&op_target); + obj_op->params.manifest = &manifest; + obj_op->params.remove_objs = &remove_objs; - obj_op.meta.manifest = &manifest; - obj_op.meta.remove_objs = &remove_objs; + obj_op->params.ptag = &s->req_id; /* use req_id as operation tag */ + obj_op->params.owner = s->owner; + obj_op->params.flags = PUT_OBJ_CREATE; + obj_op->params.modify_tail = true; + obj_op->params.completeMultipart = true; + obj_op->params.olh_epoch = olh_epoch; + obj_op->params.attrs = &attrs; + op_ret = obj_op->prepare(s->yield); + if (op_ret < 0) + return; - obj_op.meta.ptag = &s->req_id; /* use req_id as operation tag */ - obj_op.meta.owner = s->owner.get_id(); - obj_op.meta.flags = PUT_OBJ_CREATE; - obj_op.meta.modify_tail = true; - obj_op.meta.completeMultipart = true; - obj_op.meta.olh_epoch = olh_epoch; - op_ret = obj_op.write_meta(ofs, accounted_size, attrs, s->yield); + op_ret = obj_op->write_meta(ofs, accounted_size, s->yield); if (op_ret < 0) return; // remove the upload obj - int r = store->getRados()->delete_obj(*static_cast(s->obj_ctx), - s->bucket->get_info(), meta_obj->get_obj(), 0); + string version_id; + int r = meta_obj->delete_object(s->obj_ctx, ACLOwner(), ACLOwner(), ceph::real_time(), false, 0, version_id, null_yield); if (r >= 0) { /* serializer's exclusive lock is released */ - serializer.clear_locked(); + serializer->clear_locked(); } else { ldpp_dout(this, 0) << "WARNING: failed to remove object " << meta_obj << dendl; } @@ -6220,28 +6210,13 @@ void RGWCompleteMultipart::execute(optional_yield y) } } -int RGWCompleteMultipart::MPSerializer::try_lock( - const std::string& _oid, - utime_t dur, optional_yield y) -{ - oid = _oid; - op.assert_exists(); - lock.set_duration(dur); - lock.lock_exclusive(&op); - int ret = rgw_rados_operate(ioctx, oid, &op, y); - if (! ret) { - locked = true; - } - return ret; -} - void RGWCompleteMultipart::complete() { /* release exclusive lock iff not already */ - if (unlikely(serializer.locked)) { - int r = serializer.unlock(); + if (unlikely(serializer && serializer->locked)) { + int r = serializer->unlock(); if (r < 0) { - ldpp_dout(this, 0) << "WARNING: failed to unlock " << serializer.oid << dendl; + ldpp_dout(this, 0) << "WARNING: failed to unlock " << serializer->oid << dendl; } } send_response(); @@ -7052,7 +7027,7 @@ int RGWBulkUploadOp::handle_file(const std::string_view path, using namespace rgw::putobj; AtomicObjectProcessor processor(&*aio, store, bucket.get(), &s->dest_placement, bowner.get_id(), - obj_ctx, obj->get_obj(), 0, s->req_id, this, s->yield); + obj_ctx, std::move(obj), 0, s->req_id, this, s->yield); op_ret = processor.prepare(s->yield); if (op_ret < 0) { @@ -7936,7 +7911,7 @@ void RGWGetObjLegalHold::execute(optional_yield y) void RGWGetClusterStat::execute(optional_yield y) { - op_ret = this->store->getRados()->get_rados_handle()->cluster_stat(stats_op); + op_ret = store->cluster_stat(stats_op); } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index cbe856172413b..23cb45d786d25 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -48,7 +48,6 @@ #include "rgw_torrent.h" #include "rgw_tag.h" #include "rgw_object_lock.h" -#include "cls/lock/cls_lock_client.h" #include "cls/rgw/cls_rgw_client.h" #include "rgw_public_access.h" @@ -1135,7 +1134,7 @@ class RGWPutObj : public RGWOp { std::unique_ptr obj_tags; const char *dlo_manifest; RGWSLOInfo *slo_info; - map attrs; + rgw::sal::RGWAttrs attrs; ceph::real_time mtime; uint64_t olh_epoch; string version_id; @@ -1741,31 +1740,11 @@ class RGWCompleteMultipart : public RGWOp { string etag; string version_id; bufferlist data; - - struct MPSerializer { - librados::IoCtx ioctx; - rados::cls::lock::Lock lock; - librados::ObjectWriteOperation op; - std::string oid; - bool locked; - - MPSerializer() : lock("RGWCompleteMultipart"), locked(false) - {} - - int try_lock(const std::string& oid, utime_t dur, optional_yield y); - - int unlock() { - return lock.unlock(&ioctx, oid); - } - - void clear_locked() { - locked = false; - } - } serializer; + rgw::sal::MPSerializer* serializer; public: - RGWCompleteMultipart() {} - ~RGWCompleteMultipart() override {} + RGWCompleteMultipart() : serializer(nullptr) {} + ~RGWCompleteMultipart() override { delete serializer; } int verify_permission(optional_yield y) override; void pre_exec() override; @@ -2375,7 +2354,7 @@ class RGWDelBucketMetaSearch : public RGWOp { class RGWGetClusterStat : public RGWOp { protected: - struct rados_cluster_stat_t stats_op; + RGWClusterStat stats_op; public: RGWGetClusterStat() {} diff --git a/src/rgw/rgw_orphan.cc b/src/rgw/rgw_orphan.cc index 20a2d85862d5c..4aae077961082 100644 --- a/src/rgw/rgw_orphan.cc +++ b/src/rgw/rgw_orphan.cc @@ -450,7 +450,7 @@ int RGWOrphanSearch::handle_stat_result(map >& oids, RGWRados: RGWObjManifest::obj_iterator miter; for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) { - const rgw_raw_obj& loc = miter.get_location().get_raw_obj(store->getRados()); + const rgw_raw_obj& loc = miter.get_location().get_raw_obj(store); string s = loc.oid; obj_oids.insert(obj_fingerprint(s)); } @@ -1036,7 +1036,7 @@ int RGWRadosList::handle_stat_result(RGWRados::Object::Stat::Result& result, RGWObjManifest::obj_iterator miter; for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) { const rgw_raw_obj& loc = - miter.get_location().get_raw_obj(store->getRados()); + miter.get_location().get_raw_obj(store); string s = loc.oid; obj_oids.insert(s); } @@ -1525,7 +1525,7 @@ int RGWRadosList::do_incomplete_multipart( obj_it != manifest.obj_end(); ++obj_it) { const rgw_raw_obj& loc = - obj_it.get_location().get_raw_obj(store->getRados()); + obj_it.get_location().get_raw_obj(store); std::cout << loc.oid << std::endl; } } diff --git a/src/rgw/rgw_putobj_processor.cc b/src/rgw/rgw_putobj_processor.cc index f013aa2adf38f..2906e13c1cc0e 100644 --- a/src/rgw/rgw_putobj_processor.cc +++ b/src/rgw/rgw_putobj_processor.cc @@ -125,9 +125,9 @@ RadosWriter::~RadosWriter() bool need_to_remove_head = false; std::optional raw_head; - if (!head_obj.empty()) { + if (!rgw::sal::RGWObject::empty(head_obj.get())) { raw_head.emplace(); - store->getRados()->obj_to_raw(bucket->get_placement_rule(), head_obj, &*raw_head); + head_obj->get_raw_obj(&*raw_head); } /** @@ -149,15 +149,17 @@ RadosWriter::~RadosWriter() continue; } - int r = store->getRados()->delete_raw_obj(obj); + int r = store->delete_raw_obj(obj); if (r < 0 && r != -ENOENT) { ldpp_dout(dpp, 0) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl; } } if (need_to_remove_head) { + std::string version_id; ldpp_dout(dpp, 5) << "NOTE: we are going to process the head obj (" << *raw_head << ")" << dendl; - int r = store->getRados()->delete_obj(obj_ctx, bucket->get_info(), head_obj, 0, 0); + int r = head_obj->delete_object(&obj_ctx, ACLOwner(), bucket->get_acl_owner(), ceph::real_time(), + false, 0, version_id, null_yield); if (r < 0 && r != -ENOENT) { ldpp_dout(dpp, 0) << "WARNING: failed to remove obj (" << *raw_head << "), leaked" << dendl; } @@ -174,10 +176,10 @@ int ManifestObjectProcessor::next(uint64_t offset, uint64_t *pstripe_size) return r; } - rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store->getRados()); + rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store); uint64_t chunk_size = 0; - r = store->getRados()->get_max_chunk_size(stripe_obj.pool, &chunk_size); + r = store->get_raw_chunk_size(stripe_obj, &chunk_size); if (r < 0) { return r; } @@ -207,33 +209,21 @@ int AtomicObjectProcessor::prepare(optional_yield y) uint64_t head_max_size; uint64_t chunk_size = 0; uint64_t alignment; - rgw_pool head_pool; - if (!store->getRados()->get_obj_data_pool(bucket->get_placement_rule(), head_obj, &head_pool)) { - return -EIO; - } - - int r = store->getRados()->get_max_chunk_size(head_pool, &max_head_chunk_size, &alignment); + int r = head_obj->get_max_chunk_size(bucket->get_placement_rule(), + &max_head_chunk_size, &alignment); if (r < 0) { return r; } bool same_pool = true; - if (bucket->get_placement_rule() != tail_placement_rule) { - rgw_pool tail_pool; - if (!store->getRados()->get_obj_data_pool(tail_placement_rule, head_obj, &tail_pool)) { - return -EIO; - } - - if (tail_pool != head_pool) { + if (!head_obj->placement_rules_match(bucket->get_placement_rule(), tail_placement_rule)) { same_pool = false; - - r = store->getRados()->get_max_chunk_size(tail_pool, &chunk_size); + r = head_obj->get_max_chunk_size(tail_placement_rule, &chunk_size); if (r < 0) { return r; } - head_max_size = 0; } } @@ -246,19 +236,21 @@ int AtomicObjectProcessor::prepare(optional_yield y) uint64_t stripe_size; const uint64_t default_stripe_size = store->ctx()->_conf->rgw_obj_stripe_size; - store->getRados()->get_max_aligned_size(default_stripe_size, alignment, &stripe_size); + head_obj->get_max_aligned_size(default_stripe_size, alignment, &stripe_size); manifest.set_trivial_rule(head_max_size, stripe_size); + rgw_obj obj = head_obj->get_obj(); + r = manifest_gen.create_begin(store->ctx(), &manifest, bucket->get_placement_rule(), &tail_placement_rule, - head_obj.bucket, head_obj); + obj.bucket, obj); if (r < 0) { return r; } - rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store->getRados()); + rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store); r = writer.set_stripe_obj(stripe_obj); if (r < 0) { @@ -276,7 +268,7 @@ int AtomicObjectProcessor::complete(size_t accounted_size, const std::string& etag, ceph::real_time *mtime, ceph::real_time set_mtime, - std::map& attrs, + rgw::sal::RGWAttrs& attrs, ceph::real_time delete_at, const char *if_match, const char *if_nomatch, @@ -294,40 +286,43 @@ int AtomicObjectProcessor::complete(size_t accounted_size, return r; } - obj_ctx.set_atomic(head_obj); + head_obj->set_atomic(&obj_ctx); - RGWRados::Object op_target(store->getRados(), bucket->get_info(), obj_ctx, head_obj); + std::unique_ptr obj_op = head_obj->get_write_op(&obj_ctx); /* some object types shouldn't be versioned, e.g., multipart parts */ - op_target.set_versioning_disabled(!bucket->versioning_enabled()); - - RGWRados::Object::Write obj_op(&op_target); - - obj_op.meta.data = &first_chunk; - obj_op.meta.manifest = &manifest; - obj_op.meta.ptag = &unique_tag; /* use req_id as operation tag */ - obj_op.meta.if_match = if_match; - obj_op.meta.if_nomatch = if_nomatch; - obj_op.meta.mtime = mtime; - obj_op.meta.set_mtime = set_mtime; - obj_op.meta.owner = owner; - obj_op.meta.flags = PUT_OBJ_CREATE; - obj_op.meta.olh_epoch = olh_epoch; - obj_op.meta.delete_at = delete_at; - obj_op.meta.user_data = user_data; - obj_op.meta.zones_trace = zones_trace; - obj_op.meta.modify_tail = true; - - r = obj_op.write_meta(actual_size, accounted_size, attrs, y); + obj_op->params.versioning_disabled = !bucket->versioning_enabled(); + obj_op->params.data = &first_chunk; + obj_op->params.manifest = &manifest; + obj_op->params.ptag = &unique_tag; /* use req_id as operation tag */ + obj_op->params.if_match = if_match; + obj_op->params.if_nomatch = if_nomatch; + obj_op->params.mtime = mtime; + obj_op->params.set_mtime = set_mtime; + obj_op->params.owner = ACLOwner(owner); + obj_op->params.flags = PUT_OBJ_CREATE; + obj_op->params.olh_epoch = olh_epoch; + obj_op->params.delete_at = delete_at; + obj_op->params.user_data = user_data; + obj_op->params.zones_trace = zones_trace; + obj_op->params.modify_tail = true; + obj_op->params.attrs = &attrs; + + r = obj_op->prepare(y); + if (r < 0) { + return r; + } + + r = obj_op->write_meta(actual_size, accounted_size, y); if (r < 0) { return r; } - if (!obj_op.meta.canceled) { + if (!obj_op->params.canceled) { // on success, clear the set of objects for deletion writer.clear_written(); } if (pcanceled) { - *pcanceled = obj_op.meta.canceled; + *pcanceled = obj_op->params.canceled; } return 0; } @@ -344,8 +339,8 @@ int MultipartObjectProcessor::process_first_chunk(bufferlist&& data, std::string oid_rand(32, 0); gen_rand_alphanumeric(store->ctx(), oid_rand.data(), oid_rand.size()); - mp.init(target_obj.key.name, upload_id, oid_rand); - manifest.set_prefix(target_obj.key.name + "." + oid_rand); + mp.init(target_obj->get_name(), upload_id, oid_rand); + manifest.set_prefix(target_obj->get_name() + "." + oid_rand); r = prepare_head(); if (r < 0) { @@ -368,26 +363,27 @@ int MultipartObjectProcessor::prepare_head() uint64_t stripe_size; uint64_t alignment; - int r = store->getRados()->get_max_chunk_size(tail_placement_rule, target_obj, &chunk_size, &alignment); + int r = target_obj->get_max_chunk_size(tail_placement_rule, &chunk_size, &alignment); if (r < 0) { ldpp_dout(dpp, 0) << "ERROR: unexpected: get_max_chunk_size(): placement_rule=" << tail_placement_rule.to_str() << " obj=" << target_obj << " returned r=" << r << dendl; return r; } - store->getRados()->get_max_aligned_size(default_stripe_size, alignment, &stripe_size); + target_obj->get_max_aligned_size(default_stripe_size, alignment, &stripe_size); manifest.set_multipart_part_rule(stripe_size, part_num); r = manifest_gen.create_begin(store->ctx(), &manifest, - bucket->get_placement_rule(), - &tail_placement_rule, - target_obj.bucket, target_obj); + bucket->get_placement_rule(), + &tail_placement_rule, + target_obj->get_bucket()->get_key(), + target_obj->get_obj()); if (r < 0) { return r; } - rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store->getRados()); - RGWSI_Tier_RADOS::raw_obj_to_obj(head_obj.bucket, stripe_obj, &head_obj); - head_obj.index_hash_source = target_obj.key.name; + rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store); + head_obj->raw_obj_to_obj(stripe_obj); + head_obj->set_hash_source(target_obj->get_name()); r = writer.set_stripe_obj(stripe_obj); if (r < 0) { @@ -403,7 +399,7 @@ int MultipartObjectProcessor::prepare_head() int MultipartObjectProcessor::prepare(optional_yield y) { - manifest.set_prefix(target_obj.key.name + "." + upload_id); + manifest.set_prefix(target_obj->get_name() + "." + upload_id); return prepare_head(); } @@ -430,18 +426,22 @@ int MultipartObjectProcessor::complete(size_t accounted_size, return r; } - RGWRados::Object op_target(store->getRados(), bucket->get_info(), obj_ctx, head_obj); - op_target.set_versioning_disabled(true); - RGWRados::Object::Write obj_op(&op_target); + std::unique_ptr obj_op = head_obj->get_write_op(&obj_ctx); - obj_op.meta.set_mtime = set_mtime; - obj_op.meta.mtime = mtime; - obj_op.meta.owner = owner; - obj_op.meta.delete_at = delete_at; - obj_op.meta.zones_trace = zones_trace; - obj_op.meta.modify_tail = true; + obj_op->params.versioning_disabled = true; + obj_op->params.set_mtime = set_mtime; + obj_op->params.mtime = mtime; + obj_op->params.owner = ACLOwner(owner); + obj_op->params.delete_at = delete_at; + obj_op->params.zones_trace = zones_trace; + obj_op->params.modify_tail = true; + obj_op->params.attrs = &attrs; + r = obj_op->prepare(y); + if (r < 0) { + return r; + } - r = obj_op.write_meta(actual_size, accounted_size, attrs, y); + r = obj_op->write_meta(actual_size, accounted_size, y); if (r < 0) return r; @@ -473,30 +473,21 @@ int MultipartObjectProcessor::complete(size_t accounted_size, encode(info, bl); - rgw_obj meta_obj; - meta_obj.init_ns(bucket->get_key(), mp.get_meta(), RGW_OBJ_NS_MULTIPART); - meta_obj.set_in_extra_data(true); - - rgw_raw_obj raw_meta_obj; + std::unique_ptr meta_obj = + bucket->get_object(rgw_obj_key(mp.get_meta(), std::string(), RGW_OBJ_NS_MULTIPART)); + meta_obj->set_in_extra_data(true); - store->getRados()->obj_to_raw(bucket->get_placement_rule(), meta_obj, &raw_meta_obj); - - auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); - auto sysobj = obj_ctx.get_obj(raw_meta_obj); - - r = sysobj.omap() - .set_must_exist(true) - .set(p, bl, null_yield); + r = meta_obj->omap_set_val_by_key(p, bl, true, null_yield); if (r < 0) { return r == -ENOENT ? -ERR_NO_SUCH_UPLOAD : r; } - if (!obj_op.meta.canceled) { + if (!obj_op->params.canceled) { // on success, clear the set of objects for deletion writer.clear_written(); } if (pcanceled) { - *pcanceled = obj_op.meta.canceled; + *pcanceled = obj_op->params.canceled; } return 0; } @@ -514,7 +505,7 @@ int AppendObjectProcessor::process_first_chunk(bufferlist &&data, rgw::putobj::D int AppendObjectProcessor::prepare(optional_yield y) { RGWObjState *astate; - int r = store->getRados()->get_obj_state(&obj_ctx, bucket->get_info(), head_obj, &astate, y); + int r = head_obj->get_obj_state(&obj_ctx, *bucket, &astate, y); if (r < 0) { return r; } @@ -529,7 +520,7 @@ int AppendObjectProcessor::prepare(optional_yield y) //set the prefix char buf[33]; gen_rand_alphanumeric(store->ctx(), buf, sizeof(buf) - 1); - string oid_prefix = head_obj.key.name; + string oid_prefix = head_obj->get_name(); oid_prefix.append("."); oid_prefix.append(buf); oid_prefix.append("_"); @@ -572,14 +563,16 @@ int AppendObjectProcessor::prepare(optional_yield y) } manifest.set_multipart_part_rule(store->ctx()->_conf->rgw_obj_stripe_size, cur_part_num); - r = manifest_gen.create_begin(store->ctx(), &manifest, bucket->get_placement_rule(), &tail_placement_rule, head_obj.bucket, head_obj); + rgw_obj obj = head_obj->get_obj(); + + r = manifest_gen.create_begin(store->ctx(), &manifest, bucket->get_placement_rule(), &tail_placement_rule, obj.bucket, obj); if (r < 0) { return r; } - rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store->getRados()); + rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store); uint64_t chunk_size = 0; - r = store->getRados()->get_max_chunk_size(stripe_obj.pool, &chunk_size); + r = store->get_raw_chunk_size(stripe_obj, &chunk_size); if (r < 0) { return r; } @@ -601,7 +594,7 @@ int AppendObjectProcessor::prepare(optional_yield y) } int AppendObjectProcessor::complete(size_t accounted_size, const string &etag, ceph::real_time *mtime, - ceph::real_time set_mtime, map &attrs, + ceph::real_time set_mtime, rgw::sal::RGWAttrs& attrs, ceph::real_time delete_at, const char *if_match, const char *if_nomatch, const string *user_data, rgw_zone_set *zones_trace, bool *pcanceled, optional_yield y) @@ -614,27 +607,27 @@ int AppendObjectProcessor::complete(size_t accounted_size, const string &etag, c if (r < 0) { return r; } - obj_ctx.set_atomic(head_obj); - RGWRados::Object op_target(store->getRados(), bucket->get_info(), obj_ctx, head_obj); + head_obj->set_atomic(&obj_ctx); + std::unique_ptr obj_op = head_obj->get_write_op(&obj_ctx); //For Append obj, disable versioning - op_target.set_versioning_disabled(true); - RGWRados::Object::Write obj_op(&op_target); + obj_op->params.versioning_disabled = true; if (cur_manifest) { cur_manifest->append(manifest, store->svc()->zone); - obj_op.meta.manifest = cur_manifest; + obj_op->params.manifest = cur_manifest; } else { - obj_op.meta.manifest = &manifest; - } - obj_op.meta.ptag = &unique_tag; /* use req_id as operation tag */ - obj_op.meta.mtime = mtime; - obj_op.meta.set_mtime = set_mtime; - obj_op.meta.owner = owner; - obj_op.meta.flags = PUT_OBJ_CREATE; - obj_op.meta.delete_at = delete_at; - obj_op.meta.user_data = user_data; - obj_op.meta.zones_trace = zones_trace; - obj_op.meta.modify_tail = true; - obj_op.meta.appendable = true; + obj_op->params.manifest = &manifest; + } + obj_op->params.ptag = &unique_tag; /* use req_id as operation tag */ + obj_op->params.mtime = mtime; + obj_op->params.set_mtime = set_mtime; + obj_op->params.owner = ACLOwner(owner); + obj_op->params.flags = PUT_OBJ_CREATE; + obj_op->params.delete_at = delete_at; + obj_op->params.user_data = user_data; + obj_op->params.zones_trace = zones_trace; + obj_op->params.modify_tail = true; + obj_op->params.appendable = true; + obj_op->params.attrs = &attrs; //Add the append part number bufferlist cur_part_num_bl; using ceph::encode; @@ -658,16 +651,20 @@ int AppendObjectProcessor::complete(size_t accounted_size, const string &etag, c etag_bl.append(final_etag_str, strlen(final_etag_str) + 1); attrs[RGW_ATTR_ETAG] = etag_bl; } - r = obj_op.write_meta(actual_size + cur_size, accounted_size + *cur_accounted_size, attrs, y); + r = obj_op->prepare(y); + if (r < 0) { + return r; + } + r = obj_op->write_meta(actual_size + cur_size, accounted_size + *cur_accounted_size, y); if (r < 0) { return r; } - if (!obj_op.meta.canceled) { + if (!obj_op->params.canceled) { // on success, clear the set of objects for deletion writer.clear_written(); } if (pcanceled) { - *pcanceled = obj_op.meta.canceled; + *pcanceled = obj_op->params.canceled; } *cur_accounted_size += accounted_size; diff --git a/src/rgw/rgw_putobj_processor.h b/src/rgw/rgw_putobj_processor.h index 42edfa77ebf4e..2a7e89446a71f 100644 --- a/src/rgw/rgw_putobj_processor.h +++ b/src/rgw/rgw_putobj_processor.h @@ -21,6 +21,7 @@ #include "services/svc_rados.h" #include "services/svc_tier_rados.h" #include "rgw_sal.h" +#include "rgw_obj_manifest.h" namespace rgw { @@ -82,7 +83,7 @@ class RadosWriter : public DataProcessor { rgw::sal::RGWRadosStore *const store; rgw::sal::RGWBucket* bucket; RGWObjectCtx& obj_ctx; - const rgw_obj head_obj; + std::unique_ptr head_obj; RGWSI_RADOS::Obj stripe_obj; // current stripe object RawObjSet written; // set of written objects for deletion const DoutPrefixProvider *dpp; @@ -91,11 +92,16 @@ class RadosWriter : public DataProcessor { public: RadosWriter(Aio *aio, rgw::sal::RGWRadosStore *store, rgw::sal::RGWBucket* bucket, - RGWObjectCtx& obj_ctx, const rgw_obj& head_obj, + RGWObjectCtx& obj_ctx, std::unique_ptr _head_obj, const DoutPrefixProvider *dpp, optional_yield y) : aio(aio), store(store), bucket(bucket), - obj_ctx(obj_ctx), head_obj(head_obj), dpp(dpp), y(y) + obj_ctx(obj_ctx), head_obj(std::move(_head_obj)), dpp(dpp), y(y) {} + RadosWriter(RadosWriter&& r) + : aio(r.aio), store(r.store), bucket(r.bucket), + obj_ctx(r.obj_ctx), head_obj(std::move(r.head_obj)), dpp(r.dpp), y(r.y) + {} + ~RadosWriter(); // change the current stripe object @@ -124,7 +130,7 @@ class ManifestObjectProcessor : public HeadObjectProcessor, rgw_placement_rule tail_placement_rule; rgw_user owner; RGWObjectCtx& obj_ctx; - rgw_obj head_obj; + std::unique_ptr head_obj; RadosWriter writer; RGWObjManifest manifest; @@ -141,13 +147,13 @@ class ManifestObjectProcessor : public HeadObjectProcessor, rgw::sal::RGWBucket* bucket, const rgw_placement_rule *ptail_placement_rule, const rgw_user& owner, RGWObjectCtx& obj_ctx, - rgw_obj& head_obj, + std::unique_ptr _head_obj, const DoutPrefixProvider* dpp, optional_yield y) : HeadObjectProcessor(0), store(store), bucket(bucket), owner(owner), - obj_ctx(obj_ctx), head_obj(head_obj), - writer(aio, store, bucket, obj_ctx, head_obj, dpp, y), + obj_ctx(obj_ctx), head_obj(std::move(_head_obj)), + writer(aio, store, bucket, obj_ctx, std::move(head_obj->clone()), dpp, y), chunk(&writer, 0), stripe(&chunk, this, 0), dpp(dpp) { if (ptail_placement_rule) { tail_placement_rule = *ptail_placement_rule; @@ -181,12 +187,13 @@ class AtomicObjectProcessor : public ManifestObjectProcessor { rgw::sal::RGWBucket* bucket, const rgw_placement_rule *ptail_placement_rule, const rgw_user& owner, - RGWObjectCtx& obj_ctx, rgw_obj head_obj, + RGWObjectCtx& obj_ctx, + std::unique_ptr _head_obj, std::optional olh_epoch, const std::string& unique_tag, const DoutPrefixProvider *dpp, optional_yield y) : ManifestObjectProcessor(aio, store, bucket, ptail_placement_rule, - owner, obj_ctx, head_obj, dpp, y), + owner, obj_ctx, std::move(_head_obj), dpp, y), olh_epoch(olh_epoch), unique_tag(unique_tag) {} @@ -209,7 +216,7 @@ class AtomicObjectProcessor : public ManifestObjectProcessor { // part's head is written with an exclusive create to detect racing uploads of // the same part/upload id, which are restarted with a random oid prefix class MultipartObjectProcessor : public ManifestObjectProcessor { - const rgw_obj target_obj; // target multipart object + std::unique_ptr target_obj; // target multipart object const std::string upload_id; const int part_num; const std::string part_num_str; @@ -225,15 +232,15 @@ class MultipartObjectProcessor : public ManifestObjectProcessor { rgw::sal::RGWBucket* bucket, const rgw_placement_rule *ptail_placement_rule, const rgw_user& owner, RGWObjectCtx& obj_ctx, - rgw_obj head_obj, + std::unique_ptr _head_obj, const std::string& upload_id, uint64_t part_num, const std::string& part_num_str, const DoutPrefixProvider *dpp, optional_yield y) : ManifestObjectProcessor(aio, store, bucket, ptail_placement_rule, - owner, obj_ctx, head_obj, dpp, y), - target_obj(head_obj), upload_id(upload_id), + owner, obj_ctx, std::move(_head_obj), dpp, y), + target_obj(std::move(head_obj->clone())), upload_id(upload_id), part_num(part_num), part_num_str(part_num_str), - mp(head_obj.key.name, upload_id) + mp(head_obj->get_name(), upload_id) {} // prepare a multipart manifest @@ -268,12 +275,12 @@ class MultipartObjectProcessor : public ManifestObjectProcessor { rgw::sal::RGWBucket* bucket, const rgw_placement_rule *ptail_placement_rule, const rgw_user& owner, RGWObjectCtx& obj_ctx, - rgw_obj head_obj, + std::unique_ptr _head_obj, const std::string& unique_tag, uint64_t position, uint64_t *cur_accounted_size, const DoutPrefixProvider *dpp, optional_yield y) : ManifestObjectProcessor(aio, store, bucket, ptail_placement_rule, - owner, obj_ctx, head_obj, dpp, y), + owner, obj_ctx, std::move(_head_obj), dpp, y), position(position), cur_size(0), cur_accounted_size(cur_accounted_size), unique_tag(unique_tag), cur_manifest(nullptr) {} diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 2057026cf3755..0bb75ebb82269 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -149,11 +149,11 @@ rgw_raw_obj rgw_obj_select::get_raw_obj(const RGWZoneGroup& zonegroup, const RGW return raw_obj; } -rgw_raw_obj rgw_obj_select::get_raw_obj(RGWRados *store) const +rgw_raw_obj rgw_obj_select::get_raw_obj(rgw::sal::RGWStore* store) const { if (!is_raw) { rgw_raw_obj r; - store->obj_to_raw(placement_rule, obj, &r); + store->get_raw_obj(placement_rule, obj, &r); return r; } return raw_obj; @@ -2575,7 +2575,7 @@ int RGWRados::fix_tail_obj_locator(const RGWBucketInfo& bucket_info, rgw_obj_key RGWObjManifest::obj_iterator miter; RGWObjManifest& manifest = *astate->manifest; for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) { - rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(this); + rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(store); rgw_obj loc; string oid; string locator; @@ -3772,7 +3772,7 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx, const char *if_nomatch, AttrsMod attrs_mod, bool copy_if_newer, - map& attrs, + rgw::sal::RGWAttrs& attrs, RGWObjCategory category, std::optional olh_epoch, real_time delete_at, @@ -3798,7 +3798,8 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx, rgw::BlockingAioThrottle aio(cct->_conf->rgw_put_obj_min_window_size); using namespace rgw::putobj; AtomicObjectProcessor processor(&aio, this->store, dest_bucket, nullptr, user_id, - obj_ctx, dest_obj->get_obj(), olh_epoch, tag, dpp, null_yield); + obj_ctx, std::move(dest_obj->clone()), olh_epoch, + tag, dpp, null_yield); RGWRESTConn *conn; auto& zone_conn_map = svc.zone->get_zone_conn_map(); auto& zonegroup_conn_map = svc.zone->get_zonegroup_conn_map(); @@ -4155,7 +4156,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, const char *if_nomatch, AttrsMod attrs_mod, bool copy_if_newer, - map& attrs, + rgw::sal::RGWAttrs& attrs, RGWObjCategory category, uint64_t olh_epoch, real_time delete_at, @@ -4328,7 +4329,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, } rgw_rados_ref ref; - ret = get_raw_obj_ref(miter.get_location().get_raw_obj(this), &ref); + ret = get_raw_obj_ref(miter.get_location().get_raw_obj(store), &ref); if (ret < 0) { return ret; } @@ -4364,7 +4365,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, ObjectWriteOperation op; ref_tag = tag + '\0'; cls_refcount_get(op, ref_tag, true); - const rgw_raw_obj& loc = miter.get_location().get_raw_obj(this); + const rgw_raw_obj& loc = miter.get_location().get_raw_obj(store); auto& ioctx = ref.pool.ioctx(); ioctx.locator_set_key(loc.loc); @@ -4442,7 +4443,7 @@ int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx, rgw::sal::RGWObject* dest_obj, real_time *mtime, real_time set_mtime, - map& attrs, + rgw::sal::RGWAttrs& attrs, uint64_t olh_epoch, real_time delete_at, string *petag, @@ -4458,7 +4459,8 @@ int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx, // it causes crashes in the ragweed tests AtomicObjectProcessor processor(&aio, this->store, bucket, &dest_placement, bucket->get_info().owner, obj_ctx, - dest_obj->get_obj(), olh_epoch, tag, dpp, null_yield); + std::move(dest_obj->clone()), olh_epoch, tag, + dpp, null_yield); int ret = processor.prepare(y); if (ret < 0) return ret; @@ -4524,7 +4526,7 @@ int RGWRados::transition_obj(RGWObjectCtx& obj_ctx, const DoutPrefixProvider *dpp, optional_yield y) { - map attrs; + rgw::sal::RGWAttrs attrs; real_time read_mtime; uint64_t obj_size; @@ -4784,7 +4786,7 @@ void RGWRados::update_gc_chain(rgw_obj& head_obj, RGWObjManifest& manifest, cls_ rgw_raw_obj raw_head; obj_to_raw(manifest.get_head_placement_rule(), head_obj, &raw_head); for (iter = manifest.obj_begin(); iter != manifest.obj_end(); ++iter) { - const rgw_raw_obj& mobj = iter.get_location().get_raw_obj(this); + const rgw_raw_obj& mobj = iter.get_location().get_raw_obj(store); if (mobj == raw_head) continue; cls_rgw_obj_key key(mobj.oid); @@ -5233,7 +5235,7 @@ int RGWRados::delete_obj_index(const rgw_obj& obj, ceph::real_time mtime) return index_op.complete_del(-1 /* pool */, 0, mtime, NULL); } -static void generate_fake_tag(RGWRados *store, map& attrset, RGWObjManifest& manifest, bufferlist& manifest_bl, bufferlist& tag_bl) +static void generate_fake_tag(rgw::sal::RGWStore* store, map& attrset, RGWObjManifest& manifest, bufferlist& manifest_bl, bufferlist& tag_bl) { string tag; @@ -5406,7 +5408,7 @@ int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, const RGWBucketInfo& bucket s->manifest->has_explicit_objs()) { RGWObjManifest::obj_iterator mi; for (mi = s->manifest->obj_begin(); mi != s->manifest->obj_end(); ++mi) { - ldout(cct, 20) << "manifest: ofs=" << mi.get_ofs() << " loc=" << mi.get_location().get_raw_obj(this) << dendl; + ldout(cct, 20) << "manifest: ofs=" << mi.get_ofs() << " loc=" << mi.get_location().get_raw_obj(store) << dendl; } } @@ -5415,7 +5417,7 @@ int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, const RGWBucketInfo& bucket * Uh oh, something's wrong, object with manifest should have tag. Let's * create one out of the manifest, would be unique */ - generate_fake_tag(this, s->attrset, *s->manifest, manifest_bl, s->obj_tag); + generate_fake_tag(store, s->attrset, *s->manifest, manifest_bl, s->obj_tag); s->fake_tag = true; } } @@ -6214,7 +6216,7 @@ int RGWRados::Object::Read::read(int64_t ofs, int64_t end, bufferlist& bl, optio RGWObjManifest::obj_iterator iter = astate->manifest->obj_find(ofs); uint64_t stripe_ofs = iter.get_stripe_ofs(); - read_obj = iter.get_location().get_raw_obj(store); + read_obj = iter.get_location().get_raw_obj(store->store); len = std::min(len, iter.get_stripe_size() - (ofs - stripe_ofs)); read_ofs = iter.location_ofs() + (ofs - stripe_ofs); reading_from_head = (read_obj == state.head_obj); @@ -6465,7 +6467,7 @@ int RGWRados::iterate_obj(RGWObjectCtx& obj_ctx, off_t next_stripe_ofs = stripe_ofs + iter.get_stripe_size(); while (ofs < next_stripe_ofs && ofs <= end) { - read_obj = iter.get_location().get_raw_obj(this); + read_obj = iter.get_location().get_raw_obj(store); uint64_t read_len = std::min(len, iter.get_stripe_size() - (ofs - stripe_ofs)); read_ofs = iter.location_ofs() + (ofs - stripe_ofs); @@ -8143,7 +8145,7 @@ int RGWRados::process_gc(bool expired_only) } int RGWRados::list_lc_progress(string& marker, uint32_t max_entries, - vector& progress_map, + vector& progress_map, int& index) { return lc->list_lc_progress(marker, max_entries, progress_map, index); @@ -8901,7 +8903,7 @@ int RGWRados::check_disk_state(librados::IoCtx io_ctx, RGWObjManifest::obj_iterator miter; RGWObjManifest& manifest = *astate->manifest; for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) { - const rgw_raw_obj& raw_loc = miter.get_location().get_raw_obj(this); + const rgw_raw_obj& raw_loc = miter.get_location().get_raw_obj(store); rgw_obj loc; RGWSI_Tier_RADOS::raw_obj_to_obj(manifest.get_obj().bucket, raw_loc, &loc); diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 1fb788fe8c412..53fdb9b55627d 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -370,7 +370,11 @@ class RGWGetUserStats_CB : public RefCountedObject { class RGWGetDirHeader_CB; class RGWGetUserHeader_CB; -namespace rgw { namespace sal { class RGWRadosStore; } } +namespace rgw { namespace sal { + class RGWRadosStore; + class MPRadosSerializer; + class LCRadosSerializer; +} } class RGWAsyncRadosProcessor; @@ -396,7 +400,6 @@ class RGWRados friend class RGWGC; friend class RGWMetaNotifier; friend class RGWDataNotifier; - friend class RGWLC; friend class RGWObjectExpirer; friend class RGWMetaSyncProcessorThread; friend class RGWDataSyncProcessorThread; @@ -404,7 +407,8 @@ class RGWRados friend class RGWBucketReshard; friend class RGWBucketReshardLock; friend class BucketIndexLockGuard; - friend class RGWCompleteMultipart; + friend class rgw::sal::MPRadosSerializer; + friend class rgw::sal::LCRadosSerializer; friend class rgw::sal::RGWRadosStore; /** Open the pool used as root for this gateway */ @@ -1121,7 +1125,7 @@ class RGWRados const char *if_nomatch, AttrsMod attrs_mod, bool copy_if_newer, - map& attrs, + rgw::sal::RGWAttrs& attrs, RGWObjCategory category, std::optional olh_epoch, ceph::real_time delete_at, @@ -1446,7 +1450,7 @@ class RGWRados int process_lc(); int list_lc_progress(string& marker, uint32_t max_entries, - vector& progress_map, int& index); + vector& progress_map, int& index); int bucket_check_index(RGWBucketInfo& bucket_info, map *existing_stats, diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 3a6e52b507c88..757bb089f70f3 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -3961,7 +3961,7 @@ void RGWGetObjLayout_ObjStore_S3::send_response() f.open_array_section("data_location"); for (auto miter = manifest->obj_begin(); miter != manifest->obj_end(); ++miter) { f.open_object_section("obj"); - rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(store->getRados()); + rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(store); uint64_t ofs = miter.get_ofs(); uint64_t left = manifest->get_obj_size() - ofs; ::encode_json("ofs", miter.get_ofs(), &f); diff --git a/src/rgw/rgw_sal.h b/src/rgw/rgw_sal.h index 6d16dadf59b62..c0ea9df9c9fc4 100644 --- a/src/rgw/rgw_sal.h +++ b/src/rgw/rgw_sal.h @@ -16,11 +16,13 @@ #pragma once #include "rgw_user.h" -#include "rgw_obj_manifest.h" class RGWGetDataCB; struct RGWObjState; class RGWAccessListFilter; +class RGWLC; +class RGWObjManifest; +struct RGWZoneGroup; struct RGWUsageIter { string read_iter; @@ -29,6 +31,22 @@ struct RGWUsageIter { RGWUsageIter() : index(0) {} }; +/** + * @struct RGWClusterStat + * Cluster-wide usage information + */ +struct RGWClusterStat { + /// total device size + uint64_t kb; + /// total used + uint64_t kb_used; + /// total available/free + uint64_t kb_avail; + /// number of objects + uint64_t num_objects; +}; + + namespace rgw { namespace sal { #define RGW_SAL_VERSION 1 @@ -37,6 +55,8 @@ class RGWUser; class RGWBucket; class RGWObject; class RGWBucketList; +struct MPSerializer; +class Lifecycle; enum AttrsMod { ATTRSMOD_NONE = 0, @@ -55,7 +75,7 @@ class RGWStore : public DoutPrefixProvider { virtual std::unique_ptr get_object(const rgw_obj_key& k) = 0; virtual int get_bucket(RGWUser* u, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) = 0; virtual int get_bucket(RGWUser* u, const RGWBucketInfo& i, std::unique_ptr* bucket) = 0; - virtual int get_bucket(RGWUser* u, const std::string& tenant, const std::string&name, std::unique_ptr* bucket, optional_yield y) = 0; + virtual int get_bucket(RGWUser* u, const std::string& tenant, const std::string& name, std::unique_ptr* bucket, optional_yield y) = 0; virtual int create_bucket(RGWUser& u, const rgw_bucket& b, const std::string& zonegroup_id, rgw_placement_rule& placement_rule, @@ -80,6 +100,12 @@ class RGWStore : public DoutPrefixProvider { optional_yield y) = 0; virtual const RGWZoneGroup& get_zonegroup() = 0; virtual int get_zonegroup(const string& id, RGWZoneGroup& zonegroup) = 0; + virtual int cluster_stat(RGWClusterStat& stats) = 0; + virtual std::unique_ptr get_lifecycle(void) = 0; + virtual RGWLC* get_rgwlc(void) = 0; + virtual int delete_raw_obj(const rgw_raw_obj& obj) = 0; + virtual void get_raw_obj(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj* raw_obj) = 0; + virtual int get_raw_chunk_size(const rgw_raw_obj& obj, uint64_t* chunk_size) = 0; virtual void finalize(void)=0; @@ -162,7 +188,7 @@ class RGWBucket { struct ListResults { vector objs; map common_prefixes; - bool is_truncated; + bool is_truncated{false}; rgw_obj_key next_marker; }; @@ -205,6 +231,8 @@ class RGWBucket { virtual int chown(RGWUser* new_user, RGWUser* old_user, optional_yield y) = 0; virtual int put_instance_info(bool exclusive, ceph::real_time mtime) = 0; virtual bool is_owner(RGWUser* user) = 0; + virtual RGWUser* get_owner(void) { return owner; }; + virtual ACLOwner get_acl_owner(void) { return ACLOwner(info.owner); }; virtual int check_empty(optional_yield y) = 0; virtual int check_quota(RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size, optional_yield y, bool check_size_only = false) = 0; virtual int set_instance_attrs(RGWAttrs& attrs, optional_yield y) = 0; @@ -338,6 +366,39 @@ class RGWObject { virtual int get_attr(const char *name, bufferlist& dest, optional_yield y) = 0; }; + struct WriteOp { + struct Params { + bool versioning_disabled{false}; + ceph::real_time* mtime{nullptr}; + RGWAttrs* rmattrs{nullptr}; + const bufferlist* data{nullptr}; + RGWObjManifest* manifest{nullptr}; + const string* ptag{nullptr}; + list* remove_objs{nullptr}; + ceph::real_time set_mtime; + ACLOwner owner; + RGWObjCategory category{RGWObjCategory::Main}; + int flags{0}; + const char* if_match{nullptr}; + const char* if_nomatch{nullptr}; + std::optional olh_epoch; + ceph::real_time delete_at; + bool canceled{false}; + const string* user_data{nullptr}; + rgw_zone_set* zones_trace{nullptr}; + bool modify_tail{false}; + bool completeMultipart{false}; + bool appendable{false}; + RGWAttrs* attrs{nullptr}; + } params; + + virtual ~WriteOp() = default; + + virtual int prepare(optional_yield y) = 0; + virtual int write_meta(uint64_t size, uint64_t accounted_size, optional_yield y) = 0; + //virtual int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive) = 0; + }; + RGWObject() : key(), bucket(nullptr), @@ -368,7 +429,7 @@ class RGWObject { virtual int delete_object(RGWObjectCtx* obj_ctx, ACLOwner obj_owner, ACLOwner bucket_owner, ceph::real_time unmod_since, bool high_precision_time, uint64_t epoch, - std::string& version_id,optional_yield y) = 0; + std::string& version_id, optional_yield y) = 0; virtual int copy_object(RGWObjectCtx& obj_ctx, RGWUser* user, req_info *info, const rgw_zone_id& source_zone, rgw::sal::RGWObject* dest_object, rgw::sal::RGWBucket* dest_bucket, @@ -399,6 +460,22 @@ class RGWObject { virtual int delete_obj_attrs(RGWObjectCtx *rctx, const char *attr_name, optional_yield y) = 0; virtual int copy_obj_data(RGWObjectCtx& rctx, RGWBucket* dest_bucket, RGWObject* dest_obj, uint16_t olh_epoch, std::string* petag, 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 std::string& lock_name) = 0; + virtual int transition(RGWObjectCtx& rctx, + RGWBucket* bucket, + const rgw_placement_rule& placement_rule, + const real_time& mtime, + uint64_t olh_epoch, + const DoutPrefixProvider *dpp, + optional_yield y) = 0; + virtual int get_max_chunk_size(rgw_placement_rule placement_rule, + uint64_t* max_chunk_size, + uint64_t* alignment = nullptr) = 0; + virtual void get_max_aligned_size(uint64_t size, uint64_t alignment, uint64_t *max_size) = 0; + virtual bool placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2) = 0; RGWAttrs& get_attrs(void) { return attrs; } ceph::real_time get_mtime(void) const { return mtime; } @@ -412,28 +489,39 @@ class RGWObject { bool get_in_extra_data(void) { return in_extra_data; } void set_in_extra_data(bool i) { in_extra_data = i; } int range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end); + void set_obj_size(uint64_t s) { obj_size = s; } + virtual void set_name(const std::string& n) { key = n; } + virtual void set_key(const rgw_obj_key& k) { key = k; } + virtual rgw_obj get_obj(void) const { + rgw_obj obj(bucket->get_key(), key); + obj.set_in_extra_data(in_extra_data); + obj.index_hash_source = index_hash_source; + return obj; + } + + /* Swift versioning */ + virtual int swift_versioning_restore(RGWObjectCtx* obj_ctx, + bool& restored, /* out */ + const DoutPrefixProvider *dpp) = 0; + virtual int swift_versioning_copy(RGWObjectCtx* obj_ctx, + const DoutPrefixProvider *dpp, + optional_yield y) = 0; /* OPs */ - virtual std::unique_ptr get_read_op(RGWObjectCtx *) = 0; + virtual std::unique_ptr get_read_op(RGWObjectCtx*) = 0; + virtual std::unique_ptr get_write_op(RGWObjectCtx*) = 0; /* OMAP */ virtual int omap_get_vals_by_keys(const std::string& oid, const std::set& keys, RGWAttrs *vals) = 0; + virtual int omap_set_val_by_key(const std::string& key, bufferlist& val, + bool must_exist, optional_yield y) = 0; static bool empty(RGWObject* o) { return (!o || o->empty()); } virtual std::unique_ptr clone() = 0; /* dang - Not sure if we want this, but it simplifies things a lot */ - void set_obj_size(uint64_t s) { obj_size = s; } - virtual void set_name(const std::string& n) { key = n; } - virtual void set_key(const rgw_obj_key& k) { key = k; } - virtual rgw_obj get_obj(void) const { - rgw_obj obj(bucket->get_key(), key); - obj.set_in_extra_data(in_extra_data); - return obj; - } - virtual void gen_rand_obj_instance_name() = 0; /* dang - This is temporary, until the API is completed */ rgw_obj_key& get_key() { return key; } @@ -442,6 +530,8 @@ class RGWObject { bool have_instance(void) { return key.have_instance(); } friend inline ostream& operator<<(ostream& out, const RGWObject& o) { + if (o.bucket) + out << o.bucket << ":"; out << o.key; return out; } @@ -449,7 +539,7 @@ class RGWObject { if (!o) out << ""; else - out << o->key; + out << *o; return out; } friend inline ostream& operator<<(ostream& out, const std::unique_ptr& p) { @@ -458,5 +548,63 @@ class RGWObject { } }; +struct Serializer { + Serializer() = default; + virtual ~Serializer() = default; + + virtual int try_lock(utime_t dur, optional_yield y) = 0; + virtual int unlock() = 0; +}; + +struct MPSerializer : Serializer { + bool locked; + std::string oid; + MPSerializer() : locked(false) {} + virtual ~MPSerializer() = default; + + void clear_locked() { + locked = false; + } +}; + +struct LCSerializer : Serializer { + LCSerializer() {} + virtual ~LCSerializer() = default; +}; + +class Lifecycle { +public: + struct LCHead { + time_t start_date{0}; + std::string marker; + + LCHead() = default; + LCHead(time_t _date, std::string& _marker) : start_date(_date), marker(_marker) {} + }; + + struct LCEntry { + std::string bucket; + uint64_t start_time{0}; + uint32_t status{0}; + + LCEntry() = default; + LCEntry(std::string& _bucket, uint64_t _time, uint32_t _status) : bucket(_bucket), start_time(_time), status(_status) {} + }; + + Lifecycle() = default; + virtual ~Lifecycle() = default; + + virtual int get_entry(const string& oid, const std::string& marker, LCEntry& entry) = 0; + virtual int get_next_entry(const string& oid, std::string& marker, LCEntry& entry) = 0; + virtual int set_entry(const string& oid, const LCEntry& entry) = 0; + virtual int list_entries(const string& oid, const string& marker, + uint32_t max_entries, vector& entries) = 0; + virtual int rm_entry(const string& oid, const LCEntry& entry) = 0; + virtual int get_head(const string& oid, LCHead& head) = 0; + virtual int put_head(const string& oid, const LCHead& head) = 0; + + virtual LCSerializer* get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie) = 0; +}; + } } // namespace rgw::sal diff --git a/src/rgw/rgw_sal_rados.cc b/src/rgw/rgw_sal_rados.cc index 6ae2f3edd447a..043a9837515f9 100644 --- a/src/rgw/rgw_sal_rados.cc +++ b/src/rgw/rgw_sal_rados.cc @@ -28,11 +28,12 @@ #include "rgw_multi.h" #include "rgw_acl_s3.h" -/* Stuff for RGWRadosStore. Move to separate file when store split out */ #include "rgw_zone.h" #include "rgw_rest_conn.h" #include "services/svc_sys_obj.h" #include "services/svc_zone.h" +#include "services/svc_tier_rados.h" +#include "cls/rgw/cls_rgw_client.h" #define dout_subsys ceph_subsys_rgw @@ -530,6 +531,18 @@ void RGWRadosObject::gen_rand_obj_instance_name() store->getRados()->gen_rand_obj_instance_name(&key); } +void RGWRadosObject::raw_obj_to_obj(const rgw_raw_obj& raw_obj) +{ + rgw_obj tobj = get_obj(); + RGWSI_Tier_RADOS::raw_obj_to_obj(get_bucket()->get_key(), raw_obj, &tobj); + set_key(tobj.key); +} + +void RGWRadosObject::get_raw_obj(rgw_raw_obj* raw_obj) +{ + store->getRados()->obj_to_raw((bucket->get_info()).placement_rule, get_obj(), raw_obj); +} + int RGWRadosObject::omap_get_vals_by_keys(const std::string& oid, const std::set& keys, RGWAttrs *vals) @@ -548,6 +561,67 @@ int RGWRadosObject::omap_get_vals_by_keys(const std::string& oid, return cur_ioctx.omap_get_vals_by_keys(oid, keys, vals); } +int RGWRadosObject::omap_set_val_by_key(const std::string& key, bufferlist& val, + bool must_exist, optional_yield y) +{ + rgw_raw_obj raw_meta_obj; + rgw_obj obj = get_obj(); + + store->getRados()->obj_to_raw(bucket->get_placement_rule(), obj, &raw_meta_obj); + + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + auto sysobj = obj_ctx.get_obj(raw_meta_obj); + + return sysobj.omap().set_must_exist(must_exist).set(key, val, y); +} + +MPSerializer* RGWRadosObject::get_serializer(const std::string& lock_name) +{ + return new MPRadosSerializer(store, this, lock_name); +} + +int RGWRadosObject::transition(RGWObjectCtx& rctx, + RGWBucket* bucket, + const rgw_placement_rule& placement_rule, + const real_time& mtime, + uint64_t olh_epoch, + const DoutPrefixProvider *dpp, + optional_yield y) +{ + return store->getRados()->transition_obj(rctx, bucket, *this, placement_rule, mtime, olh_epoch, dpp, y); +} + +int RGWRadosObject::get_max_chunk_size(rgw_placement_rule placement_rule, uint64_t *max_chunk_size, uint64_t *alignment) +{ + return store->getRados()->get_max_chunk_size(placement_rule, get_obj(), max_chunk_size, alignment); +} + +void RGWRadosObject::get_max_aligned_size(uint64_t size, uint64_t alignment, + uint64_t *max_size) +{ + store->getRados()->get_max_aligned_size(size, alignment, max_size); +} + +bool RGWRadosObject::placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2) +{ + rgw_obj obj; + rgw_pool p1, p2; + + obj = get_obj(); + + if (r1 == r2) + return true; + + if (!store->getRados()->get_obj_data_pool(r1, obj, &p1)) { + return false; + } + if (!store->getRados()->get_obj_data_pool(r2, obj, &p2)) { + return false; + } + + return p1 == p2; +} + std::unique_ptr RGWRadosObject::get_read_op(RGWObjectCtx *ctx) { return std::unique_ptr(new RGWRadosObject::RadosReadOp(this, ctx)); @@ -694,6 +768,80 @@ int RGWRadosObject::RadosReadOp::iterate(int64_t ofs, int64_t end, RGWGetDataCB return parent_op.iterate(ofs, end, cb, y); } +std::unique_ptr RGWRadosObject::get_write_op(RGWObjectCtx* ctx) +{ + return std::unique_ptr(new RGWRadosObject::RadosWriteOp(this, ctx)); +} + +RGWRadosObject::RadosWriteOp::RadosWriteOp(RGWRadosObject* _source, RGWObjectCtx* _rctx) : + source(_source), + rctx(_rctx), + op_target(_source->store->getRados(), + _source->get_bucket()->get_info(), + *static_cast(rctx), + _source->get_obj()), + parent_op(&op_target) +{ } + +int RGWRadosObject::RadosWriteOp::prepare(optional_yield y) +{ + op_target.set_versioning_disabled(params.versioning_disabled); + parent_op.meta.mtime = params.mtime; + parent_op.meta.rmattrs = params.rmattrs; + parent_op.meta.data = params.data; + parent_op.meta.manifest = params.manifest; + parent_op.meta.ptag = params.ptag; + parent_op.meta.remove_objs = params.remove_objs; + parent_op.meta.set_mtime = params.set_mtime; + parent_op.meta.owner = params.owner.get_id(); + parent_op.meta.category = params.category; + parent_op.meta.flags = params.flags; + parent_op.meta.if_match = params.if_match; + parent_op.meta.if_nomatch = params.if_nomatch; + parent_op.meta.olh_epoch = params.olh_epoch; + parent_op.meta.delete_at = params.delete_at; + parent_op.meta.canceled = params.canceled; + parent_op.meta.user_data = params.user_data; + parent_op.meta.zones_trace = params.zones_trace; + parent_op.meta.modify_tail = params.modify_tail; + parent_op.meta.completeMultipart = params.completeMultipart; + parent_op.meta.appendable = params.appendable; + + return 0; +} + +int RGWRadosObject::RadosWriteOp::write_meta(uint64_t size, uint64_t accounted_size, optional_yield y) +{ + int ret = parent_op.write_meta(size, accounted_size, *params.attrs, y); + params.canceled = parent_op.meta.canceled; + + return ret; +} + +int RGWRadosObject::swift_versioning_restore(RGWObjectCtx* obj_ctx, + bool& restored, + const DoutPrefixProvider *dpp) +{ + return store->getRados()->swift_versioning_restore(*obj_ctx, + bucket->get_owner()->get_id(), + bucket, + this, + restored, + dpp); +} + +int RGWRadosObject::swift_versioning_copy(RGWObjectCtx* obj_ctx, + const DoutPrefixProvider *dpp, + optional_yield y) +{ + return store->getRados()->swift_versioning_copy(*obj_ctx, + bucket->get_info().owner, + bucket, + this, + dpp, + y); +} + int RGWRadosStore::get_bucket(RGWUser* u, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) { int ret; @@ -828,6 +976,23 @@ int RGWRadosStore::get_zonegroup(const string& id, RGWZoneGroup& zonegroup) return rados->svc.zone->get_zonegroup(id, zonegroup); } +int RGWRadosStore::cluster_stat(RGWClusterStat& stats) +{ + rados_cluster_stat_t rados_stats; + int ret; + + ret = rados->get_rados_handle()->cluster_stat(rados_stats); + if (ret < 0) + return ret; + + stats.kb = rados_stats.kb; + stats.kb_used = rados_stats.kb_used; + stats.kb_avail = rados_stats.kb_avail; + stats.num_objects = rados_stats.num_objects; + + return ret; +} + int RGWRadosStore::create_bucket(RGWUser& u, const rgw_bucket& b, const string& zonegroup_id, rgw_placement_rule& placement_rule, @@ -944,6 +1109,155 @@ int RGWRadosStore::create_bucket(RGWUser& u, const rgw_bucket& b, return ret; } +std::unique_ptr RGWRadosStore::get_lifecycle(void) +{ + return std::unique_ptr(new RadosLifecycle(this)); +} + +int RGWRadosStore::delete_raw_obj(const rgw_raw_obj& obj) +{ + return rados->delete_raw_obj(obj); +} + +void RGWRadosStore::get_raw_obj(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj* raw_obj) +{ + rados->obj_to_raw(placement_rule, obj, raw_obj); +} + +int RGWRadosStore::get_raw_chunk_size(const rgw_raw_obj& obj, uint64_t* chunk_size) +{ + return rados->get_max_chunk_size(obj.pool, chunk_size); +} + +MPRadosSerializer::MPRadosSerializer(RGWRadosStore* store, RGWRadosObject* obj, const std::string& lock_name) : + lock(lock_name) +{ + rgw_pool meta_pool; + rgw_raw_obj raw_obj; + + obj->get_raw_obj(&raw_obj); + oid = raw_obj.oid; + store->getRados()->get_obj_data_pool(obj->get_bucket()->get_placement_rule(), + obj->get_obj(), &meta_pool); + store->getRados()->open_pool_ctx(meta_pool, ioctx, true); +} + +int MPRadosSerializer::try_lock(utime_t dur, optional_yield y) +{ + op.assert_exists(); + lock.set_duration(dur); + lock.lock_exclusive(&op); + int ret = rgw_rados_operate(ioctx, oid, &op, y); + if (! ret) { + locked = true; + } + return ret; +} + +LCRadosSerializer::LCRadosSerializer(RGWRadosStore* store, const std::string& _oid, const std::string& lock_name, const std::string& cookie) : + lock(lock_name), oid(_oid) +{ + ioctx = &store->getRados()->lc_pool_ctx; + lock.set_cookie(cookie); +} + +int LCRadosSerializer::try_lock(utime_t dur, optional_yield y) +{ + lock.set_duration(dur); + return lock.lock_exclusive(ioctx, oid); +} + +int RadosLifecycle::get_entry(const string& oid, const std::string& marker, + LCEntry& entry) +{ + cls_rgw_lc_entry cls_entry; + int ret = cls_rgw_lc_get_entry(*store->getRados()->get_lc_pool_ctx(), oid, marker, cls_entry); + + entry.bucket = cls_entry.bucket; + entry.start_time = cls_entry.start_time; + entry.status = cls_entry.status; + + return ret; +} + +int RadosLifecycle::get_next_entry(const string& oid, std::string& marker, + LCEntry& entry) +{ + cls_rgw_lc_entry cls_entry; + int ret = cls_rgw_lc_get_next_entry(*store->getRados()->get_lc_pool_ctx(), oid, marker, + cls_entry); + + entry.bucket = cls_entry.bucket; + entry.start_time = cls_entry.start_time; + entry.status = cls_entry.status; + + return ret; +} + +int RadosLifecycle::set_entry(const string& oid, const LCEntry& entry) +{ + cls_rgw_lc_entry cls_entry; + + cls_entry.bucket = entry.bucket; + cls_entry.start_time = entry.start_time; + cls_entry.status = entry.status; + + return cls_rgw_lc_set_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry); +} + +int RadosLifecycle::list_entries(const string& oid, const string& marker, + uint32_t max_entries, vector& entries) +{ + vector cls_entries; + int ret = cls_rgw_lc_list(*store->getRados()->get_lc_pool_ctx(), oid, marker, max_entries, cls_entries); + + if (ret < 0) + return ret; + + for (auto& entry : cls_entries) { + entries.push_back(LCEntry(entry.bucket, entry.start_time, entry.status)); + } + + return ret; +} + +int RadosLifecycle::rm_entry(const string& oid, const LCEntry& entry) +{ + cls_rgw_lc_entry cls_entry; + + cls_entry.bucket = entry.bucket; + cls_entry.start_time = entry.start_time; + cls_entry.status = entry.status; + + return cls_rgw_lc_rm_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry); +} + +int RadosLifecycle::get_head(const string& oid, LCHead& head) +{ + cls_rgw_lc_obj_head cls_head; + int ret = cls_rgw_lc_get_head(*store->getRados()->get_lc_pool_ctx(), oid, cls_head); + + head.marker = cls_head.marker; + head.start_date = cls_head.start_date; + + return ret; +} + +int RadosLifecycle::put_head(const string& oid, const LCHead& head) +{ + cls_rgw_lc_obj_head cls_head; + + cls_head.marker = head.marker; + cls_head.start_date = head.start_date; + + return cls_rgw_lc_put_head(*store->getRados()->get_lc_pool_ctx(), oid, cls_head); +} + +LCSerializer* RadosLifecycle::get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie) +{ + return new LCRadosSerializer(store, oid, lock_name, cookie); +} + } // namespace rgw::sal rgw::sal::RGWRadosStore *RGWStoreManager::init_storage_provider(CephContext *cct, bool use_gc_thread, bool use_lc_thread, bool quota_threads, bool run_sync_thread, bool run_reshard_thread, bool use_cache) diff --git a/src/rgw/rgw_sal_rados.h b/src/rgw/rgw_sal_rados.h index bb0acd167bdd3..dec80ed903525 100644 --- a/src/rgw/rgw_sal_rados.h +++ b/src/rgw/rgw_sal_rados.h @@ -17,6 +17,7 @@ #include "rgw_sal.h" #include "rgw_rados.h" +#include "cls/lock/cls_lock_client.h" namespace rgw { namespace sal { @@ -67,6 +68,21 @@ class RGWRadosObject : public RGWObject { virtual int get_attr(const char *name, bufferlist& dest, optional_yield y) override; }; + struct RadosWriteOp : public WriteOp { + private: + RGWRadosObject* source; + RGWObjectCtx* rctx; + RGWRados::Object op_target; + RGWRados::Object::Write parent_op; + + public: + RadosWriteOp(RGWRadosObject* _source, RGWObjectCtx* _rctx); + + virtual int prepare(optional_yield y) override; + virtual int write_meta(uint64_t size, uint64_t accounted_size, optional_yield y) override; + //virtual int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive) override; + }; + RGWRadosObject() = default; RGWRadosObject(RGWRadosStore *_st, const rgw_obj_key& _k) @@ -115,17 +131,43 @@ class RGWRadosObject : public RGWObject { virtual int copy_obj_data(RGWObjectCtx& rctx, RGWBucket* dest_bucket, RGWObject* dest_obj, uint16_t olh_epoch, std::string* petag, const DoutPrefixProvider *dpp, optional_yield y) override; 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; virtual std::unique_ptr clone() { return std::unique_ptr(new RGWRadosObject(*this)); } + virtual MPSerializer* get_serializer(const std::string& lock_name) override; + virtual int transition(RGWObjectCtx& rctx, + RGWBucket* bucket, + const rgw_placement_rule& placement_rule, + const real_time& mtime, + uint64_t olh_epoch, + const DoutPrefixProvider *dpp, + optional_yield y) override; + virtual int get_max_chunk_size(rgw_placement_rule placement_rule, + uint64_t *max_chunk_size, + uint64_t *alignment = nullptr) override; + virtual void get_max_aligned_size(uint64_t size, uint64_t alignment, uint64_t *max_size) override; + virtual bool placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2) override; + + /* Swift versioning */ + virtual int swift_versioning_restore(RGWObjectCtx* obj_ctx, + bool& restored, + const DoutPrefixProvider *dpp) override; + virtual int swift_versioning_copy(RGWObjectCtx* obj_ctx, + const DoutPrefixProvider *dpp, + optional_yield y) override; /* OPs */ virtual std::unique_ptr get_read_op(RGWObjectCtx *) override; + virtual std::unique_ptr get_write_op(RGWObjectCtx *) override; /* OMAP */ virtual int omap_get_vals_by_keys(const std::string& oid, const std::set& keys, RGWAttrs *vals) override; + virtual int omap_set_val_by_key(const std::string& key, bufferlist& val, + bool must_exist, optional_yield y) override; private: int read_attrs(RGWRados::Object::Read &read_op, optional_yield y, rgw_obj *target_obj = nullptr); @@ -211,7 +253,7 @@ class RGWRadosBucket : public RGWBucket { bool *is_truncated, RGWUsageIter& usage_iter, map& usage) override; virtual std::unique_ptr clone() { - return std::unique_ptr(new RGWRadosBucket(*this)); + return std::move(std::unique_ptr(new RGWRadosBucket(*this))); } friend class RGWRadosStore; @@ -259,6 +301,12 @@ class RGWRadosStore : public RGWStore { optional_yield y) override; virtual const RGWZoneGroup& get_zonegroup() override; virtual int get_zonegroup(const string& id, RGWZoneGroup& zonegroup) override; + virtual int cluster_stat(RGWClusterStat& stats) override; + virtual std::unique_ptr get_lifecycle(void) override; + virtual RGWLC* get_rgwlc(void) { return rados->get_lc(); } + virtual int delete_raw_obj(const rgw_raw_obj& obj) override; + virtual void get_raw_obj(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj* raw_obj) override; + virtual int get_raw_chunk_size(const rgw_raw_obj& obj, uint64_t* chunk_size) override; void setRados(RGWRados * st) { rados = st; } RGWRados *getRados(void) { return rados; } @@ -285,6 +333,51 @@ class RGWRadosStore : public RGWStore { }; +class MPRadosSerializer : public MPSerializer { + librados::IoCtx ioctx; + rados::cls::lock::Lock lock; + librados::ObjectWriteOperation op; + +public: + MPRadosSerializer(RGWRadosStore* store, RGWRadosObject* obj, const std::string& lock_name); + + virtual int try_lock(utime_t dur, optional_yield y) override; + int unlock() { + return lock.unlock(&ioctx, oid); + } +}; + +class LCRadosSerializer : public LCSerializer { + librados::IoCtx* ioctx; + rados::cls::lock::Lock lock; + const std::string oid; + +public: + LCRadosSerializer(RGWRadosStore* store, const std::string& oid, const std::string& lock_name, const std::string& cookie); + + virtual int try_lock(utime_t dur, optional_yield y) override; + int unlock() { + return lock.unlock(ioctx, oid); + } +}; + +class RadosLifecycle : public Lifecycle { + RGWRadosStore* store; + +public: + RadosLifecycle(RGWRadosStore* _st) : store(_st) {} + + virtual int get_entry(const string& oid, const std::string& marker, LCEntry& entry) override; + virtual int get_next_entry(const string& oid, std::string& marker, LCEntry& entry) override; + virtual int set_entry(const string& oid, const LCEntry& entry) override; + virtual int list_entries(const string& oid, const string& marker, + uint32_t max_entries, vector& entries) override; + virtual int rm_entry(const string& oid, const LCEntry& entry) override; + virtual int get_head(const string& oid, LCHead& head) override; + virtual int put_head(const string& oid, const LCHead& head) override; + virtual LCSerializer* get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie) override; +}; + } } // namespace rgw::sal class RGWStoreManager { diff --git a/src/rgw/rgw_tools.cc b/src/rgw/rgw_tools.cc index 09074929b33d8..89a322b0675ad 100644 --- a/src/rgw/rgw_tools.cc +++ b/src/rgw/rgw_tools.cc @@ -486,7 +486,7 @@ int RGWDataAccess::Object::put(bufferlist& data, using namespace rgw::putobj; AtomicObjectProcessor processor(&aio, store, b.get(), nullptr, - owner.get_id(), obj_ctx, obj->get_obj(), olh_epoch, + owner.get_id(), obj_ctx, std::move(obj), olh_epoch, req_id, dpp, y); int ret = processor.prepare(y); diff --git a/src/test/common/test_static_ptr.cc b/src/test/common/test_static_ptr.cc index 4bfc77bb278d6..f1c07c81b45fa 100644 --- a/src/test/common/test_static_ptr.cc +++ b/src/test/common/test_static_ptr.cc @@ -108,7 +108,7 @@ TEST(StaticPtr, CreateEmplace) { EXPECT_EQ(p->func(), 9); } -TEST(StaticPtr, CopyMove) { +TEST(StaticPtr, Move) { // Won't compile. Good. // static_ptr p1(std::in_place_type_t{}, 3); @@ -116,11 +116,6 @@ TEST(StaticPtr, CopyMove) { static_ptr p2(std::in_place_type_t{}, 3); - // This also does not compile. Good. - // p1 = p2; - p2 = p1; - EXPECT_EQ(p1->func(), 0); - p2 = std::move(p1); EXPECT_EQ(p1->func(), 0); } @@ -129,9 +124,6 @@ TEST(StaticPtr, ImplicitUpcast) { static_ptr p1; static_ptr p2(std::in_place_type_t{}, 3); - p1 = p2; - EXPECT_EQ(p1->func(), 9); - p1 = std::move(p2); EXPECT_EQ(p1->func(), 9); @@ -145,10 +137,6 @@ TEST(StaticPtr, StaticCast) { static_ptr p1(std::in_place_type_t{}, 3); static_ptr p2; - p2 = ceph::static_pointer_cast(p1); - EXPECT_EQ(p2->func(), 9); - EXPECT_EQ(p2->call(10), 30); - p2 = ceph::static_pointer_cast(std::move(p1)); EXPECT_EQ(p2->func(), 9); EXPECT_EQ(p2->call(10), 30); @@ -156,24 +144,12 @@ TEST(StaticPtr, StaticCast) { TEST(StaticPtr, DynamicCast) { static constexpr auto sz = sizeof(great_grandchild); - { - static_ptr p1(std::in_place_type_t{}, 3); - auto p2 = ceph::dynamic_pointer_cast(p1); - EXPECT_FALSE(p2); - } { static_ptr p1(std::in_place_type_t{}, 3); auto p2 = ceph::dynamic_pointer_cast(std::move(p1)); EXPECT_FALSE(p2); } - { - static_ptr p1(std::in_place_type_t{}, 3); - auto p2 = ceph::dynamic_pointer_cast(p1); - EXPECT_TRUE(p2); - EXPECT_EQ(p2->func(), 9); - EXPECT_EQ(p2->call(10), 30); - } { static_ptr p1(std::in_place_type_t{}, 3); auto p2 = ceph::dynamic_pointer_cast(std::move(p1)); @@ -195,17 +171,6 @@ class constable { TEST(StaticPtr, ConstCast) { static constexpr auto sz = sizeof(constable); - { - auto p1 = make_static(); - static_assert(std::is_const{}, - "Things are not as const as they ought to be."); - EXPECT_EQ(p1->foo(), 5); - auto p2 = ceph::const_pointer_cast(p1); - static_assert(!std::is_const{}, - "Things are more const than they ought to be."); - EXPECT_TRUE(p2); - EXPECT_EQ(p2->foo(), 2); - } { auto p1 = make_static(); EXPECT_EQ(p1->foo(), 5); @@ -219,17 +184,6 @@ TEST(StaticPtr, ConstCast) { TEST(StaticPtr, ReinterpretCast) { static constexpr auto sz = sizeof(grandchild); - { - auto p1 = make_static(3); - auto p2 = ceph::reinterpret_pointer_cast(p1); - static_assert(std::is_same{}, - "Reinterpret is screwy."); - auto p3 = ceph::reinterpret_pointer_cast(p2); - static_assert(std::is_same{}, - "Reinterpret is screwy."); - EXPECT_EQ(p3->func(), 9); - EXPECT_EQ(p3->call(10), 30); - } { auto p1 = make_static(3); auto p2 = ceph::reinterpret_pointer_cast(std::move(p1)); @@ -255,6 +209,5 @@ struct exceptional { TEST(StaticPtr, Exceptional) { static_ptr p1(std::in_place_type_t{}); - EXPECT_ANY_THROW(static_ptr p2(p1)); EXPECT_ANY_THROW(static_ptr p2(std::move(p1))); }