| 551 | } |
| 552 | |
| 553 | bool redisDbPersistentDataSnapshot::iterate_threadsafe_core(std::function<bool(const char*, robj_roptr o)> &fn, bool fKeyOnly, bool fCacheOnly, bool fFirst) const |
| 554 | { |
| 555 | // Take the size so we can ensure we visited every element exactly once |
| 556 | // use volatile to ensure it's not checked too late. This makes it more |
| 557 | // likely we'll detect races (but it won't gurantee it) |
| 558 | aeAcquireLock(); |
| 559 | dict *dictTombstone; |
| 560 | __atomic_load(&m_pdictTombstone, &dictTombstone, __ATOMIC_ACQUIRE); |
| 561 | volatile ssize_t celem = (ssize_t)size(); |
| 562 | aeReleaseLock(); |
| 563 | |
| 564 | dictEntry *de = nullptr; |
| 565 | bool fResult = true; |
| 566 | |
| 567 | dictIterator *di = dictGetSafeIterator(m_pdict); |
| 568 | while(fResult && ((de = dictNext(di)) != nullptr)) |
| 569 | { |
| 570 | --celem; |
| 571 | robj *o = (robj*)dictGetVal(de); |
| 572 | if (!fn((const char*)dictGetKey(de), o)) |
| 573 | fResult = false; |
| 574 | } |
| 575 | dictReleaseIterator(di); |
| 576 | |
| 577 | |
| 578 | if (m_spstorage != nullptr && !fCacheOnly) |
| 579 | { |
| 580 | bool fSawAll = fResult && m_spstorage->enumerate([&](const char *key, size_t cchKey, const void *data, size_t cbData){ |
| 581 | sds sdsKey = sdsnewlen(key, cchKey); |
| 582 | dictEntry *de = dictFind(m_pdict, sdsKey); |
| 583 | bool fContinue = true; |
| 584 | if (de == nullptr) |
| 585 | { |
| 586 | robj *o = nullptr; |
| 587 | if (!fKeyOnly) |
| 588 | { |
| 589 | size_t offset = 0; |
| 590 | std::unique_ptr<expireEntry> spexpire = deserializeExpire((const char*)data, cbData, &offset); |
| 591 | o = deserializeStoredObject(reinterpret_cast<const char*>(data)+offset, cbData-offset); |
| 592 | o->SetFExpires(spexpire != nullptr); |
| 593 | if (spexpire != nullptr) { |
| 594 | o->expire = std::move(*spexpire); |
| 595 | } |
| 596 | } |
| 597 | fContinue = fn(sdsKey, o); |
| 598 | if (o != nullptr) |
| 599 | decrRefCount(o); |
| 600 | } |
| 601 | |
| 602 | sdsfree(sdsKey); |
| 603 | return fContinue; |
| 604 | }); |
| 605 | return fSawAll; |
| 606 | } |
| 607 | |
| 608 | const redisDbPersistentDataSnapshot *psnapshot; |
| 609 | __atomic_load(&m_pdbSnapshot, &psnapshot, __ATOMIC_ACQUIRE); |
| 610 | if (fResult && psnapshot != nullptr) |
nothing calls this directly
no test coverage detected