Commit 297922e6 authored by Vitaly Arbuzov's avatar Vitaly Arbuzov
Browse files

Add ability to use dbIterator as dictIterator

parent 72935b9d
...@@ -2235,7 +2235,6 @@ werr: ...@@ -2235,7 +2235,6 @@ werr:
} }
int rewriteAppendOnlyFileRio(rio *aof) { int rewriteAppendOnlyFileRio(rio *aof) {
dictIterator *di = NULL;
dictEntry *de; dictEntry *de;
int j; int j;
long key_count = 0; long key_count = 0;
...@@ -2256,14 +2255,10 @@ int rewriteAppendOnlyFileRio(rio *aof) { ...@@ -2256,14 +2255,10 @@ int rewriteAppendOnlyFileRio(rio *aof) {
if (rioWrite(aof, selectcmd, sizeof(selectcmd) - 1) == 0) goto werr; if (rioWrite(aof, selectcmd, sizeof(selectcmd) - 1) == 0) goto werr;
if (rioWriteBulkLongLong(aof, j) == 0) goto werr; if (rioWriteBulkLongLong(aof, j) == 0) goto werr;
redisDb *db = server.db + j; redisDb *db = server.db + j;
dict *d;
dbIterator dbit; dbIterator dbit;
dbIteratorInit(&dbit, db); dbIteratorInit(&dbit, db);
while ((d = dbIteratorNextDict(&dbit))) {
if (dictSize(d) == 0) continue;
di = dictGetSafeIterator(d);
/* Iterate this DB writing every entry */ /* Iterate this DB writing every entry */
while ((de = dictNext(di)) != NULL) { while ((de = dbIteratorNext(&dbit)) != NULL) {
sds keystr; sds keystr;
robj key, *o; robj key, *o;
long long expiretime; long long expiretime;
...@@ -2328,14 +2323,10 @@ int rewriteAppendOnlyFileRio(rio *aof) { ...@@ -2328,14 +2323,10 @@ int rewriteAppendOnlyFileRio(rio *aof) {
if (server.rdb_key_save_delay) if (server.rdb_key_save_delay)
debugDelay(server.rdb_key_save_delay); debugDelay(server.rdb_key_save_delay);
} }
dictReleaseIterator(di);
di = NULL;
}
} }
return C_OK; return C_OK;
werr: werr:
if (di) dictReleaseIterator(di);
return C_ERR; return C_ERR;
} }
......
...@@ -61,6 +61,23 @@ dict *dbIteratorNextDict(dbIterator *dbit) { ...@@ -61,6 +61,23 @@ dict *dbIteratorNextDict(dbIterator *dbit) {
return dbit->cur_slot >= 0 ? dbit->db->dict[dbit->cur_slot] : NULL; return dbit->cur_slot >= 0 ? dbit->db->dict[dbit->cur_slot] : NULL;
} }
/* Returns next entry from the multi slot db. */
dictEntry *dbIteratorNext(dbIterator *dbit) {
if (!dbit->di.d) { /* No current dict, need to get a new one. */
dict *d = dbIteratorNextDict(dbit);
if (!d) return NULL;
dictInitSafeIterator(&dbit->di, d);
}
dictEntry *de = dictNext(&dbit->di);
if (!de) { /* Reached the end of the dictionary, check if there are more. */
dict *d = dbIteratorNextDict(dbit);
if (!d) return NULL;
dictInitSafeIterator(&dbit->di, d);
return dictNext(&dbit->di);
}
return de;
}
/* Returns DB iterator that can be used to iterate through sub-dictionaries. /* Returns DB iterator that can be used to iterate through sub-dictionaries.
* Primary database contains only one dictionary when node runs without cluster mode, * Primary database contains only one dictionary when node runs without cluster mode,
* or 16k dictionaries (one per slot) when node runs with cluster mode enabled. */ * or 16k dictionaries (one per slot) when node runs with cluster mode enabled. */
...@@ -68,6 +85,7 @@ void dbIteratorInit(dbIterator *dbit, redisDb *db) { ...@@ -68,6 +85,7 @@ void dbIteratorInit(dbIterator *dbit, redisDb *db) {
dbit->db = db; dbit->db = db;
dbit->index = 0; dbit->index = 0;
dbit->cur_slot = -1; dbit->cur_slot = -1;
dictInitSafeIterator(&dbit->di, NULL);
} }
/* Returns next non-empty dictionary strictly after provided slot and updates slot id in the supplied reference. */ /* Returns next non-empty dictionary strictly after provided slot and updates slot id in the supplied reference. */
...@@ -846,34 +864,28 @@ void randomkeyCommand(client *c) { ...@@ -846,34 +864,28 @@ void randomkeyCommand(client *c) {
} }
void keysCommand(client *c) { void keysCommand(client *c) {
dictIterator *di;
dictEntry *de; dictEntry *de;
sds pattern = c->argv[1]->ptr; sds pattern = c->argv[1]->ptr;
int plen = sdslen(pattern), allkeys; int plen = sdslen(pattern), allkeys;
long numkeys = 0; long numkeys = 0;
void *replylen = addReplyDeferredLen(c); void *replylen = addReplyDeferredLen(c);
dict *d;
dbIterator dbit; dbIterator dbit;
dbIteratorInit(&dbit, c->db); dbIteratorInit(&dbit, c->db);
while ((d = dbIteratorNextDict(&dbit))) {
if (dictSize(d) == 0) continue;
di = dictGetSafeIterator(d);
allkeys = (pattern[0] == '*' && plen == 1); allkeys = (pattern[0] == '*' && plen == 1);
while((de = dictNext(di)) != NULL) { while ((de = dbIteratorNext(&dbit)) != NULL) {
sds key = dictGetKey(de); sds key = dictGetKey(de);
robj *keyobj; robj *keyobj;
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) { if (allkeys || stringmatchlen(pattern, plen, key, sdslen(key), 0)) {
keyobj = createStringObject(key,sdslen(key)); keyobj = createStringObject(key, sdslen(key));
if (!keyIsExpired(c->db,keyobj)) { if (!keyIsExpired(c->db, keyobj)) {
addReplyBulk(c,keyobj); addReplyBulk(c, keyobj);
numkeys++; numkeys++;
} }
decrRefCount(keyobj); decrRefCount(keyobj);
} }
if (c->flags & CLIENT_CLOSE_ASAP) if (c->flags & CLIENT_CLOSE_ASAP)
break;} break;
dictReleaseIterator(di);
} }
setDeferredArrayLen(c,replylen,numkeys); setDeferredArrayLen(c,replylen,numkeys);
} }
......
...@@ -277,7 +277,6 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o) ...@@ -277,7 +277,6 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o)
* a different digest. */ * a different digest. */
void computeDatasetDigest(unsigned char *final) { void computeDatasetDigest(unsigned char *final) {
unsigned char digest[20]; unsigned char digest[20];
dictIterator *di = NULL;
dictEntry *de; dictEntry *de;
int j; int j;
uint32_t aux; uint32_t aux;
...@@ -286,17 +285,16 @@ void computeDatasetDigest(unsigned char *final) { ...@@ -286,17 +285,16 @@ void computeDatasetDigest(unsigned char *final) {
for (j = 0; j < server.dbnum; j++) { for (j = 0; j < server.dbnum; j++) {
redisDb *db = server.db+j; redisDb *db = server.db+j;
int hasEntries = 0; if (dbSize(db) == 0) continue;
dict *d;
dbIterator dbit; dbIterator dbit;
dbIteratorInit(&dbit, db); dbIteratorInit(&dbit, db);
while ((d = dbIteratorNextDict(&dbit))) {
if (dictSize(d) == 0) continue; /* hash the DB id, so the same dataset moved in a different DB will lead to a different digest */
hasEntries = 1; aux = htonl(j);
di = dictGetSafeIterator(d); mixDigest(final, &aux, sizeof(aux));
/* Iterate this DB writing every entry */ /* Iterate this DB writing every entry */
while ((de = dictNext(di)) != NULL) { while ((de = dbIteratorNext(&dbit)) != NULL) {
sds key; sds key;
robj *keyobj, *o; robj *keyobj, *o;
...@@ -313,13 +311,6 @@ void computeDatasetDigest(unsigned char *final) { ...@@ -313,13 +311,6 @@ void computeDatasetDigest(unsigned char *final) {
xorDigest(final, digest, 20); xorDigest(final, digest, 20);
decrRefCount(keyobj); decrRefCount(keyobj);
} }
dictReleaseIterator(di);
}
if (hasEntries) {
/* hash the DB id, so the same dataset moved in a different DB will lead to a different digest */
aux = htonl(j);
mixDigest(final, &aux, sizeof(aux));
}
} }
} }
......
...@@ -2439,12 +2439,13 @@ typedef struct dbIterator { ...@@ -2439,12 +2439,13 @@ typedef struct dbIterator {
redisDb *db; redisDb *db;
int index; int index;
int cur_slot; int cur_slot;
dictIterator di;
} dbIterator; } dbIterator;
/* DB iterator specific functions */ /* DB iterator specific functions */
void dbIteratorInit(dbIterator *dbit, redisDb *db); void dbIteratorInit(dbIterator *dbit, redisDb *db);
dict *dbIteratorNextDict(dbIterator *dbit); dict *dbIteratorNextDict(dbIterator *dbit);
int dbIterCurSlot(dbIterator *dbit); dictEntry *dbIteratorNext(dbIterator *iter);
dict *dbGetNextNonEmptySlot(redisDb *db, int *slot); dict *dbGetNextNonEmptySlot(redisDb *db, int *slot);
/* SCAN specific commands for easy cursor manipulation, shared between main code and modules. */ /* SCAN specific commands for easy cursor manipulation, shared between main code and modules. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment