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