summaryrefslogtreecommitdiff
path: root/src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/module.c b/src/module.c
index c42536449..e938b98d7 100644
--- a/src/module.c
+++ b/src/module.c
@@ -625,9 +625,7 @@ int moduleCreateEmptyKey(RedisModuleKey *key, int type) {
switch(type) {
case REDISMODULE_KEYTYPE_LIST:
- obj = createQuicklistObject();
- quicklistSetOptions(obj->ptr, server.list_max_listpack_size,
- server.list_compress_depth);
+ obj = createListListpackObject();
break;
case REDISMODULE_KEYTYPE_ZSET:
obj = createZsetListpackObject();
@@ -660,6 +658,14 @@ static void moduleFreeKeyIterator(RedisModuleKey *key) {
key->iter = NULL;
}
+/* Callback for listTypeTryConversion().
+ * Frees list iterator and sets it to NULL. */
+static void moduleFreeListIterator(void *data) {
+ RedisModuleKey *key = (RedisModuleKey*)data;
+ serverAssert(key->value->type == OBJ_LIST);
+ if (key->iter) moduleFreeKeyIterator(key);
+}
+
/* This function is called in low-level API implementation functions in order
* to check if the value associated with the key remained empty after an
* operation that removed elements from an aggregate data type.
@@ -4148,7 +4154,7 @@ int moduleListIteratorSeek(RedisModuleKey *key, long index, int mode) {
/* Seek the iterator to the requested index. */
unsigned char dir = key->u.list.index < index ? LIST_TAIL : LIST_HEAD;
- listTypeSetIteratorDirection(key->iter, dir);
+ listTypeSetIteratorDirection(key->iter, &key->u.list.entry, dir);
while (key->u.list.index != index) {
serverAssert(listTypeNext(key->iter, &key->u.list.entry));
key->u.list.index += dir == LIST_HEAD ? -1 : 1;
@@ -4183,6 +4189,7 @@ int RM_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele) {
if (key->value && key->value->type != OBJ_LIST) return REDISMODULE_ERR;
if (key->iter) moduleFreeKeyIterator(key);
if (key->value == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_LIST);
+ listTypeTryConversionAppend(key->value, &ele, 0, 0, moduleFreeListIterator, key);
listTypePush(key->value, ele,
(where == REDISMODULE_LIST_HEAD) ? LIST_HEAD : LIST_TAIL);
return REDISMODULE_OK;
@@ -4216,7 +4223,8 @@ RedisModuleString *RM_ListPop(RedisModuleKey *key, int where) {
(where == REDISMODULE_LIST_HEAD) ? LIST_HEAD : LIST_TAIL);
robj *decoded = getDecodedObject(ele);
decrRefCount(ele);
- moduleDelKeyIfEmpty(key);
+ if (!moduleDelKeyIfEmpty(key))
+ listTypeTryConversion(key->value, LIST_CONV_SHRINKING, moduleFreeListIterator, key);
autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
return decoded;
}
@@ -4270,6 +4278,11 @@ int RM_ListSet(RedisModuleKey *key, long index, RedisModuleString *value) {
errno = EINVAL;
return REDISMODULE_ERR;
}
+ if (!key->value || key->value->type != OBJ_LIST) {
+ errno = ENOTSUP;
+ return REDISMODULE_ERR;
+ }
+ listTypeTryConversionAppend(key->value, &value, 0, 0, moduleFreeListIterator, key);
if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
listTypeReplace(&key->u.list.entry, value);
/* A note in quicklist.c forbids use of iterator after insert, so
@@ -4315,6 +4328,7 @@ int RM_ListInsert(RedisModuleKey *key, long index, RedisModuleString *value) {
/* Insert before the first element => push head. */
return RM_ListPush(key, REDISMODULE_LIST_HEAD, value);
}
+ listTypeTryConversionAppend(key->value, &value, 0, 0, moduleFreeListIterator, key);
if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
int where = index < 0 ? LIST_TAIL : LIST_HEAD;
listTypeInsert(&key->u.list.entry, value, where);
@@ -4341,6 +4355,8 @@ int RM_ListDelete(RedisModuleKey *key, long index) {
if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
listTypeDelete(key->iter, &key->u.list.entry);
if (moduleDelKeyIfEmpty(key)) return REDISMODULE_OK;
+ listTypeTryConversion(key->value, LIST_CONV_SHRINKING, moduleFreeListIterator, key);
+ if (!key->iter) return REDISMODULE_OK; /* Return ASAP if iterator has been freed */
if (listTypeNext(key->iter, &key->u.list.entry)) {
/* After delete entry at position 'index', we need to update
* 'key->u.list.index' according to the following cases: