| 502 | } |
| 503 | |
| 504 | std::pair<Status, std::string> BlockCache::getRandomAlloc(Buffer& value) { |
| 505 | // Get rendom region and offset within the region |
| 506 | auto rid = regionManager_.getRandomRegion(); |
| 507 | auto& region = regionManager_.getRegion(rid); |
| 508 | auto randOffset = folly::Random::rand32(0, regionSize_); |
| 509 | auto offset = region.getLastEntryEndOffset(); |
| 510 | if (randOffset >= offset) { |
| 511 | return std::make_pair(Status::NotFound, ""); |
| 512 | } |
| 513 | |
| 514 | const auto seqNumber = regionManager_.getSeqNumber(); |
| 515 | RegionDescriptor rdesc = regionManager_.openForRead(rid, seqNumber); |
| 516 | if (rdesc.status() != OpenStatus::Ready) { |
| 517 | return std::make_pair(Status::NotFound, ""); |
| 518 | } |
| 519 | |
| 520 | auto buffer = regionManager_.read(rdesc, RelAddress{rid, 0}, offset); |
| 521 | // The region had been read out to Buffer, so can be closed here |
| 522 | regionManager_.close(std::move(rdesc)); |
| 523 | if (buffer.size() != offset) { |
| 524 | return std::make_pair(Status::NotFound, ""); |
| 525 | } |
| 526 | |
| 527 | // Iterate the entries backward until we find the entry |
| 528 | // where the randOffset falls into |
| 529 | while (offset > 0) { |
| 530 | RelAddress addrEnd{rid, offset}; |
| 531 | auto entryEnd = buffer.data() + offset; |
| 532 | auto desc = |
| 533 | *reinterpret_cast<const EntryDesc*>(entryEnd - sizeof(EntryDesc)); |
| 534 | if (desc.csSelf != desc.computeChecksum()) { |
| 535 | XLOGF(ERR, |
| 536 | "Item header checksum mismatch in getRandomAlloc(). Region {} is " |
| 537 | "likely corrupted. Expected: {}, Actual: {}, Offset-end: {}, " |
| 538 | "Physical-offset-end: {}, Header size: {}, Header (hex): {}", |
| 539 | rid.index(), |
| 540 | desc.csSelf, |
| 541 | desc.computeChecksum(), |
| 542 | addrEnd.offset(), |
| 543 | regionManager_.physicalOffset(addrEnd), |
| 544 | sizeof(EntryDesc), |
| 545 | folly::hexlify( |
| 546 | folly::ByteRange(entryEnd - sizeof(EntryDesc), entryEnd))); |
| 547 | break; |
| 548 | } |
| 549 | |
| 550 | const auto entrySize = serializedSize(desc.keySize, desc.valueSize); |
| 551 | |
| 552 | XDCHECK_GE(offset, entrySize); |
| 553 | offset -= entrySize; // start of this entry |
| 554 | if (randOffset < offset) { |
| 555 | continue; |
| 556 | } |
| 557 | |
| 558 | BufferView valueView{desc.valueSize, entryEnd - entrySize}; |
| 559 | if (checksumData_ && desc.cs != checksum(valueView)) { |
| 560 | XLOGF(ERR, |
| 561 | "Item value checksum mismatch in getRandomAlloc(). Region {} is " |