Ensure iterating the keyspace still works during background save
Former-commit-id: 23d7a8a293f253262801bc6ce88ad85e4e38f59a
This commit is contained in:
parent
a60925c949
commit
80f9b812ca
57
src/db.cpp
57
src/db.cpp
@ -646,6 +646,61 @@ bool redisDbPersistentData::iterate(std::function<bool(const char*, robj*)> fn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
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;
|
return fResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,7 +711,7 @@ void keysCommand(client *c) {
|
|||||||
void *replylen = addReplyDeferredLen(c);
|
void *replylen = addReplyDeferredLen(c);
|
||||||
|
|
||||||
allkeys = (pattern[0] == '*' && pattern[1] == '\0');
|
allkeys = (pattern[0] == '*' && pattern[1] == '\0');
|
||||||
c->db->iterate([&](const char *key, robj *)->bool {
|
c->db->iterate([&](const char *key)->bool {
|
||||||
robj *keyobj;
|
robj *keyobj;
|
||||||
|
|
||||||
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
||||||
|
@ -1193,7 +1193,9 @@ public:
|
|||||||
int removeSubkeyExpire(robj *key, robj *subkey);
|
int removeSubkeyExpire(robj *key, robj *subkey);
|
||||||
void clear(void(callback)(void*));
|
void clear(void(callback)(void*));
|
||||||
void emptyDbAsync();
|
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*, robj*)> fn);
|
||||||
|
bool iterate(std::function<bool(const char*)> fn);
|
||||||
void setExpire(robj *key, robj *subkey, long long when);
|
void setExpire(robj *key, robj *subkey, long long when);
|
||||||
void setExpire(expireEntry &&e);
|
void setExpire(expireEntry &&e);
|
||||||
expireEntry *getExpire(robj_roptr key);
|
expireEntry *getExpire(robj_roptr key);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user