| 325 | } |
| 326 | |
| 327 | ACTOR Future<RangeResult> SpecialKeySpace::getRangeAggregationActor(SpecialKeySpace* sks, |
| 328 | ReadYourWritesTransaction* ryw, |
| 329 | KeySelector begin, |
| 330 | KeySelector end, |
| 331 | GetRangeLimits limits, |
| 332 | Reverse reverse) { |
| 333 | // This function handles ranges which cover more than one keyrange and aggregates all results |
| 334 | // KeySelector, GetRangeLimits and reverse are all handled here |
| 335 | state RangeResult result; |
| 336 | state RangeResult pairs; |
| 337 | state RangeMap<Key, SpecialKeyRangeReadImpl*, KeyRangeRef>::iterator iter; |
| 338 | state int actualBeginOffset; |
| 339 | state int actualEndOffset; |
| 340 | state KeyRangeRef moduleBoundary; |
| 341 | // used to cache results from potential first async read |
| 342 | // the current implementation will read the whole range result to save in the cache |
| 343 | state KeyRangeMap<Optional<RangeResult>> cache(Optional<RangeResult>(), specialKeys.end); |
| 344 | |
| 345 | if (ryw->specialKeySpaceRelaxed()) { |
| 346 | moduleBoundary = sks->range; |
| 347 | } else { |
| 348 | auto beginIter = sks->getModules().rangeContaining(begin.getKey()); |
| 349 | if (beginIter->begin() <= end.getKey() && end.getKey() <= beginIter->end()) { |
| 350 | if (beginIter->value() == SpecialKeySpace::MODULE::UNKNOWN) |
| 351 | throw special_keys_no_module_found(); |
| 352 | else |
| 353 | moduleBoundary = beginIter->range(); |
| 354 | } else { |
| 355 | TraceEvent(SevInfo, "SpecialKeyCrossModuleRead") |
| 356 | .detail("Begin", begin) |
| 357 | .detail("End", end) |
| 358 | .detail("BoundaryBegin", beginIter->begin()) |
| 359 | .detail("BoundaryEnd", beginIter->end()); |
| 360 | throw special_keys_cross_module_read(); |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | wait(normalizeKeySelectorActor(sks, ryw, &begin, moduleBoundary, &actualBeginOffset, &result, &cache)); |
| 365 | wait(normalizeKeySelectorActor(sks, ryw, &end, moduleBoundary, &actualEndOffset, &result, &cache)); |
| 366 | // Handle all corner cases like what RYW does |
| 367 | // return if range inverted |
| 368 | if (actualBeginOffset >= actualEndOffset && begin.getKey() >= end.getKey()) { |
| 369 | CODE_PROBE(true, "inverted range"); |
| 370 | return RangeResultRef(false, false); |
| 371 | } |
| 372 | // If touches begin or end, return with readToBegin and readThroughEnd flags |
| 373 | if (begin.getKey() == moduleBoundary.end || end.getKey() == moduleBoundary.begin) { |
| 374 | CODE_PROBE(true, "query touches begin or end"); |
| 375 | return result; |
| 376 | } |
| 377 | state RangeMap<Key, SpecialKeyRangeReadImpl*, KeyRangeRef>::Ranges ranges = |
| 378 | sks->getReadImpls().intersectingRanges(KeyRangeRef(begin.getKey(), end.getKey())); |
| 379 | // TODO : workaround to write this two together to make the code compact |
| 380 | // The issue here is boost::iterator_range<> doest not provide rbegin(), rend() |
| 381 | iter = reverse ? ranges.end() : ranges.begin(); |
| 382 | if (reverse) { |
| 383 | while (iter != ranges.begin()) { |
| 384 | --iter; |
nothing calls this directly
no test coverage detected