]> git.saurik.com Git - redis.git/commitdiff
TTL, EXPIRE and EXPIREAT now support the milliseconds input/output form
authorantirez <antirez@gmail.com>
Wed, 9 Nov 2011 17:05:35 +0000 (18:05 +0100)
committerantirez <antirez@gmail.com>
Wed, 9 Nov 2011 17:05:35 +0000 (18:05 +0100)
src/db.c
src/redis.c

index dc9ca8c53091221affcf94c89c8db3a4fedc307e..755e295e52273d74367ff6c779c9179ee01ec709 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -514,6 +514,14 @@ int expireIfNeeded(redisDb *db, robj *key) {
  * Expires Commands
  *----------------------------------------------------------------------------*/
 
+/* Given an string object return true if it contains exactly the "ms"
+ * or "MS" string. This is used in order to check if the last argument
+ * of EXPIRE, EXPIREAT or TTL is "ms" to switch into millisecond input/output */
+int stringObjectEqualsMs(robj *a) {
+    char *arg = a->ptr;
+    return tolower(arg[0]) == 'm' && tolower(arg[1]) == 's' && arg[2] == '\0';
+}
+
 void expireGenericCommand(redisClient *c, long long offset) {
     dictEntry *de;
     robj *key = c->argv[1], *param = c->argv[2];
@@ -526,9 +534,7 @@ void expireGenericCommand(redisClient *c, long long offset) {
     /* If no "ms" argument was passed the time is in second, so we need
      * to multilpy it by 1000 */
     if (c->argc == 4) {
-        char *arg = c->argv[3]->ptr;
-
-        if (tolower(arg[0]) != 'm' || tolower(arg[1]) != 's' || arg[2]) {
+        if (!stringObjectEqualsMs(c->argv[3])) {
             addReply(c,shared.syntaxerr);
             return;
         }
@@ -572,15 +578,33 @@ void expireGenericCommand(redisClient *c, long long offset) {
 }
 
 void expireCommand(redisClient *c) {
+    if (c->argc > 4) {
+        addReply(c,shared.syntaxerr);
+        return;
+    }
     expireGenericCommand(c,0);
 }
 
 void expireatCommand(redisClient *c) {
+    if (c->argc > 4) {
+        addReply(c,shared.syntaxerr);
+        return;
+    }
     expireGenericCommand(c,mstime());
 }
 
 void ttlCommand(redisClient *c) {
     long long expire, ttl = -1;
+    int output_ms = 0;
+
+    if (c->argc == 3) {
+        if (stringObjectEqualsMs(c->argv[2])) {
+            output_ms = 1;
+        } else {
+            addReply(c,shared.syntaxerr);
+            return;
+        }
+    }
 
     expire = getExpire(c->db,c->argv[1]);
     if (expire != -1) {
@@ -590,7 +614,7 @@ void ttlCommand(redisClient *c) {
     if (ttl == -1) {
         addReplyLongLong(c,-1);
     } else {
-        addReplyLongLong(c,(ttl+500)/1000);
+        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));
     }
 }
 
index 7ccd823ac812f20e0567dbde907055a18344bdce..b8853253d001312393d19cc1a299d694135640ea 100644 (file)
@@ -172,8 +172,8 @@ struct redisCommand redisCommandTable[] = {
     {"move",moveCommand,3,"w",0,NULL,1,1,1,0,0},
     {"rename",renameCommand,3,"w",0,renameGetKeys,1,2,1,0,0},
     {"renamenx",renamenxCommand,3,"w",0,renameGetKeys,1,2,1,0,0},
-    {"expire",expireCommand,3,"w",0,NULL,1,1,1,0,0},
-    {"expireat",expireatCommand,3,"w",0,NULL,1,1,1,0,0},
+    {"expire",expireCommand,-3,"w",0,NULL,1,1,1,0,0},
+    {"expireat",expireatCommand,-3,"w",0,NULL,1,1,1,0,0},
     {"keys",keysCommand,2,"r",0,NULL,0,0,0,0,0},
     {"dbsize",dbsizeCommand,1,"r",0,NULL,0,0,0,0,0},
     {"auth",authCommand,2,"r",0,NULL,0,0,0,0,0},
@@ -194,7 +194,7 @@ struct redisCommand redisCommandTable[] = {
     {"sort",sortCommand,-2,"wm",0,NULL,1,1,1,0,0},
     {"info",infoCommand,-1,"r",0,NULL,0,0,0,0,0},
     {"monitor",monitorCommand,1,"ars",0,NULL,0,0,0,0,0},
-    {"ttl",ttlCommand,2,"r",0,NULL,1,1,1,0,0},
+    {"ttl",ttlCommand,-2,"r",0,NULL,1,1,1,0,0},
     {"persist",persistCommand,2,"w",0,NULL,1,1,1,0,0},
     {"slaveof",slaveofCommand,3,"aws",0,NULL,0,0,0,0,0},
     {"debug",debugCommand,-2,"aw",0,NULL,0,0,0,0,0},