Redis源码分析系列十六:processCommand研究

现在让我们回到processInputBuffer函数。

剩下的代码是:

/* Multibulk processing could see a <= 0 length. */
        if (c->argc == 0) 
{
            resetClient(c);

else 
{
            /* Only reset the client when the command was executed. */
            if (processCommand(c) == REDIS_OK)
                resetClient(c);
}

假设我们已经取到了一些命令,那么c->argc则大于0

那就会执行processCommand函数。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/* The QUIT command is handled separately. Normal command procs will
* go through checking for replication and QUIT will cause trouble
* when FORCE_REPLICATION is enabled and would be implemented in
* a regular command proc. */
//解释说明
 

if (!strcasecmp(c->argv[0]->ptr,"quit")) 
{
addReply(c,shared.ok);
c->flags |= REDIS_CLOSE_AFTER_REPLY;
return REDIS_ERR;
}
//quit命令暂且不看,后面再解释。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

在网上搜到了一篇罗列redis命令的文章

http://redis.readthedocs.org/en/latest/

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

继续往下走,下面的代码是:

c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);

//查找命令的作用

这个函数最终调用了dictFetchValue(server.commands, name);

让我们想想server.commands里存的是什么?

我翻了我之前的代码记录,发现这里面存的是:redisCommandTable里的命令

name是什么,是client发给服务器的字符串的第一个字符串命令。

自然用这个来查找对应的命令了。

好,现在我们已经取到了相关命令,剩下自然是执行这个命令了。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);

执行前先保存起来做个记录。

~~~~~~~~

if (!c->cmd) 
{
flagTransaction(c);
addReplyErrorFormat(c,"unknown command '%s'",
(char*)c->argv[0]->ptr);
return REDIS_OK;

如果是无法识别的命令,则提示无法识别

~~~~

下面会对命令参数进行合法性判断,代码如下:

f ((c->cmd->arity > 0 
&& c->cmd->arity != c->argc) 
||
  (c->argc < -c->cmd->arity)) 
我们来分析下具体的。

查阅redisCommandTable的定义数组,发现第3个参数arity有正有负,

这是为啥呢???

在大脑中思考了0.0001飞秒之后,我终于顿悟。

首先有些命令的个数必须一个不多一个不少,而有的命令必须至少要有多少个,

带着这样的观点来理解上面这句校验代码,就知道:

如果参数arity为正,表示一个不多一个不少。如3就表示必须=3.

如果参数为负,表示这个命令的参数至少为多少个,如-3就表示>=3.

~~~~~~~~~~~~~~~~

/* Check if the user is authenticated */
if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)
{
flagTransaction(c);
addReply(c,shared.noautherr);
return REDIS_OK;
}
判断是否需要验证。

还记得获取配置文件项的函数吗?

loadServerConfigFromString,我去翻了下这个函数的代码,

找到

else if (!strcasecmp(argv[0],"requirepass") && argc == 2) {
            if (strlen(argv[1]) > REDIS_AUTHPASS_MAX_LEN) {
                err = "Password is longer than REDIS_AUTHPASS_MAX_LEN";
                goto loaderr;
            }
            server.requirepass = zstrdup(argv[1]);
        } 
然后我在redis.conf文件里搜索requirepass字符串,发现这个配置项没有定义

于是我们可以认为不需要认证。

好,继续执行。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

freeMemoryIfNeeded暂且不分析。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

继续执行。

下面的代码是:

if (server.stop_writes_on_bgsave_err 
&&
server.saveparamslen > 0
&& 
server.lastbgsave_status == REDIS_ERR 
&&
c->cmd->flags & REDIS_CMD_WRITE)
{
flagTransaction(c);
addReply(c, shared.bgsaveerr);
return REDIS_OK;
}
我看了我的server.lastbgsave_status是REDIS_OK,所以这个不执行。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if (server.repl_min_slaves_to_write 
&&
server.repl_min_slaves_max_lag 
&&
c->cmd->flags & REDIS_CMD_WRITE 
&&
server.repl_good_slaves_count < server.repl_min_slaves_to_write)
{
flagTransaction(c);
addReply(c, shared.noreplicaserr);
return REDIS_OK;
}
这个也同样不执行。

~~~~~~~~~~~~~~

/* Don't accept write commands if this is a read only slave. But
* accept write commands if this is our master. */
if (server.masterhost && server.repl_slave_ro &&
!(c->flags & REDIS_MASTER) &&
c->cmd->flags & REDIS_CMD_WRITE)
{
addReply(c, shared.roslaveerr);
return REDIS_OK;
}

这个也不执行

~~~~~~~~~~~~~~~~~~~

休息一会,待会再看!



转载于:https://my.oschina.net/qiangzigege/blog/171019

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值