std::unique_ptr NvmCache::createItemAsIOBuf()

in cachelib/allocator/nvmcache/NvmCache-inl.h [663:723]


std::unique_ptr<folly::IOBuf> NvmCache<C>::createItemAsIOBuf(
    folly::StringPiece key, const NvmItem& nvmItem) {
  const size_t numBufs = nvmItem.getNumBlobs();
  // parent item
  XDCHECK_GE(numBufs, 1u);
  const auto pBlob = nvmItem.getBlob(0);

  stats().numNvmAllocForItemDestructor.inc();
  std::unique_ptr<folly::IOBuf> head;
  try {
    // use the original alloc size to allocate, but make sure that the usable
    // size matches the pBlob's size
    auto size = Item::getRequiredSize(key, pBlob.origAllocSize);
    head = folly::IOBuf::create(size);
    head->append(size);
  } catch (const std::bad_alloc&) {
    stats().numNvmItemDestructorAllocErrors.inc();
    return nullptr;
  }
  auto item = new (head->writableData())
      Item(key, pBlob.origAllocSize, nvmItem.getCreationTime(),
           nvmItem.getExpiryTime());

  XDCHECK_LE(pBlob.origAllocSize, item->getSize());
  XDCHECK_LE(pBlob.origAllocSize, pBlob.data.size());
  ::memcpy(item->getMemory(), pBlob.data.data(), pBlob.origAllocSize);
  item->markNvmClean();
  item->markNvmEvicted();

  // if we have more, then we need to allocate them as chained items and add
  // them in the same order. To do that, we need to add them from the inverse
  // order
  if (numBufs > 1) {
    // chained items need to be added in reverse order to maintain the same
    // order as what we serialized.
    for (int i = numBufs - 1; i >= 1; i--) {
      auto cBlob = nvmItem.getBlob(i);
      XDCHECK_GT(cBlob.origAllocSize, 0u);
      XDCHECK_GT(cBlob.data.size(), 0u);
      stats().numNvmAllocForItemDestructor.inc();
      std::unique_ptr<folly::IOBuf> chained;
      try {
        auto size = ChainedItem::getRequiredSize(cBlob.origAllocSize);
        chained = folly::IOBuf::create(size);
        chained->append(size);
      } catch (const std::bad_alloc&) {
        stats().numNvmItemDestructorAllocErrors.inc();
        return nullptr;
      }
      auto chainedItem = new (chained->writableData()) ChainedItem(
          CompressedPtr(), cBlob.origAllocSize, util::getCurrentTimeSec());
      XDCHECK(chainedItem->isChainedItem());
      ::memcpy(chainedItem->getMemory(), cBlob.data.data(),
               cBlob.origAllocSize);
      head->appendChain(std::move(chained));
      item->markHasChainedItem();
      XDCHECK(item->hasChainedItem());
    }
  }
  return head;
}