From fddeeae724bec1a8e1a3dbb2f18e608b79c2ddfc Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Tue, 31 Jul 2018 12:07:57 +0800 Subject: [PATCH] refactor dbOverwrite to make lazyfree work --- src/db.c | 17 +++++++++++------ src/lazyfree.c | 11 +++++++++++ src/server.h | 1 + src/t_set.c | 10 ++++------ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/db.c b/src/db.c index 6efe47011..ec92a2b4e 100644 --- a/src/db.c +++ b/src/db.c @@ -184,14 +184,19 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) { dictEntry *de = dictFind(db->dict,key->ptr); serverAssertWithInfo(NULL,key,de != NULL); + dictEntry auxentry = *de; + robj *old = dictGetVal(de); if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { - robj *old = dictGetVal(de); - int saved_lru = old->lru; - dictReplace(db->dict, key->ptr, val); - val->lru = saved_lru; - } else { - dictReplace(db->dict, key->ptr, val); + val->lru = old->lru; } + dictSetVal(db->dict, de, val); + + if (server.lazyfree_lazy_server_del) { + freeObjAsync(old); + dictSetVal(db->dict, &auxentry, NULL); + } + + dictFreeVal(db->dict, &auxentry); } /* High level Set operation. This function can be used in order to set diff --git a/src/lazyfree.c b/src/lazyfree.c index ac8a6bee9..3d3159c90 100644 --- a/src/lazyfree.c +++ b/src/lazyfree.c @@ -90,6 +90,17 @@ int dbAsyncDelete(redisDb *db, robj *key) { } } +/* Free an object, if the object is huge enough, free it in async way. */ +void freeObjAsync(robj *o) { + size_t free_effort = lazyfreeGetFreeEffort(o); + if (free_effort > LAZYFREE_THRESHOLD && o->refcount == 1) { + atomicIncr(lazyfree_objects,1); + bioCreateBackgroundJob(BIO_LAZY_FREE,o,NULL,NULL); + } else { + decrRefCount(o); + } +} + /* Empty a Redis DB asynchronously. What the function does actually is to * create a new empty set of hash tables and scheduling the old ones for * lazy freeing. */ diff --git a/src/server.h b/src/server.h index 14aed7fc0..a7985a39d 100644 --- a/src/server.h +++ b/src/server.h @@ -1824,6 +1824,7 @@ int dbAsyncDelete(redisDb *db, robj *key); void emptyDbAsync(redisDb *db); void slotToKeyFlushAsync(void); size_t lazyfreeGetPendingObjectsCount(void); +void freeObjAsync(robj *o); /* API to get key arguments from commands */ int *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys); diff --git a/src/t_set.c b/src/t_set.c index 8f21f71b1..5d48e3c43 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -516,11 +516,7 @@ void spopWithCountCommand(client *c) { sdsfree(sdsele); } - /* Assign the new set as the key value. */ - incrRefCount(set); /* Protect the old set value. */ - dbOverwrite(c->db,c->argv[1],newset); - - /* Tranfer the old set to the client and release it. */ + /* Tranfer the old set to the client. */ setTypeIterator *si; si = setTypeInitIterator(set); while((encoding = setTypeNext(si,&sdsele,&llele)) != -1) { @@ -539,7 +535,9 @@ void spopWithCountCommand(client *c) { decrRefCount(objele); } setTypeReleaseIterator(si); - decrRefCount(set); + + /* Assign the new set as the key value. */ + dbOverwrite(c->db,c->argv[1],newset); } /* Don't propagate the command itself even if we incremented the