Status BigHash::remove()

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;
}