From ece74202bbb2ff6b97b407755d5b9206db82cb17 Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Wed, 6 Apr 2011 12:19:45 +0200
Subject: [PATCH] OBJECT command implemented

---
 src/object.c | 39 +++++++++++++++++++++++++++++++++++++++
 src/redis.c  |  3 ++-
 src/redis.h  |  1 +
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/src/object.c b/src/object.c
index e6b02da8..4de9dbaa 100644
--- a/src/object.c
+++ b/src/object.c
@@ -416,3 +416,42 @@ unsigned long estimateObjectIdleTime(robj *o) {
                     REDIS_LRU_CLOCK_RESOLUTION;
     }
 }
+
+/* This is an helper function for the DEBUG command. We need to lookup keys
+ * without any modification of LRU or other parameters. */
+robj *objectCommandLookup(redisClient *c, robj *key) {
+    dictEntry *de;
+
+    if ((de = dictFind(c->db->dict,key->ptr)) == NULL) return NULL;
+    return (robj*) dictGetEntryVal(de);
+}
+
+robj *objectCommandLookupOrReply(redisClient *c, robj *key, robj *reply) {
+    robj *o = objectCommandLookup(c,key);
+
+    if (!o) addReply(c, reply);
+    return o;
+}
+
+/* Object command allows to inspect the internals of an Redis Object.
+ * Usage: OBJECT <verb> ... arguments ... */
+void objectCommand(redisClient *c) {
+    robj *o;
+
+    if (!strcasecmp(c->argv[1]->ptr,"refcount") && c->argc == 3) {
+        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))
+                == NULL) return;
+        addReplyLongLong(c,o->refcount);
+    } else if (!strcasecmp(c->argv[1]->ptr,"encoding") && c->argc == 3) {
+        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))
+                == NULL) return;
+        addReplyBulkCString(c,strEncoding(o->encoding));
+    } else if (!strcasecmp(c->argv[1]->ptr,"idletime") && c->argc == 3) {
+        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))
+                == NULL) return;
+        addReplyLongLong(c,estimateObjectIdleTime(o));
+    } else {
+        addReplyError(c,"Syntax error. Try OBJECT (refcount|encoding|idletime)");
+    }
+}
+
diff --git a/src/redis.c b/src/redis.c
index 1cc8cc75..9c726151 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -191,7 +191,8 @@ struct redisCommand redisCommandTable[] = {
     {"cluster",clusterCommand,-2,0,NULL,0,0,0,0,0},
     {"restore",restoreCommand,4,0,NULL,0,0,0,0,0},
     {"migrate",migrateCommand,6,0,NULL,0,0,0,0,0},
-    {"dump",dumpCommand,2,0,NULL,0,0,0,0,0}
+    {"dump",dumpCommand,2,0,NULL,0,0,0,0,0},
+    {"object",objectCommand,-2,0,NULL,0,0,0,0,0}
 };
 
 /*============================ Utility functions ============================ */
diff --git a/src/redis.h b/src/redis.h
index 91a64ecf..3ceffd42 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -1181,6 +1181,7 @@ void clusterCommand(redisClient *c);
 void restoreCommand(redisClient *c);
 void migrateCommand(redisClient *c);
 void dumpCommand(redisClient *c);
+void objectCommand(redisClient *c);
 
 #if defined(__GNUC__)
 void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
-- 
2.47.2