眼观千遍 → 耳听万遍 → 不如手动一遍√

  :: :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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中取得的。

posted on 2011-04-03 11:10  无恙  阅读(4171)  评论(8编辑  收藏  举报