Commit 526d00a5 authored by antirez's avatar antirez
Browse files

SETEX implemented

parent c8d0ea0e
...@@ -67,6 +67,7 @@ static struct redisCommand cmdTable[] = { ...@@ -67,6 +67,7 @@ static struct redisCommand cmdTable[] = {
{"get",2,REDIS_CMD_INLINE}, {"get",2,REDIS_CMD_INLINE},
{"set",3,REDIS_CMD_BULK}, {"set",3,REDIS_CMD_BULK},
{"setnx",3,REDIS_CMD_BULK}, {"setnx",3,REDIS_CMD_BULK},
{"setex",4,REDIS_CMD_BULK},
{"append",3,REDIS_CMD_BULK}, {"append",3,REDIS_CMD_BULK},
{"substr",4,REDIS_CMD_INLINE}, {"substr",4,REDIS_CMD_INLINE},
{"del",-2,REDIS_CMD_INLINE}, {"del",-2,REDIS_CMD_INLINE},
......
...@@ -628,6 +628,7 @@ static void pingCommand(redisClient *c); ...@@ -628,6 +628,7 @@ static void pingCommand(redisClient *c);
static void echoCommand(redisClient *c); static void echoCommand(redisClient *c);
static void setCommand(redisClient *c); static void setCommand(redisClient *c);
static void setnxCommand(redisClient *c); static void setnxCommand(redisClient *c);
static void setexCommand(redisClient *c);
static void getCommand(redisClient *c); static void getCommand(redisClient *c);
static void delCommand(redisClient *c); static void delCommand(redisClient *c);
static void existsCommand(redisClient *c); static void existsCommand(redisClient *c);
...@@ -736,6 +737,7 @@ static struct redisCommand cmdTable[] = { ...@@ -736,6 +737,7 @@ static struct redisCommand cmdTable[] = {
{"get",getCommand,2,REDIS_CMD_INLINE,NULL,1,1,1}, {"get",getCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
{"set",setCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0}, {"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}, {"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}, {"append",appendCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
{"substr",substrCommand,4,REDIS_CMD_INLINE,NULL,1,1,1}, {"substr",substrCommand,4,REDIS_CMD_INLINE,NULL,1,1,1},
{"del",delCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0}, {"del",delCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
...@@ -3984,40 +3986,55 @@ static void echoCommand(redisClient *c) { ...@@ -3984,40 +3986,55 @@ static void echoCommand(redisClient *c) {
/*=================================== Strings =============================== */ /*=================================== Strings =============================== */
static void setGenericCommand(redisClient *c, int nx) { static void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire) {
int retval; int retval;
long seconds;
if (nx) deleteIfVolatile(c->db,c->argv[1]); if (expire) {
retval = dictAdd(c->db->dict,c->argv[1],c->argv[2]); 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 (retval == DICT_ERR) {
if (!nx) { if (!nx) {
/* If the key is about a swapped value, we want a new key object /* 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. * 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 * This will also make sure that swap pages about the old object
* will be marked as free. */ * will be marked as free. */
if (server.vm_enabled && deleteIfSwapped(c->db,c->argv[1])) if (server.vm_enabled && deleteIfSwapped(c->db,key))
incrRefCount(c->argv[1]); incrRefCount(key);
dictReplace(c->db->dict,c->argv[1],c->argv[2]); dictReplace(c->db->dict,key,val);
incrRefCount(c->argv[2]); incrRefCount(val);
} else { } else {
addReply(c,shared.czero); addReply(c,shared.czero);
return; return;
} }
} else { } else {
incrRefCount(c->argv[1]); incrRefCount(key);
incrRefCount(c->argv[2]); incrRefCount(val);
} }
server.dirty++; 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); addReply(c, nx ? shared.cone : shared.ok);
} }
static void setCommand(redisClient *c) { static void setCommand(redisClient *c) {
setGenericCommand(c,0); setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
} }
static void setnxCommand(redisClient *c) { 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) { static int getGenericCommand(redisClient *c) {
......
...@@ -40,7 +40,7 @@ array set ::redis::multibulkarg {} ...@@ -40,7 +40,7 @@ array set ::redis::multibulkarg {}
# Flag commands requiring last argument as a bulk write operation # Flag commands requiring last argument as a bulk write operation
foreach redis_bulk_cmd { 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) {} set ::redis::bulkarg($redis_bulk_cmd) {}
} }
......
...@@ -1941,6 +1941,30 @@ proc main {} { ...@@ -1941,6 +1941,30 @@ proc main {} {
$r ttl x $r ttl x
} {1[345]} } {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} { test {ZSETs skiplist implementation backlink consistency test} {
set diff 0 set diff 0
set elements 10000 set elements 10000
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment