reuse the sds from the main dictionary in the expiration dictionary

This commit is contained in:
Pieter Noordhuis 2010-06-07 20:44:12 +02:00
parent 65cc766581
commit 829137b9a0

52
redis.c
View File

@ -1252,7 +1252,7 @@ static dictType keyptrDictType = {
NULL, /* key dup */ NULL, /* key dup */
NULL, /* val dup */ NULL, /* val dup */
dictSdsKeyCompare, /* key compare */ dictSdsKeyCompare, /* key compare */
dictSdsDestructor, /* key destructor */ NULL, /* key destructor */
NULL /* val destructor */ NULL /* val destructor */
}; };
@ -3525,12 +3525,10 @@ static robj *dbRandomKey(redisDb *db) {
/* Delete a key, value, and associated expiration entry if any, from the DB */ /* Delete a key, value, and associated expiration entry if any, from the DB */
static int dbDelete(redisDb *db, robj *key) { static int dbDelete(redisDb *db, robj *key) {
int retval; /* Deleting an entry from the expires dict will not free the sds of
* the key, because it is shared with the main dictionary. */
if (dictSize(db->expires)) dictDelete(db->expires,key->ptr); if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);
retval = dictDelete(db->dict,key->ptr); return dictDelete(db->dict,key->ptr) == DICT_OK;
return retval == DICT_OK;
} }
/*============================ RDB saving/loading =========================== */ /*============================ RDB saving/loading =========================== */
@ -7750,6 +7748,9 @@ static void monitorCommand(redisClient *c) {
/* ================================= Expire ================================= */ /* ================================= Expire ================================= */
static int removeExpire(redisDb *db, robj *key) { static int removeExpire(redisDb *db, robj *key) {
/* An expire may only be removed if there is a corresponding entry in the
* main dict. Otherwise, the key will never be freed. */
redisAssert(dictFind(db->dict,key->ptr) != NULL);
if (dictDelete(db->expires,key->ptr) == DICT_OK) { if (dictDelete(db->expires,key->ptr) == DICT_OK) {
return 1; return 1;
} else { } else {
@ -7758,9 +7759,11 @@ static int removeExpire(redisDb *db, robj *key) {
} }
static int setExpire(redisDb *db, robj *key, time_t when) { static int setExpire(redisDb *db, robj *key, time_t when) {
sds copy = sdsdup(key->ptr); dictEntry *de;
if (dictAdd(db->expires,copy,(void*)when) == DICT_ERR) {
sdsfree(copy); /* Reuse the sds from the main dict in the expire dict */
redisAssert((de = dictFind(db->dict,key->ptr)) != NULL);
if (dictAdd(db->expires,dictGetEntryKey(de),(void*)when) == DICT_ERR) {
return 0; return 0;
} else { } else {
return 1; return 1;
@ -7776,39 +7779,32 @@ static time_t getExpire(redisDb *db, robj *key) {
if (dictSize(db->expires) == 0 || if (dictSize(db->expires) == 0 ||
(de = dictFind(db->expires,key->ptr)) == NULL) return -1; (de = dictFind(db->expires,key->ptr)) == NULL) return -1;
/* The entry was found in the expire dict, this means it should also
* be present in the main dict (safety check). */
redisAssert(dictFind(db->dict,key->ptr) != NULL);
return (time_t) dictGetEntryVal(de); return (time_t) dictGetEntryVal(de);
} }
static int expireIfNeeded(redisDb *db, robj *key) { static int expireIfNeeded(redisDb *db, robj *key) {
time_t when; time_t when = getExpire(db,key);
dictEntry *de; if (when < 0) return 0;
/* No expire? return ASAP */ /* Return when this key has not expired */
if (dictSize(db->expires) == 0 ||
(de = dictFind(db->expires,key->ptr)) == NULL) return 0;
/* Lookup the expire */
when = (time_t) dictGetEntryVal(de);
if (time(NULL) <= when) return 0; if (time(NULL) <= when) return 0;
/* Delete the key */ /* Delete the key */
dbDelete(db,key);
server.stat_expiredkeys++; server.stat_expiredkeys++;
return 1; server.dirty++;
return dbDelete(db,key);
} }
static int deleteIfVolatile(redisDb *db, robj *key) { static int deleteIfVolatile(redisDb *db, robj *key) {
dictEntry *de; if (getExpire(db,key) < 0) return 0;
/* No expire? return ASAP */
if (dictSize(db->expires) == 0 ||
(de = dictFind(db->expires,key->ptr)) == NULL) return 0;
/* Delete the key */ /* Delete the key */
server.dirty++;
server.stat_expiredkeys++; server.stat_expiredkeys++;
dictDelete(db->expires,key->ptr); server.dirty++;
return dictDelete(db->dict,key->ptr) == DICT_OK; return dbDelete(db,key);
} }
static void expireGenericCommand(redisClient *c, robj *key, robj *param, long offset) { static void expireGenericCommand(redisClient *c, robj *key, robj *param, long offset) {