void brpoplpushCommand(redisClient *c) { time_t timeout; if (getTimeoutFromObjectOrReply(c,c->argv[3],&timeout) != REDIS_OK) return; robj *key = lookupKeyWrite(c->db, c->argv[1]); if (key == NULL) { if (c->flags & REDIS_MULTI) { /* Blocking against an empty list in a multi state * returns immediately. */ addReply(c, shared.nullbulk); } else { /* The list is empty and the client blocks. */ blockForKeys(c, c->argv + 1, 1, timeout, c->argv[2]); } } else { if (key->type != REDIS_LIST) { addReply(c, shared.wrongtypeerr); } else { /* The list exists and has elements, so * the regular rpoplpushCommand is executed. */ redisAssertWithInfo(c,key,listTypeLength(key) > 0); rpoplpushCommand(c); } } }
// BRPOPLPUSH source destination timeout // BRPOPLPUSH命令的实现 void brpoplpushCommand(client *c) { mstime_t timeout; //以秒为单位取出超时时间 if (getTimeoutFromObjectOrReply(c,c->argv[3],&timeout,UNIT_SECONDS) != C_OK) return; //以写操作读取出 source的值 robj *key = lookupKeyWrite(c->db, c->argv[1]); //如果键为空,阻塞 if (key == NULL) { // 如果命令在一个事务中执行,则发送一个空回复以避免死等待 if (c->flags & CLIENT_MULTI) { /* Blocking against an empty list in a multi state * returns immediately. */ addReply(c, shared.nullbulk); } else { /* The list is empty and the client blocks. */ // 列表为空,则将client阻塞 blockForKeys(c, c->argv + 1, 1, timeout, c->argv[2]); } //如果键不为空,指向RPOPLPUSH } else { //判断取出的value对象是否为列表类型,不是的话发送类型错误信息 if (key->type != OBJ_LIST) { addReply(c, shared.wrongtypeerr); } else { /* The list exists and has elements, so * the regular rpoplpushCommand is executed. */ // value对象的列表存在且有元素,所以调用普通的rpoplpush命令 serverAssertWithInfo(c,key,listTypeLength(key) > 0); rpoplpushCommand(c); } } }