summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2020-02-28 17:47:52 +0100
committerGitHub <noreply@github.com>2020-02-28 17:47:52 +0100
commit86cbddc475048ffa1939a2787a3dd28fe159a1f3 (patch)
treeeb9907ca369fffc2a0dd8e242f56f47d5f95cbe4 /src
parent4ccb56d0e68829315b55624b25a50fce24693357 (diff)
parent28ef18a8946815e0d83a1c0a9b6baf9d27022461 (diff)
downloadredis-86cbddc475048ffa1939a2787a3dd28fe159a1f3.tar.gz
Merge pull request #6838 from oranagra/rm_scan_dict_rehash
RM_Scan disable dict rehashing
Diffstat (limited to 'src')
-rw-r--r--src/dict.c7
-rw-r--r--src/module.c20
2 files changed, 21 insertions, 6 deletions
diff --git a/src/dict.c b/src/dict.c
index 106467ef7..93e6c39a7 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -871,6 +871,10 @@ unsigned long dictScan(dict *d,
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)) {
t0 = &(d->ht[0]);
m0 = t0->sizemask;
@@ -937,6 +941,9 @@ unsigned long dictScan(dict *d,
} while (v & (m0 ^ m1));
}
+ /* undo the ++ at the top */
+ d->iterators--;
+
return v;
}
diff --git a/src/module.c b/src/module.c
index b00118681..b821f0c31 100644
--- a/src/module.c
+++ b/src/module.c
@@ -6553,9 +6553,13 @@ void RM_ScanCursorDestroy(RedisModuleScanCursor *cursor) {
* }
* RedisModule_ScanCursorDestroy(c);
*
- * The function will return 1 if there are more elements to scan and 0 otherwise,
- * possibly setting errno if the call failed.
- * It is also possible to restart and existing cursor using RM_CursorRestart. */
+ * The function will return 1 if there are more elements to scan and 0 otherwise,
+ * possibly setting errno if the call failed.
+ * 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) {
if (cursor->done) {
errno = ENOENT;
@@ -6633,9 +6637,13 @@ static void moduleScanKeyCallback(void *privdata, const dictEntry *de) {
* RedisModule_CloseKey(key);
* RedisModule_ScanCursorDestroy(c);
*
- * The function will return 1 if there are more elements to scan and 0 otherwise,
- * possibly setting errno if the call failed.
- * It is also possible to restart and existing cursor using RM_CursorRestart. */
+ * The function will return 1 if there are more elements to scan and 0 otherwise,
+ * possibly setting errno if the call failed.
+ * 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) {
if (key == NULL || key->value == NULL) {
errno = EINVAL;