| 166 | } |
| 167 | |
| 168 | CachePin CacheShard::findOrCreate( |
| 169 | RawFileCacheKey key, |
| 170 | uint64_t size, |
| 171 | folly::SemiFuture<bool>* wait, |
| 172 | bool cacheable) { |
| 173 | AsyncDataCacheEntry* entryToInit = nullptr; |
| 174 | { |
| 175 | std::lock_guard<std::mutex> l(mutex_); |
| 176 | ++eventCounter_; |
| 177 | auto it = entryMap_.find(key); |
| 178 | if (it != entryMap_.end()) { |
| 179 | auto* found = it->second; |
| 180 | if (found->isExclusive()) { |
| 181 | ++numWaitExclusive_; |
| 182 | if (wait == nullptr) { |
| 183 | return CachePin(); |
| 184 | } |
| 185 | *wait = found->getFuture(); |
| 186 | return CachePin(); |
| 187 | } |
| 188 | if (found->size() >= size) { |
| 189 | found->touch(); |
| 190 | // The entry is in a readable state. Add a pin. |
| 191 | if (found->isPrefetch()) { |
| 192 | found->isFirstUse_ = true; |
| 193 | found->setPrefetch(false); |
| 194 | } else { |
| 195 | ++numHit_; |
| 196 | hitBytes_ += found->size(); |
| 197 | } |
| 198 | ++found->numPins_; |
| 199 | CachePin pin; |
| 200 | pin.setEntry(found); |
| 201 | return pin; |
| 202 | } |
| 203 | |
| 204 | // TODO: add stats to report or send alert in production. |
| 205 | |
| 206 | // This can happen if different load quanta apply to access via different |
| 207 | // connectors. This is not an error but still worth logging. |
| 208 | BOLT_CACHE_LOG_EVERY_MS(WARNING, 1'000) |
| 209 | << "Requested larger entry. Found size " << found->size() |
| 210 | << " requested size " << size; |
| 211 | // The old entry is superseded. Possible readers of the old entry still |
| 212 | // retain a valid read pin. |
| 213 | found->key_.fileNum.clear(); |
| 214 | } |
| 215 | |
| 216 | auto newEntry = getFreeEntry(); |
| 217 | // Initialize the members that must be set inside 'mutex_'. |
| 218 | newEntry->numPins_ = AsyncDataCacheEntry::kExclusive; |
| 219 | newEntry->promise_ = nullptr; |
| 220 | entryToInit = newEntry.get(); |
| 221 | entryMap_[key] = newEntry.get(); |
| 222 | if (emptySlots_.empty()) { |
| 223 | entries_.push_back(std::move(newEntry)); |
| 224 | } else { |
| 225 | const auto index = emptySlots_.back(); |