Atlas源码学习(四)

来源:互联网 发布:网络印刷电商平台 编辑:程序博客网 时间:2024/06/10 00:39

部分数据结构描述:

在Atlas中,有一些重要的数据结构会贯穿程序的整个生命周期,并在后面的工作中频繁被使用,因此有必要对这些数据结构进行了解。

chassis_frontend_t :  描述Atlas启动参数,设置一些有关程序运行的全局控制选项,如运行模式,工作目录等。

typedef struct {                                              int print_version;  //打印版本信息    int verbose_shutdown; //是否关闭前端输出                                                                                                                                              int daemon_mode;  //是否以守护进程的模式运行                                       gchar *user;      //当程序插件监听端口时,需要退出特权模式,因此需要制定一个用户来替代root                                                                         gchar *base_dir;  //程序工作目录                                                                                        int auto_base_dir;                                                                                                                                                                                                gchar *default_file; //默认配置文件名                                                                                       GKeyFile *keyfile;   //glib中用于读取配置文件的对象                                                                                 chassis_plugin *p;   //指向插件的指针                                                                                                                                                                  GOptionEntry *config_entries;//glib用于解析命令行参数和配置文件的 对象                                                                   gchar *pid_file; //存放程序进程id的文件,对程序的命令行控制和keepalive有非常重要的作用         gchar *plugin_dir;  //插件程序存放目录                                                                                                 gchar **plugin_names;  //插件名称                                                                            guint invoke_dbg_on_crash;                                                                                                                                                         #ifndef _WIN32                                             /* the --keepalive option isn't available on Unix */                                                                                                                                   guint auto_restart;                            #endif                                                                                                   gint max_files_number;  //最大打开文件数                                                                            gint event_thread_count; //event线程数量,与backend中的pools大小相等                                                                                                                                             gchar *log_level; //默认日志级别                                     gchar *log_path;  //默认日志路径                                     use_syslog;                                                                char *lua_path;                                     char *lua_cpath;                                                                                                                                                                       char **lua_subdirs;                            gchar *instance_name; //进程名,用于配置pid和log文件,instance.pid和 instance.log                                } chassis_frontend_t;    

daemon选项:

if (frontend->daemon_mode) {        chassis_unix_daemonize();}void chassis_unix_daemonize(void) {#ifdef _WIN32    g_assert_not_reached(); /* shouldn't be tried to be called on win32 */#else#ifdef SIGTTOU    signal(SIGTTOU, SIG_IGN);#endif#ifdef SIGTTIN    signal(SIGTTIN, SIG_IGN);#endif#ifdef SIGTSTP    signal(SIGTSTP, SIG_IGN);//忽略以上三类信号,以上三个信号一半来自终端#endif    if (fork() != 0) exit(0);//fork子进程,父进程退出。子进程称为会话组的非首进程,其父进程变为守护进程。    if (setsid() == -1) exit(0);//创建一个新的会话,子进程称为组长进程,脱离终端控制。    signal(SIGHUP, SIG_IGN); //忽略SIGHUP信号,该信号一般有进程退出时发出(进程组有进程退出,发送其给组长进程)    if (fork() != 0) exit(0);//再次fork保证进程非组长进程,保证其不会被分配到终端    chdir("/");//更改进程工作目录,设为当前目录    umask(0);//修改创建文件的屏蔽字模式为0,保证创建文件可读写#endif}

chassis_plugin

typedef struct chassis_plugin {    long      magic;    /**用于验证插件是否与接口一致 */            gchar    *option_grp_name;     /**插件选项组,用于解析配置参数 */    gchar    *name;     /**插件名 */    gchar    *version;  /**插件版本号 */    GModule  *module;   /**插件句柄,保存插件对象的实例 */        chassis_plugin_stats_t *stats;  /**< contains the plugin-specific statistics */                    chassis_plugin_stats_t *(*new_stats)(void);     /**< handler function to initialize the plugin-specific stats */    void (*free_stats)(chassis_plugin_stats_t *user_data);  /**< handler function to dealloc the plugin-specific stats */    GHashTable *(*get_stats)(chassis_plugin_stats_t *user_data);    /**< handler function to retrieve the plugin-specific stats */        chassis_plugin_config *config;  /**用于存放插件的配置数据,很重要 */                    chassis_plugin_config *(*init)(void);   /**<span style="font-family: Arial, Helvetica, sans-serif;">插件配置信息初始化函数</span> */    void     (*destroy)(chassis_plugin_config *user_data);  /**插件配置信息销毁函数 */    GOptionEntry * (*get_options)(chassis_plugin_config *user_data); /**用于获取配置信息 */    int      (*apply_config)(chassis *chas, chassis_plugin_config * user_data); /**<span style="font-family: Arial, Helvetica, sans-serif;">将配置信息加载到config中的处理函数</span> */    void*    (*get_global_state)(chassis_plugin_config *user_data, const char* member);     } chassis_plugin;


chassis_plugin_config

struct chassis_plugin_config {         gchar *address;                   /**proxy的监听地址*/        gchar **backend_addresses;        /**读写服务器地址,即master */    gchar **read_only_backend_addresses; /**只读服务器地址,即slave*/        gint fix_bug_25371;               /**< suppress the second ERR packet of bug #25371 */        gint profiling;                   /**< skips the execution of the read_query() function */        gchar *lua_script;                /**建立连接时应启动的脚本,在Atlas中用处不大了 */        gint pool_change_user;            /**< don't reset the connection, when a connection is taken from the pool                           - this safes a round-trip, but we also don't cleanup the connection                           - another name could be "fast-pool-connect", but that's too friendly                           */        gint start_proxy; /** 开启代理模式*/            gchar **client_ips;/** 客户端列表,用于ip过滤*/    GHashTable *ip_table;/** 用于ip过滤的hash表    gchar **lvs_ips;/**lvs地址,也用ip过滤*/    GHashTable *lvs_table; /用于存放lvs地址的hash表    gchar **tables;/**表信息,用于分表*/    GHashTable *dt_table;/** 用于分表的hash表*/    gchar **pwds;    GHashTable *pwd_table;/** 用于存放用户登录信息的hash表*、    network_mysqld_con *listen_con;/** 监听端口对象,该对象包含处理符合mysql协议的连接的各种回调函数,每当一个连接来到都会创建一个network_mysqld_con的对象,其中我们所监听的端口的连接对象中不含有client信息。这个对象的具体信息可参看,network_mysqld_con@<span style="font-family: Arial, Helvetica, sans-serif;">network-mysqld.h</span>*/    FILE *sql_log;    gchar *sql_log_type;    gchar *charset;/** 字符集合*/};
chassis_plugin_config中的大部分配置会在main_loop函数以下部分完成(即向hash表中填入数据)

for (i = 0; i < chas->modules->len; i++) {        chassis_plugin *p = chas->modules->pdata[i];        g_assert(p->apply_config);        if (0 != p->apply_config(chas, p->config)) {            g_critical("%s: applying config of plugin %s failed",                    G_STRLOC, p->name);            return -1;        }    }


上面围绕chassis_frontend_t结构进行了数据分析,该结构主要用于解析命令行,读取配置文件和加载插件。实际上,贯穿Atlas运行的另外一个数据结构chassis也是我们理解Atlas的一个 重要部分。

chassis

struct chassis {    struct event_base *event_base; //主线程的libevent实例    gchar *event_hdr_version;    GPtrArray *modules;                       /**一个数组,数组中存放加载进来的插件,array(chassis_plugin) */    gchar *base_dir;                /**程序运行期间各个模块的根目录*/    gchar *log_path;                /**日志存放目录  */    gchar *user;                    /**运行程序的用户属主名 */    gchar *instance_name;                   /**程序启动的实例名*/    chassis_private *priv;  /**保存运行期间的各个backend信息*/    void (*priv_shutdown)(chassis *chas, chassis_private *priv);    void (*priv_free)(chassis *chas, chassis_private *priv);    chassis_log *log; /** 与日志相关的数据结构*/    chassis_stats_t *stats;         /**全局chassis状态,包括glib等 */    /* network-io threads */    guint event_thread_count;/**事件处理线程数,这里包含主线程*/    chassis_event_threads_t *threads;/** 所有的事件处理线程都放在这里面,由多个chassis_event_thread_t对象构成*/    chassis_shutdown_hooks_t *shutdown_hooks;//  struct event_base *remove_base;};
chassis对象贯穿了程序运行的整个周期,在负载均衡,读写分离的实现上都需要以来它。可以通过其中的modules对象获取到插件的句柄,进而获取插件的配置,处理函数等各种信息,在加载插件的过程中即chassis_frontend_load_plugins函数里,将插件与之关联。

chassis_private

struct chassis_private {//  GPtrArray *cons;                          /**< array(network_mysqld_con) */    lua_scope *sc;    network_backends_t *backends;}


network_backends_t

typedef struct {                                                                                                                                                                                                GPtrArray *backends;//后台组信息                                                                                                                                                                                 GMutex    *backends_mutex;  /*remove lock*/                                                                                                                                                                 g_wrr_poll *global_wrr;//权重                                                                                                                                                                  guint event_thread_count;//线程数量                                                                                                                                                            } network_backends_t;
其中用于表述一个后台结构的backend类型为
typedef struct {                                                                                                                                                                                              network_address *addr;        backend_state_t state;   /**UP or DOWN 当前数据库的状态*/                                                                                                                              backend_type_t type;     /**ReadWrite or ReadOnly 当前数据库的类型*/    GPtrArray *pools;//存放当前打开的连接,其数量一般与进程所持有的线程数相同      guint connected_clients; /**< number of open connections to this backend for SQF当前已连接的客户端个数 */        GString *uuid;           /**< the UUID of the backend */                                                           guint weight;//权重                   } network_backend_t;//这个结构用于存储一个backend对象   

network_address

typedef struct {    union {        struct sockaddr_in ipv4;        struct sockaddr_in6 ipv6;#ifdef HAVE_SYS_UN_H        struct sockaddr_un un;#endif          struct sockaddr common;    } addr;                GString *name;    network_socklen_t len;    gboolean can_unlink_socket; /* set TRUE *only* after successful bind */} network_address;

以后想起来再说 。。。。




0 0