Path和Path项
Path是一个字符串,代表一个文件,目录或者是一个符号链接。
Path不能包含. /或者一些其他的字符,如果符号不可行,那么文件系统应该报出InvalidPathException
path相关方法
- valid-path-element
检查path项是否符合规范 - valid-path
- parent
获取parent项 - filename
获取filename项 - childElements
- ancestors
- 处理绝对路径和相对路径
定义文件系统
- 定义目录
路径指向文件系统中的目录
路径要有父目录,或者该目录是/
子路径不能重复 - 定义文件
- 定义符号连接
- 定义文件大小
如果是文件的话是它的长度,如果是目录的话返回0
-userhome
用户的HomeDirectory - 排他性
一个路径不能指向两个东西 - 加密区
加密的本质和机制没有说明
这个模型考虑了除了权限和元数据之外的其他部分的查询和操作。
FileSystem
实现一个文件系统,要关注的就是原子性,一致性,并发性,以及操作反馈等等。FS定义了一些基本操作,不同的文件系统都要实现,只不过实现时也有些许差别。比如说s3很多操作不支持原子性,它没有属性的文件系统,所以list,rename效率比较低,实现也不一样。所以使用过程中需要注意。
抽象的FileSystem类是访问Hadoop文件系统的原始类,对所有的Hadoop支持的文件系统,都存在非抽象子类。
所有的接口路径操作必须支持相对路径,相对于setWorkingDirectory定义的工作目录进行解析。
对于客户端,添加了组件组件PWD的概念,对应客户机实例是唯一的。
所有对于FileSystem的操作都可以返回一个新的FileSystem
可行性功能
可以定义一些保护目录,删除保护目录会抛出异常
非抽象类需要实现以下方法
断言和其他状态访问操作
- exists
- isDirectory
- isFile
- getFileStatus
返回状态有关ACL,加密和擦除编码信息的详细信息。
yarn启动时,缓存所有的都可以访问,如果声明为加密的,可以控制访问。但是有些文件系统,比如s3不支持POSIX访问控制,就需要创建FileStatus时,直接指定为t-rue - msync
同步元数据,客户端/HA集群
HDFS Observer请求ActiveNamenode获取最新的事务id来支持msync - listStatusIterator
- listStatus
list路径下所有文件的status,不保证一致性 - listLocatedStatus
返回的是FieStatus的子集
默认实现是使用了listStatus(path),其他的方式可能实现更动态的枚举,比如说获取child entries的子集.
调用方需要假定,如果迭代过程中,文件发生了变化,可能会执行失败。 - listFiles(path,recurive)
创建一个迭代器,访问目录下的文件和目录。最终调用的是listLocatedStatus - getFileBlockLocations(FileStatus,s,l)
需要可以的快速获取包含s,s+l数据block的位置 - getDefaultBlockSize
得到文件系统的默认块大小。尽管没有定义最小值,因为它用于作业提交过程中对工作进行分区,但是块大小太小将导致工作负载的分区很差,计算分区时可能导致客户端内存耗尽。 - getBlockSize(path)
改变状态的接口
- mkdir
- create
有一些约束
对于非overwrite的文件创建,该文件必须不存在
任何祖先都不可以是文件
约束就是实现时的判断
可能会失败,比如说readonly FS,block size小于块最小值,副本数超了,配额,重复等问题。返回的结果是FSDataoutputStream
不同实现的说明:
1)一些实现将Create拆分为几个步骤,会导致该操作不是原子的。
2)S3,Swift等对象存储会在outputStrem close时候才真正的改变FS的状态。这和FileSystem不同。会导致即使获取的独占锁也可能不是安全的。
- createFile
返回的是FSDataOutputStreamBuilder,不会立即对文件系统更改。在FSdataOutputStreamBuilder上调用build时,验证构造器参数,底层的文件系统上调用create(path p) - append
- appendFile
- open
需要预先检查是不是文件,返回的结果是FSDataInputStrem(0,FS.Files[p])
异常的话会报错(Cannot open filename + src) - openfile
建造者模式返回一个InputStreamBuilder,依赖open方法。
有些FS实现是懒加载,(比如S3)因为探测比较耗资源。 - getPathHandle
- open(PathHandle handle, bufferSize)
pathHandle包含path,mtime,nodeid等信息。
- delete
删除文件,目录或者符号连接。 - (object stores)root directory deletion
S3定义了不可以直接删除根目录,为了避免删除特定存储和容器本身混淆。
在删除语义上S3不是原子性的,所以它并没有很好的替代HDFS - rename
需要预先检查:src是否存在,dest不能是src的后继,dest必须要有parent(除非是root),dest不能是root,dest不能存在文件。
rename有许多方法,不翻译了。主要看看实现不一致的部分。
rename到一个不存在的路径
HDFS: false
Local FS: 返回true,隐含parent目录存在。
S3: 只检查dest父节点不能是一个文件,不管祖先节点。
rename在一些文件系统的实现也是非原子性的。
- concat
多个block合并成一个文件,目前仅仅hdfs实现了。 - truncate
文件截断成目标长度,不能处理writing或者appending的文件。
dfs实现为,client调用truncate,namenode rpc服务调用namesystem的truncate方法,这里面校验之后,获取iip,找到block,然后进行truncate操作。
- copyFromLocalFile
从本地拷贝到文件系统,可以指定删除或者覆盖。
hdfs是递归拷贝的,object store可以利用并行上传来最大化吞吐。
RemoteIterator
remoteiterator和本地的iterator使用相似,只不过是远程的,不支持remove操作。
最终还是通过一个rpc,从namenode中获取批量文件信息。减少rpc调用次数。通过iterator的接口进行访问。
StreamCapabilities
支持通过编程来查询OutputStream,InputStream,FileSystem支持什么能力
比如说:
hflush:flush缓冲区,其他的reader可见
hsync:buffer到磁盘
dropbehnd: 丢弃缓存
EtagSource
FileSystem支持从FileStatus获取Etag标签
和HTTP资源相关,不太关注