From: Yehuda Sadeh Date: Thu, 3 Jan 2019 01:43:44 +0000 (-0800) Subject: rgw: lifecycle: current obj transitions X-Git-Tag: v14.1.0~314^2~26 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8cd2d02a3244450476140d385d53acf95201a241;p=ceph.git rgw: lifecycle: current obj transitions Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_lc.cc b/src/rgw/rgw_lc.cc index e3da5f77aeb8..3dbb0674821d 100644 --- a/src/rgw/rgw_lc.cc +++ b/src/rgw/rgw_lc.cc @@ -106,7 +106,7 @@ bool RGWLifecycleConfiguration::_add_rule(const LCRule& rule) } else { action.date = ceph::from_iso_8601(elem.second.get_date()); } - action.storage_class = elem.first; + action.storage_class = rgw_placement_rule::get_canonical_storage_class(elem.first); op.transitions.emplace(elem.first, std::move(action)); } for (const auto &elem : rule.get_noncur_transitions()) { @@ -402,7 +402,9 @@ static bool is_valid_op(const lc_op& op) (op.expiration > 0 || op.expiration_date != boost::none || op.noncur_expiration > 0 - || op.dm_expiration)); + || op.dm_expiration + || !op.transitions.empty() + || !op.noncur_transitions.empty())); } class LCObjsLister { @@ -749,6 +751,61 @@ public: } }; +class LCOpAction_Transition : public LCOpAction { + const transition_action& transition; +public: + LCOpAction_Transition(const transition_action& _transition) : transition(_transition) {} + + bool check(lc_op_ctx& oc, ceph::real_time *exp_time) override { + auto& o = oc.o; + + if (o.is_delete_marker()) { + return false; + } + + if (!o.is_current()) { + return false; + } + + if (rgw_placement_rule::get_canonical_storage_class(o.meta.storage_class) == transition.storage_class) { + /* already at target storage class */ + return false; + } + + auto& mtime = o.meta.mtime; + bool is_expired; + if (transition.days <= 0) { + if (transition.date == boost::none) { + ldout(oc.cct, 20) << __func__ << "(): key=" << o.key << ": no transition day/date set in rule, skipping" << dendl; + return false; + } + is_expired = ceph_clock_now() >= ceph::real_clock::to_time_t(*transition.date); + *exp_time = *transition.date; + } else { + is_expired = obj_has_expired(oc.cct, mtime, transition.days, exp_time); + } + + return is_expired; + } + + int process(lc_op_ctx& oc) { + auto& o = oc.o; + + rgw_placement_rule target_placement; + target_placement.inherit_from(oc.bucket_info.placement_rule); + target_placement.storage_class = transition.storage_class; + + int r = oc.store->transition_obj(oc.rctx, oc.bucket_info, oc.obj, + target_placement, o.meta.mtime, o.versioned_epoch); + if (r < 0) { + ldout(oc.cct, 0) << "ERROR: failed to transition obj (r=" << r << ")" << dendl; + return r; + } + ldout(oc.cct, 2) << "TRANSITIONED:" << oc.bucket_info.bucket << ":" << o.key << " -> " << transition.storage_class << dendl; + return 0; + } +}; + void LCOpRule::build() { filters.emplace_back(new LCOpFilter_Tags); @@ -767,6 +824,15 @@ void LCOpRule::build() if (op.noncur_expiration > 0) { actions.emplace_back(new LCOpAction_NonCurrentExpiration); } + + for (auto& iter : op.transitions) { + actions.emplace_back(new LCOpAction_Transition(iter.second)); + } +#if 0 + for (auto& t : op.noncur_transitions) { + actions.emplace_back(new LOpAction_Transition); + } +#endif } int LCOpRule::process(rgw_bucket_dir_entry& o) diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 9e7f82733da3..a69c950ba712 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -4852,6 +4852,53 @@ int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx, nullptr, nullptr, nullptr, nullptr, nullptr); } +int RGWRados::transition_obj(RGWObjectCtx& obj_ctx, + RGWBucketInfo& bucket_info, + rgw_obj& obj, + const rgw_placement_rule& placement_rule, + const real_time& mtime, + uint64_t olh_epoch) +{ + map attrs; + real_time read_mtime; + uint64_t obj_size; + + RGWRados::Object op_target(this, bucket_info, obj_ctx, obj); + RGWRados::Object::Read read_op(&op_target); + + read_op.params.attrs = &attrs; + read_op.params.lastmod = &read_mtime; + read_op.params.obj_size = &obj_size; + + int ret = read_op.prepare(); + if (ret < 0) { + return ret; + } + + if (read_mtime != mtime) { + /* raced */ + return -ECANCELED; + } + + ret = copy_obj_data(obj_ctx, + bucket_info, + placement_rule, + read_op, + obj_size - 1, + obj, + nullptr /* pmtime */, + mtime, + attrs, + olh_epoch, + real_time(), + nullptr /* petag */); + if (ret < 0) { + return ret; + } + + return 0; +} + int RGWRados::check_bucket_empty(RGWBucketInfo& bucket_info) { std::vector ent_list; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 91d02e139fb3..d0988ca59a72 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1974,6 +1974,13 @@ public: ceph::real_time delete_at, string *petag); + int transition_obj(RGWObjectCtx& obj_ctx, + RGWBucketInfo& bucket_info, + rgw_obj& obj, + const rgw_placement_rule& placement_rule, + const real_time& mtime, + uint64_t olh_epoch); + int check_bucket_empty(RGWBucketInfo& bucket_info); /**