From 1b722bbcd691e0a4a39ea77cd28e309fd723ec88 Mon Sep 17 00:00:00 2001 From: Dmytro Iurchenko Date: Fri, 20 Feb 2015 18:31:03 +0200 Subject: [PATCH] rgw: Swift API. Allows setting attributes with COPY object operation. http://developer.openstack.org/api-ref-objectstorage-v1.html says: "With COPY, you can add additional metadata to the object." Fixes: #10662 Backport: hammer Reported-by: Ahmad Faheem Signed-off-by: Dmytro Iurchenko --- src/rgw/rgw_op.cc | 2 +- src/rgw/rgw_op.h | 4 ++-- src/rgw/rgw_rados.cc | 47 ++++++++++++++++++++++++++------------- src/rgw/rgw_rados.h | 19 +++++++++++++--- src/rgw/rgw_rest_s3.cc | 8 +++---- src/rgw/rgw_rest_swift.cc | 4 ++++ 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 87710fc744a..c0333de8d8e 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2376,7 +2376,7 @@ void RGWCopyObj::execute() unmod_ptr, if_match, if_nomatch, - replace_attrs, + attrs_mod, attrs, RGW_OBJ_CATEGORY_MAIN, olh_epoch, (version_id.empty() ? NULL : &version_id), diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index a24b328192d..bb2fdeda89c 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -585,7 +585,7 @@ protected: rgw_bucket dest_bucket; string dest_object; time_t mtime; - bool replace_attrs; + RGWRados::AttrsMod attrs_mod; RGWBucketInfo src_bucket_info; RGWBucketInfo dest_bucket_info; string source_zone; @@ -616,7 +616,7 @@ public: unmod_ptr = NULL; ret = 0; mtime = 0; - replace_attrs = false; + attrs_mod = RGWRados::ATTRSMOD_NONE; last_ofs = 0; olh_epoch = 0; } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 036204e4a95..b590e7fee50 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -3255,19 +3255,27 @@ public: }; /* - * prepare attrset, either replace it with new attrs, or keep it (other than acls). + * prepare attrset depending on attrs_mod. */ -static void set_copy_attrs(map& src_attrs, map& attrs, bool replace_attrs, bool intra_region) +static void set_copy_attrs(map& src_attrs, + map& attrs, + RGWRados::AttrsMod attrs_mod) { - if (replace_attrs) { - if (!attrs[RGW_ATTR_ETAG].length()) + switch (attrs_mod) { + case RGWRados::ATTRSMOD_NONE: + src_attrs[RGW_ATTR_ACL] = attrs[RGW_ATTR_ACL]; + break; + case RGWRados::ATTRSMOD_REPLACE: + if (!attrs[RGW_ATTR_ETAG].length()) { attrs[RGW_ATTR_ETAG] = src_attrs[RGW_ATTR_ETAG]; - + } src_attrs = attrs; - } else { - /* copying attrs from source, however acls should only be copied if it's intra-region operation */ - if (!intra_region) - src_attrs[RGW_ATTR_ACL] = attrs[RGW_ATTR_ACL]; + break; + case RGWRados::ATTRSMOD_MERGE: + for (map::iterator it = attrs.begin(); it != attrs.end(); ++it) { + src_attrs[it->first] = it->second; + } + break; } } @@ -3322,7 +3330,7 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, - bool replace_attrs, + AttrsMod attrs_mod, map& attrs, RGWObjCategory category, uint64_t olh_epoch, @@ -3414,7 +3422,9 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx, } } - set_copy_attrs(src_attrs, attrs, replace_attrs, !source_zone.empty()); + if (source_zone.empty()) { + set_copy_attrs(src_attrs, attrs, attrs_mod); + } ret = cb.complete(etag, mtime, set_mtime, src_attrs); if (ret < 0) @@ -3465,7 +3475,14 @@ int RGWRados::copy_obj_to_remote_dest(RGWObjState *astate, * Copy an object. * dest_obj: the object to copy into * src_obj: the object to copy from - * attrs: if replace_attrs is set then these are placed on the new object + * attrs: usage depends on attrs_mod parameter + * attrs_mod: the modification mode of the attrs, may have the following values: + * ATTRSMOD_NONE - the attributes of the source object will be + * copied without modifications, attrs parameter is ignored; + * ATTRSMOD_REPLACE - new object will have the attributes provided by attrs + * parameter, source object attributes are not copied; + * ATTRSMOD_MERGE - any conflicting meta keys on the source object's attributes + * are overwritten by values contained in attrs parameter. * err: stores any errors resulting from the get of the original object * Returns: 0 on success, -ERR# otherwise. */ @@ -3484,7 +3501,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, - bool replace_attrs, + AttrsMod attrs_mod, map& attrs, RGWObjCategory category, uint64_t olh_epoch, @@ -3520,7 +3537,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, if (remote_src || !source_zone.empty()) { return fetch_remote_obj(obj_ctx, user_id, client_id, op_id, info, source_zone, dest_obj, src_obj, dest_bucket_info, src_bucket_info, mtime, mod_ptr, - unmod_ptr, if_match, if_nomatch, replace_attrs, attrs, category, + unmod_ptr, if_match, if_nomatch, attrs_mod, attrs, category, olh_epoch, version_id, ptag, petag, err, progress_cb, progress_data); } @@ -3545,7 +3562,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, return ret; } - set_copy_attrs(src_attrs, attrs, replace_attrs, false); + set_copy_attrs(src_attrs, attrs, attrs_mod); src_attrs.erase(RGW_ATTR_ID_TAG); RGWObjManifest manifest; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index e6fe72b60d5..a9ae0b74fa5 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1674,6 +1674,12 @@ public: virtual int aio_wait(void *handle); virtual bool aio_completed(void *handle); + enum AttrsMod { + ATTRSMOD_NONE = 0, + ATTRSMOD_REPLACE = 1, + ATTRSMOD_MERGE = 2 + }; + int rewrite_obj(RGWBucketInfo& dest_bucket_info, rgw_obj& obj); int fetch_remote_obj(RGWObjectCtx& obj_ctx, const string& user_id, @@ -1690,7 +1696,7 @@ public: const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, - bool replace_attrs, + AttrsMod attrs_mod, map& attrs, RGWObjCategory category, uint64_t olh_epoch, @@ -1710,7 +1716,14 @@ public: * Copy an object. * dest_obj: the object to copy into * src_obj: the object to copy from - * attrs: if replace_attrs is set then these are placed on the new object + * attrs: usage depends on attrs_mod parameter + * attrs_mod: the modification mode of the attrs, may have the following values: + * ATTRSMOD_NONE - the attributes of the source object will be + * copied without modifications, attrs parameter is ignored; + * ATTRSMOD_REPLACE - new object will have the attributes provided by attrs + * parameter, source object attributes are not copied; + * ATTRSMOD_MERGE - any conflicting meta keys on the source object's attributes + * are overwritten by values contained in attrs parameter. * err: stores any errors resulting from the get of the original object * Returns: 0 on success, -ERR# otherwise. */ @@ -1729,7 +1742,7 @@ public: const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, - bool replace_attrs, + AttrsMod attrs_mod, map& attrs, RGWObjCategory category, uint64_t olh_epoch, diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 9479601e435..af9bea2dcab 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1448,11 +1448,11 @@ int RGWCopyObj_ObjStore_S3::get_params() const char *md_directive = s->info.env->get("HTTP_X_AMZ_METADATA_DIRECTIVE"); if (md_directive) { if (strcasecmp(md_directive, "COPY") == 0) { - replace_attrs = false; + attrs_mod = RGWRados::ATTRSMOD_NONE; } else if (strcasecmp(md_directive, "REPLACE") == 0) { - replace_attrs = true; + attrs_mod = RGWRados::ATTRSMOD_REPLACE; } else if (!source_zone.empty()) { - replace_attrs = false; // default for intra-region copy + attrs_mod = RGWRados::ATTRSMOD_NONE; // default for intra-region copy } else { ldout(s->cct, 0) << "invalid metadata directive" << dendl; return -EINVAL; @@ -1463,7 +1463,7 @@ int RGWCopyObj_ObjStore_S3::get_params() (dest_bucket_name.compare(src_bucket_name) == 0) && (dest_object.compare(src_object.name) == 0) && src_object.instance.empty() && - !replace_attrs) { + (attrs_mod != RGWRados::ATTRSMOD_REPLACE)) { /* can only copy object into itself if replacing attrs */ ldout(s->cct, 0) << "can't copy object into itself if not replacing attrs" << dendl; return -ERR_INVALID_REQUEST; diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index c0aef74fe56..5738bbc50c7 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -557,6 +557,10 @@ int RGWCopyObj_ObjStore_SWIFT::get_params() dest_bucket_name = s->bucket_name_str; dest_object = s->object.name; + if (!s->info.x_meta_map.empty()) { + attrs_mod = RGWRados::ATTRSMOD_MERGE; + } + return 0; }