From: Radoslaw Zarzynski Date: Mon, 28 Aug 2017 19:54:56 +0000 (+0200) Subject: rgw: add basic support for Swift's reversed account listings. X-Git-Tag: v12.2.2~149^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8582664267b2e72a836e27df859910481371dee0;p=ceph.git rgw: add basic support for Swift's reversed account listings. Fixes: http://tracker.ceph.com/issues/21148 Signed-off-by: Radoslaw Zarzynski (cherry picked from commit 870f54806b7c1f570d2e82d3d2aa308b2178c6f0) --- diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 96f7cb7e505..41101923042 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -38,6 +38,7 @@ int RGWListBuckets_ObjStore_SWIFT::get_params() prefix = s->info.args.get("prefix"); marker = s->info.args.get("marker"); end_marker = s->info.args.get("end_marker"); + wants_reversed = s->info.args.exists("reverse"); string limit_str = s->info.args.get("limit"); if (!limit_str.empty()) { @@ -170,6 +171,17 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_begin(bool has_buckets) } } +void RGWListBuckets_ObjStore_SWIFT::handle_listing_chunk(RGWUserBuckets& buckets) +{ + if (wants_reversed) { + /* Just store in the reversal buffer. Its content will be handled later, + * in send_response_end(). */ + reverse_buffer.emplace(std::begin(reverse_buffer), std::move(buckets)); + } else { + return send_response_data(buckets); + } +} + void RGWListBuckets_ObjStore_SWIFT::send_response_data(RGWUserBuckets& buckets) { if (! sent_data) { @@ -184,23 +196,61 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_data(RGWUserBuckets& buckets) for (auto iter = m.lower_bound(prefix); iter != m.end() && boost::algorithm::starts_with(iter->first, prefix); ++iter) { - const RGWBucketEnt& obj = iter->second; + dump_bucket_entry(iter->second); + } +} - s->formatter->open_object_section("container"); - s->formatter->dump_string("name", obj.bucket.name); - if (need_stats) { - s->formatter->dump_int("count", obj.count); - s->formatter->dump_int("bytes", obj.size); - } - s->formatter->close_section(); - if (! s->cct->_conf->rgw_swift_enforce_content_length) { - rgw_flush_formatter(s, s->formatter); - } +void RGWListBuckets_ObjStore_SWIFT::dump_bucket_entry(const RGWBucketEnt& obj) +{ + s->formatter->open_object_section("container"); + s->formatter->dump_string("name", obj.bucket.name); + + if (need_stats) { + s->formatter->dump_int("count", obj.count); + s->formatter->dump_int("bytes", obj.size); + } + + s->formatter->close_section(); + + if (! s->cct->_conf->rgw_swift_enforce_content_length) { + rgw_flush_formatter(s, s->formatter); + } +} + +void RGWListBuckets_ObjStore_SWIFT::send_response_data_reversed(RGWUserBuckets& buckets) +{ + if (! sent_data) { + return; + } + + /* Take care of the prefix parameter of Swift API. There is no business + * in applying the filter earlier as we really need to go through all + * entries regardless of it (the headers like X-Account-Container-Count + * aren't affected by specifying prefix). */ + std::map& m = buckets.get_buckets(); + + auto iter = m.rbegin(); + for (/* initialized above */; + iter != m.rend() && !boost::algorithm::starts_with(iter->first, prefix); + ++iter) { + /* NOP */; + } + + for (/* iter carried */; + iter != m.rend() && boost::algorithm::starts_with(iter->first, prefix); + ++iter) { + dump_bucket_entry(iter->second); } } void RGWListBuckets_ObjStore_SWIFT::send_response_end() { + if (wants_reversed) { + for (auto& buckets : reverse_buffer) { + send_response_data_reversed(buckets); + } + } + if (sent_data) { s->formatter->close_section(); } @@ -216,7 +266,7 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_end() user_quota, static_cast(*s->user_acl)); dump_errno(s); - end_header(s, NULL, NULL, s->formatter->get_len(), true); + end_header(s, nullptr, nullptr, s->formatter->get_len(), true); } if (sent_data || s->cct->_conf->rgw_swift_enforce_content_length) { diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 296b83acde4..6cdaef487d9 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -37,18 +37,27 @@ public: class RGWListBuckets_ObjStore_SWIFT : public RGWListBuckets_ObjStore { bool need_stats; + bool wants_reversed; std::string prefix; + std::vector reverse_buffer; uint64_t get_default_max() const override { return 0; } + public: - RGWListBuckets_ObjStore_SWIFT() : need_stats(true) {} + RGWListBuckets_ObjStore_SWIFT() + : need_stats(true), + wants_reversed(false) { + } ~RGWListBuckets_ObjStore_SWIFT() override {} int get_params() override; + void handle_listing_chunk(RGWUserBuckets& buckets) override; void send_response_begin(bool has_buckets) override; void send_response_data(RGWUserBuckets& buckets) override; + void send_response_data_reversed(RGWUserBuckets& buckets); + void dump_bucket_entry(const RGWBucketEnt& obj); void send_response_end() override; bool should_get_stats() override { return need_stats; }