Merge pull request #4054 from diurchenko/wip-10662

rgw: Swift API. Allows setting attributes with COPY object operation.

Reviewed-by: Yehuda Sadeh <yehuda@redhat.com>
This commit is contained in:
Yehuda Sadeh 2015-03-19 07:41:10 -07:00
commit 6c5fe91e2c
6 changed files with 59 additions and 25 deletions

View File

@ -2407,7 +2407,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),

View File

@ -595,7 +595,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;
@ -626,7 +626,7 @@ public:
unmod_ptr = NULL;
ret = 0;
mtime = 0;
replace_attrs = false;
attrs_mod = RGWRados::ATTRSMOD_NONE;
last_ofs = 0;
olh_epoch = 0;
}

View File

@ -3374,19 +3374,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<string, bufferlist>& src_attrs, map<string, bufferlist>& attrs, bool replace_attrs, bool intra_region)
static void set_copy_attrs(map<string, bufferlist>& src_attrs,
map<string, bufferlist>& 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<string, bufferlist>::iterator it = attrs.begin(); it != attrs.end(); ++it) {
src_attrs[it->first] = it->second;
}
break;
}
}
@ -3441,7 +3449,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<string, bufferlist>& attrs,
RGWObjCategory category,
uint64_t olh_epoch,
@ -3533,7 +3541,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)
@ -3584,7 +3594,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.
*/
@ -3603,7 +3620,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<string, bufferlist>& attrs,
RGWObjCategory category,
uint64_t olh_epoch,
@ -3639,7 +3656,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);
}
@ -3664,7 +3681,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;

View File

@ -1685,6 +1685,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,
@ -1701,7 +1707,7 @@ public:
const time_t *unmod_ptr,
const char *if_match,
const char *if_nomatch,
bool replace_attrs,
AttrsMod attrs_mod,
map<string, bufferlist>& attrs,
RGWObjCategory category,
uint64_t olh_epoch,
@ -1721,7 +1727,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.
*/
@ -1740,7 +1753,7 @@ public:
const time_t *unmod_ptr,
const char *if_match,
const char *if_nomatch,
bool replace_attrs,
AttrsMod attrs_mod,
map<std::string, bufferlist>& attrs,
RGWObjCategory category,
uint64_t olh_epoch,

View File

@ -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;

View File

@ -572,6 +572,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;
}