| 336 | } |
| 337 | |
| 338 | void SparseMapIndex::persist( |
| 339 | std::optional<std::reference_wrapper<RecordWriter>> rw) const { |
| 340 | XDCHECK(rw.has_value()); |
| 341 | if (!rw) { |
| 342 | XLOG(ERR, |
| 343 | "Cannot persist Block Cache index: No RecordWriter is available."); |
| 344 | return; |
| 345 | } |
| 346 | |
| 347 | serialization::IndexBucket bucketMap; |
| 348 | auto prevPos = rw->get().getCurPos(); |
| 349 | uint64_t persisted = 0; |
| 350 | |
| 351 | for (uint32_t i = 0; i < numBucketMaps_; i++) { |
| 352 | *bucketMap.bucketId() = i; |
| 353 | // Convert index entries to thrift objects |
| 354 | for (const auto& [key, record] : bucketMaps_[i]) { |
| 355 | serialization::IndexEntry entry; |
| 356 | entry.key() = key; |
| 357 | entry.address() = record.address; |
| 358 | entry.sizeHint() = record.sizeHint; |
| 359 | entry.totalHits() = record.extra.totalHits; |
| 360 | entry.currentHits() = record.currentHits; |
| 361 | bucketMap.entries()->push_back(entry); |
| 362 | } |
| 363 | |
| 364 | try { |
| 365 | // Serialize bucket and this may throw exception when it's exceeding the |
| 366 | // meta data size limit |
| 367 | serializeProto(bucketMap, rw->get()); |
| 368 | persisted += bucketMap.entries()->size(); |
| 369 | } catch (const std::exception& e) { |
| 370 | // Log the error and more info on current index |
| 371 | XLOGF(ERR, |
| 372 | "Error persisting Block Cache Index: {}, persist() began at pos {} " |
| 373 | "and current pos {}, trying to add {} entries from bucketMap {}", |
| 374 | e.what(), prevPos, rw->get().getCurPos(), |
| 375 | bucketMap.entries()->size(), i); |
| 376 | auto memFootprint = computeMemFootprintRange(); |
| 377 | XLOGF(ERR, |
| 378 | "Current Block cache items count: {}, persisted {} items, index " |
| 379 | "size in memory {} " |
| 380 | "(max) - {} (min)", |
| 381 | computeSize(), |
| 382 | persisted, |
| 383 | memFootprint.maxUsedBytes, |
| 384 | memFootprint.minUsedBytes); |
| 385 | // rethrow to the caller |
| 386 | throw; |
| 387 | } |
| 388 | // Clear contents to reuse memory. |
| 389 | bucketMap.entries()->clear(); |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | void SparseMapIndex::recover( |
| 394 | std::optional<std::reference_wrapper<RecordReader>> rr) { |
nothing calls this directly
no test coverage detected