Skip to content

Commit

Permalink
Merge pull request ceph#7764 from rzarzynski/wip-rgw-etag-dlo
Browse files Browse the repository at this point in the history
rgw: multiple improvements regarding etag calculation for SLO/DLO of Swift API.

Reviewed-by: Yehuda Sadeh <[email protected]>
  • Loading branch information
yehudasa committed Mar 3, 2016
2 parents be3544f + 533b617 commit bc60ba3
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 40 deletions.
60 changes: 41 additions & 19 deletions src/rgw/rgw_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ static int iterate_user_manifest_parts(CephContext * const cct,
RGWAccessControlPolicy * const bucket_policy,
uint64_t * const ptotal_len,
uint64_t * const pobj_size,
string * const pobj_sum,
int (*cb)(rgw_bucket& bucket,
const RGWObjEnt& ent,
RGWAccessControlPolicy * const bucket_policy,
Expand All @@ -757,16 +758,15 @@ static int iterate_user_manifest_parts(CephContext * const cct,
list_op.params.prefix = obj_prefix;
list_op.params.delim = delim;

MD5 etag_sum;
do {
#define MAX_LIST_OBJS 100
int r = list_op.list_objects(MAX_LIST_OBJS, &objs, NULL, &is_truncated);
if (r < 0)
if (r < 0) {
return r;
}

vector<RGWObjEnt>::iterator viter;

for (viter = objs.begin(); viter != objs.end(); ++viter) {
RGWObjEnt& ent = *viter;
for (RGWObjEnt& ent : objs) {
uint64_t cur_total_len = obj_ofs;
uint64_t start_ofs = 0, end_ofs = ent.size;

Expand All @@ -776,6 +776,10 @@ static int iterate_user_manifest_parts(CephContext * const cct,
}

obj_ofs += ent.size;
if (pobj_sum) {
etag_sum.Update((const byte *)ent.etag.c_str(),
ent.etag.length());
}

if (!found_end && obj_ofs > (uint64_t)end) {
end_ofs = end - cur_total_len + 1;
Expand Down Expand Up @@ -807,6 +811,9 @@ static int iterate_user_manifest_parts(CephContext * const cct,
if (pobj_size) {
*pobj_size = obj_ofs;
}
if (pobj_sum) {
complete_etag(etag_sum, pobj_sum);
}

return 0;
}
Expand Down Expand Up @@ -947,10 +954,14 @@ int RGWGetObj::handle_user_manifest(const char *prefix)
bucket_policy = s->bucket_acl;
}

/* dry run to find out total length */
/* dry run to find out:
* - total length (of the parts we are going to send to client),
* - overall DLO's content size,
* - md5 sum of overall DLO's content (for etag of Swift API). */
int r = iterate_user_manifest_parts(s->cct, store, ofs, end,
bucket, obj_prefix, bucket_policy, &total_len, &s->obj_size,
NULL, NULL);
bucket, obj_prefix, bucket_policy,
&total_len, &s->obj_size, &lo_etag,
nullptr /* cb */, nullptr /* cb arg */);
if (r < 0) {
return r;
}
Expand All @@ -962,7 +973,8 @@ int RGWGetObj::handle_user_manifest(const char *prefix)
}

r = iterate_user_manifest_parts(s->cct, store, ofs, end,
bucket, obj_prefix, bucket_policy, NULL, NULL,
bucket, obj_prefix, bucket_policy,
nullptr, nullptr, nullptr,
get_obj_user_manifest_iterate_cb, (void *)this);
if (r < 0) {
return r;
Expand All @@ -989,13 +1001,15 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)

map<uint64_t, rgw_slo_part> slo_parts;

MD5 etag_sum;
total_len = 0;

for (vector<rgw_slo_entry>::iterator iter = slo_info.entries.begin(); iter != slo_info.entries.end(); ++iter) {
string& path = iter->path;
int pos = path.find('/', 1); /* skip first / */
if (pos < 0)
for (const auto& entry : slo_info.entries) {
const string& path = entry.path;
const size_t pos = path.find('/', 1); /* skip first / */
if (pos == string::npos) {
return -EINVAL;
}

string bucket_name = path.substr(1, pos - 1);
string obj_name = path.substr(pos + 1);
Expand All @@ -1004,7 +1018,7 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)
RGWAccessControlPolicy *bucket_policy;

if (bucket_name.compare(s->bucket.name) != 0) {
map<string, RGWAccessControlPolicy *>::iterator piter = policies.find(bucket_name);
const auto& piter = policies.find(bucket_name);
if (piter != policies.end()) {
bucket_policy = piter->second;
bucket = buckets[bucket_name];
Expand All @@ -1016,7 +1030,8 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)
map<string, bufferlist> bucket_attrs;
RGWObjectCtx obj_ctx(store);
int r = store->get_bucket_info(obj_ctx, s->user->user_id.tenant,
bucket_name, bucket_info, NULL, &bucket_attrs);
bucket_name, bucket_info, nullptr,
&bucket_attrs);
if (r < 0) {
ldout(s->cct, 0) << "could not get bucket info for bucket="
<< bucket_name << dendl;
Expand All @@ -1025,9 +1040,11 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)
bucket = bucket_info.bucket;
rgw_obj_key no_obj;
bucket_policy = &_bucket_policy;
r = read_policy(store, s, bucket_info, bucket_attrs, bucket_policy, bucket, no_obj);
r = read_policy(store, s, bucket_info, bucket_attrs, bucket_policy,
bucket, no_obj);
if (r < 0) {
ldout(s->cct, 0) << "failed to read bucket policy for bucket " << bucket << dendl;
ldout(s->cct, 0) << "failed to read bucket policy for bucket "
<< bucket << dendl;
return r;
}
buckets[bucket_name] = bucket;
Expand All @@ -1042,19 +1059,24 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)
part.bucket_policy = bucket_policy;
part.bucket = bucket;
part.obj_name = obj_name;
part.size = iter->size_bytes;
part.etag = iter->etag;
part.size = entry.size_bytes;
part.etag = entry.etag;
ldout(s->cct, 20) << "slo_part: ofs=" << ofs
<< " bucket=" << part.bucket
<< " obj=" << part.obj_name
<< " size=" << part.size
<< " etag=" << part.etag
<< dendl;

etag_sum.Update((const byte *)entry.etag.c_str(),
entry.etag.length());

slo_parts[total_len] = part;
total_len += part.size;
}

complete_etag(etag_sum, &lo_etag);

s->obj_size = slo_info.total_size;
ldout(s->cct, 20) << "s->obj_size=" << s->obj_size << dendl;

Expand Down
1 change: 1 addition & 0 deletions src/rgw/rgw_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class RGWGetObj : public RGWOp {
rgw_obj obj;
utime_t gc_invalidate_time;
bool is_slo;
string lo_etag;

int init_common();
public:
Expand Down
22 changes: 15 additions & 7 deletions src/rgw/rgw_rest_s3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,20 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
dump_last_modified(s, lastmod);

if (! op_ret) {
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
bufferlist& bl = iter->second;
if (bl.length()) {
char *etag = bl.c_str();
dump_etag(s, etag);
if (! lo_etag.empty()) {
/* Handle etag of Swift API's large objects (DLO/SLO). It's entirerly
* legit to perform GET on them through S3 API. In such situation,
* a client should receive the composited content with corresponding
* etag value. */
dump_etag(s, lo_etag.c_str());
} else {
auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
bufferlist& bl = iter->second;
if (bl.length()) {
const char * etag = bl.c_str();
dump_etag(s, etag);
}
}
}

Expand All @@ -208,7 +216,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
}
}

for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
for (auto iter = attrs.begin(); iter != attrs.end(); ++iter) {
const char *name = iter->first.c_str();
map<string, string>::iterator aiter = rgw_to_http_attrs.find(name);
if (aiter != rgw_to_http_attrs.end()) {
Expand Down
60 changes: 46 additions & 14 deletions src/rgw/rgw_rest_swift.cc
Original file line number Diff line number Diff line change
Expand Up @@ -603,11 +603,19 @@ int RGWPutObj_ObjStore_SWIFT::get_params()
return -EINVAL;
}

MD5 etag_sum;
uint64_t total_size = 0;
for (vector<rgw_slo_entry>::iterator iter = slo_info->entries.begin(); iter != slo_info->entries.end(); ++iter) {
total_size += iter->size_bytes;
ldout(s->cct, 20) << "slo_part: " << iter->path << " size=" << iter->size_bytes << dendl;
for (const auto& entry : slo_info->entries) {
etag_sum.Update((const byte *)entry.etag.c_str(),
entry.etag.length());
total_size += entry.size_bytes;

ldout(s->cct, 20) << "slo_part: " << entry.path
<< " size=" << entry.size_bytes
<< " etag=" << entry.etag
<< dendl;
}
complete_etag(etag_sum, &lo_etag);
slo_info->total_size = total_size;

ofs = slo_info->raw_data_len;
Expand All @@ -618,9 +626,24 @@ int RGWPutObj_ObjStore_SWIFT::get_params()

void RGWPutObj_ObjStore_SWIFT::send_response()
{
if (! op_ret)
if (! op_ret) {
op_ret = STATUS_CREATED;
dump_etag(s, etag.c_str());
}

if (!lo_etag.empty()) {
/* Static Large Object of Swift API has two etags represented by
* following members:
* - etag - for the manifest itself (it will be stored in xattrs),
* - lo_etag - for the content composited from SLO's segments.
* The value is calculated basing on segments' etags.
* In response for PUT request we have to expose the second one.
* The first one may be obtained by GET with "multipart-manifest=get"
* in query string on a given SLO. */
dump_etag(s, ("\"" + lo_etag + "\"").c_str());
} else {
dump_etag(s, etag.c_str());
}

dump_last_modified(s, mtime);
set_req_state_err(s, op_ret);
dump_errno(s);
Expand Down Expand Up @@ -823,9 +846,11 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response()

set_req_state_err(s, r);
dump_errno(s);
end_header(s, this);

if (multipart_delete) {
end_header(s, this /* RGWOp */, nullptr /* contype */,
NO_CONTENT_LENGTH);

if (deleter) {
bulkdelete_respond(deleter->get_num_deleted(),
deleter->get_num_unfound(),
Expand All @@ -845,6 +870,8 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response()

bulkdelete_respond(0, 0, { fail_desc }, s->prot_flags, *s->formatter);
}
} else {
end_header(s, this);
}

rgw_flush_formatter_and_reset(s, s->formatter);
Expand Down Expand Up @@ -1012,8 +1039,9 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data_error()
return send_response_data(bl, 0, 0);
}

int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl, off_t bl_ofs,
off_t bl_len)
int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl,
const off_t bl_ofs,
const off_t bl_len)
{
string content_type;

Expand Down Expand Up @@ -1041,12 +1069,16 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl, off_t bl_ofs,
}

if (! op_ret) {
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
bufferlist& bl = iter->second;
if (bl.length()) {
char *etag = bl.c_str();
dump_etag(s, etag);
if (!lo_etag.empty()) {
dump_etag(s, ("\"" + lo_etag + "\"").c_str());
} else {
auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
bufferlist& bl = iter->second;
if (bl.length()) {
char *etag = bl.c_str();
dump_etag(s, etag);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/rgw/rgw_rest_swift.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class RGWDeleteBucket_ObjStore_SWIFT : public RGWDeleteBucket_ObjStore {
};

class RGWPutObj_ObjStore_SWIFT : public RGWPutObj_ObjStore {
string lo_etag;
public:
RGWPutObj_ObjStore_SWIFT() {}
~RGWPutObj_ObjStore_SWIFT() {}
Expand Down

0 comments on commit bc60ba3

Please sign in to comment.