zoukankan      html  css  js  c++  java
  • MooseFS源代码分析(三)——mfsmaster模块

    1.masterserver的启动过程

    ▲首先读取命令行参数和配置文件。如果当前用户是root,切换到默认用户。检查masterserver主进程是否已经启动。

    ▲初始化日志。

    ▲启动对chunkserver的监听。

    ▲启动对客户端的监听。

    ▲初始化文件系统,初始化存储文件节点的数组fsnodehash和存储块的数组chunkhash,全部初始化为空。

    文件节点对应的是一个树状的数据结构,具体如下:

    fsnode
    1. typedef struct _fsnode {
    2.     uint32_t id;
    3.     uint32_t ctime,mtime,atime;
    4.     uint8_t type;
    5.     uint8_t goal;
    6.     uint16_t mode;
    7.     uint32_t uid;
    8.     uint32_t gid;
    9.     uint32_t trashtime;
    10.     union _data {
    11.         struct _ddata {
    12.             fsedge *children;
    13.             uint32_t nlink;
    14.             uint32_t elements;
    15.         } ddata;
    16.         struct _sdata {
    17.             uint32_t pleng;
    18.             uint8_t *path;
    19.         } sdata;
    20.         uint32_t rdev;
    21.         struct _fdata {
    22.             uint64_t length;
    23.             uint64_t *chunktab;
    24.             uint32_t chunks;
    25.             cuidrec *cuids;
    26.         } fdata;
    27.     } data;
    28.     fsedge *parents;
    29.     struct _fsnode *next;
    30. } fsnode;

    chunk对应的结构是一个链表的结构:

    chunk
    1. typedef struct chunk {
    2.     uint64_t chunkid;
    3.     uint32_t version;
    4.     uint8_t goal;
    5.     uint32_t lockedto;
    6.     flist *flisthead;
    7.     struct chunk *next;
    8. } chunk;

    ▲从元数据存储文件(metadata.mfs)中读取所有的文件节点(fsnode)数据和存储块(chunk)的信息。在读取完数据后会把metadata.mfs重命名为metadata.mfs.back。至于fsnode和chunk在元数据中到底存储些什么内容,后面专门来描述。

    ▲进行用于数据统计的相关初始化工作。

    ▲进入到主循环(mainloop)。

    2.主循环(loop)的工作

    在主循环中,会重复执行由几个register函数注册的函数链。

    7个register 函数
    1. void main_destructregister (void (*fun)(void));
    2. void main_canexitregister (int (*fun)(void));
    3. void main_wantexitregister (void (*fun)(void));
    4. void main_reloadregister (void (*fun)(void));
    5. void main_selectregister (int (*desc)(fd_set *,fd_set *),void (*serve)(fd_set *,fd_set *));
    6. void main_eachloopregister (void (*fun)(void));
    7. void main_timeregister (int mode,int seconds,int offset,void (*fun)(void));

    拿其中的main_timeregister的实现看一下:

    main_timeregister
    1. void main_timeregister (int mode,int seconds,int offset,void (*fun)(void)) {
    2.     timeentry *aux;
    3.     if (seconds<1) return;
    4.     if (offset>=seconds || offset<0) return;
    5.     aux = (timeentry*)malloc(sizeof(timeentry));
    6.     aux->nextevent = ((now / seconds) * seconds) + offset + seconds;
    7.     aux->seconds = seconds;
    8.     aux->mode = mode;
    9.     aux->fun = fun;
    10.     aux->next = timehead;
    11.     timehead = aux;
    12. }

    他的作用就是把一些要执行的函数放到一个链表里面,后面方便由一个统一的入口timehead去执行。其它的几个register函数实现是类似的。

    每个函数的作用说明一下:

    ▲main_reloadregister、main_wantexitregister、main_canexitregister这个三个注册的是在masterserver需要退出或者重新载入的时候要运行的函数。main_desturctregister注册的函数会在masterserver退出时执行。

    ▲main_selectregister所注册的函数中,包括了masterserver对chunkserver和客户端通讯的处理。在前面讲到mfsmount模块的时候说到客户端和masterserver的通信,masterserver就是在这里去处理所有与客户端和chunkserver的网络通信的:

    main_selectregister
    1. main_selectregister(matocuserv_desc,matocuserv_serve);
    2. main_selectregister(matocsserv_desc,matocsserv_serve);

    上面的代码中,matocuserv_serve和matocsserv_serve就是响应客户端和chunkserver的相应入口。

    ▲main_eachloopregister注册的函数在每次循环时都会被执行到,但是这种register在所有的代码中都没有被用到。

    ▲main_timerregister,大部分任务都是用这个register注册的:

    main_timeregisters
    1. main_timeregister(TIMEMODE_SKIP,60,0,matocsserv_status);
    2. main_timeregister(TIMEMODE_RUNONCE,10,0,matocu_customer_check);
    3. main_timeregister(TIMEMODE_RUNONCE,3600,0,matocu_customer_statsmove);
    4. main_timeregister(TIMEMODE_RUNONCE,1,0,chunk_jobs_main)
    5. main_timeregister(TIMEMODE_RUNONCE,1,0,fs_test_files);
    6. main_timeregister(TIMEMODE_RUNONCE,3600,0,fs_dostoreall);
    7. main_timeregister(TIMEMODE_RUNONCE,300,0,fs_emptytrash);
    8. main_timeregister(TIMEMODE_RUNONCE,60,0,fs_emptyreserved);
    9. main_timeregister(TIMEMODE_SKIP,60,0,fs_show_counts);
    10. main_timeregister(TIMEMODE_RUNONCE,60,0,fsnodes_freeinodes);

    注意main_timerregister中的第二个参数,这个是以秒为单位的,所以下面每个任务执行的频率是不一样的。

    ◆matocsserv_status用于定时统计chunkserver的存储情况。

    ◆matocu_customer_check用于检查客户端是否还有连接,如果长时间不连接,则释放关联的资源。

    ◆matocu_customer_statsmove更新客户端的状态。

    ◆chunk_jobs_main做的工作比较复杂,首先它会在存储chunk信息的数组chunkhash中删除已经没有被使用的chunk。然后针对剩下的chunkhash数组中的每个chunkItem做如下的操作:
    ①计算这个chunkItem指向的chunk有效和无效的备份数量。删除已经无效的备份。

    ②如果当前chunkItem指向的chunk正在做某个操作,例如正在复制数据,则返回。

    ③如果当前chunkItem已经不指向任何chunk,从数组中删除。

    ④如果当前chunkItem指向的chunk的备份数量太多,删除其中某些状态的chunk。

    ⑤如果当前chunkItem指向的chunk的备份数量小于配置的值,则让chunk进行复制。

    ⑥检查所有的chunkserver的信息,如果这些chunkserver上的存储空间的状态差别太大,那么把一些chunk从存储空间比较紧张的chunkserver上转移到存储空间比较宽裕的chunkserver上。

    ◆fs_test_files用于检查文件的结构是否完好,例如,检查文件所在的chunk是否完好等。

    ◆fs_storeall用于将当前的文件结构更新到元数据中。

    ◆fs_emptytrash和fs_emptyreserved顾名思义。

    ◆fs_show_counts在日志中记录当前一些计数器的值。

    ◆fsnodes_freeinodes释放资源。

    3.存储结构

    metadata.mfs是最重要的一个文件,其中保存了所有的元数据,里面的具体内容如下:

    metamfsstructure

    最前面的是元数据的格式,说明按照什么格式去读取,每个fsnode中的数据可以看前面他的定义,目录、文件并没有分开存放,都作为一个节点,文件节点信息这部分更具maxnodeid可以知道读到什么地方结束。freenode和chunk的结构比较简单,注意chunk结构里面虽然有goal(每个文件需要多少个备份)的值,但是这个值是从chunk所属的fsnode中取得的。

  • 相关阅读:
    python3随记——字符编码
    python基础3(元祖、字典、深浅copy、集合、文件处理)
    python的颜色显示
    python基础2(数据类型、数据运算、for循环、while循环、列表)
    python基础之初始python
    0423作业(函数)
    0423上课练习(list、while、def)
    函数的定义与调用(4.23)
    0422作业:基础(if,while)
    while,for,if输入账号密码判断(还请各位大牛能够优化,本人刚学习一周)
  • 原文地址:https://www.cnblogs.com/JeffreySun/p/2004260.html
Copyright © 2011-2022 走看看