淘宝分布式文件系统(四)–>索引头文件的定义
目录:
1. 简单说明整个模块各功能的实现
2.具体的实现过程
一 、块的初始化
1、生成主块文件
- 根据 id 创建文件
- 预分配空间
2、生成索引文件
- 根据 id 创建文件
- 头部初始化-》 块信息初始化-》索引信息初始化
- 同步写入磁盘
- 映射至内存访问
二、 块中写入文件
1、加载索引文件
- 映射索引文件至内存
2、文件写入至主块
- 从索引文件中读取块数据的偏移
- 将文件写入主块对应的偏移位置中
3、文件索引信息写入索引文件
- 生成MetaInfo 信息(包括文件在块中的 fd)->fd 文件的句柄
- 将MetaInfo 写入索引文件
- 更新块信息 BlockInfo
三、块中读取文件
1、加载索引文件
- 映射索引文件至内存
2、从索引文件中获取文件MetaInfo
- 根据文件 id 从块索引内存映射的Hash文件链表中查找文件的MetaInfo
3、根据MetaInfo 从主块中读取文件
四、块中删除文件
1、加载索引文件
- 映射索引文件至内存
2、从索引文件中获取文件MetaInfo
- 根据文件 id 从块索引内存映射的Hash文件链表中查找文件的MetaInfo
3、索引文件中删除MetaInfo
- 将当前文件对应的MetaInfo 在哈希链表中的上一个节点指向其后的节点
- 当前 MetaInfo 加入可从用的空闲节点链表中
- 更新块信息
以上的所有操作无非是对我们的关键数据结构的操作,具体的关键数据有哪些,在我的*淘宝分布式文件系统 (一)*中有进行说明,大家可以回顾一下
文件的结构:
设计类图 :
对于类的设计,我们可能会感到困惑, 我怎么知道他需要什么样的方法呢, 这里呢大家只要了解就行了,毕竟这是架构师做的事情 。现在的我们可能距离架构师还有一些距离。这里给大家介绍的分布式文件系统,让大家有一个大致的了解,以及对于文件映射的实现,不会也没有关系。
接下来,我们来 一 一 实现
-
对索引头文件 —BlockInfo ,注意: 在淘宝的分布式文件系统中,它是采用结构体的方式来进行实现的
为什么要这样设计,这里我不做多的讲解,实际上我也不清楚。struct BlockInfo //每一个块的结构 { uint32_t block_id_ ; //块编号1 , 2 ... int32_t version_ ; //块当前版本号 int32_t file_count_; //当前已保存文件总数 int32_t size_; //当前已保存文件数据的大小 int32_t del_file_count_; //已删除文件的数量 int32_t del_size_ ; // 已删除的文件数据总大小 uint32_t seq_no_; //下一个可分配的文件编号1 , 2 .... BlockInfo(){ memset(this,0,sizeof(BlockInfo)); } inline bool operator == (BlockInfo &blok_info){ return (this->block_id_==blok_info.block_id_ && this->version_==blok_info.version_ && this->file_count_== blok_info.file_count_ && this->size_==blok_info.size_ && this->del_file_count_==blok_info.del_file_count_ && this->del_size_==blok_info.del_size_ && this->seq_no_==blok_info.seq_no_ ); } };
-
对索引文件—MetaInfo 同样也是采用结构体的方式进行实现。
struct MetaInfo{ public: MetaInfo(){ init(); } MetaInfo(const uint64_t fileid , const int32_t inner_offset ,const int32_t size ,const int32_t next_meta_offset){ fileid_=fileid; location_.inner_offset_=inner_offset; location_.size_=size; next_meta_offset_=next_meta_offset; } //拷贝构造 MetaInfo(const MetaInfo& mete_info){ memcpy(this,&mete_info ,sizeof(mete_info)); } //重载 = MetaInfo& operator=(const MetaInfo &mete_info){ if(this==&mete_info){ return *this; } fileid_=mete_info.fileid_; location_.inner_offset_=mete_info.inner_offset_; location_.size_=mete_info.size_; next_meta_offset_=mete_info.next_meta_offset_; return *this; } //克隆clong MetaInfo& clong(const MetaInfo &mate_info){ assert(this==&mete_info); //assert 一个宏,如果为真,将整个程序干掉 fileid_=mete_info.fileid_; location_.inner_offset_=mete_info.inner_offset_; location_.size_=mete_info.size_; next_meta_offset_=mete_info.next_meta_offset_; return *this; } //重载== bool operator==(const MetaInfo &mete_info)const{ return (fileid_==mete_info.fileid_ && location_.inner_offset_==mete_info.inner_offset_ && location_.size_==mete_info.size_ && next_meta_offset_==mete_info.next_meta_offset_); } // 获取文件的 fileid uint64_t get_fileid()const{ return fileid_; } // 这里也是获取文件的 fileid void set_fileid(uint64_t fileid){ fileid_=fileid; } uint32_t get_file_key()const{ return fileid_; } void set_file_key(uint64_t){ fileid_=fileid; } int32_t get_inner_offset()const{ return location_.inner_offset_; } void set__inner_offset(int32_t inner_offset){ location_.inner_offset_=inner_offset; } int32_t get_size()const{ return location_.size_; } void set_size(int32_t size){ location_.size_=size; } int32_t get_next_meta_offset()const{ return next_meta_offset_; } void set_next_meta_offset(int32_t next_meta_offset){ next_meta_offset_=next_meta_offset; } private : uint64_t fileid_; //文件编号 struct { int32_t inner_offset_; //文件在块内部的偏移量 int32_t size_; //文件大小 }location_; int32_t next_meta_offset_; //当前哈希链下一个节点在索引中的偏移量 void init(){ //将内部元素初始化 fileid_=0; location_.inner_offset_=0; location_.size_=0; next_meta_offset_=0; } };