diff --git a/src/db.cpp b/src/db.cpp index f5c8c68cc..bd48275a4 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -556,6 +556,16 @@ int getFlushCommandFlags(client *c, int *flags) { void flushdbCommand(client *c) { int flags; + if (c->argc == 2) + { + if (!strcasecmp(szFromObj(c->argv[1]), "cache")) + { + c->db->removeAllCachedValues(); + addReply(c,shared.ok); + return; + } + } + if (getFlushCommandFlags(c,&flags) == C_ERR) return; signalFlushedDb(c->db->id); g_pserver->dirty += emptyDb(c->db->id,flags,NULL); @@ -568,6 +578,17 @@ void flushdbCommand(client *c) { void flushallCommand(client *c) { int flags; + if (c->argc == 2) + { + if (!strcasecmp(szFromObj(c->argv[1]), "cache")) + { + for (int idb = 0; idb < cserver.dbnum; ++idb) + g_pserver->db[idb]->removeAllCachedValues(); + addReply(c,shared.ok); + return; + } + } + if (getFlushCommandFlags(c,&flags) == C_ERR) return; signalFlushedDb(-1); g_pserver->dirty += emptyDb(-1,flags,NULL); @@ -2219,4 +2240,17 @@ bool redisDbPersistentData::removeCachedValue(const char *key) void redisDbPersistentData::trackChanges() { m_fTrackingChanges++; +} + +void redisDbPersistentData::removeAllCachedValues() +{ + // First we have to flush the tracked changes + if (m_fTrackingChanges) + { + auto vec = processChanges(); + commitChanges(vec); + trackChanges(); + } + + dictEmpty(m_pdict, nullptr); } \ No newline at end of file diff --git a/src/server.h b/src/server.h index c5576b30b..44b18f317 100644 --- a/src/server.h +++ b/src/server.h @@ -1342,6 +1342,7 @@ public: bool FStorageProvider() { return m_spstorage != nullptr; } bool removeCachedValue(const char *key); + void removeAllCachedValues(); private: void ensure(const char *key); @@ -1468,6 +1469,7 @@ typedef struct redisDb : public redisDbPersistentDataSnapshot using redisDbPersistentData::createSnapshot; using redisDbPersistentData::endSnapshot; using redisDbPersistentData::consolidate_snapshot; + using redisDbPersistentData::removeAllCachedValues; public: expireset::setiter expireitr; diff --git a/tests/unit/flash.tcl b/tests/unit/flash.tcl index 47c8081cd..54940aa9d 100644 --- a/tests/unit/flash.tcl +++ b/tests/unit/flash.tcl @@ -1,15 +1,31 @@ start_server {tags {"flash"} overrides {"storage-provider flash ./rocks.db"}} { + test { FLASH - GET works after eviction } { + r set testkey foo + r flushall cache + assert_equal {foo} [r get testkey] + } + + test { DEL of nonexistant key returns 0 } { + assert_equal {0} [r del foobar] + } + + test { SET of existing but flushed key works } { + r set testkey foo + r flushall cache + r set testkey bar + assert_equal {bar} [r get testkey] + } + + r flushall foreach policy { allkeys-random allkeys-lru allkeys-lfu } { test "FLASH - is eviction working without data loss (successfully stored to flash)? (policy $policy)" { - # make sure to start with a blank instance - r flushall # Get the current memory limit and calculate a new limit. # Set limit to 100M. set used [s used_memory] - set limit [expr {$used+100000*1024}] + set limit [expr {$used+50000*1024}] r config set maxmemory $limit r config set maxmemory-policy $policy # Now add keys equivalent to 1024b until the limit is almost reached. @@ -38,7 +54,9 @@ start_server {tags {"flash"} overrides {"storage-provider flash ./rocks.db"}} { assert {$dbsize == $numkeys+10002} assert {[r get first] == {val}} assert {[r get last] == {val}} + r flushall } } + }