tracker 的入口在 fdfs_trackerd.c, 而 storage 的入口在fdfs_storaged.c.下面首先分析tracker的,我们从main 函数开始。
fdfs_trackerd.c 109 行:
- conf_filename = argv[1];
- memset(bind_addr, 0, sizeof(bind_addr));
- if ((result=tracker_load_from_conf_file(conf_filename, \
- bind_addr, sizeof(bind_addr))) != 0)
- {
- log_destroy();
- return result;
- }
代码分析:
1. 从命令行接收配置文件名称;
2. 调用tracker_load_from_conf_file 载入配置,具体参数保存在对应的全局变量中。
接着往下分析,fdfs_trackerd.c 117 行:
- if ((result=tracker_load_status_from_file(&g_tracker_last_status)) != 0)
- {
- log_destroy();
- return result;
- }
这里面主要是从隐藏文件 .tracker_status 读取 tracker 上次的状态。
接着往下分析,fdfs_trackerd.c 131行:
- if ((result=tracker_mem_init()) != 0)
- {
- log_destroy();
- return result;
- }
tracker_mem* 相关操作目的是 tracker 在内存中维护 storage 运行状态。这里需要进行初始化动作,会调用 tracker_mem.c 1535行的 tracker_load_data 函数,实现包括从文件中载入groups、storage等信息。
接着往下分析,fdfs_trackerd.c 150行:
- daemon_init(true);
- umask(0);
这里是后台守护进程初始化,目的是为了让tracker 后台运行。
接着往下分析,fdfs_trackerd.c 163行:
- if ((result=tracker_service_init()) != 0)
- {
- log_destroy();
- return result;
- }
tracker_service_init 是 tracker 服务的初始化函数。里面主要的动作是pthread_create创建工作者线程,线程的执行函数是work_thread_entrance。
接下来,fdfs_trackerd.c 172行开始,是sigaction设置信号的处理方式。这是linux信号处理机制基础。
接着往下分析,fdfs_trackerd.c 242行:
- #ifdef WITH_HTTPD
- if (!g_http_params.disabled)
- {
- if ((result=tracker_httpd_start(bind_addr)) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "tracker_httpd_start fail, program exit!", \
- __LINE__);
- return result;
- }
- }
- if ((result=tracker_http_check_start()) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "tracker_http_check_start fail, " \
- "program exit!", __LINE__);
- return result;
- }
- #endif
代码分析:
1. tracker 内置了 httpd 服务,但是需要开启编译选项 WITH_HTTPD
fdfs_trackerd.c 270行:
- scheduleArray.entries = scheduleEntries;
- scheduleArray.count = SCHEDULE_ENTRIES_COUNT;
- memset(scheduleEntries, 0, sizeof(scheduleEntries));
- scheduleEntries[0].id = 1;
- scheduleEntries[0].time_base.hour = TIME_NONE;
- scheduleEntries[0].time_base.minute = TIME_NONE;
- scheduleEntries[0].interval = g_sync_log_buff_interval;
- scheduleEntries[0].task_func = log_sync_func;
- scheduleEntries[0].func_args = &g_log_context;
- scheduleEntries[1].id = 2;
- scheduleEntries[1].time_base.hour = TIME_NONE;
- scheduleEntries[1].time_base.minute = TIME_NONE;
- scheduleEntries[1].interval = g_check_active_interval;
- scheduleEntries[1].task_func = tracker_mem_check_alive;
- scheduleEntries[1].func_args = NULL;
- scheduleEntries[2].id = 3;
- scheduleEntries[2].time_base.hour = 0;
- scheduleEntries[2].time_base.minute = 0;
- scheduleEntries[2].interval = TRACKER_SYNC_STATUS_FILE_INTERVAL;
- scheduleEntries[2].task_func = tracker_write_status_to_file;
- scheduleEntries[2].func_args = NULL;
- if ((result=sched_start(&scheduleArray, &schedule_tid, \
- g_thread_stack_size, &g_continue_flag)) != 0)
- {
- log_destroy();
- return result;
- }
代码分析:
1. sched_start 是开启线程 sched_thread_entrance (sched_thread.c 260行),定期执行指定的任务;
2. 这些任务有log_sync_func、tracker_mem_check_alive、tracker_write_status_to_file;
我们深入分析下 tracker_mem_check_alive,tracker_mem.c 5139行:
- current_time = time(NULL);
- ppGroupEnd = g_groups.groups + g_groups.count;
- for (ppGroup=g_groups.groups; ppGroup<ppGroupEnd; ppGroup++)
- {
- deactiveCount = 0;
- ppServerEnd = (*ppGroup)->active_servers + (*ppGroup)->active_count;
- for (ppServer=(*ppGroup)->active_servers; ppServer<ppServerEnd; ppServer++)
- {
- if (current_time - (*ppServer)->stat.last_heart_beat_time > \
- g_check_active_interval)
- {
- deactiveServers[deactiveCount] = *ppServer;
- deactiveCount++;
- if (deactiveCount >= FDFS_MAX_SERVERS_EACH_GROUP)
- {
- break;
- }
- }
- }
这里,通过时间对比,找出不活动的 storage server,接下来并更改 storage 的状态为 FDFS_STORAGE_STATUS_OFFLINE。
接着往下分析,fdfs_trackerd.c 301行:
- if ((result=tracker_relationship_init()) != 0)
- {
- log_destroy();
- return result;
- }
tracker 间地位相对平等的,首先初始化tracker间的关系,tracker_relationship_init 内部是创建线程 relationship_thread_entrance。在线程内部,会执行 relationship_select_leader、relationship_ping_leader等函数。tracker leader 的内部机制,以后章节会详细展开。
fdfs_trackerd.c 接下来的代码,就是进入上节分析过的网络部分。至此,tracker 入口分析完成。
我们在分析storage的入口,整体来说和tracker 的入口很相似,我们只分析不同的地方。
fdfs_storage.c 144行:
- if ((result=storage_sync_init()) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "storage_sync_init fail, program exit!", __LINE__);
- g_continue_flag = false;
- return result;
- }
- if ((result=tracker_report_init()) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "tracker_report_init fail, program exit!", __LINE__);
- g_continue_flag = false;
- return result;
- }
- if ((result=storage_service_init()) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "storage_service_init fail, program exit!", __LINE__);
- g_continue_flag = false;
- return result;
- }
代码分析:
1. storage_sync_init 同步初始化,storage_sync.c 990行。包括 读取 binlog 的index 动作,binlog 会在对FastDFS 同步机制的分析章节详细介绍;
2.storage_service_init 内部和 tracker 的一样,是创建工作者线程。
fdfs_storage.c 263行:
- if ((result=tracker_report_thread_start()) != 0)
- {
- logCrit("file: "__FILE__", line: %d, " \
- "tracker_report_thread_start fail, " \
- "program exit!", __LINE__);
- g_continue_flag = false;
- storage_func_destroy();
- log_destroy();
- return result;
- }
这里tracker_report_thread_start是创建上报线程tracker_report_thread_entrance。里面涉及到同步机制,这里暂时不做展开,后面章节详细分析。
fdfs_storage.c 327行:
- if ((result=storage_dio_init()) != 0)
- {
- log_destroy();
- return result;
- }
storage 是存储服务,通过执行storage_dio_init 实现dio (磁盘IO)的初始化。storage_dio_init函数是创建dio线程 dio_thread_entrance。关于dio的机制,我们可以放到upload、download 里面分析。
fdfs_storaged.c 接下来的代码,就是进入上节分析过的网络部分。 OK, 入口分析完成。
欢迎感兴趣的朋友一起交流研究,提出意见。
FastDFS技术交流群:164684842
阅读(718) | 评论(0) | 转发(0) |