Atlas在基本的配置结束后,就进入到
int chassis_mainloop(void *_chas)
在该函数中,其首先将libevent的日志输出重定向到glibc的日志输出中。
event_set_log_callback(event_log_use_glib);
随后其定义了一个线程对象,并为其做初始化工作
mainloop_thread = chassis_event_thread_new(0);
chassis_event_threads_init_thread(chas->threads, mainloop_thread, chas);
chassis_event_threads_add(chas->threads, mainloop_thread);//将该线程对象加入到线程组中
chas->event_base = mainloop_thread->event_base;
实际上,Atlas用mainloop_thread表示当前工作的主线程。该线程除负责全局信号的一些处理之外上面的代码中
chassis_event_threads_init_thread这个函数是Atlas中所有线程的初始化函数。其主要的工作包括两部分:
工作1,创建管道:
int fds[2];
if (pipe(fds)) {
int err;
err = errno;
g_error("%s: evutil_socketpair() failed: %s (%d)",
G_STRLOC,
g_strerror(err),
err);
}
event_thread->notify_receive_fd = fds[0];
event_thread->notify_send_fd = fds[1];
使用libevent对管道的读端进行监听,进而接收来自proxy插件的消息,获取新的连接请求并做相应的处理:
event_set(&(event_thread->notify_fd_event), event_thread->notify_receive_fd, EV_READ | EV_PERSIST, chassis_event_handle, event_thread);
event_base_set(event_thread->event_base, &(event_thread->notify_fd_event));
event_add(&(event_thread->notify_fd_event), NULL);
随后,Atlas开始启动所有的插件,一般是Mysql 和 Proxy插件。其中proxy插件负责接收连接请求,并将请求教导不同的线程中去 处理。
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;
}
}
在apply_config函数中,程序会将从配置文件中读入的配置,加载到插件的配置中,该步骤很重要,因此我们会在后面单独讲解。
在为主线程配置完需要监听的信号后,Atlas开始初始化并启动工作线程
for (i = 1; i < (guint)chas->event_thread_count; i++) { /* we already have 1 event-thread running, the main-thread */
chassis_event_thread_t *event_thread;
event_thread = chassis_event_thread_new(i);
chassis_event_threads_init_thread(chas->threads, event_thread, chas);
chassis_event_threads_add(chas->threads, event_thread);
}
启动:
if (chas->event_thread_count > 1) {
chassis_event_threads_start(chas->threads);
}
最后主线程进入事件循环
chassis_event_thread_loop(mainloop_thread);