in cachelib/navy/bighash/BigHash.cpp [358:423]
Status BigHash::remove(HashedKey hk) {
const auto bid = getBucketId(hk);
removeCount_.inc();
uint32_t oldRemainingBytes = 0;
uint32_t newRemainingBytes = 0;
// we copy the items and trigger the destructorCb after bucket lock is
// released to avoid possible heavy operations or locks in the destrcutor.
Buffer valueCopy;
DestructorCallback cb = [&valueCopy](
BufferView, BufferView value, DestructorEvent) {
valueCopy = Buffer{value};
};
{
std::unique_lock<folly::SharedMutex> lock{getMutex(bid)};
if (bfReject(bid, hk.keyHash())) {
return Status::NotFound;
}
auto buffer = readBucket(bid);
if (buffer.isNull()) {
ioErrorCount_.inc();
return Status::DeviceError;
}
auto* bucket = reinterpret_cast<Bucket*>(buffer.data());
oldRemainingBytes = bucket->remainingBytes();
if (!bucket->remove(hk, cb)) {
bfFalsePositiveCount_.inc();
return Status::NotFound;
}
newRemainingBytes = bucket->remainingBytes();
// We compute bloom filter before writing the bucket because when encryption
// is enabled, we will "move" the bucket content into writeBucket().
if (bloomFilter_) {
bfRebuild(bid, bucket);
}
const auto res = writeBucket(bid, std::move(buffer));
if (!res) {
if (bloomFilter_) {
bloomFilter_->clear(bid.index());
}
ioErrorCount_.inc();
return Status::DeviceError;
}
}
if (!valueCopy.isNull()) {
destructorCb_(hk.key(), valueCopy.view(), DestructorEvent::Removed);
}
XDCHECK_LE(oldRemainingBytes, newRemainingBytes);
usedSizeBytes_.sub(newRemainingBytes - oldRemainingBytes);
itemCount_.dec();
// We do not bump logicalWrittenCount_ because logically a
// remove operation does not write, but for BigHash, it does
// incur physical writes.
physicalWrittenCount_.add(bucketSize_);
succRemoveCount_.inc();
return Status::Ok;
}