Ensure iterating the keyspace still works during background save

Former-commit-id: 23d7a8a293f253262801bc6ce88ad85e4e38f59a
This commit is contained in:
John Sully 2019-11-19 15:47:06 -05:00
parent a60925c949
commit 80f9b812ca
2 changed files with 58 additions and 1 deletions

View File

@ -646,6 +646,61 @@ bool redisDbPersistentData::iterate(std::function<bool(const char*, robj*)> fn)
}
}
dictReleaseIterator(di);
if (m_pdbSnapshot != nullptr)
{
fResult = m_pdbSnapshot->iterate([&](const char *key){
// Before passing off to the user we need to make sure it's not already in the
// the current set, and not deleted
dictEntry *deCurrent = dictFind(m_pdict, key);
if (deCurrent != nullptr)
return true;
dictEntry *deTombstone = dictFind(m_pdictTombstone, key);
if (deTombstone != nullptr)
return true;
// Alright it's a key in the use keyspace, lets ensure it and then pass it off
ensure(key);
deCurrent = dictFind(m_pdict, key);
return fn(key, (robj*)dictGetVal(deCurrent));
});
}
return fResult;
}
bool redisDbPersistentData::iterate(std::function<bool(const char*)> fn)
{
dictIterator *di = dictGetSafeIterator(m_pdict);
dictEntry *de = nullptr;
bool fResult = true;
while((de = dictNext(di)) != nullptr)
{
if (!fn((const char*)dictGetKey(de)))
{
fResult = false;
break;
}
}
dictReleaseIterator(di);
if (m_pdbSnapshot != nullptr)
{
fResult = m_pdbSnapshot->iterate([&](const char *key){
// Before passing off to the user we need to make sure it's not already in the
// the current set, and not deleted
dictEntry *deCurrent = dictFind(m_pdict, key);
if (deCurrent != nullptr)
return true;
dictEntry *deTombstone = dictFind(m_pdictTombstone, key);
if (deTombstone != nullptr)
return true;
// Alright it's a key in the use keyspace
return fn(key);
});
}
return fResult;
}
@ -656,7 +711,7 @@ void keysCommand(client *c) {
void *replylen = addReplyDeferredLen(c);
allkeys = (pattern[0] == '*' && pattern[1] == '\0');
c->db->iterate([&](const char *key, robj *)->bool {
c->db->iterate([&](const char *key)->bool {
robj *keyobj;
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {

View File

@ -1193,7 +1193,9 @@ public:
int removeSubkeyExpire(robj *key, robj *subkey);
void clear(void(callback)(void*));
void emptyDbAsync();
// Note: If you do not need the obj then use the objless iterator version. It's faster
bool iterate(std::function<bool(const char*, robj*)> fn);
bool iterate(std::function<bool(const char*)> fn);
void setExpire(robj *key, robj *subkey, long long when);
void setExpire(expireEntry &&e);
expireEntry *getExpire(robj_roptr key);