in cachelib/navy/block_cache/BlockCache.cpp [418:489]
BlockCache::ReinsertionRes BlockCache::reinsertOrRemoveItem(
HashedKey hk, BufferView value, uint32_t entrySize, RelAddress currAddr) {
auto removeItem = [this, hk, entrySize, currAddr] {
sizeDist_.removeSize(entrySize);
if (index_.removeIfMatch(hk.keyHash(), encodeRelAddress(currAddr))) {
return ReinsertionRes::kEvicted;
}
return ReinsertionRes::kRemoved;
};
const auto lr = index_.peek(hk.keyHash());
if (!lr.found() || decodeRelAddress(lr.address()) != currAddr) {
evictionLookupMissCounter_.inc();
sizeDist_.removeSize(entrySize);
return ReinsertionRes::kRemoved;
}
folly::StringPiece strKey{reinterpret_cast<const char*>(hk.key().data()),
hk.key().size()};
if (!reinsertionPolicy_ || !reinsertionPolicy_->shouldReinsert(strKey)) {
return removeItem();
}
// Priority of an re-inserted item is determined by its past accesses
// since the time it was last (re)inserted.
// TODO: T95784621 this should be made configurable by having the reinsertion
// policy return a priority rank for an item.
uint16_t priority =
numPriorities_ == 0
? kDefaultItemPriority
: std::min<uint16_t>(lr.currentHits(), numPriorities_ - 1);
uint32_t size = serializedSize(hk.key().size(), value.size());
auto [desc, slotSize, addr] = allocator_.allocate(size, priority);
switch (desc.status()) {
case OpenStatus::Ready:
break;
case OpenStatus::Error:
allocErrorCount_.inc();
reinsertionErrorCount_.inc();
break;
case OpenStatus::Retry:
reinsertionErrorCount_.inc();
return removeItem();
}
auto closeRegionGuard =
folly::makeGuard([this, desc = std::move(desc)]() mutable {
allocator_.close(std::move(desc));
});
// After allocation a region is opened for writing. Until we close it, the
// region would not be reclaimed and index never gets an invalid entry.
const auto status = writeEntry(addr, slotSize, hk, value);
if (status != Status::Ok) {
reinsertionErrorCount_.inc();
return removeItem();
}
const auto replaced =
index_.replaceIfMatch(hk.keyHash(),
encodeRelAddress(addr.add(slotSize)),
encodeRelAddress(currAddr));
if (!replaced) {
reinsertionErrorCount_.inc();
return removeItem();
}
reinsertionCount_.inc();
reinsertionBytes_.add(entrySize);
return ReinsertionRes::kReinserted;
}