| 1350 | } |
| 1351 | |
| 1352 | void BlockCache::readEntry(RegionDescriptor& regionDesc, |
| 1353 | LookupData& ld, |
| 1354 | RelAddress addrEnd, |
| 1355 | uint32_t approxSize, |
| 1356 | std::optional<HashedKey> expected) { |
| 1357 | // Because region opened for read, nobody will reclaim it or modify. Safe |
| 1358 | // without locks. |
| 1359 | |
| 1360 | // The item layout is as thus |
| 1361 | // | --- value --- | --- empty --- | --- header --- | |
| 1362 | // The size itself is determined by serializedSize(), so |
| 1363 | // we will try to read exactly that size or just slightly over. |
| 1364 | |
| 1365 | // Because we either use a predefined read buffer size, or align the size |
| 1366 | // up by kMinAllocAlignSize, our size might be bigger than the actual item |
| 1367 | // size. So we need to ensure we're not reading past the region's beginning. |
| 1368 | approxSize = std::min(approxSize, addrEnd.offset()); |
| 1369 | |
| 1370 | XDCHECK_EQ(approxSize % allocAlignSize_, 0ULL) << fmt::format( |
| 1371 | " alignSize={}, approxSize={}", allocAlignSize_, approxSize); |
| 1372 | |
| 1373 | // Because we are going to look for EntryDesc in the buffer read, the buffer |
| 1374 | // must be atleast as big as EntryDesc aligned to next 2 power |
| 1375 | XDCHECK_GE(approxSize, folly::nextPowTwo(sizeof(EntryDesc))); |
| 1376 | |
| 1377 | auto buffer = |
| 1378 | regionManager_.read(regionDesc, addrEnd.sub(approxSize), approxSize); |
| 1379 | if (buffer.isNull()) { |
| 1380 | ld.status_ = Status::DeviceError; |
| 1381 | return; |
| 1382 | } |
| 1383 | |
| 1384 | auto entryEnd = buffer.data() + buffer.size(); |
| 1385 | auto desc = *reinterpret_cast<EntryDesc*>(entryEnd - sizeof(EntryDesc)); |
| 1386 | if (desc.csSelf != desc.computeChecksum()) { |
| 1387 | lookupEntryHeaderChecksumErrorCount_.inc(); |
| 1388 | XLOG_N_PER_MS(ERR, 10, 10'000) << folly::sformat( |
| 1389 | "Header checksum mismatch in readEntry() at Region: {}, Expected: {}, " |
| 1390 | "Actual: {}, Offset-end: {}, Physical-offset-end: {}, Header size: {}, " |
| 1391 | "Header (hex): {}", |
| 1392 | addrEnd.rid().index(), desc.csSelf, desc.computeChecksum(), |
| 1393 | addrEnd.offset(), regionManager_.physicalOffset(addrEnd), |
| 1394 | sizeof(EntryDesc), |
| 1395 | folly::hexlify( |
| 1396 | folly::ByteRange(entryEnd - sizeof(EntryDesc), entryEnd))); |
| 1397 | ld.status_ = Status::ChecksumError; |
| 1398 | return; |
| 1399 | } |
| 1400 | |
| 1401 | folly::StringPiece key{reinterpret_cast<const char*>( |
| 1402 | entryEnd - sizeof(EntryDesc) - desc.keySize), |
| 1403 | desc.keySize}; |
| 1404 | if (expected.has_value() && |
| 1405 | HashedKey::precomputed(key, desc.keyHash) != *expected) { |
| 1406 | lookupFalsePositiveCount_.inc(); |
| 1407 | ld.status_ = Status::NotFound; |
| 1408 | return; |
| 1409 | } |
nothing calls this directly
no test coverage detected