]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: bucket_list_ordered loops until it gets a unique candidate
authorCasey Bodley <cbodley@redhat.com>
Fri, 28 Feb 2020 17:49:58 +0000 (12:49 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 28 Feb 2020 18:02:54 +0000 (13:02 -0500)
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 <cbodley@redhat.com>
src/rgw/rgw_rados.cc

index 2e0a9f77c3c232a7259b74b319b0677f06e0585c..416a952b23326b93d78e974f04af9755a29f1d77 100644 (file)
@@ -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<std::string, size_t>& 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<string, size_t> 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