FastDFS分布式文件系统点滴记录4 -- tracker 、storage 入口分析

来源:互联网 发布:java和php 知乎 编辑:程序博客网 时间:2024/06/05 00:35
tracker 的入口在 fdfs_trackerd.c, 而 storage 的入口在fdfs_storaged.c.下面首先分析tracker的,我们从main 函数开始。

fdfs_trackerd.c 109 行:

  1.     conf_filename = argv[1];
  2.     memset(bind_addr, 0, sizeof(bind_addr));
  3.     if ((result=tracker_load_from_conf_file(conf_filename,\
  4.             bind_addr, sizeof(bind_addr)))!= 0)
  5.     {
  6.         log_destroy();
  7.         return result;
  8.     }
代码分析:
1. 从命令行接收配置文件名称;
2. 调用tracker_load_from_conf_file 载入配置,具体参数保存在对应的全局变量中。

接着往下分析,fdfs_trackerd.c 117 行:

  1.     if ((result=tracker_load_status_from_file(&g_tracker_last_status))!= 0)
  2.     {
  3.         log_destroy();
  4.         return result;
  5.     }
这里面主要是从隐藏文件 .tracker_status 读取 tracker 上次的状态。

接着往下分析,fdfs_trackerd.c 131行:

  1.     if ((result=tracker_mem_init())!= 0)
  2.     {
  3.         log_destroy();
  4.         return result;
  5.     }
tracker_mem* 相关操作目的是 tracker 在内存中维护 storage 运行状态。这里需要进行初始化动作,会调用 tracker_mem.c 1535行的 tracker_load_data 函数,实现包括从文件中载入groups、storage等信息。

接着往下分析,fdfs_trackerd.c 150行:

  1.     daemon_init(true);
  2.     umask(0);
这里是后台守护进程初始化,目的是为了让tracker 后台运行。

接着往下分析,fdfs_trackerd.c 163行:

  1. if ((result=tracker_service_init())!= 0)
  2.     {
  3.         log_destroy();
  4.         return result;
  5.     }
tracker_service_init 是 tracker 服务的初始化函数。里面主要的动作是pthread_create创建工作者线程,线程的执行函数是work_thread_entrance。

接下来,fdfs_trackerd.c 172行开始,是sigaction设置信号的处理方式。这是linux信号处理机制基础。

接着往下分析,fdfs_trackerd.c 242行: 

  1. #ifdef WITH_HTTPD
  2.     if (!g_http_params.disabled)
  3.     {
  4.         if ((result=tracker_httpd_start(bind_addr))!= 0)
  5.         {
  6.             logCrit("file: "__FILE__", line: %d, "\
  7.                 "tracker_httpd_start fail, program exit!",\
  8.                 __LINE__);
  9.             return result;
  10.         }

  11.     }

  12.     if ((result=tracker_http_check_start())!= 0)
  13.     {
  14.         logCrit("file: "__FILE__", line: %d, "\
  15.             "tracker_http_check_start fail, "\
  16.             "program exit!", __LINE__);
  17.         return result;
  18.     }
  19. #endif
代码分析:
1. tracker 内置了 httpd 服务,但是需要开启编译选项 WITH_HTTPD
fdfs_trackerd.c 270行: 
  1.     scheduleArray.entries = scheduleEntries;
  2.     scheduleArray.count = SCHEDULE_ENTRIES_COUNT;

  3.     memset(scheduleEntries, 0, sizeof(scheduleEntries));
  4.     scheduleEntries[0].id= 1;
  5.     scheduleEntries[0].time_base.hour= TIME_NONE;
  6.     scheduleEntries[0].time_base.minute= TIME_NONE;
  7.     scheduleEntries[0].interval= g_sync_log_buff_interval;
  8.     scheduleEntries[0].task_func= log_sync_func;
  9.     scheduleEntries[0].func_args= &g_log_context;

  10.     scheduleEntries[1].id= 2;
  11.     scheduleEntries[1].time_base.hour= TIME_NONE;
  12.     scheduleEntries[1].time_base.minute= TIME_NONE;
  13.     scheduleEntries[1].interval= g_check_active_interval;
  14.     scheduleEntries[1].task_func= tracker_mem_check_alive;
  15.     scheduleEntries[1].func_args= NULL;

  16.     scheduleEntries[2].id= 3;
  17.     scheduleEntries[2].time_base.hour= 0;
  18.     scheduleEntries[2].time_base.minute= 0;
  19.     scheduleEntries[2].interval= TRACKER_SYNC_STATUS_FILE_INTERVAL;
  20.     scheduleEntries[2].task_func= tracker_write_status_to_file;
  21.     scheduleEntries[2].func_args= NULL;
  22.     if ((result=sched_start(&scheduleArray,&schedule_tid,\
  23.         g_thread_stack_size, &g_continue_flag))!= 0)
  24.     {
  25.         log_destroy();
  26.         return result;
  27.     }
代码分析:
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行:

  1.     current_time = time(NULL);
  2.     ppGroupEnd = g_groups.groups+ g_groups.count;
  3.     for (ppGroup=g_groups.groups; ppGroup<ppGroupEnd; ppGroup++)
  4.     {
  5.     deactiveCount = 0;
  6.     ppServerEnd = (*ppGroup)->active_servers+ (*ppGroup)->active_count;
  7.     for (ppServer=(*ppGroup)->active_servers; ppServer<ppServerEnd; ppServer++)
  8.     {
  9.         if (current_time- (*ppServer)->stat.last_heart_beat_time> \
  10.             g_check_active_interval)
  11.         {
  12.             deactiveServers[deactiveCount]= *ppServer;
  13.             deactiveCount++;
  14.             if (deactiveCount >= FDFS_MAX_SERVERS_EACH_GROUP)
  15.             {
  16.                 break;
  17.             }
  18.         }
  19.     }
这里,通过时间对比,找出不活动的 storage server,接下来并更改 storage 的状态为 FDFS_STORAGE_STATUS_OFFLINE。

接着往下分析,fdfs_trackerd.c 301行:  
  1.     if ((result=tracker_relationship_init())!= 0)
  2.     {
  3.         log_destroy();
  4.         return result;
  5.     }
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行:  
  1.     if ((result=storage_sync_init())!= 0)
  2.     {
  3.         logCrit("file: "__FILE__", line: %d, "\
  4.             "storage_sync_init fail, program exit!", __LINE__);
  5.         g_continue_flag = false;
  6.         return result;
  7.     }

  8.     if ((result=tracker_report_init())!= 0)
  9.     {
  10.         logCrit("file: "__FILE__", line: %d, "\
  11.             "tracker_report_init fail, program exit!", __LINE__);
  12.         g_continue_flag = false;
  13.         return result;
  14.     }

  15.     if ((result=storage_service_init())!= 0)
  16.     {
  17.         logCrit("file: "__FILE__", line: %d, "\
  18.             "storage_service_init fail, program exit!", __LINE__);
  19.         g_continue_flag = false;
  20.         return result;
  21.     }
代码分析:
1. storage_sync_init  同步初始化,storage_sync.c 990行。包括 读取 binlog 的index 动作,binlog 会在对FastDFS 同步机制的分析章节详细介绍;
2.storage_service_init 内部和 tracker 的一样,是创建工作者线程。

fdfs_storage.c 263行: 
  1.     if ((result=tracker_report_thread_start())!= 0)
  2.     {
  3.         logCrit("file: "__FILE__", line: %d, "\
  4.             "tracker_report_thread_start fail, "\
  5.             "program exit!", __LINE__);
  6.         g_continue_flag = false;
  7.         storage_func_destroy();
  8.         log_destroy();
  9.         return result;
  10.     }
这里tracker_report_thread_start是创建上报线程tracker_report_thread_entrance。里面涉及到同步机制,这里暂时不做展开,后面章节详细分析。

fdfs_storage.c 327行:  
  1.     if ((result=storage_dio_init())!= 0)
  2.     {
  3.         log_destroy();
  4.         return result;
  5.     }
storage 是存储服务,通过执行storage_dio_init 实现dio (磁盘IO)的初始化。storage_dio_init函数是创建dio线程 dio_thread_entrance。关于dio的机制,我们可以放到upload、download 里面分析。

fdfs_storaged.c 接下来的代码,就是进入上节分析过的网络部分。 OK, 入口分析完成。
欢迎感兴趣的朋友一起交流研究,提出意见。
FastDFS技术交流群:164684842