From 526d00a572a3562bfab0cefd732aa13b7fcc0bff Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 23 Apr 2010 19:07:33 +0200 Subject: [PATCH 1/1] SETEX implemented --- redis-cli.c | 1 + redis.c | 41 +++++++++++++++++++++++++++++------------ redis.tcl | 2 +- test-redis.tcl | 24 ++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/redis-cli.c b/redis-cli.c index b34c4277..35582445 100644 --- a/redis-cli.c +++ b/redis-cli.c @@ -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}, diff --git a/redis.c b/redis.c index c4325c4b..1aae04c9 100644 --- a/redis.c +++ b/redis.c @@ -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) { diff --git a/redis.tcl b/redis.tcl index 81569796..0f4e401f 100644 --- a/redis.tcl +++ b/redis.tcl @@ -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) {} } diff --git a/test-redis.tcl b/test-redis.tcl index 7f4ce9c7..26b7f12a 100644 --- a/test-redis.tcl +++ b/test-redis.tcl @@ -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 -- 2.45.2