Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rgw: add the remove-x-delete feature to cancel swift object expiration #13621

Merged
merged 1 commit into from Apr 3, 2017

Conversation

Jing-Scott
Copy link
Contributor

@Jing-Scott Jing-Scott commented Feb 24, 2017

In openstack swift, it also support the feature to cancel the object expiration, which could be found at last point in https://docs.openstack.org/user-guide/cli-swift-set-object-expiration.html. we can remove the object expiration by set 'X-Remove-Delete-At:'.

This patch also could fix the bug that when we set the object expiration and then upload the same object to the container again. The previous object expiration also works, which is not compatible with the openstack swift.

Fixes: http://tracker.ceph.com/issues/19074
Signed-off-by: Jing Wenjun jingwenjun@cmss.chinamobile.com

@Jing-Scott
Copy link
Contributor Author

Hi, @rzarzynski
Could you help me to take a look? Thanks!

@rzarzynski rzarzynski self-assigned this Feb 27, 2017
src/rgw/rgw_op.h Outdated
{
if (real_clock::is_zero(delete_at)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks we started treating0 in delete_at as special value saying "expiration hint revoked". Does the expirer part is OK with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. @rzarzynski : In this change, if we want to set the object expiration time. The var set_delete_at will be true and the delete_at updated relatively.

In int RGWObjectExpirer::garbage_single_object(objexp_hint_entry& hint) it will call delete_obj()
In int RGWRados::Object::Delete::delete_obj(), you will find these code:

if (!real_clock::is_zero(params.expiration_time)) {
    bufferlist bl;
    real_time delete_at;

    if (state->get_attr(RGW_ATTR_DELETE_AT, bl)) {
      try {
        bufferlist::iterator iter = bl.begin();
        ::decode(delete_at, iter);
      } catch (buffer::error& err) {
        ldout(store->ctx(), 0) << "ERROR: couldn't decode RGW_ATTR_DELETE_AT" << dendl;
	return -EIO;
      }

      if (params.expiration_time != delete_at) {
        return -ERR_PRECONDITION_FAILED;
      }
    }
  }

In if (params.expiration_time != delete_at) { :
if the expiration time of object is updated, the delete_at is the current expiration time in bufferlist and the params,expiration_time is the non-current expiration time in the list of cls_timeindex_entry.

So, that means if the two expriation time is not consistent, the object will not be deleted.
If we intend to cancel the object expiration time, the delete_at will be 0 and the object will never be deleted because of if (!real_clock::is_zero(params.expiration_time)) { in upper code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the very detailed explanation! Conceptually everything looks good.

src/rgw/rgw_op.h Outdated
{
if (real_clock::is_zero(delete_at)) {
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_DELETE_AT);
if (!set_delete_at && iter != attrs.end()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rzarzynski in this change, the delete_at will be encoded only in two situations:

  1. the object was upload in first time
  2. the object expiration time was updated(including remove the expiration time)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about switching to boost::optional<ceph::real_time> instead of introducing theset_delete_at flag? Optional seems to be intended for handling cases exactly like this one.

@Jing-Scott
Copy link
Contributor Author

@rzarzynski Hi, thanks for your suggestion! I've updated them with boost::optional<ceph::real_time> delete_at instead of ceph::real_time delete_at.

@@ -1145,7 +1145,7 @@ namespace rgw {
emplace_attr(RGW_ATTR_SLO_UINDICATOR, std::move(slo_userindicator_bl));
}

op_ret = processor->complete(s->obj_size, etag, &mtime, real_time(), attrs, delete_at,
op_ret = processor->complete(s->obj_size, etag, &mtime, real_time(), attrs, *delete_at,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks we might be dereferencing an empty boost::optional here. If that's true, following check should help:

delete_at ? *delete_at : 0

@@ -3343,7 +3343,7 @@ void RGWPostObj::execute()
emplace_attr(RGW_ATTR_COMPRESSION, std::move(tmp));
}

op_ret = processor.complete(s->obj_size, etag, NULL, real_time(), attrs, delete_at);
op_ret = processor.complete(s->obj_size, etag, NULL, real_time(), attrs, *delete_at);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here.

src/rgw/rgw_op.h Outdated
if (real_clock::is_zero(delete_at)) {
return;
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_DELETE_AT);
if (delete_at == boost::none) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much more readable now. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I wonder whether we really need to have the RGW_ATTR_DELETE_AT set for all objects (including those created through the S3 API). Maybe the check solely for boost::none would be enough? What do you think?

Copy link
Contributor Author

@Jing-Scott Jing-Scott Mar 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rzarzynski ,I've updated them. I considered the http://tracker.ceph.com/issues/19074, so I set RGW_ATTR_DELETE_AT to all objects before. But now there is another solution instead which is described below.

@Jing-Scott Jing-Scott force-pushed the add-remov-x-delete-feature branch 6 times, most recently from 1347007 to e0ade73 Compare March 8, 2017 12:56
In openstack swift, it also support the feature to cancel the object expiration,
which could be found at last point in
https://docs.openstack.org/user-guide/cli-swift-set-object-expiration.html. we
can remove the object expiration by set 'X-Remove-Delete-At:'.

This patch also could fix the bug that when we set the object expiration and
then upload the same object to the container again. The previous object expiration
also works, which is not compatible with the openstack swift.

Fixes: http://tracker.ceph.com/issues/19074
Signed-off-by: Jing Wenjun <jingwenjun@cmss.chinamobile.com>
@@ -8328,6 +8328,8 @@ int RGWRados::Object::Delete::delete_obj()
if (params.expiration_time != delete_at) {
return -ERR_PRECONDITION_FAILED;
}
} else {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, RGWRados::delete_obj takes expiration_time which is by default ceph::real_time():

  /** Delete an object.*/
  int delete_obj(RGWObjectCtx& obj_ctx,
                         const RGWBucketInfo& bucket_owner,
                         const rgw_obj& src_obj,
                         int versioning_status,
                         uint16_t bilog_flags = 0,
                         const ceph::real_time& expiration_time = ceph::real_time());

@cbodley
Copy link
Contributor

cbodley commented Mar 24, 2017

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks, @Jing-Scott!

op_ret = processor->complete(s->obj_size, etag, &mtime, real_time(), attrs, delete_at,
if_match, if_nomatch);
op_ret = processor->complete(s->obj_size, etag, &mtime, real_time(), attrs,
(delete_at ? *delete_at : real_time()), if_match, if_nomatch);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If delete_at is empty, then we supply an instance of real_time. ceph::real_time is an alias over std::chrono::time_point<ceph::time_detail::real_clock>. Its default-constructed instance represents logical zero --real_clock::is_zero(ceph::real_time()) == true. OK.

@@ -8328,6 +8328,8 @@ int RGWRados::Object::Delete::delete_obj()
if (params.expiration_time != delete_at) {
return -ERR_PRECONDITION_FAILED;
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, RGWRados::delete_obj takes expiration_time which is by default ceph::real_time():

  /** Delete an object.*/
  int delete_obj(RGWObjectCtx& obj_ctx,
                         const RGWBucketInfo& bucket_owner,
                         const rgw_obj& src_obj,
                         int versioning_status,
                         uint16_t bilog_flags = 0,
                         const ceph::real_time& expiration_time = ceph::real_time());

@rzarzynski rzarzynski merged commit 51dd349 into ceph:master Apr 3, 2017
@Jing-Scott Jing-Scott deleted the add-remov-x-delete-feature branch April 5, 2017 07:29
@Jing-Scott Jing-Scott restored the add-remov-x-delete-feature branch June 8, 2017 09:32
@Jing-Scott Jing-Scott deleted the add-remov-x-delete-feature branch June 8, 2017 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants