From 42b3e32c8d6c9ef71dcd662b5d8f59c32289ddbc Mon Sep 17 00:00:00 2001 From: John Sully Date: Mon, 3 Feb 2020 20:01:53 -0500 Subject: [PATCH 01/24] Bump version Former-commit-id: ac84153f61b213d42ad503ac38948f9740a5f923 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index db32931f1..c03690a8d 100644 --- a/src/version.h +++ b/src/version.h @@ -1,3 +1,3 @@ -#define KEYDB_REAL_VERSION "0.0.0" +#define KEYDB_REAL_VERSION "6.0.0" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config From fbf70741692d961fb16d36926a7056b6026295d2 Mon Sep 17 00:00:00 2001 From: John Sully Date: Mon, 17 Feb 2020 22:27:50 -0500 Subject: [PATCH 02/24] Bump version Former-commit-id: 7f84d6d6301303a3277910bf93e5d8dc900908c1 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index c03690a8d..d21c2cd91 100644 --- a/src/version.h +++ b/src/version.h @@ -1,3 +1,3 @@ -#define KEYDB_REAL_VERSION "6.0.0" +#define KEYDB_REAL_VERSION "6.0.1" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config From a711a040e4e5a5e18535d8806952d5a7a9edfa39 Mon Sep 17 00:00:00 2001 From: John Sully Date: Mon, 17 Feb 2020 23:29:03 -0500 Subject: [PATCH 03/24] C++14 build fix Former-commit-id: b45f50efa2fb56aa995ee6ceb6bd91380c28187c --- src/ae.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ae.cpp b/src/ae.cpp index 25898007e..00926d9f5 100644 --- a/src/ae.cpp +++ b/src/ae.cpp @@ -131,7 +131,7 @@ struct aeCommand aeCommandControl *pctl; }; #ifdef PIPE_BUF -static_assert(sizeof(aeCommand) <= PIPE_BUF); +static_assert(sizeof(aeCommand) <= PIPE_BUF, "aeCommand must be small enough to send atomically through a pipe"); #endif void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int ) From f45939f147f605e9e43358436674ff9c10d48835 Mon Sep 17 00:00:00 2001 From: John Sully Date: Mon, 17 Feb 2020 23:45:40 -0500 Subject: [PATCH 04/24] Change Redis to KeyDB Former-commit-id: ee5f026eea133ad851bfb3e8788a15ac798ca7e6 --- src/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index d35656290..f1791c107 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4952,7 +4952,7 @@ void daemonize(void) { } void version(void) { - printf("Redis server v=%s sha=%s:%d malloc=%s bits=%d build=%llx\n", + printf("KeyDB server v=%s sha=%s:%d malloc=%s bits=%d build=%llx\n", KEYDB_REAL_VERSION, redisGitSHA1(), atoi(redisGitDirty()) > 0, From b950b89326c2dc45ef0f9f6e616e584d0a95159e Mon Sep 17 00:00:00 2001 From: John Sully Date: Sat, 29 Feb 2020 00:04:24 -0500 Subject: [PATCH 05/24] Bump version Former-commit-id: e5776fd1a05b329c3113b94d26fba9e39816644f --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index d21c2cd91..10802fab8 100644 --- a/src/version.h +++ b/src/version.h @@ -1,3 +1,3 @@ -#define KEYDB_REAL_VERSION "6.0.1" +#define KEYDB_REAL_VERSION "6.0.2" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config From 366e00df797727373eba157f5e5239a75f5cdcd7 Mon Sep 17 00:00:00 2001 From: John Sully Date: Thu, 26 Mar 2020 01:18:21 -0400 Subject: [PATCH 06/24] bump version Former-commit-id: 8e855c4568fd555f6df9a5b00bab2e42248127e3 --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 7b9664059..8e588cfb3 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.2" +#define KEYDB_REAL_VERSION "6.0.3" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult @@ -25,4 +25,4 @@ enum VersionCompareResult compareVersion(struct SymVer *pver); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif From 8becc84c6111b8cbdca532a0e18dc7b6e33c43b9 Mon Sep 17 00:00:00 2001 From: John Sully Date: Thu, 26 Mar 2020 15:20:55 -0400 Subject: [PATCH 07/24] OS X Build break fix Former-commit-id: 98da479d9241c077d3c11787800075dea91e989e --- src/fastlock.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fastlock.cpp b/src/fastlock.cpp index 9c7577a16..627d15e93 100644 --- a/src/fastlock.cpp +++ b/src/fastlock.cpp @@ -27,6 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "fmacros.h" #include "fastlock.h" #include #include From 412e3a059fc8b405662fa869ee5545e826d8622e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 16 Apr 2020 02:56:49 +0000 Subject: [PATCH 08/24] updating version Former-commit-id: f994436486b2e8b4eb63f8ce29ab9c8595e1a694 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 8e588cfb3..8c077ebff 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.3" +#define KEYDB_REAL_VERSION "6.0.4" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 6b02c556e846a391f88467a1b8e6667ef4c521e2 Mon Sep 17 00:00:00 2001 From: John Sully Date: Wed, 22 Apr 2020 01:07:14 -0400 Subject: [PATCH 09/24] Bump version Former-commit-id: f527649f156147f29efb81a7a20057909fe43748 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 8c077ebff..dee7da0cc 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.4" +#define KEYDB_REAL_VERSION "6.0.5" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 83118f258436c12be91b9c2cf92633e09b49903a Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 28 Apr 2020 20:49:39 -0400 Subject: [PATCH 10/24] Bump version Former-commit-id: 8e12ff0cd9e50867b42b165af278a7dc91fc17e1 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index dee7da0cc..ea0861241 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.5" +#define KEYDB_REAL_VERSION "6.0.6" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 87b5eb649a3351a49c9da7237a98930987eaff99 Mon Sep 17 00:00:00 2001 From: John Sully Date: Fri, 8 May 2020 00:25:19 -0400 Subject: [PATCH 11/24] Bump version Former-commit-id: 88eeb1c13cdf21df274ea9c364f35c4de522d215 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index ea0861241..232fb2fcc 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.6" +#define KEYDB_REAL_VERSION "6.0.7" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 2857bed8bdf68143043baa73a7bbd3dec31523aa Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 24 May 2020 18:35:03 -0400 Subject: [PATCH 12/24] bump version Former-commit-id: 9353b3aac2ab65120f2ad5caa2f8272ae02df380 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 232fb2fcc..1390f3567 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.7" +#define KEYDB_REAL_VERSION "6.0.8" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 16f86db5e49b3625eb85db1e87433d3ed7c2b4d5 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 7 Jun 2020 16:41:59 -0400 Subject: [PATCH 13/24] Bump version Former-commit-id: 52a0556ba15b26d84ca9b5c804eb8fe438c9c888 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 1390f3567..4403f3d74 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.8" +#define KEYDB_REAL_VERSION "6.0.9" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 27f454bafc9e1ac454397fc4aaed4c330a385a98 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 7 Jun 2020 20:17:32 -0400 Subject: [PATCH 14/24] fix valgrind false error Former-commit-id: 887d8bdd110e04b30ffb215726e8aade39f0387a --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 81ccece77..b85500cfe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -425,7 +425,7 @@ noopt: $(MAKE) OPTIMIZATION="-O0" valgrind: - $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" + $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" CFLAGS="-DSANITIZE" CXXFLAGS="-DSANITIZE" helgrind: $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" CFLAGS="-D__ATOMIC_VAR_FORCE_SYNC_MACROS" From 725fa84a06ce5349aebda66f58778c2168185c74 Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 9 Jun 2020 18:57:36 -0400 Subject: [PATCH 15/24] keys command should look at the snapshots expire datastructure Former-commit-id: 70563afab48e607e127c07d637660d94d1eede6d --- src/db.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index d1b33be61..156784634 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -39,7 +39,7 @@ * C-level DB API *----------------------------------------------------------------------------*/ -int keyIsExpired(redisDb *db, robj *key); +int keyIsExpired(const redisDbPersistentDataSnapshot *db, robj *key); int expireIfNeeded(redisDb *db, robj *key, robj *o); void slotToKeyUpdateKeyCore(const char *key, size_t keylen, int add); @@ -840,7 +840,7 @@ void keysCommandCore(client *cIn, const redisDbPersistentDataSnapshot *db, sds p if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) { keyobj = createStringObject(key,sdslen(key)); - if (!keyIsExpired(c->db,keyobj)) { + if (!keyIsExpired(db,keyobj)) { addReplyBulk(c,keyobj); numkeys++; } @@ -1647,8 +1647,8 @@ void propagateSubkeyExpire(redisDb *db, int type, robj *key, robj *subkey) } /* Check if the key is expired. Note, this does not check subexpires */ -int keyIsExpired(redisDb *db, robj *key) { - expireEntry *pexpire = db->getExpire(key); +int keyIsExpired(const redisDbPersistentDataSnapshot *db, robj *key) { + const expireEntry *pexpire = db->getExpire(key); mstime_t now; if (pexpire == nullptr) return 0; /* No expire for this key */ From 324e8e01f20aa040ae9c8ce3264d3be8ad1e6466 Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 9 Jun 2020 19:58:42 -0400 Subject: [PATCH 16/24] COW pointer is not thread safe so we need a global expire lock Former-commit-id: ac12eef75301564d920e622a08e4f586486fd395 --- src/aof.cpp | 6 ++++-- src/cluster.cpp | 1 + src/db.cpp | 12 +++++++++++- src/debug.cpp | 1 + src/defrag.cpp | 1 + src/evict.cpp | 1 + src/expire.cpp | 4 ++++ src/lazyfree.cpp | 1 + src/module.cpp | 1 + src/object.cpp | 4 +++- src/rdb.cpp | 3 +++ src/server.cpp | 1 + src/server.h | 1 + src/snapshot.cpp | 15 +++++++++++++-- 14 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/aof.cpp b/src/aof.cpp index 0a15204d0..35402cd25 100644 --- a/src/aof.cpp +++ b/src/aof.cpp @@ -1432,8 +1432,6 @@ int rewriteAppendOnlyFileRio(rio *aof) { initStaticStringObject(key,(sds)keystr); - expireEntry *pexpire = db->getExpire(&key); - /* Save the key and associated value */ if (o->type == OBJ_STRING) { /* Emit a SET command */ @@ -1458,6 +1456,8 @@ int rewriteAppendOnlyFileRio(rio *aof) { serverPanic("Unknown object type"); } /* Save the expire time */ + std::unique_lock ul(g_expireLock); + expireEntry *pexpire = db->getExpire(&key); if (pexpire != nullptr) { for (auto &subExpire : *pexpire) { if (subExpire.subkey() == nullptr) @@ -1476,6 +1476,8 @@ int rewriteAppendOnlyFileRio(rio *aof) { if (rioWriteBulkLongLong(aof,subExpire.when()) == 0) return false; // common } } + ul.unlock(); + /* Read some diff from the parent process from time to time. */ if (aof->processed_bytes > processed+AOF_READ_DIFF_INTERVAL_BYTES) { processed = aof->processed_bytes; diff --git a/src/cluster.cpp b/src/cluster.cpp index 389c6dd98..e0ddab80c 100644 --- a/src/cluster.cpp +++ b/src/cluster.cpp @@ -5324,6 +5324,7 @@ try_again: /* Create RESTORE payload and generate the protocol to call the command. */ for (j = 0; j < num_keys; j++) { long long ttl = 0; + std::unique_lock ul(g_expireLock); expireEntry *pexpire = c->db->getExpire(kv[j]); long long expireat = -1; if (pexpire != nullptr) diff --git a/src/db.cpp b/src/db.cpp index 156784634..f0df31f5a 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -1241,6 +1241,7 @@ void renameGenericCommand(client *c, int nx) { std::unique_ptr spexpire; { // scope pexpireOld since it will be invalid soon + std::unique_lock ul(g_expireLock); expireEntry *pexpireOld = c->db->getExpire(c->argv[1]); if (pexpireOld != nullptr) spexpire = std::make_unique(std::move(*pexpireOld)); @@ -1319,6 +1320,7 @@ void moveCommand(client *c) { std::unique_ptr spexpire; { // scope pexpireOld + std::unique_lock ul(g_expireLock); expireEntry *pexpireOld = c->db->getExpire(c->argv[1]); if (pexpireOld != nullptr) spexpire = std::make_unique(std::move(*pexpireOld)); @@ -1441,6 +1443,7 @@ int redisDbPersistentData::removeExpire(robj *key, dict_iter itr) { /* An expire may only be removed if there is a corresponding entry in the * main dict. Otherwise, the key will never be freed. */ serverAssertWithInfo(NULL,key,itr != nullptr); + std::unique_lock ul(g_expireLock); robj *val = itr.val(); if (!val->FExpires()) @@ -1457,7 +1460,8 @@ int redisDbPersistentData::removeExpire(robj *key, dict_iter itr) { int redisDbPersistentData::removeSubkeyExpire(robj *key, robj *subkey) { auto de = find(szFromObj(key)); serverAssertWithInfo(NULL,key,de != nullptr); - + std::unique_lock ul(g_expireLock); + robj *val = de.val(); if (!val->FExpires()) return 0; @@ -1489,6 +1493,7 @@ int redisDbPersistentData::removeSubkeyExpire(robj *key, robj *subkey) { void redisDbPersistentData::resortExpire(expireEntry &e) { + std::unique_lock ul(g_expireLock); auto itr = m_setexpire->find(e.key()); expireEntry eT = std::move(e); m_setexpire->erase(itr); @@ -1648,6 +1653,7 @@ void propagateSubkeyExpire(redisDb *db, int type, robj *key, robj *subkey) /* Check if the key is expired. Note, this does not check subexpires */ int keyIsExpired(const redisDbPersistentDataSnapshot *db, robj *key) { + std::unique_lock ul(g_expireLock); const expireEntry *pexpire = db->getExpire(key); mstime_t now; @@ -2273,6 +2279,7 @@ void redisDbPersistentData::clear(void(callback)(void*)) void redisDbPersistentData::setExpire(robj *key, robj *subkey, long long when) { /* Reuse the sds from the main dict in the expire dict */ + std::unique_lock ul(g_expireLock); dictEntry *kde = dictFind(m_pdict,ptrFromObj(key)); serverAssertWithInfo(NULL,key,kde != NULL); trackkey(key, true /* fUpdate */); @@ -2302,12 +2309,14 @@ void redisDbPersistentData::setExpire(robj *key, robj *subkey, long long when) void redisDbPersistentData::setExpire(expireEntry &&e) { + std::unique_lock ul(g_expireLock); trackkey(e.key(), true /* fUpdate */); m_setexpire->insert(e); } bool redisDb::FKeyExpires(const char *key) { + std::unique_lock ul(g_expireLock); return setexpireUnsafe()->find(key) != setexpire()->end(); } @@ -2327,6 +2336,7 @@ void redisDbPersistentData::ensure(const char *sdsKey, dictEntry **pde) { serverAssert(sdsKey != nullptr); serverAssert(FImplies(*pde != nullptr, dictGetVal(*pde) != nullptr)); // early versions set a NULL object, this is no longer valid + std::unique_lock ul(g_expireLock); // First see if the key can be obtained from a snapshot if (*pde == nullptr && m_pdbSnapshot != nullptr) diff --git a/src/debug.cpp b/src/debug.cpp index 9aebe8885..fc565d436 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -127,6 +127,7 @@ void mixStringObjectDigest(unsigned char *digest, robj_roptr o) { void xorObjectDigest(redisDb *db, robj_roptr keyobj, unsigned char *digest, robj_roptr o) { uint32_t aux = htonl(o->type); mixDigest(digest,&aux,sizeof(aux)); + std::unique_lock ul(g_expireLock); expireEntry *pexpire = db->getExpire(keyobj); long long expiretime = -1; char buf[128]; diff --git a/src/defrag.cpp b/src/defrag.cpp index e60705a3e..65aecfa34 100644 --- a/src/defrag.cpp +++ b/src/defrag.cpp @@ -811,6 +811,7 @@ long defragStream(redisDb *db, dictEntry *kde) { * all the various pointers it has. Returns a stat of how many pointers were * moved. */ long defragKey(redisDb *db, dictEntry *de) { + std::unique_lock ul(g_expireLock); sds keysds = (sds)dictGetKey(de); robj *newob, *ob; unsigned char *newzl; diff --git a/src/evict.cpp b/src/evict.cpp index a6dfd9ba9..da17314ea 100644 --- a/src/evict.cpp +++ b/src/evict.cpp @@ -262,6 +262,7 @@ int evictionPoolPopulate(int dbid, redisDb *db, expireset *setexpire, struct evi { if (setexpire != nullptr) { + std::unique_lock ul(g_expireLock); visitFunctor visitor { dbid, db->dictUnsafeKeyOnly(), pool, 0 }; setexpire->random_visit(visitor); return visitor.count; diff --git a/src/expire.cpp b/src/expire.cpp index 14c65449d..2aa398a76 100644 --- a/src/expire.cpp +++ b/src/expire.cpp @@ -33,6 +33,8 @@ #include "server.h" #include "cron.h" +fastlock g_expireLock {"Expire"}; + /* Helper function for the activeExpireCycle() function. * This function will try to expire the key that is stored in the hash table * entry 'de' of the 'expires' hash table of a Redis database. @@ -372,6 +374,7 @@ void activeExpireCycle(int type) { continue; } + std::unique_lock ul(g_expireLock); size_t expired = 0; size_t tried = 0; long long check = ACTIVE_EXPIRE_CYCLE_FAST_DURATION; // assume a check is roughly 1us. It isn't but good enough @@ -661,6 +664,7 @@ void ttlGenericCommand(client *c, int output_ms) { /* The key exists. Return -1 if it has no expire, or the actual * TTL value otherwise. */ + std::unique_lock ul(g_expireLock); expireEntry *pexpire = c->db->getExpire(c->argv[1]); if (c->argc == 2) { diff --git a/src/lazyfree.cpp b/src/lazyfree.cpp index 6bca4481b..7cb3efbd9 100644 --- a/src/lazyfree.cpp +++ b/src/lazyfree.cpp @@ -118,6 +118,7 @@ void freeObjAsync(robj *o) { * create a new empty set of hash tables and scheduling the old ones for * lazy freeing. */ void redisDbPersistentData::emptyDbAsync() { + std::unique_lock ul(g_expireLock); dict *oldht1 = m_pdict; auto *set = m_setexpire; m_setexpire = new (MALLOC_LOCAL) expireset(); diff --git a/src/module.cpp b/src/module.cpp index 4f79b9f95..a772c0cbb 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -2167,6 +2167,7 @@ int RM_UnlinkKey(RedisModuleKey *key) { * If no TTL is associated with the key or if the key is empty, * REDISMODULE_NO_EXPIRE is returned. */ mstime_t RM_GetExpire(RedisModuleKey *key) { + std::unique_lock ul(g_expireLock); expireEntry *pexpire = key->db->getExpire(key->key); mstime_t expire = -1; if (pexpire != nullptr) diff --git a/src/object.cpp b/src/object.cpp index 72ac1b961..a45a91db8 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1078,8 +1078,10 @@ struct redisMemOverhead *getMemoryOverheadData(void) { db->size() * sizeof(robj); mh->db[mh->num_dbs].overhead_ht_main = mem; mem_total+=mem; - + + std::unique_lock ul(g_expireLock); mem = db->setexpire()->bytes_used(); + mh->db[mh->num_dbs].overhead_ht_expires = mem; mem_total+=mem; diff --git a/src/rdb.cpp b/src/rdb.cpp index befb43430..4feb1d6a7 100644 --- a/src/rdb.cpp +++ b/src/rdb.cpp @@ -1150,8 +1150,11 @@ int saveKey(rio *rdb, const redisDbPersistentDataSnapshot *db, int flags, size_t robj key; initStaticStringObject(key,(char*)keystr); + std::unique_lock ul(g_expireLock); const expireEntry *pexpire = db->getExpire(&key); serverAssert((o->FExpires() && pexpire != nullptr) || (!o->FExpires() && pexpire == nullptr)); + if (pexpire == nullptr) + ul.unlock(); // no need to hold the lock if we're not saving the expire if (rdbSaveKeyValuePair(rdb,&key,o,pexpire) == -1) return 0; diff --git a/src/server.cpp b/src/server.cpp index f5f2a93bd..ce817947d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2853,6 +2853,7 @@ bool getCommandAsync(client *c) } // Are we expired? + std::unique_lock ul(g_expireLock); const expireEntry *expire = serverTL->rgdbSnapshot[idb]->getExpire(c->argv[1]); long long when; if (expire && expire->FGetPrimaryExpire(&when) && when > 0) { diff --git a/src/server.h b/src/server.h index ad15c319a..8e21f6aa5 100644 --- a/src/server.h +++ b/src/server.h @@ -1171,6 +1171,7 @@ public: explicit operator long long() const noexcept { return when(); } }; typedef semiorderedset expireset; +extern fastlock g_expireLock; /* The a string name for an object's type as listed above * Native types are checked against the OBJ_STRING, OBJ_LIST, OBJ_* defines, diff --git a/src/snapshot.cpp b/src/snapshot.cpp index cb65eb30a..f863a2b1d 100644 --- a/src/snapshot.cpp +++ b/src/snapshot.cpp @@ -49,8 +49,10 @@ const redisDbPersistentDataSnapshot *redisDbPersistentData::createSnapshot(uint6 dictForceRehash(m_spdbSnapshotHOLDER->m_pdictTombstone); dictMerge(m_pdbSnapshot->m_pdict, m_pdict); dictEmpty(m_pdictTombstone, nullptr); - delete m_spdbSnapshotHOLDER->m_setexpire; - m_spdbSnapshotHOLDER->m_setexpire = new (MALLOC_LOCAL) expireset(*m_setexpire); + { + std::unique_lock ul(g_expireLock); + (*m_spdbSnapshotHOLDER->m_setexpire) = *m_setexpire; + } m_pdbSnapshotASYNC = nullptr; serverAssert(m_pdbSnapshot->m_pdict->iterators == 1); @@ -79,6 +81,7 @@ const redisDbPersistentDataSnapshot *redisDbPersistentData::createSnapshot(uint6 spdb->m_mvccCheckpoint = getMvccTstamp(); if (m_setexpire != nullptr) { + std::unique_lock ul(g_expireLock); spdb->m_setexpire = new (MALLOC_LOCAL) expireset(*m_setexpire); spdb->m_setexpire->pause_rehash(); // needs to be const } @@ -158,8 +161,11 @@ void redisDbPersistentData::restoreSnapshot(const redisDbPersistentDataSnapshot size_t expectedSize = psnapshot->size(); dictEmpty(m_pdict, nullptr); dictEmpty(m_pdictTombstone, nullptr); + { + std::unique_lock ul(g_expireLock); delete m_setexpire; m_setexpire = new (MALLOC_LOCAL) expireset(*psnapshot->m_setexpire); + } endSnapshot(psnapshot); serverAssert(size() == expectedSize); } @@ -504,6 +510,11 @@ void redisDbPersistentDataSnapshot::consolidate_children(redisDbPersistentData * return true; }, true /*fKeyOnly*/, true /*fCacheOnly*/); spdb->m_spstorage = m_pdbSnapshot->m_spstorage; + { + std::unique_lock ul(g_expireLock); + delete spdb->m_setexpire; + spdb->m_setexpire = new (MALLOC_LOCAL) expireset(*m_pdbSnapshot->m_setexpire); + } spdb->m_pdict->iterators++; From ec01cc23b1d96d93ff1f7b27e17539187831b072 Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 9 Jun 2020 20:58:03 -0400 Subject: [PATCH 17/24] Fix lock inversion Former-commit-id: 430cf88623fce8f0675ea19f73d98f6cafe9070f --- src/server.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/server.h b/src/server.h index 8e21f6aa5..008b47b6e 100644 --- a/src/server.h +++ b/src/server.h @@ -2412,9 +2412,7 @@ struct redisServer { inline int redisServerThreadVars::getRdbKeySaveDelay() { if (rdb_key_save_delay < 0) { - aeAcquireLock(); - rdb_key_save_delay = g_pserver->rdb_key_save_delay; - aeReleaseLock(); + __atomic_load(&g_pserver->rdb_key_save_delay, &rdb_key_save_delay, __ATOMIC_ACQUIRE); } return rdb_key_save_delay; } From 29faa06028e15f0a8e8a0967b105b48771058400 Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 9 Jun 2020 20:59:09 -0400 Subject: [PATCH 18/24] Fix assert false alarm when freeTombstoneObjects is called Former-commit-id: e21a011072505cfa0a37afefb94f7270e80625c5 --- src/snapshot.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/snapshot.cpp b/src/snapshot.cpp index f863a2b1d..0f5bb079e 100644 --- a/src/snapshot.cpp +++ b/src/snapshot.cpp @@ -502,10 +502,13 @@ void redisDbPersistentDataSnapshot::consolidate_children(redisDbPersistentData * spdb->initialize(); dictExpand(spdb->m_pdict, m_pdbSnapshot->size()); + volatile size_t skipped = 0; m_pdbSnapshot->iterate_threadsafe([&](const char *key, robj_roptr o) { if (o != nullptr) { dictAdd(spdb->m_pdict, sdsdupshared(key), o.unsafe_robjcast()); incrRefCount(o); + } else { + ++skipped; } return true; }, true /*fKeyOnly*/, true /*fCacheOnly*/); @@ -518,7 +521,11 @@ void redisDbPersistentDataSnapshot::consolidate_children(redisDbPersistentData * spdb->m_pdict->iterators++; - serverAssert(spdb->size() == m_pdbSnapshot->size()); + if (m_spstorage) { + serverAssert(spdb->size() == m_pdbSnapshot->size()); + } else { + serverAssert((spdb->size()+skipped) == m_pdbSnapshot->size()); + } // Now wire us in (Acquire the LOCK) AeLocker locker; From 15e2b066f3d77ea5528f0b6088094d4fa1d4eae0 Mon Sep 17 00:00:00 2001 From: John Sully Date: Tue, 9 Jun 2020 21:03:11 -0400 Subject: [PATCH 19/24] Bump version Former-commit-id: c7b16835b1c52e9d8a4859a5b6e42ea5f6a31df2 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 4403f3d74..1ae66bc98 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.9" +#define KEYDB_REAL_VERSION "6.0.10" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 4d6b7c278b4ff796445d97777a674854d3b3180e Mon Sep 17 00:00:00 2001 From: Ben Schermel Date: Tue, 16 Jun 2020 14:17:20 -0400 Subject: [PATCH 20/24] bump version after merge Former-commit-id: 59279d36e9337ca89518c4d1edef6c26911ea190 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 1ae66bc98..6c1f041a1 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.10" +#define KEYDB_REAL_VERSION "6.0.11" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From 8256661b7adadde00bc78c4125c917a87e585ea2 Mon Sep 17 00:00:00 2001 From: John Sully Date: Fri, 10 Jul 2020 04:13:42 +0000 Subject: [PATCH 21/24] Bump version Former-commit-id: ee5a281ed0012aca359b9448df5236bef719f4a7 --- pkg/deb/master_changelog | 6 ++++++ src/version.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/deb/master_changelog b/pkg/deb/master_changelog index 999c9c872..e92f8cc95 100644 --- a/pkg/deb/master_changelog +++ b/pkg/deb/master_changelog @@ -1,3 +1,9 @@ +keydb-pro (6:6.0.12-1distribution_placeholder) codename_placeholder; urgency=medium + + * 6.0.12 Enable SCAN for MVCC + + -- Ben Schermel Fri, 10 Jul 2020 20:00:37 +0000 + keydb-pro (6:6.0.11-1distribution_placeholder) codename_placeholder; urgency=medium * 6.0.11 fixes applied related to cluster usage and expires diff --git a/src/version.h b/src/version.h index 6c1f041a1..92689b67a 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define KEYDB_REAL_VERSION "6.0.11" +#define KEYDB_REAL_VERSION "6.0.12" extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config enum VersionCompareResult From a3cf9ce10988949c3aa06d4e129fa9075a3aa7ed Mon Sep 17 00:00:00 2001 From: John Sully Date: Sat, 11 Jul 2020 04:23:35 +0000 Subject: [PATCH 22/24] Eliminate eviction loops. And don't OOM so often with storage providers set Former-commit-id: 189674aea74c483bf0869050ecf7bf2b0b49f34e --- src/evict.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/evict.cpp b/src/evict.cpp index da17314ea..ce9c420c4 100644 --- a/src/evict.cpp +++ b/src/evict.cpp @@ -497,6 +497,7 @@ int freeMemoryIfNeeded(bool fPreSnapshot) { int slaves = listLength(g_pserver->slaves); const bool fEvictToStorage = !cserver.delete_on_evict && g_pserver->db[0]->FStorageProvider(); int result = C_ERR; + int ckeysFailed = 0; /* When clients are paused the dataset should be static not just from the * POV of clients not being able to write, but also from the POV of @@ -619,8 +620,16 @@ int freeMemoryIfNeeded(bool fPreSnapshot) { { // This key is in the storage so we only need to free the object delta = (long long) zmalloc_used_memory(); - db->removeCachedValue(bestkey); - delta -= (long long) zmalloc_used_memory(); + if (db->removeCachedValue(bestkey)) { + delta -= (long long) zmalloc_used_memory(); + ckeysFailed = 0; + } + else { + delta = 0; + ckeysFailed++; + if (ckeysFailed > 1024) + goto cant_free; + } mem_freed += delta; } else @@ -679,6 +688,13 @@ int freeMemoryIfNeeded(bool fPreSnapshot) { result = C_OK; cant_free: + if (g_pserver->m_pstorageFactory) + { + if (mem_reported < g_pserver->maxmemory*1.2) { + return C_OK; // Allow us to temporarily go over without OOMing + } + } + if (!cserver.delete_on_evict && result != C_OK) { for (int idb = 0; idb < cserver.dbnum; ++idb) From dedfe2d63ccd8f9f4e6eeb8e9a6accd8d8032c71 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 12 Jul 2020 05:14:59 +0000 Subject: [PATCH 23/24] Fix failure to replicate with license key Former-commit-id: d34723c567b36f8222c93fac6f0ed1f79104f33e --- src/replication.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/replication.cpp b/src/replication.cpp index 477fe6e10..ea290363e 100644 --- a/src/replication.cpp +++ b/src/replication.cpp @@ -2723,9 +2723,6 @@ void syncWithMaster(connection *conn) { if (err[1] == 'E' && err[2] == 'R' && err[3] == 'R') { // Replicating with non-pro serverLog(LL_WARNING, "Replicating with non-pro server."); - mi->repl_state = REPL_STATE_SEND_PORT; - sdsfree(err); - return; } else { serverLog(LL_WARNING, "Recieved error from client: %s", err); sdsfree(err); From 3eca9ea38d9af5ec4df6f0e2f873f0bbc34a4a05 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 12 Jul 2020 05:37:43 +0000 Subject: [PATCH 24/24] Fix CLI crash on arch with hostname Former-commit-id: 55fd37e8d6c3775d0b1bd13966ca033f63945d7e --- src/Makefile | 2 +- src/ae.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 938531b3a..efb353219 100644 --- a/src/Makefile +++ b/src/Makefile @@ -279,7 +279,7 @@ REDIS_SERVER_NAME=keydb-pro-server REDIS_SENTINEL_NAME=keydb-sentinel REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o new.o tracking.o cron.o connection.o tls.o sha256.o motd.o timeout.o setcpuaffinity.o AsyncWorkQueue.o snapshot.o storage/rocksdb.o storage/rocksdbfactory.o storage/teststorageprovider.o keydbutils.o $(ASM_OBJ) REDIS_CLI_NAME=keydb-cli -REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crcspeed.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o new.o motd.o $(ASM_OBJ) +REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crcspeed.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o motd.o $(ASM_OBJ) REDIS_BENCHMARK_NAME=keydb-benchmark REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o redis-benchmark.o storage-lite.o fastlock.o new.o $(ASM_OBJ) REDIS_CHECK_RDB_NAME=keydb-check-rdb diff --git a/src/ae.cpp b/src/ae.cpp index 1e9dd1fc2..6d87a85c7 100644 --- a/src/ae.cpp +++ b/src/ae.cpp @@ -247,7 +247,7 @@ int aeCreateRemoteFileEvent(aeEventLoop *eventLoop, int fd, int mask, cmd.fLock = true; if (fSynchronous) { - cmd.pctl = new (MALLOC_LOCAL) aeCommandControl(); + cmd.pctl = new aeCommandControl(); cmd.pctl->mutexcv.lock(); } @@ -299,12 +299,12 @@ int aePostFunction(aeEventLoop *eventLoop, std::function fn, bool fSynch aeCommand cmd = {}; memset(&cmd, 0, sizeof(aeCommand)); cmd.op = AE_ASYNC_OP::PostCppFunction; - cmd.pfn = new (MALLOC_LOCAL) std::function(fn); + cmd.pfn = new std::function(fn); cmd.pctl = nullptr; cmd.fLock = fLock; if (fSynchronous) { - cmd.pctl = new (MALLOC_LOCAL) aeCommandControl(); + cmd.pctl = new aeCommandControl(); cmd.pctl->mutexcv.lock(); }