Redis源码分析系列三:initServerConfig下半部分
2013-10-16 00:00
489 查看
经过短暂的休息,开始研究initServerConfig下半部分。
//开始研究下半部分
/* Replication related */
server.masterauth = NULL;//设置masterauth为NULL
server.masterhost = NULL;
server.masterport = 6379;
server.master = NULL;
server.cached_master = NULL;
server.repl_master_initial_offset = -1;
server.repl_state = REDIS_REPL_NONE;
server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;
server.repl_serve_stale_data = REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA;
server.repl_slave_ro = REDIS_DEFAULT_SLAVE_READ_ONLY;
server.repl_down_since = 0; /* Never connected, repl is down since EVER. */
server.repl_disable_tcp_nodelay = REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY;
server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;
server.master_repl_offset = 0;
/* Replication partial resync backlog */
server.repl_backlog = NULL;
//设置repl_backlog为NULL
server.repl_backlog_size = REDIS_DEFAULT_REPL_BACKLOG_SIZE;
server.repl_backlog_histlen = 0;
server.repl_backlog_idx = 0;
server.repl_backlog_off = 0;
server.repl_backlog_time_limit = REDIS_DEFAULT_REPL_BACKLOG_TIME_LIMIT;
//设置repl_backlog_time_limit为 3600
server.repl_no_slaves_since = time(NULL);
//设置为当前时间
/* Client output buffer limits */
for (j = 0; j < REDIS_CLIENT_LIMIT_NUM_CLASSES; j++)
{
server.client_obuf_limits[j] = clientBufferLimitsDefaults[j];
//设置的三个成员分别如下所示:
// {0, 0, 0}, /* normal */
// {1024*1024*256, 1024*1024*64, 60}, /* slave */
//{1024*1024*32, 1024*1024*8, 60}
}
/* Double constants initialization */
R_Zero = 0.0;
R_PosInf = 1.0/R_Zero;
R_NegInf = -1.0/R_Zero;
R_Nan = R_Zero/R_Zero;
/* Command table -- we initiialize it here as it is part of the
* initial configuration, since command names may be changed via
* redis.conf using the rename-command directive. */
下面开始分析dictCreate函数:
这个函数不难,经过执行完后,任何一个 struct dict的变量都是如下所示,可以作为模板使用:
typedef struct dict
{
dictType *type; //(会变化) commandTableDictType
void *privdata; // NULL
dictht ht[2];
// ht[0]定义开始
/*
table = NULL;
size = 0;
sizemask = 0;
used = 0;
*/
// ht[0]定义结束
// ht[1]定义开始
/*
table = NULL;
size = 0;
sizemask = 0;
used = 0;
*/
// ht[1]定义结束
int rehashidx; /* rehashing not in progress if rehashidx == -1 */
// -1
int iterators; /* number of iterators currently running */
// 0
} dict;
然后继续看代码:
server.commands = dictCreate(&commandTableDictType,NULL);
//则commands就是上面的模板一样的变量
server.orig_commands = dictCreate(&commandTableDictType,NULL);
//同上
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
到了本部分最关键的函数 populateCommandTable();
在这个函数里,
首先看代码:
while(*f != '\0')
{
switch(*f)
{
case 'w': c->flags |= REDIS_CMD_WRITE; break;
case 'r': c->flags |= REDIS_CMD_READONLY; break;
case 'm': c->flags |= REDIS_CMD_DENYOOM; break;
case 'a': c->flags |= REDIS_CMD_ADMIN; break;
case 'p': c->flags |= REDIS_CMD_PUBSUB; break;
case 's': c->flags |= REDIS_CMD_NOSCRIPT; break;
case 'R': c->flags |= REDIS_CMD_RANDOM; break;
case 'S': c->flags |= REDIS_CMD_SORT_FOR_SCRIPT; break;
case 'l': c->flags |= REDIS_CMD_LOADING; break;
case 't': c->flags |= REDIS_CMD_STALE; break;
case 'M': c->flags |= REDIS_CMD_SKIP_MONITOR; break;
default: redisPanic("Unsupported command flag"); break;
}
f++;
}
//表示根据每个成员的第4个参数的值来确定当前成员的第5个成员的值,这个没什么好说的。
再看下面两行代码:
retval1 = dictAdd(server.commands, sdsnew(c->name), c);
retval2 = dictAdd(server.orig_commands, sdsnew(c->name), c);
可以看到2个函数都是一样的,只是参数不同,一个是server.commands,一个是server.orig_commands.
现在来分析下dictAdd函数的实现原理即可。
这里偷懒一下,我发现网上已经有个现成的讲解文章。
传送门: http://www.kuqin.com/database/20110904/264306.html
然后我的理解就是把它当做是一个命令的哈希表,存了2份而已。
然后后面肯定某个地方会通过哈希表找到这个命令。
思考:跟之前数组的方式有什么区别?
数组是顺序查找,哈希表是哈希查找,降低了一个数量级。比较快。
这里是为了提高效率,不用过于研究细节,不影响对整体的把握,具体请看传送门即可。
~~~
好,继续往下看
server.delCommand = lookupCommandByCString("del");
//redisCommandTable[7];
server.multiCommand = lookupCommandByCString("multi");
//redisCommandTable[7];
server.lpushCommand = lookupCommandByCString("lpush");
//redisCommandTable[18];
server.lpopCommand = lookupCommandByCString("lpop");
//redisCommandTable[23];
server.rpopCommand = lookupCommandByCString("rpop");
//redisCommandTable[22];
server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;
//设置为 10000
server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;
//设置为 10000
/* Debugging */
server.assert_failed = "<no assertion failed>";
//设置为 10000
server.assert_file = "<no file>";
//设置为 10000
server.assert_line = 0;
//设置为 0
server.bug_report_start = 0;
// 0
server.watchdog_period = 0;
//设置为 0
到快到12点的时候,终于把这个函数给搞定了,累啊。
码农的春天什么时候到来?
休息片刻,继续往下执行!!!
不努力能赚钱付按揭吗,不能!!!
//开始研究下半部分
/* Replication related */
server.masterauth = NULL;//设置masterauth为NULL
server.masterhost = NULL;
server.masterport = 6379;
server.master = NULL;
server.cached_master = NULL;
server.repl_master_initial_offset = -1;
server.repl_state = REDIS_REPL_NONE;
server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;
server.repl_serve_stale_data = REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA;
server.repl_slave_ro = REDIS_DEFAULT_SLAVE_READ_ONLY;
server.repl_down_since = 0; /* Never connected, repl is down since EVER. */
server.repl_disable_tcp_nodelay = REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY;
server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;
server.master_repl_offset = 0;
/* Replication partial resync backlog */
server.repl_backlog = NULL;
//设置repl_backlog为NULL
server.repl_backlog_size = REDIS_DEFAULT_REPL_BACKLOG_SIZE;
server.repl_backlog_histlen = 0;
server.repl_backlog_idx = 0;
server.repl_backlog_off = 0;
server.repl_backlog_time_limit = REDIS_DEFAULT_REPL_BACKLOG_TIME_LIMIT;
//设置repl_backlog_time_limit为 3600
server.repl_no_slaves_since = time(NULL);
//设置为当前时间
/* Client output buffer limits */
for (j = 0; j < REDIS_CLIENT_LIMIT_NUM_CLASSES; j++)
{
server.client_obuf_limits[j] = clientBufferLimitsDefaults[j];
//设置的三个成员分别如下所示:
// {0, 0, 0}, /* normal */
// {1024*1024*256, 1024*1024*64, 60}, /* slave */
//{1024*1024*32, 1024*1024*8, 60}
}
/* Double constants initialization */
R_Zero = 0.0;
R_PosInf = 1.0/R_Zero;
R_NegInf = -1.0/R_Zero;
R_Nan = R_Zero/R_Zero;
/* Command table -- we initiialize it here as it is part of the
* initial configuration, since command names may be changed via
* redis.conf using the rename-command directive. */
下面开始分析dictCreate函数:
这个函数不难,经过执行完后,任何一个 struct dict的变量都是如下所示,可以作为模板使用:
typedef struct dict
{
dictType *type; //(会变化) commandTableDictType
void *privdata; // NULL
dictht ht[2];
// ht[0]定义开始
/*
table = NULL;
size = 0;
sizemask = 0;
used = 0;
*/
// ht[0]定义结束
// ht[1]定义开始
/*
table = NULL;
size = 0;
sizemask = 0;
used = 0;
*/
// ht[1]定义结束
int rehashidx; /* rehashing not in progress if rehashidx == -1 */
// -1
int iterators; /* number of iterators currently running */
// 0
} dict;
然后继续看代码:
server.commands = dictCreate(&commandTableDictType,NULL);
//则commands就是上面的模板一样的变量
server.orig_commands = dictCreate(&commandTableDictType,NULL);
//同上
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
到了本部分最关键的函数 populateCommandTable();
在这个函数里,
首先看代码:
while(*f != '\0')
{
switch(*f)
{
case 'w': c->flags |= REDIS_CMD_WRITE; break;
case 'r': c->flags |= REDIS_CMD_READONLY; break;
case 'm': c->flags |= REDIS_CMD_DENYOOM; break;
case 'a': c->flags |= REDIS_CMD_ADMIN; break;
case 'p': c->flags |= REDIS_CMD_PUBSUB; break;
case 's': c->flags |= REDIS_CMD_NOSCRIPT; break;
case 'R': c->flags |= REDIS_CMD_RANDOM; break;
case 'S': c->flags |= REDIS_CMD_SORT_FOR_SCRIPT; break;
case 'l': c->flags |= REDIS_CMD_LOADING; break;
case 't': c->flags |= REDIS_CMD_STALE; break;
case 'M': c->flags |= REDIS_CMD_SKIP_MONITOR; break;
default: redisPanic("Unsupported command flag"); break;
}
f++;
}
//表示根据每个成员的第4个参数的值来确定当前成员的第5个成员的值,这个没什么好说的。
再看下面两行代码:
retval1 = dictAdd(server.commands, sdsnew(c->name), c);
retval2 = dictAdd(server.orig_commands, sdsnew(c->name), c);
可以看到2个函数都是一样的,只是参数不同,一个是server.commands,一个是server.orig_commands.
现在来分析下dictAdd函数的实现原理即可。
这里偷懒一下,我发现网上已经有个现成的讲解文章。
传送门: http://www.kuqin.com/database/20110904/264306.html
然后我的理解就是把它当做是一个命令的哈希表,存了2份而已。
然后后面肯定某个地方会通过哈希表找到这个命令。
思考:跟之前数组的方式有什么区别?
数组是顺序查找,哈希表是哈希查找,降低了一个数量级。比较快。
这里是为了提高效率,不用过于研究细节,不影响对整体的把握,具体请看传送门即可。
~~~
好,继续往下看
server.delCommand = lookupCommandByCString("del");
//redisCommandTable[7];
server.multiCommand = lookupCommandByCString("multi");
//redisCommandTable[7];
server.lpushCommand = lookupCommandByCString("lpush");
//redisCommandTable[18];
server.lpopCommand = lookupCommandByCString("lpop");
//redisCommandTable[23];
server.rpopCommand = lookupCommandByCString("rpop");
//redisCommandTable[22];
server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;
//设置为 10000
server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;
//设置为 10000
/* Debugging */
server.assert_failed = "<no assertion failed>";
//设置为 10000
server.assert_file = "<no file>";
//设置为 10000
server.assert_line = 0;
//设置为 0
server.bug_report_start = 0;
// 0
server.watchdog_period = 0;
//设置为 0
到快到12点的时候,终于把这个函数给搞定了,累啊。
码农的春天什么时候到来?
休息片刻,继续往下执行!!!
不努力能赚钱付按揭吗,不能!!!
相关文章推荐
- Redis源码分析系列一:main函数分析
- Redis源码分析系列十二:readQueryFromClient
- Redis源码分析系列二十一: 4 select---selectCommand
- redis客户端Jedis源码分析系列——集合JedisByteHashMap
- Redis源码分析系列:引子
- Redis源码分析系列六:initserver中
- Redis源码分析系列二十:3 命令"ping"---pingCommand
- Redis源码分析系列五:initServer上
- Redis源码分析系列十一:createClient后面内容
- Redis源码分析系列
- Redis源码分析系列十:acceptTcpHandler
- redis客户端Jedis源码分析系列——从缓存池中获取资源和销毁资源
- Redis 源码分析系列1-main函数相关调用分析
- Redis源码分析系列十六:processCommand研究
- redis客户端Jedis源码分析系列——连接池的创建过程
- Redis源码分析系列十五:processInlineBuffer
- Redis源码分析系列十四:processInputBuffer
- Redis源码分析系列七:initServer下
- Redis源码分析系列二十四: 7 set---setCommand解析
- [置顶] Spring Boot系列十二 通过redis实现Tomcat集群的Session同步及从源码分析其原理