To retrieve the 64bit key hash from the given address. This function will not (and cannot) check if index changed in between this function call for whatever reasons. It's caller's responsibility to make sure the index is not changed and no race condition happens.
| 799 | // the index is not changed and no race condition happens. |
| 800 | // |
| 801 | std::optional<uint64_t> BlockCache::onKeyHashRetrievalFromLocation( |
| 802 | uint32_t address) { |
| 803 | auto addrEnd = decodeRelAddress(address); |
| 804 | // It won't care about seq number here (giving it as std::nullopt). It's |
| 805 | // caller's responsibility to check about the race condition for the index |
| 806 | // change. |
| 807 | auto desc = regionManager_.openForRead(addrEnd.rid(), std::nullopt); |
| 808 | |
| 809 | if (desc.status() != OpenStatus::Ready) { |
| 810 | // In rare cases, Region can return 'Retry' when it's being released after |
| 811 | // the reclaim. Checking the index again will resolve it since index should |
| 812 | // have been updated with the new location |
| 813 | return std::nullopt; |
| 814 | } |
| 815 | |
| 816 | EntryDesc entryDesc{}; |
| 817 | uint8_t* entryEnd{nullptr}; |
| 818 | { |
| 819 | SCOPE_EXIT { regionManager_.close(std::move(desc)); }; |
| 820 | // We only need to read EntryDesc + key. (Key is just for integrity check). |
| 821 | // Since we don't know the key size before reading EntryDesc, let's just |
| 822 | // read enough buffer to cover most keys. If it's not enough, we can read |
| 823 | // more for the key, but that'll be rare cases. |
| 824 | auto readSize = std::min(512u, addrEnd.offset()); |
| 825 | |
| 826 | auto buffer = regionManager_.read(desc, addrEnd.sub(readSize), readSize); |
| 827 | if (buffer.isNull()) { |
| 828 | return std::nullopt; |
| 829 | } |
| 830 | |
| 831 | entryEnd = buffer.data() + buffer.size(); |
| 832 | entryDesc = *reinterpret_cast<EntryDesc*>(entryEnd - sizeof(EntryDesc)); |
| 833 | // check if we have enough buffer read to cover the key |
| 834 | if (buffer.size() < sizeof(EntryDesc) + entryDesc.keySize) { |
| 835 | // re-read to cover the key. This should be just for the larger keys |
| 836 | readSize = sizeof(EntryDesc) + entryDesc.keySize; |
| 837 | if (readSize > addrEnd.offset()) { |
| 838 | // something's wrong with the key size. It's not within the region |
| 839 | // boundary |
| 840 | XLOGF( |
| 841 | ERR, |
| 842 | "Key size {} in item header is crossing the region boundary in " |
| 843 | "onKeyHashRetrievalFromLocation(). Region {} is likely corrupted. " |
| 844 | "Offset-end: {}, Physical-offset-end: {}, Header size: {}, Header " |
| 845 | "(hex): {}", |
| 846 | entryDesc.keySize, addrEnd.rid().index(), addrEnd.offset(), |
| 847 | regionManager_.physicalOffset(addrEnd), sizeof(EntryDesc), |
| 848 | folly::hexlify( |
| 849 | folly::ByteRange(entryEnd - sizeof(EntryDesc), entryEnd))); |
| 850 | return std::nullopt; |
| 851 | } |
| 852 | buffer = regionManager_.read(desc, addrEnd.sub(readSize), readSize); |
| 853 | if (buffer.isNull()) { |
| 854 | return std::nullopt; |
| 855 | } |
| 856 | |
| 857 | // modify the address for these variables accordingly |
| 858 | entryEnd = buffer.data() + buffer.size(); |
nothing calls this directly
no test coverage detected