| 242 | } |
| 243 | |
| 244 | void RowSetTree::ForEachRowSetContainingKeys( |
| 245 | const vector<Slice>& encoded_keys, |
| 246 | const function<void(RowSet*, int)>& cb) const { |
| 247 | |
| 248 | DCHECK(std::is_sorted(encoded_keys.cbegin(), encoded_keys.cend(), |
| 249 | Slice::Comparator())); |
| 250 | // All rowsets with unknown bounds need to be checked. |
| 251 | for (const shared_ptr<RowSet> &rs : unbounded_rowsets_) { |
| 252 | for (int i = 0; i < encoded_keys.size(); i++) { |
| 253 | cb(rs.get(), i); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | // The interval tree batch query callback would naturally just give us back |
| 258 | // the matching Slices, but that won't allow us to easily tell the caller |
| 259 | // which specific operation _index_ matched the RowSet. So, we make a vector |
| 260 | // of QueryStructs to pair the Slice with its original index. |
| 261 | vector<QueryStruct> queries(encoded_keys.size()); |
| 262 | for (auto i = 0; i < encoded_keys.size(); ++i) { |
| 263 | queries[i] = {encoded_keys[i], i}; |
| 264 | } |
| 265 | |
| 266 | tree_->ForEachIntervalContainingPoints( |
| 267 | queries, |
| 268 | [&](const QueryStruct& qs, RowSetWithBounds* rs) { |
| 269 | cb(rs->rowset, qs.idx); |
| 270 | }); |
| 271 | } |
| 272 | |
| 273 | } // namespace tablet |
| 274 | } // namespace kudu |