Atlas源码学习(一)

研究Atlas源码,首先需要从程序的起点开始。Atlas的主函数位于,无论对于Unix系统还是windows,其实际的入口函数为

int main_cmdline(int argc, char **argv) 
{ .....}
由于Atlas是基于glibc完成的开发,因此其在启动过程首先做的是验证glibc的版本:

if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */
        GOTO_EXIT(EXIT_FAILURE);
}

接下来,配置日志输出参数:

chassis_log *log = NULL;
log = chassis_log_new();
log->min_lvl = G_LOG_LEVEL_MESSAGE; /* display messages while parsing or loading plugins */
g_log_set_default_handler(chassis_log_func, log);
其中chassis_log为如下结构:

typedef struct {
    GLogLevelFlags min_lvl;//日志级别

    gchar *log_filename;//日志文件路径
    gint log_file_fd;//日志文件描述符
    
    gboolean use_syslog;

    gboolean rotate_logs;
    
    GString *log_ts_str;
    gint     log_ts_resolution; /*<< timestamp resolution (sec, ms) */

    GString *last_msg;
    time_t   last_msg_ts;
    guint    last_msg_count;
} chassis_log;
由此,之后便可以通过g_log等函数实现标准化的日志输出。


随后,Atlas将进行命令行参数及配置文件的解析工作。解析出来的数据保存在

chassis_frontend_t *frontend;
其具体结构如下

 typedef struct {
    int print_version; //打印版本
    int verbose_shutdown;//关闭输出


    int daemon_mode;//后台运行
    gchar *user;//用户


    gchar *base_dir;//工作目录
    int auto_base_dir;//是否使用默认目录                                                                                               

    gchar *default_file;//默认配置文件
    GKeyFile *keyfile;//配置文件对象                                                                                                   

    chassis_plugin *p;//插件
    GOptionEntry *config_entries;//命令行配置选项                                                                                      

    gchar *pid_file;//pid文件存放处                                                                                                    

    gchar *plugin_dir;//插件目录   
    gchar **plugin_names;//插件名                                                                                                      

    guint invoke_dbg_on_crash;

    gint max_files_number;//最大文件数

    gchar *log_level;//日志级别
    gchar *log_path;//日志存放路径
    int    use_syslog;//是否启用syslog


    char *lua_path;//lua脚本存放路径
    char *lua_cpath;//
    char **lua_subdirs;//lua脚本子目录

} chassis_frontend_t;
实际上,Atlas在解析命令行和配置文件的过程中是有一定的顺序的,其首先要从配置项中获取两个参数 frontend->print_version 和 frontend->default_file。

chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version),&(frontend->default_file),&gerr));
然后根据 frontend->default_file指定的路径加载配置文件:

frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr);

下一步,开始解析命令行和配置文件中的其他配置参数

chassis_options_t *opts = NULL;
opts = chassis_options_new();
chassis_frontend_set_chassis_options(frontend, opts);
main_entries = chassis_options_to_g_option_entries(opts);
g_option_context_add_main_entries(option_ctx, main_entries, NULL);//指定需要解析的配置命令
g_option_context_parse(option_ctx, &argc, &argv, &gerr);//解析命令行其他参数
chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries);解析配置文件中参数
至此,Atlas的配置加载工作就完成了。


配置加载完成之后,做了一下工作:

1. 指定lua脚本目录

2.检查工作线程数配置是否正确

3.更新Atlas server配置,并完成一部分初始化工作(主要是lua脚本运行需要的一些初始化工作,这一部分设计到部分lua脚本运行的问题,目前不是很懂)

network_mysqld_init(srv);


接下来,其对SIGSEGV信号设置了相应的处理函数

memset(&sigsegv_sa, 0, sizeof(sigsegv_sa));
sigsegv_sa.sa_handler = sigsegv_handler;
sigemptyset(&sigsegv_sa.sa_mask);
if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) {
    sigaction(SIGSEGV, &sigsegv_sa, NULL);
}

sigsegv_handler中主要做了两个工作:跟踪错误位置,抛出SIGABRT信号。


随后,Atlas开始为创建log和pid文件做准备,并根据配置文件重新设定日志级别,这部分的代码比较好理解,就不赘述了。


接下来,Atlas开始加载插件,mysql和proxy。

if (!frontend->plugin_names) {
        frontend->plugin_names = g_new(char *, 3);

        frontend->plugin_names[0] = g_strdup("admin");
        frontend->plugin_names[1] = g_strdup("proxy");
        frontend->plugin_names[2] = NULL;
    }
    //在这里加载插件,使用glibc的方式,关于这一部分可以参考http://www.ibm.com/developerworks/cn/linux/l-gtkplgin/
    if (chassis_frontend_load_plugins(srv->modules,
                frontend->plugin_dir,
                frontend->plugin_names)) {
        GOTO_EXIT(EXIT_FAILURE);
    }

    //这里的主要工作是获取插件的配置选项,并先读入部分配置
    if (chassis_frontend_init_plugins(srv->modules,
                option_ctx,
                &argc, &argv,
                frontend->keyfile,
                "mysql-proxy",
                srv->base_dir,
                &gerr)) {
        g_critical("%s: %s",
                G_STRLOC,
                gerr->message);
        g_clear_error(&gerr);

        GOTO_EXIT(EXIT_FAILURE);
    }
插件加载完毕后,就可以开始解析命令行参数中之前未知的一些命令行参数:

g_option_context_parse(option_ctx, &argc, &argv, &gerr);

随后,Atlass又进行了部分配置,包括

1. deamon模式运行

2. 修改pid文件

3. 设定最大文件限制


最后,其进入服务器程序主循环:

chassis_mainloop(srv);






你可能感兴趣的:(Atlas源码学习(一))