|
\r\nbar\r\n"
return REDIS_OK;
}
c->multibulklen = ll;//得到指令参数个数
/* Setup argv array on client structure */
if (c->argv) zfree(c->argv);
c->argv = zmalloc(sizeof(robj*) * c->multibulklen);//申请参数内存空间
}
redisAssertWithInfo(c,NULL,c->multibulklen > 0);
/**
开始抽取字符串
querybuf = "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"
pos = 4
*/
while(c->multibulklen) {
/* Read bulk length if unknown */
if (c->bulklen == -1) {//参数的长度为-1,这里用来处理每个参数的字符串长度值
/**newline = "\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"*/
newline = strchr(c->querybuf+pos,'\r');
if (newline == NULL) {
if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {
addReplyError(c,"Protocol error: too big bulk count string");
setProtocolError(c,0);
}
break;
}
/* Buffer should also contain \n */
if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))
break;
//每个字符串以$开头,后面的数字表示其长度
if (c->querybuf[pos] != '$') {
addReplyErrorFormat(c,
"Protocol error: expected '$', got '%c'",
c->querybuf[pos]);
setProtocolError(c,pos);
return REDIS_ERR;
}
//得到字符串的长度值,ll
ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll);
if (!ok || ll < 0 || ll > 512*1024*1024) {
addReplyError(c,"Protocol error: invalid bulk length");
setProtocolError(c,pos);
return REDIS_ERR;
}
//pos = 8
pos += newline-(c->querybuf+pos)+2;//跳过\r\n "SET\r\n$3\r\nfoo\r\n$3\r\nbar\r"
if (ll >= REDIS_MBULK_BIG_ARG) {//字符串长度超过1024*32,需要扩展
size_t qblen;
/* If we are going to read a large object from network
* try to make it likely that it will start at c->querybuf
* boundary so that we can optimize object creation
* avoiding a large copy of data. */
/**
sdsrange(querybuf,pos,-1)是将[pos,len-1]之间的字符串使用memmove前移,
然后后面的直接截断
*/
sdsrange(c->querybuf,pos,-1);//"SET\r\n$3\r\nfoo\r\n$3\r\nbar\r"
pos = 0;
qblen = sdslen(c->querybuf);
/* Hint the sds library about the amount of bytes this string is
* going to contain. */
if (qblen < ll+2)//这里只会到最后一个字符串才可能为True,并且数据不完整,数据不完整是由于redis使用非阻塞的原因
c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen);
}
c->bulklen = ll;
}
/* Read bulk argument */
//读取参数,没有\r\n表示数据不全,也就是说服务器接收到的数据不完整
if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) {
/* Not enough data (+2 == trailing \r\n) */
break;
} else {//数据完整
/* Optimization: if the buffer contains JUST our bulk element
* instead of creating a new object by *copying* the sds we
* just use the current sds string. */
if (pos == 0 &&
c->bulklen >= REDIS_MBULK_BIG_ARG &&
(signed) sdslen(c->querybuf) == c->bulklen+2)
{//数据刚好完整,那么就直接使用c->querybuf,然后清空querybuf,注意这里只可能在最后一个字符串才可能出现
c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf);
sdsIncrLen(c->querybuf,-2); /* remove CRLF */
c->querybuf = sdsempty();
/* Assume that if we saw a fat argument we'll see another one
* likely... */
c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2);
pos = 0;
} else {
//抽取出具体的字符串,比如SET,建立一个stringObject
c->argv[c->argc++] =
createStringObject(c->querybuf+pos,c->bulklen);
pos += c->bulklen+2;//跳过\r\n
}
c->bulklen = -1;
c->multibulklen--;
}
}
/**
由于采用的是非阻塞读取客户端数据的方式,那么如果c->multibulklen != 0,那么就表示
数据没有接收完全,首先需要将当前的querybuf数据截断
*/
/* Trim to pos */
if (pos) sdsrange(c->querybuf,pos,-1);
/* We're done when c->multibulk == 0 */
if (c->multibulklen == 0) return REDIS_OK;
/* Still not read to process the command */
return R |