in cachelib/datatype/Map-inl.h [318:388]
typename Map<K, V, C>::InsertOrReplaceResult Map<K, V, C>::insertImpl(
const EntryKey& key, const EntryValue& value) {
bool chainCloned = false;
auto accessible = hashtable_.viewItemHandle()->isAccessible();
// We try to expand hash table if it's full, if we can't do it
// we have to abort this insert because we may not be albe to insert
if (hashtable_->overLimit()) {
const auto res = expandHashTable();
if (!res) {
throw std::bad_alloc();
}
chainCloned = true;
}
// If wasted space is more than threshold, trigger compaction
if (bufferManager_.wastedBytesPct() > kWastedBytesPctThreshold) {
compact();
}
const uint32_t valueSize = util::getValueSize(value);
const uint32_t keySize = sizeof(EntryKey);
auto addr = bufferManager_.allocate(keySize + valueSize);
if (!addr) {
// Clone the buffers (chained items), if we have not already done that in
// this insert, so that if a user holds an old handle to the Map, that
// handle will still allow the user to access the old Map.
if (!chainCloned) {
auto newHashTable = detail::copyHashTable<K, C>(*cache_, hashtable_,
hashtable_->capacity());
if (!newHashTable) {
throw std::bad_alloc();
}
auto newBufferManager =
bufferManager_.clone(newHashTable.viewItemHandle());
if (newBufferManager.empty()) {
throw std::bad_alloc();
}
hashtable_ = std::move(newHashTable);
bufferManager_ = BufferManager(*cache_, hashtable_.viewItemHandle());
chainCloned = true;
}
if (bufferManager_.expand(keySize + valueSize)) {
addr = bufferManager_.allocate(keySize + valueSize);
}
}
if (chainCloned && accessible) {
cache_->insertOrReplace(hashtable_.viewItemHandle());
}
if (!addr) {
throw std::bad_alloc();
}
auto* kv = bufferManager_.template get<EntryKeyValue>(addr);
std::memcpy(&kv->key, &key, keySize);
std::memcpy(&kv->value, &value, valueSize);
detail::BufferAddr oldAddr;
try {
oldAddr = hashtable_->insertOrReplace(key, addr);
} catch (const std::bad_alloc& e) {
bufferManager_.remove(addr);
throw;
}
if (oldAddr) {
bufferManager_.remove(oldAddr);
return kReplaced;
}
return kInserted;
}