+static void monitorCommand(redisClient *c) {
+ /* ignore MONITOR if aleady slave or in monitor mode */
+ if (c->flags & REDIS_SLAVE) return;
+
+ c->flags |= (REDIS_SLAVE|REDIS_MONITOR);
+ c->slaveseldb = 0;
+ if (!listAddNodeTail(server.monitors,c)) oom("listAddNodeTail");
+ addReply(c,shared.ok);
+}
+
+/* ================================= Expire ================================= */
+static int removeExpire(redisDb *db, robj *key) {
+ if (dictDelete(db->expires,key) == DICT_OK) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int setExpire(redisDb *db, robj *key, time_t when) {
+ if (dictAdd(db->expires,key,(void*)when) == DICT_ERR) {
+ return 0;
+ } else {
+ incrRefCount(key);
+ return 1;
+ }
+}
+
+static int expireIfNeeded(redisDb *db, robj *key) {
+ time_t when;
+ dictEntry *de;
+
+ /* No expire? return ASAP */
+ if (dictSize(db->expires) == 0 ||
+ (de = dictFind(db->expires,key)) == NULL) return 0;
+
+ /* Lookup the expire */
+ when = (time_t) dictGetEntryVal(de);
+ if (time(NULL) <= when) return 0;
+
+ /* Delete the key */
+ dictDelete(db->expires,key);
+ return dictDelete(db->dict,key) == DICT_OK;
+}
+
+static int deleteIfVolatile(redisDb *db, robj *key) {
+ dictEntry *de;
+
+ /* No expire? return ASAP */
+ if (dictSize(db->expires) == 0 ||
+ (de = dictFind(db->expires,key)) == NULL) return 0;
+
+ /* Delete the key */
+ dictDelete(db->expires,key);
+ return dictDelete(db->dict,key) == DICT_OK;
+}
+
+static void expireCommand(redisClient *c) {
+ dictEntry *de;
+ int seconds = atoi(c->argv[2]->ptr);
+
+ de = dictFind(c->db->dict,c->argv[1]);
+ if (de == NULL) {
+ addReply(c,shared.czero);
+ return;
+ }
+ if (seconds <= 0) {
+ addReply(c, shared.czero);
+ return;
+ } else {
+ time_t when = time(NULL)+seconds;
+ if (setExpire(c->db,c->argv[1],when))
+ addReply(c,shared.cone);
+ else
+ addReply(c,shared.czero);
+ return;
+ }
+}
+