void pushGenericCommand(client *c, int where) { int j, waiting = 0, pushed = 0; robj *lobj = lookupKeyWrite(c->db,c->argv[1]); if (lobj && lobj->type != OBJ_LIST) { addReply(c,shared.wrongtypeerr); return; } for (j = 2; j < c->argc; j++) { c->argv[j] = tryObjectEncoding(c->argv[j]); if (!lobj) { lobj = createQuicklistObject(); quicklistSetOptions(lobj->ptr, server.list_max_ziplist_size, server.list_compress_depth); dbAdd(c->db,c->argv[1],lobj); } listTypePush(lobj,c->argv[j],where); pushed++; } addReplyLongLong(c, waiting + (lobj ? listTypeLength(lobj) : 0)); if (pushed) { char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; signalModifiedKey(c->db,c->argv[1]); notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); } server.dirty += pushed; }
void rpoplpushHandlePush(client *c, robj *dstkey, robj *dstobj, robj *value) { /* Create the list if the key does not exist */ if (!dstobj) { dstobj = createQuicklistObject(); quicklistSetOptions(dstobj->ptr, server.list_max_ziplist_size, server.list_compress_depth); dbAdd(c->db,dstkey,dstobj); } signalModifiedKey(c->db,dstkey); listTypePush(dstobj,value,LIST_HEAD); notifyKeyspaceEvent(NOTIFY_LIST,"lpush",dstkey,c->db->id); /* Always send the pushed value to the client. */ addReplyBulk(c,value); }
//PUSH命令的底层实现,where保存push的位置 void pushGenericCommand(client *c, int where) { int j, waiting = 0, pushed = 0; robj *lobj = lookupKeyWrite(c->db,c->argv[1]); //以写操作读取key对象的value //如果value对象不是列表类型则发送错误信息,返回 if (lobj && lobj->type != OBJ_LIST) { addReply(c,shared.wrongtypeerr); return; } //从第一个value开始遍历 for (j = 2; j < c->argc; j++) { c->argv[j] = tryObjectEncoding(c->argv[j]); //将value对象优化编码 //如果没有找到key对象 if (!lobj) { //创建一个quicklist类型的对象 lobj = createQuicklistObject(); //设置ziplist最大的长度和压缩程度,配置文件指定 quicklistSetOptions(lobj->ptr, server.list_max_ziplist_size, server.list_compress_depth); //将新的key对象和优化编码过的value对象进行组成键值对 dbAdd(c->db,c->argv[1],lobj); } //在where推入一个value对象 listTypePush(lobj,c->argv[j],where); pushed++; //更新计数器 } //发送当前列表中元素的个数 addReplyLongLong(c, waiting + (lobj ? listTypeLength(lobj) : 0)); //如果推入元素成功 if (pushed) { char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; //当数据库的键被改动,则会调用该函数发送信号 signalModifiedKey(c->db,c->argv[1]); //发送"lpush"或"rpush"事件通知 notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); } server.dirty += pushed; //更新脏键 }
//将一个value推入到列表头部,被rpoplpushCommand调用 void rpoplpushHandlePush(client *c, robj *dstkey, robj *dstobj, robj *value) { /* Create the list if the key does not exist */ //如果目标dstkey不存在 if (!dstobj) { //创建一个quicklist对象 dstobj = createQuicklistObject(); //设置ziplist的最大长度和压缩程度 quicklistSetOptions(dstobj->ptr, server.list_max_ziplist_size, server.list_compress_depth); //将key添加到数据库中 dbAdd(c->db,dstkey,dstobj); } //当数据库的键被改动,则会调用该函数发送信号 signalModifiedKey(c->db,dstkey); //将vlaue推入到列表的头部 listTypePush(dstobj,value,LIST_HEAD); //发送"lpush"时间通知 notifyKeyspaceEvent(NOTIFY_LIST,"lpush",dstkey,c->db->id); /* Always send the pushed value to the client. */ //将value值发送给client addReplyBulk(c,value); }