#include "rgw_common.h"
#include "rgw_bucket.h"
#include "rgw_lc.h"
+#include "rgw_zone.h"
#include "rgw_string.h"
#include "services/svc_sys_obj.h"
return (timediff >= cmp);
}
+static bool pass_object_lock_check(RGWRados *store, RGWBucketInfo& bucket_info, rgw_obj& obj, RGWObjectCtx& ctx)
+{
+ if (!bucket_info.obj_lock_enabled()) {
+ return true;
+ }
+ RGWRados::Object op_target(store, bucket_info, ctx, obj);
+ RGWRados::Object::Read read_op(&op_target);
+ map<string, bufferlist> attrs;
+ read_op.params.attrs = &attrs;
+ int ret = read_op.prepare();
+ if (ret < 0) {
+ if (ret == -ENOENT) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ auto iter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
+ if (iter != attrs.end()) {
+ RGWObjectRetention retention;
+ try {
+ decode(retention, iter->second);
+ } catch (buffer::error& err) {
+ ldout(store->ctx(), 0) << "ERROR: failed to decode RGWObjectRetention" << dendl;
+ return false;
+ }
+ if (ceph::real_clock::to_time_t(retention.get_retain_until_date()) > ceph_clock_now()) {
+ return false;
+ }
+ }
+ iter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD);
+ if (iter != attrs.end()) {
+ RGWObjectLegalHold obj_legal_hold;
+ try {
+ decode(obj_legal_hold, iter->second);
+ } catch (buffer::error& err) {
+ ldout(store->ctx(), 0) << "ERROR: failed to decode RGWObjectLegalHold" << dendl;
+ return false;
+ }
+ if (obj_legal_hold.is_enabled()) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
int RGWLC::handle_multipart_expiration(
RGWRados::Bucket *target, const multimap<string, lc_op>& prefix_map)
{
ldout(oc.cct, 20) << __func__ << "(): key=" << o.key << ": not current, skipping" << dendl;
return false;
}
+ if (o.is_delete_marker()) {
+ if (oc.ol.next_has_same_name()) {
+ return false;
+ } else {
+ *exp_time = real_clock::now();
+ return true;
+ }
+ }
auto& mtime = o.meta.mtime;
bool is_expired;
int process(lc_op_ctx& oc) {
auto& o = oc.o;
- int r = remove_expired_obj(oc, !oc.bucket_info.versioned());
+ int r;
+ if (o.is_delete_marker()) {
+ r = remove_expired_obj(oc, true);
+ } else {
+ r = remove_expired_obj(oc, !oc.bucket_info.versioned());
+ }
if (r < 0) {
ldout(oc.cct, 0) << "ERROR: remove_expired_obj " << dendl;
return r;
bool is_expired = obj_has_expired(oc.cct, mtime, expiration, exp_time);
ldout(oc.cct, 20) << __func__ << "(): key=" << o.key << ": is_expired=" << is_expired << dendl;
- return is_expired;
+ return is_expired && pass_object_lock_check(oc.store, oc.bucket_info, oc.obj, oc.rctx);
}
int process(lc_op_ctx& oc) {
target_placement.inherit_from(oc.bucket_info.placement_rule);
target_placement.storage_class = transition.storage_class;
+ if (!oc.store->svc.zone->get_zone_params().valid_placement(target_placement)) {
+ ldout(oc.cct, 0) << "ERROR: non existent dest placement: " << target_placement
+ << " bucket="<< oc.bucket_info.bucket
+ << " rule_id=" << oc.op.id << dendl;
+ return -EINVAL;
+ }
+
int r = oc.store->transition_obj(oc.rctx, oc.bucket_info, oc.obj,
target_placement, o.meta.mtime, o.versioned_epoch);
if (r < 0) {