summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2013-12-10 18:18:24 +0100
committerantirez <antirez@gmail.com>2013-12-10 18:18:36 +0100
commitb6610a569d80e13d5927a661d2cfa784081ff2bf (patch)
tree8414c6059ee06b22eed3345cb1aa0aaff99e4de7
parent26cf5c8ac6386667ed8ab46c7017e249babfc063 (diff)
downloadredis-b6610a569d80e13d5927a661d2cfa784081ff2bf.tar.gz
dict.c: added optional callback to dictEmpty().
Redis hash table implementation has many non-blocking features like incremental rehashing, however while deleting a large hash table there was no way to have a callback called to do some incremental work. This commit adds this support, as an optiona callback argument to dictEmpty() that is currently called at a fixed interval (one time every 65k deletions).
-rw-r--r--src/db.c12
-rw-r--r--src/debug.c4
-rw-r--r--src/dict.c15
-rw-r--r--src/dict.h2
-rw-r--r--src/redis.h2
-rw-r--r--src/replication.c4
-rw-r--r--src/sentinel.c2
-rw-r--r--src/t_list.c2
8 files changed, 22 insertions, 21 deletions
diff --git a/src/db.c b/src/db.c
index b91e4f86c..b625fea53 100644
--- a/src/db.c
+++ b/src/db.c
@@ -166,14 +166,14 @@ int dbDelete(redisDb *db, robj *key) {
}
}
-long long emptyDb() {
+long long emptyDb(void(callback)(void*)) {
int j;
long long removed = 0;
for (j = 0; j < server.dbnum; j++) {
removed += dictSize(server.db[j].dict);
- dictEmpty(server.db[j].dict);
- dictEmpty(server.db[j].expires);
+ dictEmpty(server.db[j].dict,callback);
+ dictEmpty(server.db[j].expires,callback);
}
return removed;
}
@@ -209,14 +209,14 @@ void signalFlushedDb(int dbid) {
void flushdbCommand(redisClient *c) {
server.dirty += dictSize(c->db->dict);
signalFlushedDb(c->db->id);
- dictEmpty(c->db->dict);
- dictEmpty(c->db->expires);
+ dictEmpty(c->db->dict,NULL);
+ dictEmpty(c->db->expires,NULL);
addReply(c,shared.ok);
}
void flushallCommand(redisClient *c) {
signalFlushedDb(-1);
- server.dirty += emptyDb();
+ server.dirty += emptyDb(NULL);
addReply(c,shared.ok);
if (server.rdb_child_pid != -1) {
kill(server.rdb_child_pid,SIGUSR1);
diff --git a/src/debug.c b/src/debug.c
index 7c1a277f7..032653fb2 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -261,7 +261,7 @@ void debugCommand(redisClient *c) {
addReply(c,shared.err);
return;
}
- emptyDb();
+ emptyDb(NULL);
if (rdbLoad(server.rdb_filename) != REDIS_OK) {
addReplyError(c,"Error trying to load the RDB dump");
return;
@@ -269,7 +269,7 @@ void debugCommand(redisClient *c) {
redisLog(REDIS_WARNING,"DB reloaded by DEBUG RELOAD");
addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"loadaof")) {
- emptyDb();
+ emptyDb(NULL);
if (loadAppendOnlyFile(server.aof_filename) != REDIS_OK) {
addReply(c,shared.err);
return;
diff --git a/src/dict.c b/src/dict.c
index 4d2514799..d0607f56a 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -444,14 +444,15 @@ int dictDeleteNoFree(dict *ht, const void *key) {
}
/* Destroy an entire dictionary */
-int _dictClear(dict *d, dictht *ht)
-{
+int _dictClear(dict *d, dictht *ht, void(callback)(void *)) {
unsigned long i;
/* Free all the elements */
for (i = 0; i < ht->size && ht->used > 0; i++) {
dictEntry *he, *nextHe;
+ if (callback && (i & 65535) == 0) callback(d->privdata);
+
if ((he = ht->table[i]) == NULL) continue;
while(he) {
nextHe = he->next;
@@ -472,8 +473,8 @@ int _dictClear(dict *d, dictht *ht)
/* Clear & Release the hash table */
void dictRelease(dict *d)
{
- _dictClear(d,&d->ht[0]);
- _dictClear(d,&d->ht[1]);
+ _dictClear(d,&d->ht[0],NULL);
+ _dictClear(d,&d->ht[1],NULL);
zfree(d);
}
@@ -882,9 +883,9 @@ static int _dictKeyIndex(dict *d, const void *key)
return idx;
}
-void dictEmpty(dict *d) {
- _dictClear(d,&d->ht[0]);
- _dictClear(d,&d->ht[1]);
+void dictEmpty(dict *d, void(callback)(void*)) {
+ _dictClear(d,&d->ht[0],callback);
+ _dictClear(d,&d->ht[1],callback);
d->rehashidx = -1;
d->iterators = 0;
}
diff --git a/src/dict.h b/src/dict.h
index 11e1b97ee..3385e9f06 100644
--- a/src/dict.h
+++ b/src/dict.h
@@ -160,7 +160,7 @@ dictEntry *dictGetRandomKey(dict *d);
void dictPrintStats(dict *d);
unsigned int dictGenHashFunction(const void *key, int len);
unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);
-void dictEmpty(dict *d);
+void dictEmpty(dict *d, void(callback)(void*));
void dictEnableResize(void);
void dictDisableResize(void);
int dictRehash(dict *d, int n);
diff --git a/src/redis.h b/src/redis.h
index 357145902..d23dc69fa 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -1165,7 +1165,7 @@ void setKey(redisDb *db, robj *key, robj *val);
int dbExists(redisDb *db, robj *key);
robj *dbRandomKey(redisDb *db);
int dbDelete(redisDb *db, robj *key);
-long long emptyDb();
+long long emptyDb(void(callback)(void*));
int selectDb(redisClient *c, int id);
void signalModifiedKey(redisDb *db, robj *key);
void signalFlushedDb(int dbid);
diff --git a/src/replication.c b/src/replication.c
index b5941be14..ffcad39f2 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -782,7 +782,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
}
redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Flushing old data");
signalFlushedDb(-1);
- emptyDb();
+ emptyDb(NULL);
/* Before loading the DB into memory we need to delete the readable
* handler, otherwise it will get called recursively since
* rdbLoad() will call the event loop to process events from time to
@@ -1445,7 +1445,7 @@ void replicationScriptCacheInit(void) {
* to reclaim otherwise unused memory.
*/
void replicationScriptCacheFlush(void) {
- dictEmpty(server.repl_scriptcache_dict);
+ dictEmpty(server.repl_scriptcache_dict,NULL);
listRelease(server.repl_scriptcache_fifo);
server.repl_scriptcache_fifo = listCreate();
}
diff --git a/src/sentinel.c b/src/sentinel.c
index 909f7e8ea..4c5ebfd7a 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -393,7 +393,7 @@ void initSentinel(void) {
/* Remove usual Redis commands from the command table, then just add
* the SENTINEL command. */
- dictEmpty(server.commands);
+ dictEmpty(server.commands,NULL);
for (j = 0; j < sizeof(sentinelcmds)/sizeof(sentinelcmds[0]); j++) {
int retval;
struct redisCommand *cmd = sentinelcmds+j;
diff --git a/src/t_list.c b/src/t_list.c
index 3790628d3..24febe51a 100644
--- a/src/t_list.c
+++ b/src/t_list.c
@@ -837,7 +837,7 @@ void unblockClientWaitingData(redisClient *c) {
dictReleaseIterator(di);
/* Cleanup the client structure */
- dictEmpty(c->bpop.keys);
+ dictEmpty(c->bpop.keys,NULL);
if (c->bpop.target) {
decrRefCount(c->bpop.target);
c->bpop.target = NULL;