summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bitops.c2
-rw-r--r--src/db.c24
-rw-r--r--src/geo.c2
-rw-r--r--src/module.c6
-rw-r--r--src/server.h8
-rw-r--r--src/sort.c2
-rw-r--r--src/t_set.c4
-rw-r--r--src/t_string.c18
-rw-r--r--src/t_zset.c4
9 files changed, 43 insertions, 27 deletions
diff --git a/src/bitops.c b/src/bitops.c
index 5190e1035..f69e6b4c6 100644
--- a/src/bitops.c
+++ b/src/bitops.c
@@ -777,7 +777,7 @@ void bitopCommand(client *c) {
/* Store the computed value into the target key */
if (maxlen) {
o = createObject(OBJ_STRING,res);
- setKey(c,c->db,targetkey,o);
+ setKey(c,c->db,targetkey,o,0);
notifyKeyspaceEvent(NOTIFY_STRING,"set",targetkey,c->db->id);
decrRefCount(o);
server.dirty++;
diff --git a/src/db.c b/src/db.c
index 4ae0d768d..8a90d3215 100644
--- a/src/db.c
+++ b/src/db.c
@@ -243,25 +243,29 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) {
* 1) The ref count of the value object is incremented.
* 2) clients WATCHing for the destination key notified.
* 3) The expire time of the key is reset (the key is made persistent),
- * unless 'keepttl' is true.
+ * unless 'SETKEY_KEEPTTL' is enabled in flags.
+ * 4) The key lookup can take place outside this interface outcome will be
+ * delivered with 'SETKEY_ALREADY_EXIST' or 'SETKEY_DOESNT_EXIST'
*
* All the new keys in the database should be created via this interface.
* The client 'c' argument may be set to NULL if the operation is performed
* in a context where there is no clear client performing the operation. */
-void genericSetKey(client *c, redisDb *db, robj *key, robj *val, int keepttl, int signal) {
- if (lookupKeyWrite(db,key) == NULL) {
+void setKey(client *c, redisDb *db, robj *key, robj *val, int flags) {
+ int keyfound = 0;
+
+ if (flags & SETKEY_ALREADY_EXIST)
+ keyfound = 1;
+ else if (!(flags & SETKEY_DOESNT_EXIST))
+ keyfound = (lookupKeyWrite(db,key) != NULL);
+
+ if (!keyfound) {
dbAdd(db,key,val);
} else {
dbOverwrite(db,key,val);
}
incrRefCount(val);
- if (!keepttl) removeExpire(db,key);
- if (signal) signalModifiedKey(c,db,key);
-}
-
-/* Common case for genericSetKey() where the TTL is not retained. */
-void setKey(client *c, redisDb *db, robj *key, robj *val) {
- genericSetKey(c,db,key,val,0,1);
+ if (!(flags & SETKEY_KEEPTTL)) removeExpire(db,key);
+ if (!(flags & SETKEY_NO_SIGNAL)) signalModifiedKey(c,db,key);
}
/* Return a random key, in form of a Redis object.
diff --git a/src/geo.c b/src/geo.c
index d60cebf53..26feea698 100644
--- a/src/geo.c
+++ b/src/geo.c
@@ -820,7 +820,7 @@ void georadiusGeneric(client *c, int srcKeyIndex, int flags) {
if (returned_items) {
zsetConvertToListpackIfNeeded(zobj,maxelelen,totelelen);
- setKey(c,c->db,storekey,zobj);
+ setKey(c,c->db,storekey,zobj,0);
decrRefCount(zobj);
notifyKeyspaceEvent(NOTIFY_ZSET,flags & GEOSEARCH ? "geosearchstore" : "georadiusstore",storekey,
c->db->id);
diff --git a/src/module.c b/src/module.c
index 37bfa2173..53ba70f77 100644
--- a/src/module.c
+++ b/src/module.c
@@ -3079,7 +3079,7 @@ int RM_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx) {
int RM_StringSet(RedisModuleKey *key, RedisModuleString *str) {
if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
RM_DeleteKey(key);
- genericSetKey(key->ctx->client,key->db,key->key,str,0,0);
+ setKey(key->ctx->client,key->db,key->key,str,SETKEY_NO_SIGNAL);
key->value = str;
return REDISMODULE_OK;
}
@@ -3159,7 +3159,7 @@ int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
if (key->value == NULL) {
/* Empty key: create it with the new size. */
robj *o = createObject(OBJ_STRING,sdsnewlen(NULL, newlen));
- genericSetKey(key->ctx->client,key->db,key->key,o,0,0);
+ setKey(key->ctx->client,key->db,key->key,o,SETKEY_NO_SIGNAL);
key->value = o;
decrRefCount(o);
} else {
@@ -5437,7 +5437,7 @@ int RM_ModuleTypeSetValue(RedisModuleKey *key, moduleType *mt, void *value) {
if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
RM_DeleteKey(key);
robj *o = createModuleObject(mt,value);
- genericSetKey(key->ctx->client,key->db,key->key,o,0,0);
+ setKey(key->ctx->client,key->db,key->key,o,SETKEY_NO_SIGNAL);
decrRefCount(o);
key->value = o;
return REDISMODULE_OK;
diff --git a/src/server.h b/src/server.h
index fd5762db9..9eca98230 100644
--- a/src/server.h
+++ b/src/server.h
@@ -2645,8 +2645,12 @@ int objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
void dbAdd(redisDb *db, robj *key, robj *val);
int dbAddRDBLoad(redisDb *db, sds key, robj *val);
void dbOverwrite(redisDb *db, robj *key, robj *val);
-void genericSetKey(client *c, redisDb *db, robj *key, robj *val, int keepttl, int signal);
-void setKey(client *c, redisDb *db, robj *key, robj *val);
+
+#define SETKEY_KEEPTTL 1
+#define SETKEY_NO_SIGNAL 2
+#define SETKEY_ALREADY_EXIST 4
+#define SETKEY_DOESNT_EXIST 8
+void setKey(client *c, redisDb *db, robj *key, robj *val, int flags);
robj *dbRandomKey(redisDb *db);
int dbSyncDelete(redisDb *db, robj *key);
int dbDelete(redisDb *db, robj *key);
diff --git a/src/sort.c b/src/sort.c
index 1eb61f83a..436c7fb0e 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -570,7 +570,7 @@ void sortCommandGeneric(client *c, int readonly) {
}
}
if (outputlen) {
- setKey(c,c->db,storekey,sobj);
+ setKey(c,c->db,storekey,sobj,0);
notifyKeyspaceEvent(NOTIFY_LIST,"sortstore",storekey,
c->db->id);
server.dirty += outputlen;
diff --git a/src/t_set.c b/src/t_set.c
index 72743a6fd..ec9749f13 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -987,7 +987,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
/* Store the resulting set into the target, if the intersection
* is not an empty set. */
if (setTypeSize(dstset) > 0) {
- setKey(c,c->db,dstkey,dstset);
+ setKey(c,c->db,dstkey,dstset,0);
addReplyLongLong(c,setTypeSize(dstset));
notifyKeyspaceEvent(NOTIFY_SET,"sinterstore",
dstkey,c->db->id);
@@ -1191,7 +1191,7 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
/* If we have a target key where to store the resulting set
* create this key with the result set inside */
if (setTypeSize(dstset) > 0) {
- setKey(c,c->db,dstkey,dstset);
+ setKey(c,c->db,dstkey,dstset,0);
addReplyLongLong(c,setTypeSize(dstset));
notifyKeyspaceEvent(NOTIFY_SET,
op == SET_OP_UNION ? "sunionstore" : "sdiffstore",
diff --git a/src/t_string.c b/src/t_string.c
index f1c1fdca2..e1917958b 100644
--- a/src/t_string.c
+++ b/src/t_string.c
@@ -77,6 +77,9 @@ static int getExpireMillisecondsOrReply(client *c, robj *expire, int flags, int
void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) {
long long milliseconds = 0; /* initialized to avoid any harmness warning */
+ int found = 0;
+ int setkey_flags = 0;
+
if (expire && getExpireMillisecondsOrReply(c, expire, flags, unit, &milliseconds) != C_OK) {
return;
}
@@ -85,8 +88,10 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
if (getGenericCommand(c) == C_ERR) return;
}
- if ((flags & OBJ_SET_NX && lookupKeyWrite(c->db,key) != NULL) ||
- (flags & OBJ_SET_XX && lookupKeyWrite(c->db,key) == NULL))
+ found = (lookupKeyWrite(c->db,key) != NULL);
+
+ if ((flags & OBJ_SET_NX && found) ||
+ (flags & OBJ_SET_XX && !found))
{
if (!(flags & OBJ_SET_GET)) {
addReply(c, abort_reply ? abort_reply : shared.null[c->resp]);
@@ -94,7 +99,10 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
return;
}
- genericSetKey(c,c->db,key, val,flags & OBJ_KEEPTTL,1);
+ setkey_flags |= (flags & OBJ_KEEPTTL) ? SETKEY_KEEPTTL : 0;
+ setkey_flags |= found ? SETKEY_ALREADY_EXIST : SETKEY_DOESNT_EXIST;
+
+ setKey(c,c->db,key,val,setkey_flags);
server.dirty++;
notifyKeyspaceEvent(NOTIFY_STRING,"set",key,c->db->id);
@@ -418,7 +426,7 @@ void getdelCommand(client *c) {
void getsetCommand(client *c) {
if (getGenericCommand(c) == C_ERR) return;
c->argv[2] = tryObjectEncoding(c->argv[2]);
- setKey(c,c->db,c->argv[1],c->argv[2]);
+ setKey(c,c->db,c->argv[1],c->argv[2],0);
notifyKeyspaceEvent(NOTIFY_STRING,"set",c->argv[1],c->db->id);
server.dirty++;
@@ -567,7 +575,7 @@ void msetGenericCommand(client *c, int nx) {
for (j = 1; j < c->argc; j += 2) {
c->argv[j+1] = tryObjectEncoding(c->argv[j+1]);
- setKey(c,c->db,c->argv[j],c->argv[j+1]);
+ setKey(c,c->db,c->argv[j],c->argv[j+1],0);
notifyKeyspaceEvent(NOTIFY_STRING,"set",c->argv[j],c->db->id);
}
server.dirty += (c->argc-1)/2;
diff --git a/src/t_zset.c b/src/t_zset.c
index 952d24709..06c2d2372 100644
--- a/src/t_zset.c
+++ b/src/t_zset.c
@@ -2762,7 +2762,7 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in
if (dstkey) {
if (dstzset->zsl->length) {
zsetConvertToListpackIfNeeded(dstobj, maxelelen, totelelen);
- setKey(c, c->db, dstkey, dstobj);
+ setKey(c, c->db, dstkey, dstobj, 0);
addReplyLongLong(c, zsetLength(dstobj));
notifyKeyspaceEvent(NOTIFY_ZSET,
(op == SET_OP_UNION) ? "zunionstore" :
@@ -2955,7 +2955,7 @@ static void zrangeResultEmitLongLongForStore(zrange_result_handler *handler,
static void zrangeResultFinalizeStore(zrange_result_handler *handler, size_t result_count)
{
if (result_count) {
- setKey(handler->client, handler->client->db, handler->dstkey, handler->dstobj);
+ setKey(handler->client, handler->client->db, handler->dstkey, handler->dstobj, 0);
addReplyLongLong(handler->client, result_count);
notifyKeyspaceEvent(NOTIFY_ZSET, "zrangestore", handler->dstkey, handler->client->db->id);
server.dirty++;