]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: lifecycle: current obj transitions
authorYehuda Sadeh <yehuda@redhat.com>
Thu, 3 Jan 2019 01:43:44 +0000 (17:43 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Fri, 4 Jan 2019 03:00:24 +0000 (19:00 -0800)
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/rgw/rgw_lc.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h

index e3da5f77aeb8085503356c3bf851af87dabeb656..3dbb0674821dfbfbf431059a0e3afa842a61eaaf 100644 (file)
@@ -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)
index 9e7f82733da30cbe727ca1900a78c30d23771bc0..a69c950ba7129a1b06e0f91cbe516e98779265a5 100644 (file)
@@ -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<string, bufferlist> 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<rgw_bucket_dir_entry> ent_list;
index 91d02e139fb355b4f7d9bf2e7452e99710144922..d0988ca59a720e15368232d8c95383d484139adf 100644 (file)
@@ -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);
 
   /**