前面,分析了org.apache.hadoop.fs.Filesystem抽象类,我们已经了解到,要实现一个最基本的文件系统都需要包含哪些要点。下面具体到某个实现Filesystem的具体实现类,基于该抽象类Filesystem派生的类的继承关系:
? extends FileSystem
下面分析FileSystem类的两个直接子类FilterFileSystem与RawLocalFileSystem的实现:
- FilterFileSystem类
这里,首先分析FileSystem抽象类的子类org.apache.hadoop.fs.FilterFileSystem类,它是一个文件系统的实现类,该文件系统包含了一些其他的Filesystem文件系统,并以这些Filesystem文件系统作为基本的文件系统,可能用来转换数据或者提供附加功能。
该类主要是在其内部定义了一个Filesystem属性:
其实现了基类Filesystem的全部方法,是通过fs直接调用Filesystem抽象类中的方法达到的,似乎并没有增加任何其它的功能,但是可以作为一个具有最基本功能的文件系统。
- RawLocalFileSystem类
RawLocalFileSystem类是实现了FileSystem的API的一个原生本地文件系统,它的属性如下所示:
workingDir在该类的构造方法中,通过获取系统的属性“user.dir”属性初始化的:
该类中包含了3个与文件读写相关的内部类,分别为:
TrackingFileInputStream类通过继承自基类FileSystem类的Statistics statistics属性,来跟踪文件系统中数据流动。
LocalFSFileInputStream类包装了一个FileInputStream流属性,通过构造方法构造一个TrackingFileInputStream来完成输入流的相关操作。
LocalFSFileOutputStream类包装了一个FileOutputStream流属性,以来FileOutputStream定义的操作来实现对文件系统中的输出流的操作。该类还实现了org.apache.hadoop.fs.Syncable接口,使得该文件输出流类能够实现并调用该接口定义的sync()方法,实现强制对基本设备的缓冲区执行同步操作。
还有一个内部类,是封装文件信息的实体类RawLocalFileStatus,实现了getGroup、setOwner与getOwner、setPermission与getPermission、execCommand等方法,其中set前缀的方法设置对应的信息都是通过执行Shell命令来实现的;而get前缀的方法获取对应的信息也是通过执行Shell命令,并调用一个私有方法loadPermissionInfo加载必要的信息。
另外,RawLocalFileSystem继承实现了FileSystem抽象类中基本的文件操作,例如文件创建、打开、删除等等。
? extends FilterFileSystem
下面分析FilterFileSystem类的两个直接子类ChecksumFileSystem与HarFileSystem的实现:
- ChecksumFileSystem类
该类是一个基于校验和的文件系统的抽象类,它继承自FilterFileSystem类,它的特点就是在客户端为每一个原生文件(raw file)创建一个校验和文件,扩展名为“.crc”,用它可以校验原生文件的完整性。
1、增加的属性
这个基于校验和文件的文件系统,增加了如下两个属性:
其中,bytesPerChecksum默认值为512字节,你可以通过配置Hadoop的core-default.xml文件中的I/O属性io.bytes.per.checksum:
每个校验和文件的大小不能比一个文件所对应的的缓存大,一个文件的缓存大小通过io.file.buffer.size属性可以在core-default.xml文件中进行配置。
verifyChecksum属性默认为true,表示基于ChecksumFileSystem文件系统的文件,在读写过程中,需要检查校验和文件,验证原生文件的完整性。
2、校验和文件
ChecksumFileSystem提供了与校验和文件相关的一些基本的操作:
(1)通过setConf方法,设置文件系统的校验和文件大小:
从基于core-default.xml配置文件的配置类Configuration的实例来获取,默认大小512字节。
(2)判断文件系统中的文件是否是校验和文件:
一个Path file文件的名称为“.crc”时,才被认为是校验和文件。
(3)获取文件系统校验和文件大小参数:
(4)获取指定大小的文件对应的校验和文件大小:
可以看一下,getChecksumLength方法是如何计算一个校验和文件的大小的:
(5) 计算校验和文件所分配的缓存的大小:
校验和文件如果全部放入到文件缓存中,至少分配的缓存的大小,等于校验和文件的大小。但是,可能文件缓存bufferSize可能会足够大,从而在为校验和文件分配缓存的时候,可能会比一个校验和文件的大小要大。检验和文件需要加入到文件缓存中,然后系统从缓存中执行读写操作操作。
3、基本文件操作
实现的基本操作包括文件创建、打开、读写、拷贝、移动。最主要的是真正实现了文件在不同文件系统之间的拷贝操作,如下所示:
其中,文件工具类org.apache.hadoop.fs.FileUtil的copy方法是实现拷贝操作的核心方法,实现过程比较复杂,可以从此处开始一步步跟踪代码,了解拷贝的实现细节。
4、读写校验和文件
当读校验和文件时,是为了验证数据文件的完整性,在该文件系统实现类中,与检查校验和文件相关的类的继承层次关系如下所示:
ChecksumFSInputChecker类对一个打开的文件(以FSInputStream输入流的形式),验证该文件与其对应的校验和文件是否匹配,做一个匹配性检查。
该类封装了ChecksumFileSystem、FSDataInputStream、FSDataInputStream三个类的对象,如下所示:
当一个原生文件需要被存储到指定的主机文件系统中,同时计算该文件对应的校验和信息,并将该校验和信息流式写入到对应的校验和文件中。与校验和文件创建与写操作相关的类的继承层次关系如下所示:
ChecksumFSOutputSummer类为一个校验和文件提供了一个FSDataOutputStream输出流对象,它为原生文件数据生成一个校验和,并流式写入到FSDataOutputStream sums输出流中。
在读写校验和文件的时候,都是将校验和文件数据放到文件缓冲区,通过流对象来执行读写操作。
- HarFileSystem类
HarFileSystem是Hadoop归档文件系统(Hadoop Archive Filesystem)的实现,该文件系统具有索引文件及其相关内容。用来标识归档文件系统的URI的形式如下所示:
har://underlyingfsscheme-host:port/archivepath
或者
har:///archivepath
首先看该文件系统的属性:
该文件系统类其它文件系统实现类一样,实现了归档文件系统的中对文件的基本操作。
? extends ChecksumFileSystem
下面分析ChecksumFileSystem类的直接子类LocalFileSystem类的实现。
LocalFileSystem类实现了FileSystem的API,它是一个基于校验和的本地文件系统。
通过构造方法可以看到,它是以org.apache.hadoop.fs.RawLocalFileSystem为基本文件系统的,如下所示:
该类实现了ChecksumFileSystem类中定义但未实现的,用于向文件系统报告校验和文件出错的方法,同时把出错的校验和文件重命名后,移动到指定的目录(bad_files)中,在该目录中的文件是不能够被重新使用的,如下所示: