// add the next unique candidate, or return false if we reach the end
auto next_candidate = [] (CephContext *cct, ShardTracker& t,
- std::map<std::string, size_t>& candidates,
+ std::multimap<std::string, size_t>& candidates,
size_t tracker_idx) {
- while (!t.at_end()) {
- if (candidates.emplace(t.entry_name(), tracker_idx).second) {
- return;
- }
- t.advance(); // skip duplicate common prefixes
+ if (!t.at_end()) {
+ candidates.emplace(t.entry_name(), tracker_idx);
}
+ return;
};
// one tracker per shard requested (may not be all shards)
// (key=candidate, value=index into results_trackers); as we consume
// entries from shards, we replace them with the next entries in the
// shards until we run out
- std::map<std::string, size_t> candidates;
+ std::multimap<std::string, size_t> candidates;
size_t tracker_idx = 0;
+ std::vector<size_t> vidx;
+ vidx.reserve(shard_list_results.size());
for (auto& t : results_trackers) {
// it's important that the values in the map refer to the index
// into the results_trackers vector, which may not be the same
}
// refresh the candidates map
- candidates.erase(candidates.begin());
- tracker.advance();
-
- next_candidate(cct, tracker, candidates, tracker_idx);
-
- if (tracker.at_end() && tracker.is_truncated()) {
+ vidx.clear();
+ bool need_to_stop = false;
+ auto range = candidates.equal_range(name);
+ for (auto i = range.first; i != range.second; ++i) {
+ vidx.push_back(i->second);
+ }
+ candidates.erase(range.first, range.second);
+ for (auto idx : vidx) {
+ auto& tracker_match = results_trackers.at(idx);
+ tracker_match.advance();
+ next_candidate(cct, tracker_match, candidates, idx);
+ if (tracker_match.at_end() && tracker_match.is_truncated()) {
+ need_to_stop = true;
+ break;
+ }
+ }
+ if (need_to_stop) {
// 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
// come from that shard; S3 and swift protocols allow returning
ldpp_dout(dpp, 10) << __PRETTY_FUNCTION__ <<
": stopped accumulating results at count=" << count <<
", dirent=\"" << dirent.key <<
- "\", because its shard is untruncated and exhaused" << dendl;
+ "\", because its shard is truncated and exhausted" << dendl;
break;
}
} // while we haven't provided requested # of result entries