SmartFileSystem 项目介绍

本文详细介绍了设计一个类似UNIX的SmartFileSystem,包括文件、块、文件管理器和块管理器的实现。系统强调文件的备份、数据的冗余存储以增强可靠性,同时通过智能数据分配确保系统数据均衡。还提出了减少未修改数据存储的操作,提高系统性能,并利用缓冲区提升读写效率。此外,文件的快速拷贝和智能错误检测也是系统的重要特性。
摘要由CSDN通过智能技术生成

一、项目解读

​ 参考UNIX文件系统仿写一个小型的Smart file system,主要实现文件的抽象,读取与存储等功能。

  1. 文件是一个抽象,在系统中其data、meta信息都是单独存在的,个人实现是物理fileMeta就足够代表一个可见的文件,所以在系统中文件是一个对象,通过调用方法完善或者更改meta、data信息。file对象应该含有read,setSize,write、close等功能。关于file的读取,应通过fileManager来查找,故而每个file应归属于某个fileManager。而file的存储,实现中采用了buffer,故而应在文件close的时候进行完整数据(包括file meta与data)的存储,同时还需考虑data的备份等任务。

  2. block也是抽象,文件的每个数据段都会随机设置2-3个block来存储,以保证文件系统的可靠性。block含有自己的meta信息(以下指代为blockMeta , 文件为fileMeta ),也含有真正用于存储数据的data信息(和blockMeta做区分,data应该叫blockData)。其meta用于检查数据的正确性(记录数据块存写信息以及检验和等,以保证数据块读出时的正确性),同时也提供了blockDdata的路径(即对应磁盘的存储地址)等。

  3. fileManager和blockManager是用于管理file和block的类,用户不该直接接触block,也不该直接使用blockManager类,不然就显得“权限”过大;用户应通过FileManager获取或者新建一个file,file可使用BlockManager进行相关数据的读取和存储。

二、项目主要结构

项目主要结构

三、类的具体设计–自底向上开发法

1.Block
Block的成员变量
  • bid: block Id, 形式为bmx-bx(表示该block对应的blockManager以及序号bx)
  • CAPACITY: 调节block的size,应由系统设置,且不能随意改变(即从系统层面上设置一个物理block能存储的数据量)
  • data:且因为block是不可重写的,所以data只能读,应封装为私有成员
  • meta:也许一个block最好有一个封装的meta信息,在获取block时进行创建;或者在新建block时记录
  • isMatched: 用于标记此block是否坏掉,坏掉的block不应该被读取,应寻找替代(标记方式,block的方法在调用时先进行判断该block的有效性,即是否能和对应的blockMeta匹配,包括检验和等验证。如果不能匹配的话,就代表这是一个损坏或者不能使用的块,需要抛弃,不能进行相关的操作)
  • bm : 此block所属的BlockManager
  • dataPath : 块的数据路径
Block的构造方法

首先Block是不可重写的,所以Block的读应该由read完成,且无须修改也不该调用write去再存储;而如果BM新建一个block用于给file存储新数据的话,就必须调用write方法了;

  • Block(bid , bm,meta)

​ 此构造方法应该由已有的meta与data信息去构造一个抽象block,以供调用;同时需将block获取的数据与meta的checksum进行比较,以核实块是否损坏

  • Block(bid, bm ,meta , data)

    用于创建一个空Block,并且该Block的write方法应该考虑到相关信息的存储与更新,比如block的meta信息以及data数据的存入

Block的函数方法
  • write(byte[] data):写入数据
  • read() : 检查data文件是否存在,不存在应该设置isMatched为false;存在则读取数据
2.BlockMeta
重要成员变量
  • id:String ;表示block的id ->bmx-bx
  • dataPath:String;block数据的存储地址(由此可随机化)
  • metaPah: String;blockMeta的存储位置
  • exist:boolean;meta是否存在,用于简化不必要的解析工作
  • checksum:meta保存的检验和信息,用于验证block独到的数据是否异常
构造函数
  • BlockMeta(String id , String dataPath , String metaPath, String checksum):用于创建新的block时对应meta的初始化,即一个并不存在的block
  • BlockMeta(String metaPath):用于获取一个已存在的block对应meta信息
功能函数(主要)
  • saveMeta():在对应的blockManager中调用以持久化保存meta信息
  • getChecksum(): 获取meta的checksum信息
3.BlockManager
重要成员变量
  • id:String; bmx
  • blockCounter:用户不需要知道怎么创建一个block以及如何给其命名等;这些工作应该由blockManager自动完成,系统只需要将数据以某种格式传给bm即可;所以blockCounter是用于自动化创建block的一种计算器,以避免覆盖block或者浪费命名空间
  • root:bm的路径根,用于简化路径创建
构造函数
  • BlockManager(String id):创建bm并且初始化blockCounter与id信息;主要在IFile中调用;
功能函数
  • getBlock(String bid):根据block id获取一个已存在的block,需对其进行检查,如果不正常则返回空以避免错误的传递
  • newBlock(byte[] data):创建一个新的block以存储data数据,同时还需创建对应的meta信息并持久化
  • newEmptyBlock(int blockSize):创建一个给定size的空block,其内数据为0000…
  • init():bm的初始化
  • shut():bm关闭,需要保存blockCounter信息
4.FileManager

​ 因为fileManager是可是实例化的,所以可以根据对应的fm去创建file,收录file id并在创建时进行名字修改;FM理应在新增或者获取文件的时候判断其存在性,减少不必要工作

成员变量
  • id: int ; x --不采用String是因为这一层已经是用户可以接触的了,应该简单化
  • name: fmx ;fm的具体名称;
  • root:路径跟信息,简化文件创建与读取的路径加载工作
构造函数
  • FileManager(int id):新建一个fileManager
功能函数
  • getFile( int fileId ):根据用户提供的id在对应fm中查找并返回IFile对象以供使用
  • newFile(int fileId):在对应的fm中创建一个给定id的新文件,需要判断其存在性
5.IFile

​ 文件的抽象,用于系统对一个文件读、写、存等操作

主要成员变量
  • checksum:用于文件读取后和fileMeta的checksum比较,以判断文件是否正常
  • buffer:byte[] ;缓冲区,减少“磁盘”读取操作,提升工作效率
  • blocks : ArrayList(); 用于保存读取一个文件时的所有block,以简化文件存储时的工作——比如数据是否改变或者重复,是否需要新建block等
  • bmRandom:Random ;用于文件数据块保存时随机选取两个或多个bm进行保存,实现冗余
  • MOVE系列:主要有三个,HEAD,TAIL与CURR,用于文件在控制台的写和读记录
  • isNormal:boolean;用于实时判断文件是否正常,以确定文件的相关操作是否有效
构造函数
  • IFile():创建一个空文件,其isNormal = false;即在系统不正常地创建一个file时用此构造方法返回file对象,然后关闭其功能权限
  • IFile(int fileId , FileManager fileManager):系统新建一个文件
  • IFile(int fileId , FileManager fileManager , String metaPath):系统打开一个文件,需要获取文件的meta信息并且对file对象各数据初始化,同时将file的buffer初始化以供使用
功能函数

每个函数的调用都需要判断文件是否正常,以避免不必要工作以及损毁工作

  • read():file内部读取数据;即初始化buffer;
  • read(int length):byte[] ;用户从当前光标位置读取length个字节数据
  • write(byte[] b):用户在当前位置写入数据
  • close():文件关闭时相关数据的持久化——比如buffer,meta等
  • pos():int ; 获取当前光标的位置
  • move(offset , where):int ;移动光标到距离where -> offset个位置的地方并返回MOVE_CURR = where+ offeset
  • init():IFile的blockManagers初始化;//系统调用
  • shut():IFile的blockManagers关闭(相关数据保存);//系统调用
  • setBroken():将一个文件标记为broken;
  • isNormal():boolean ;返回文件的isNormal变量;

四、ErrorCode-异常类

​ 主要用于处理系统的可能异常类型以及信息汇报

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T08fkz5o-1647153960886)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211022125722751.png)]

五、SmartFileSystem

​ 系统运行以及几个smart工具的提供类;涵盖IFile、FileManager、BlockManager等的初始化以及smart工具的实现与使用;

六、meta、data内容的设计

1. root

关于 root,设定为src同级的root目录,

  • root下有BM,对应bm-1,bm-2…;
  • root下有FM,对应fm-1,fm-2…;
2. file.meta
checksum
size
-------------(logic blocks)
 bmx-bx|bmx-bx|...|  
 bmx-bx|bmx-bx|...|
...
 bmx-bx|bmx-bx|...|

【注:每一行是拥有同样数据的逻辑块,当一个逻辑块获取数据有效,则进入下一行,获取另一个块的数据;如果当前逻辑块获取数据失败,则在同一行里尝试读取同样数据含义的逻辑块;一行中不同的逻辑块会存入不同的BlockManager,即备份】

3 . block.meta

地址:root\BM\bmx\bmx-bx.meta

id:bmx-bx
dataPath
metaPath
checksum
4.block.data

地址:root\BM\Data\bmx-bx.data

data:(文件分块后的对应数据)

七、My Bonus – 亮点

1.数据块的备份与随机性

​ 我在系统中实现了file每个数据块的数据备份,且同一数据块的备份将存储在不同的blockManager中,以确保文件数据的可靠性以及系统数据的可靠性。此外,对于file的每段数据,我都进行了冗余的随机化,即可能有一个备份,也可能有两个备份,以免增加过多的数据压力。

2.数据的“智能化”均衡

​ 数据拥有了备份后,可能各个blockManager的数据量会产生差异,因此有可能会造成各“服务器”间不同的数据访问量或者数据压力。所以我在系统中加入了一个均衡器,即数据优先存入数据量较小的两个blockManager中。如此一来,系统始终处于数据均衡的状态。

3.减少文件未改变数据的存储操作

​ 文件是可以修改的,但系统的block应该是不可重写的;所以我们可能会遇到一种特殊的情况,文件的内容增加了,或者减少了,亦或修改了,但其实文件的某些数据段并没有发生变动。如果这个时候对文件存储时,重新对所有数据段进行块分配与存储,一是可能造成系统的数据压力,同样也会增加文件存储的时间与空间。

​ 因此,在关闭文件时,系统会对文件的每个数据段与原文件(未修改)的数据段进行检验和对比,倘若数据段是一样的,那么此数据段仅需使用原来的block即可。这一设定并未违反block的不可重写特点,同时也减轻了文件存储所带来的各种压力。

4.buffer减少“磁盘”读取

​ 系统对每个文件维护了一个buffer,以供文件打开时的读写操作,同时减少IO的读取频率以提升系统性能和降低出错率

5.文件的快速拷贝

​ 同样用到了UNIX的设计,因为块是不可改变的,所以我们可以在文件拷贝时直接复制目标文件的meta信息,如此一来避免了blockMeta与blockData的不必要复制操作。也不用担心一个文件的变化对另一个文件的影响,文件做更改会将更改的数据使用新的数据块进行记录。

N、相关知识

– 并不全面,仅做项目知识储备

文件系统结构从下到上

1.块层

​ UNIX文件系统最底层是可持久储存数据的物理设备,块将这些物理设备的存储空间划分为固定大小的单位以供使用,不宜过大也不宜过小。

​ 块命名:块一般以到存储设备起始位置的偏移量为名字;

​ 块的查找可由块名直接映射到具体设备具体位置,且直接返回该块的内容。

public Block BLOCK_NUMBER_TO_BLOCK( interger b ) {

​ return block;

}

名字发现:块名是整数构成的紧致集的元素,块层需记录正在使用的块以及可供分配的块。文件系统需要路自身在磁盘上的分布信息。UNIX系统在超级块中记录这些信息

磁盘布局:引导块、超级块、位图、inode表、文件块、…、文件块

​ 超级块:一般位于磁盘第一块,以块为单位记录inode表和位图的大小;引导块:磁盘第0块,存储启动操作系统的程序。

​ 空闲块列表的组织形式:链表记录、位图跟踪。

​ 位图跟踪:位图存储于磁盘上的公知位置,其第i位记录了第i块的使用情况;

2.文件层

​ 用户数据超过单个块大小时,就需要引入文件层去支持此类数据。文件可以是任意长度的线性排列字节,这些字节分别记录在文件对应的若干块中,所以文件还需要记录其对应的多个块信息–引入inode。

inode:记录文件的元数据,包含组成文件的所有块号信息(块号数组),文件的大小;

​ 可根据偏移量offset与inode查找某字节所在的块以及位置:

​ index = offset/block_size;

​ block = inode(index);

3.inode编号层

​ 查找块的过程中,直接传递inode也很不方便——文件系统为inode新增了一个命名层:inode号,如此可通过一张inode表来记录所有inode!

​ inode_table(inode_number)

​ 名字发现:inode号也是整数构成的紧致集,所以inode编号层记录正在使用和未使用的inode,可采用记录块的多种方式实现,也可在inode中增加一个属性以表示此inode是否可用。

4.文件名层

inode号和块号都是与位置相关的整数,并不适合用户直接使用和记忆。因此,文件系统增加了新的命名层,可以以此来隐藏文件管理的元数据

新引入的命名层可实现对用户友好的命名方案,同时该层也能继续分层,可引入“目录”,作为将字符串和inode号绑定的上下文。

创建文件过程: 文件系统分配一个inode,初始化元数据,在特定目录中将指定的文件名字和inode号绑定;写文件时系统将为inode分配块。新的文件默认新增至当前工作目录,目录也是一个文件,同文件具有一样的结构,只是内容不同而已。表示目录的文件会包含一个 映射文件名到inode号的表,从而再根据inode表寻找对应的inode。

​ inode是文件还是目录?在inode中新增一个属性去表示——type;

目录创建:MKDIR创建一个空目录,设置type = DIRECTORY;

创建文件过程:* 文件系统分配一个inode,初始化元数据,在特定目录中将指定的文件名字和inode号绑定;写文件时系统将为inode分配块。新的文件默认新增至当前工作目录,目录也是一个文件,同文件具有一样的结构,只是内容不同而已。表示目录的文件会包含一个 映射文件名到inode号的表,从而再根据inode表寻找对应的inode。

​ inode是文件还是目录?在inode中新增一个属性去表示——type;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值