Merge pull request #6838 from oranagra/rm_scan_dict_rehash

RM_Scan disable dict rehashing
This commit is contained in:
Salvatore Sanfilippo 2020-02-28 17:47:52 +01:00 committed by GitHub
commit 86cbddc475
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 6 deletions

View File

@ -871,6 +871,10 @@ unsigned long dictScan(dict *d,
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. */
d->iterators++;
if (!dictIsRehashing(d)) { if (!dictIsRehashing(d)) {
t0 = &(d->ht[0]); t0 = &(d->ht[0]);
m0 = t0->sizemask; m0 = t0->sizemask;
@ -937,6 +941,9 @@ unsigned long dictScan(dict *d,
} while (v & (m0 ^ m1)); } while (v & (m0 ^ m1));
} }
/* undo the ++ at the top */
d->iterators--;
return v; return v;
} }

View File

@ -6555,7 +6555,11 @@ void RM_ScanCursorDestroy(RedisModuleScanCursor *cursor) {
* *
* The function will return 1 if there are more elements to scan and 0 otherwise, * The function will return 1 if there are more elements to scan and 0 otherwise,
* possibly setting errno if the call failed. * possibly setting errno if the call failed.
* It is also possible to restart and existing cursor using RM_CursorRestart. */ * It is also possible to restart and existing cursor using RM_CursorRestart.
*
* NOTE: You must avoid doing any database changes from within the callback, you should avoid any
* RedisModule_OpenKey or RedisModule_Call, if you need to do these, you need to keep the key name
* and do any work you need to do after the call to Scan returns. */
int RM_Scan(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanCB fn, void *privdata) { int RM_Scan(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanCB fn, void *privdata) {
if (cursor->done) { if (cursor->done) {
errno = ENOENT; errno = ENOENT;
@ -6635,7 +6639,11 @@ static void moduleScanKeyCallback(void *privdata, const dictEntry *de) {
* *
* The function will return 1 if there are more elements to scan and 0 otherwise, * The function will return 1 if there are more elements to scan and 0 otherwise,
* possibly setting errno if the call failed. * possibly setting errno if the call failed.
* It is also possible to restart and existing cursor using RM_CursorRestart. */ * It is also possible to restart and existing cursor using RM_CursorRestart.
*
* NOTE: You must avoid doing any database changes from within the callback, you should avoid any
* RedisModule_OpenKey or RedisModule_Call, if you need to do these, you need to keep the field name
* and do any work you need to do after the call to Scan returns. */
int RM_ScanKey(RedisModuleKey *key, RedisModuleScanCursor *cursor, RedisModuleScanKeyCB fn, void *privdata) { int RM_ScanKey(RedisModuleKey *key, RedisModuleScanCursor *cursor, RedisModuleScanKeyCB fn, void *privdata) {
if (key == NULL || key->value == NULL) { if (key == NULL || key->value == NULL) {
errno = EINVAL; errno = EINVAL;