From: Casey Bodley Date: Fri, 28 Feb 2020 17:49:58 +0000 (-0500) Subject: rgw: bucket_list_ordered loops until it gets a unique candidate X-Git-Tag: v15.1.1~172^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bcc1bcf5e6f4c6a58b0c0bd7a5b290cec463b10d;p=ceph.git rgw: bucket_list_ordered loops until it gets a unique candidate when we detect a duplicate common prefix, we need to loop until we get the next unique candidate. we must add a new candidate for each shard, or we won't visit it again and would miss later entries Fixes: https://tracker.ceph.com/issues/44353 Signed-off-by: Casey Bodley --- diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 2e0a9f77c3c2..416a952b2332 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -8281,6 +8281,17 @@ int RGWRados::cls_bucket_list_ordered(RGWBucketInfo& bucket_info, inline bool at_end() const { return cursor == end; } + // add the next unique candidate, or return false if we reach the end + bool next_candidate(std::map& candidates, + size_t tracker_idx) { + while (!at_end()) { + if (candidates.emplace(entry_name(), tracker_idx).second) { + return true; + } + advance(); // skip duplicate common prefixes + } + return false; + } }; // ShardTracker // one tracker per shard requested (may not be all shards) @@ -8305,14 +8316,10 @@ int RGWRados::cls_bucket_list_ordered(RGWBucketInfo& bucket_info, map candidates; size_t tracker_idx = 0; for (auto& t : results_trackers) { - if (!t.at_end()) { - // it's important that the values in the map refer to the index - // into the results_trackers vector, which may not be the same - // as the shard number (i.e., when not all shards are requested) - if (!candidates.emplace(t.entry_name(), tracker_idx).second) { - t.advance(); // skip duplicate common prefixes - } - } + // it's important that the values in the map refer to the index + // into the results_trackers vector, which may not be the same + // as the shard number (i.e., when not all shards are requested) + t.next_candidate(candidates, tracker_idx); ++tracker_idx; } @@ -8368,10 +8375,9 @@ int RGWRados::cls_bucket_list_ordered(RGWBucketInfo& bucket_info, // refresh the candidates map candidates.erase(candidates.begin()); - if (! tracker.advance().at_end()) { - if (!candidates.emplace(tracker.entry_name(), tracker_idx).second) { - tracker.advance(); // skip duplicate common prefixes - } + tracker.advance(); + if (tracker.next_candidate(candidates, tracker_idx)) { + // we got a candidate, so we're not at the end yet } else if (tracker.is_truncated()) { // once we exhaust one shard that is truncated, we need to stop, // as we cannot be certain that one of the next entries needs to