| 280 | } |
| 281 | |
| 282 | void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, |
| 283 | bool (*func)(void*, int, FileMetaData*)) { |
| 284 | const Comparator* ucmp = vset_->icmp_.user_comparator(); |
| 285 | |
| 286 | // Search level-0 in order from newest to oldest. |
| 287 | std::vector<FileMetaData*> tmp; |
| 288 | tmp.reserve(files_[0].size()); |
| 289 | for (uint32_t i = 0; i < files_[0].size(); i++) { |
| 290 | FileMetaData* f = files_[0][i]; |
| 291 | if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && |
| 292 | ucmp->Compare(user_key, f->largest.user_key()) <= 0) { |
| 293 | tmp.push_back(f); |
| 294 | } |
| 295 | } |
| 296 | if (!tmp.empty()) { |
| 297 | std::sort(tmp.begin(), tmp.end(), NewestFirst); |
| 298 | for (uint32_t i = 0; i < tmp.size(); i++) { |
| 299 | if (!(*func)(arg, 0, tmp[i])) { |
| 300 | return; |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | // Search other levels. |
| 306 | for (int level = 1; level < config::kNumLevels; level++) { |
| 307 | size_t num_files = files_[level].size(); |
| 308 | if (num_files == 0) continue; |
| 309 | |
| 310 | // Binary search to find earliest index whose largest key >= internal_key. |
| 311 | uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); |
| 312 | if (index < num_files) { |
| 313 | FileMetaData* f = files_[level][index]; |
| 314 | if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { |
| 315 | // All of "f" is past any data for user_key |
| 316 | } else { |
| 317 | if (!(*func)(arg, level, f)) { |
| 318 | return; |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | Status Version::Get(const ReadOptions& options, const LookupKey& k, |
| 326 | std::string* value, GetStats* stats) { |