in cachelib/navy/block_cache/BlockCache.cpp [296:357]
uint32_t BlockCache::onRegionReclaim(RegionId rid, BufferView buffer) {
// Eviction callback guarantees are the following:
// - Every value inserted will get eviction callback at some point of
// time.
// - It is invoked only once per insertion.
//
// We do not guarantee time between remove and callback invocation. If a
// value v1 was replaced with v2 user will get callbacks for both v1 and
// v2 when they are evicted (in no particular order).
uint32_t evictionCount = 0; // item that was evicted during reclaim
auto& region = regionManager_.getRegion(rid);
auto offset = region.getLastEntryEndOffset();
while (offset > 0) {
auto entryEnd = buffer.data() + offset;
auto desc =
*reinterpret_cast<const EntryDesc*>(entryEnd - sizeof(EntryDesc));
if (desc.csSelf != desc.computeChecksum()) {
reclaimEntryHeaderChecksumErrorCount_.inc();
XLOGF(ERR,
"Item header checksum mismatch. Region {} is likely corrupted. "
"Expected:{}, Actual: {}. Aborting reclaim. Remaining items in the "
"region will not be cleaned up (destructor won't be invoked).",
rid.index(),
desc.csSelf,
desc.computeChecksum());
break;
}
const auto entrySize = serializedSize(desc.keySize, desc.valueSize);
HashedKey hk{
BufferView{desc.keySize, entryEnd - sizeof(EntryDesc) - desc.keySize}};
BufferView value{desc.valueSize, entryEnd - entrySize};
if (checksumData_ && desc.cs != checksum(value)) {
// We do not need to abort here since the EntryDesc checksum was good, so
// we can safely proceed to read the next entry.
reclaimValueChecksumErrorCount_.inc();
}
const auto reinsertionRes =
reinsertOrRemoveItem(hk, value, entrySize, RelAddress{rid, offset});
switch (reinsertionRes) {
case ReinsertionRes::kEvicted:
evictionCount++;
break;
case ReinsertionRes::kRemoved:
holeCount_.sub(1);
holeSizeTotal_.sub(decodeSizeHint(encodeSizeHint(entrySize)));
break;
case ReinsertionRes::kReinserted:
break;
}
if (destructorCb_ && reinsertionRes == ReinsertionRes::kEvicted) {
destructorCb_(hk.key(), value, DestructorEvent::Recycled);
}
XDCHECK_GE(offset, entrySize);
offset -= entrySize;
}
XDCHECK_GE(region.getNumItems(), evictionCount);
return evictionCount;
}