SETEX implemented

This commit is contained in:
antirez 2010-04-23 19:07:33 +02:00
parent c8d0ea0ef1
commit 526d00a572
4 changed files with 55 additions and 13 deletions

View File

@ -67,6 +67,7 @@ static struct redisCommand cmdTable[] = {
{"get",2,REDIS_CMD_INLINE},
{"set",3,REDIS_CMD_BULK},
{"setnx",3,REDIS_CMD_BULK},
{"setex",4,REDIS_CMD_BULK},
{"append",3,REDIS_CMD_BULK},
{"substr",4,REDIS_CMD_INLINE},
{"del",-2,REDIS_CMD_INLINE},

41
redis.c
View File

@ -628,6 +628,7 @@ static void pingCommand(redisClient *c);
static void echoCommand(redisClient *c);
static void setCommand(redisClient *c);
static void setnxCommand(redisClient *c);
static void setexCommand(redisClient *c);
static void getCommand(redisClient *c);
static void delCommand(redisClient *c);
static void existsCommand(redisClient *c);
@ -736,6 +737,7 @@ static struct redisCommand cmdTable[] = {
{"get",getCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
{"set",setCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},
{"setnx",setnxCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},
{"setex",setexCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},
{"append",appendCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
{"substr",substrCommand,4,REDIS_CMD_INLINE,NULL,1,1,1},
{"del",delCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
@ -3984,40 +3986,55 @@ static void echoCommand(redisClient *c) {
/*=================================== Strings =============================== */
static void setGenericCommand(redisClient *c, int nx) {
static void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire) {
int retval;
long seconds;
if (nx) deleteIfVolatile(c->db,c->argv[1]);
retval = dictAdd(c->db->dict,c->argv[1],c->argv[2]);
if (expire) {
if (getLongFromObjectOrReply(c, expire, &seconds, NULL) != REDIS_OK)
return;
if (seconds <= 0) {
addReplySds(c,sdsnew("-ERR invalid expire time in SETEX\r\n"));
return;
}
}
if (nx) deleteIfVolatile(c->db,key);
retval = dictAdd(c->db->dict,key,val);
if (retval == DICT_ERR) {
if (!nx) {
/* If the key is about a swapped value, we want a new key object
* to overwrite the old. So we delete the old key in the database.
* This will also make sure that swap pages about the old object
* will be marked as free. */
if (server.vm_enabled && deleteIfSwapped(c->db,c->argv[1]))
incrRefCount(c->argv[1]);
dictReplace(c->db->dict,c->argv[1],c->argv[2]);
incrRefCount(c->argv[2]);
if (server.vm_enabled && deleteIfSwapped(c->db,key))
incrRefCount(key);
dictReplace(c->db->dict,key,val);
incrRefCount(val);
} else {
addReply(c,shared.czero);
return;
}
} else {
incrRefCount(c->argv[1]);
incrRefCount(c->argv[2]);
incrRefCount(key);
incrRefCount(val);
}
server.dirty++;
removeExpire(c->db,c->argv[1]);
removeExpire(c->db,key);
if (expire) setExpire(c->db,key,time(NULL)+seconds);
addReply(c, nx ? shared.cone : shared.ok);
}
static void setCommand(redisClient *c) {
setGenericCommand(c,0);
setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
}
static void setnxCommand(redisClient *c) {
setGenericCommand(c,1);
setGenericCommand(c,1,c->argv[1],c->argv[2],NULL);
}
static void setexCommand(redisClient *c) {
setGenericCommand(c,0,c->argv[1],c->argv[3],c->argv[2]);
}
static int getGenericCommand(redisClient *c) {

View File

@ -40,7 +40,7 @@ array set ::redis::multibulkarg {}
# Flag commands requiring last argument as a bulk write operation
foreach redis_bulk_cmd {
set setnx rpush lpush lset lrem sadd srem sismember echo getset smove zadd zrem zscore zincrby append zrank zrevrank hget hdel hexists
set setnx rpush lpush lset lrem sadd srem sismember echo getset smove zadd zrem zscore zincrby append zrank zrevrank hget hdel hexists setex
} {
set ::redis::bulkarg($redis_bulk_cmd) {}
}

View File

@ -1941,6 +1941,30 @@ proc main {} {
$r ttl x
} {1[345]}
test {SETEX - Set + Expire combo operation. Check for TTL} {
$r setex x 12 test
$r ttl x
} {1[012]}
test {SETEX - Check value} {
$r get x
} {test}
test {SETEX - Overwrite old key} {
$r setex y 1 foo
$r get y
} {foo}
test {SETEX - Wait for the key to expire} {
after 3000
$r get y
} {}
test {SETEX - Wrong time parameter} {
catch {$r setex z -10 foo} e
set _ $e
} {*invalid expire*}
test {ZSETs skiplist implementation backlink consistency test} {
set diff 0
set elements 10000