"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/dict.c" between
redis-6.2-rc3.tar.gz and redis-6.2.0.tar.gz

About: redis is an advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.

dict.c  (redis-6.2-rc3):dict.c  (redis-6.2.0)
skipping to change at line 129 skipping to change at line 129
/* Initialize the hash table */ /* Initialize the hash table */
int _dictInit(dict *d, dictType *type, int _dictInit(dict *d, dictType *type,
void *privDataPtr) void *privDataPtr)
{ {
_dictReset(&d->ht[0]); _dictReset(&d->ht[0]);
_dictReset(&d->ht[1]); _dictReset(&d->ht[1]);
d->type = type; d->type = type;
d->privdata = privDataPtr; d->privdata = privDataPtr;
d->rehashidx = -1; d->rehashidx = -1;
d->iterators = 0; d->pauserehash = 0;
return DICT_OK; return DICT_OK;
} }
/* Resize the table to the minimal size that contains all the elements, /* Resize the table to the minimal size that contains all the elements,
* but with the invariant of a USED/BUCKETS ratio near to <= 1 */ * but with the invariant of a USED/BUCKETS ratio near to <= 1 */
int dictResize(dict *d) int dictResize(dict *d)
{ {
unsigned long minimal; unsigned long minimal;
if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR; if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;
skipping to change at line 267 skipping to change at line 267
struct timeval tv; struct timeval tv;
gettimeofday(&tv,NULL); gettimeofday(&tv,NULL);
return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);
} }
/* Rehash in ms+"delta" milliseconds. The value of "delta" is larger /* Rehash in ms+"delta" milliseconds. The value of "delta" is larger
* than 0, and is smaller than 1 in most cases. The exact upper bound * than 0, and is smaller than 1 in most cases. The exact upper bound
* depends on the running time of dictRehash(d,100).*/ * depends on the running time of dictRehash(d,100).*/
int dictRehashMilliseconds(dict *d, int ms) { int dictRehashMilliseconds(dict *d, int ms) {
if (d->iterators > 0) return 0; if (d->pauserehash > 0) return 0;
long long start = timeInMilliseconds(); long long start = timeInMilliseconds();
int rehashes = 0; int rehashes = 0;
while(dictRehash(d,100)) { while(dictRehash(d,100)) {
rehashes += 100; rehashes += 100;
if (timeInMilliseconds()-start > ms) break; if (timeInMilliseconds()-start > ms) break;
} }
return rehashes; return rehashes;
} }
/* This function performs just a step of rehashing, and only if there are /* This function performs just a step of rehashing, and only if hashing has
* no safe iterators bound to our hash table. When we have iterators in the * not been paused for our hash table. When we have iterators in the
* middle of a rehashing we can't mess with the two hash tables otherwise * middle of a rehashing we can't mess with the two hash tables otherwise
* some element can be missed or duplicated. * some element can be missed or duplicated.
* *
* This function is called by common lookup or update operations in the * This function is called by common lookup or update operations in the
* dictionary so that the hash table automatically migrates from H1 to H2 * dictionary so that the hash table automatically migrates from H1 to H2
* while it is actively used. */ * while it is actively used. */
static void _dictRehashStep(dict *d) { static void _dictRehashStep(dict *d) {
if (d->iterators == 0) dictRehash(d,1); if (d->pauserehash == 0) dictRehash(d,1);
} }
/* Add an element to the target hash table */ /* Add an element to the target hash table */
int dictAdd(dict *d, void *key, void *val) int dictAdd(dict *d, void *key, void *val)
{ {
dictEntry *entry = dictAddRaw(d,key,NULL); dictEntry *entry = dictAddRaw(d,key,NULL);
if (!entry) return DICT_ERR; if (!entry) return DICT_ERR;
dictSetVal(d, entry, val); dictSetVal(d, entry, val);
return DICT_OK; return DICT_OK;
} }
/* Low level add or find: /* Low level add or find:
* This function adds the entry but instead of setting a value returns the * This function adds the entry but instead of setting a value returns the
* dictEntry structure to the user, that will make sure to fill the value * dictEntry structure to the user, that will make sure to fill the value
* field as he wishes. * field as they wish.
* *
* This function is also directly exposed to the user API to be called * This function is also directly exposed to the user API to be called
* mainly in order to store non-pointers inside the hash value, example: * mainly in order to store non-pointers inside the hash value, example:
* *
* entry = dictAddRaw(dict,mykey,NULL); * entry = dictAddRaw(dict,mykey,NULL);
* if (entry != NULL) dictSetSignedIntegerVal(entry,1000); * if (entry != NULL) dictSetSignedIntegerVal(entry,1000);
* *
* Return values: * Return values:
* *
* If key already exists NULL is returned, and "*existing" is populated * If key already exists NULL is returned, and "*existing" is populated
skipping to change at line 596 skipping to change at line 596
return i; return i;
} }
dictEntry *dictNext(dictIterator *iter) dictEntry *dictNext(dictIterator *iter)
{ {
while (1) { while (1) {
if (iter->entry == NULL) { if (iter->entry == NULL) {
dictht *ht = &iter->d->ht[iter->table]; dictht *ht = &iter->d->ht[iter->table];
if (iter->index == -1 && iter->table == 0) { if (iter->index == -1 && iter->table == 0) {
if (iter->safe) if (iter->safe)
iter->d->iterators++; dictPauseRehashing(iter->d);
else else
iter->fingerprint = dictFingerprint(iter->d); iter->fingerprint = dictFingerprint(iter->d);
} }
iter->index++; iter->index++;
if (iter->index >= (long) ht->size) { if (iter->index >= (long) ht->size) {
if (dictIsRehashing(iter->d) && iter->table == 0) { if (dictIsRehashing(iter->d) && iter->table == 0) {
iter->table++; iter->table++;
iter->index = 0; iter->index = 0;
ht = &iter->d->ht[1]; ht = &iter->d->ht[1];
} else { } else {
skipping to change at line 628 skipping to change at line 628
return iter->entry; return iter->entry;
} }
} }
return NULL; return NULL;
} }
void dictReleaseIterator(dictIterator *iter) void dictReleaseIterator(dictIterator *iter)
{ {
if (!(iter->index == -1 && iter->table == 0)) { if (!(iter->index == -1 && iter->table == 0)) {
if (iter->safe) if (iter->safe)
iter->d->iterators--; dictResumeRehashing(iter->d);
else else
assert(iter->fingerprint == dictFingerprint(iter->d)); assert(iter->fingerprint == dictFingerprint(iter->d));
} }
zfree(iter); zfree(iter);
} }
/* Return a random entry from the hash table. Useful to /* Return a random entry from the hash table. Useful to
* implement randomized algorithms */ * implement randomized algorithms */
dictEntry *dictGetRandomKey(dict *d) dictEntry *dictGetRandomKey(dict *d)
{ {
skipping to change at line 899 skipping to change at line 899
dictScanFunction *fn, dictScanFunction *fn,
dictScanBucketFunction* bucketfn, dictScanBucketFunction* bucketfn,
void *privdata) void *privdata)
{ {
dictht *t0, *t1; dictht *t0, *t1;
const dictEntry *de, *next; const dictEntry *de, *next;
unsigned long m0, m1; unsigned long m0, m1;
if (dictSize(d) == 0) return 0; if (dictSize(d) == 0) return 0;
/* Having a safe iterator means no rehashing can happen, see _dictRehashStep /* This is needed in case the scan callback tries to do dictFind or alike. *
. /
* This is needed in case the scan callback tries to do dictFind or alike. * dictPauseRehashing(d);
/
d->iterators++;
if (!dictIsRehashing(d)) { if (!dictIsRehashing(d)) {
t0 = &(d->ht[0]); t0 = &(d->ht[0]);
m0 = t0->sizemask; m0 = t0->sizemask;
/* Emit entries at cursor */ /* Emit entries at cursor */
if (bucketfn) bucketfn(privdata, &t0->table[v & m0]); if (bucketfn) bucketfn(privdata, &t0->table[v & m0]);
de = t0->table[v & m0]; de = t0->table[v & m0];
while (de) { while (de) {
next = de->next; next = de->next;
skipping to change at line 969 skipping to change at line 968
/* Increment the reverse cursor not covered by the smaller mask.*/ /* Increment the reverse cursor not covered by the smaller mask.*/
v |= ~m1; v |= ~m1;
v = rev(v); v = rev(v);
v++; v++;
v = rev(v); v = rev(v);
/* Continue while bits covered by mask difference is non-zero */ /* Continue while bits covered by mask difference is non-zero */
} while (v & (m0 ^ m1)); } while (v & (m0 ^ m1));
} }
/* undo the ++ at the top */ dictResumeRehashing(d);
d->iterators--;
return v; return v;
} }
/* ------------------------- private functions ------------------------------ */ /* ------------------------- private functions ------------------------------ */
/* Because we may need to allocate huge memory chunk at once when dict /* Because we may need to allocate huge memory chunk at once when dict
* expands, we will check this allocation is allowed or not if the dict * expands, we will check this allocation is allowed or not if the dict
* type has expandAllowed member function. */ * type has expandAllowed member function. */
static int dictTypeExpandAllowed(dict *d) { static int dictTypeExpandAllowed(dict *d) {
skipping to change at line 1059 skipping to change at line 1057
} }
if (!dictIsRehashing(d)) break; if (!dictIsRehashing(d)) break;
} }
return idx; return idx;
} }
void dictEmpty(dict *d, void(callback)(void*)) { void dictEmpty(dict *d, void(callback)(void*)) {
_dictClear(d,&d->ht[0],callback); _dictClear(d,&d->ht[0],callback);
_dictClear(d,&d->ht[1],callback); _dictClear(d,&d->ht[1],callback);
d->rehashidx = -1; d->rehashidx = -1;
d->iterators = 0; d->pauserehash = 0;
} }
void dictEnableResize(void) { void dictEnableResize(void) {
dict_can_resize = 1; dict_can_resize = 1;
} }
void dictDisableResize(void) { void dictDisableResize(void) {
dict_can_resize = 0; dict_can_resize = 0;
} }
 End of changes. 10 change blocks. 
16 lines changed or deleted 13 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)