[Hadoop]源码分析(1)----FileSytem

分析的Hadoop目前最新版本-2.7.1。

ServiceLoader在FileSystem类的使用

客户端通过调用FileSystem对象的open方法来打开希望读取的文件。
FileSystem是一个抽象类。

首先,给出Hadoop的一个简单的代码如下:

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.io.IOUtils;

public class OpenFileSrc {
    public static void main(String[] args) throws IOException,
            URISyntaxException {
        String uri = "file:///Users/arthur/Desktop/test.txt";
        FileSystem dfs = FileSystem
                .get(new URI(uri), new Configuration());
        InputStream fsinput = dfs.open(new Path(uri));
        System.out.println(dfs instanceof LocalFileSystem);
        IOUtils.copyBytes(fsinput,System.out,4,true);
        //read方法返回的是读取的下一个字节的ascii码
//        System.out.println(fsinput.read());
    }
}

研究的重点在于下面的代码。

FileSystem dfs = FileSystem.get(new URI(uri), new Configuration());

关联代码以后我们点进去查看它是如何工作的?
Step 1:
这里写图片描述
Step 2:
这里写图片描述
Step 3:
这里写图片描述
Step 4:
这里写图片描述
Step 5:
这里写图片描述

第五步时,我们可以通过SERVICE_FILE_SYSTEMS这个Map类来获取FileSytem类。那么问题来了,Map的初始化工作是怎么做的?

注意到下面这个类,这里利用了ServiceLoader类进行了加载。使用这个类的好处在于,可以很方便的给Hadoop添加我们自己的文件系统。关于ServiceLoader的介绍可以参考我的博文
这里写图片描述

FileSystem的静态内部类–Cache类

FileSystem类里面有个内部静态类Cache。包含下面方法和变量。
这里写图片描述
Cache顾名思义,缓存。查看FileSystem类。定义了静态变量。

  /** FileSystem cache */
  static final Cache CACHE = new Cache();

定义为final类的理由我就不多说了,final的目的是为了防止变量再次被赋值。
在介绍Cache类之前,先介绍下它的一个静态内部类,Cache.Key类。Key类保存着scheme、authority、 UserGroupInformation,unique信息。
在调用方法FileSystem的get(URI uri, Configuration conf)的时候,我们会调用new Key(uri,conf,0)方法。而 FileSystem dfs1= FileSystem.newInstance(URI uri, Configuration conf)调用 new Key(uri, conf, unique.getAndIncrement())来实现的。而这种自增并不是基本类型,而是AtomicLonge类。

private static AtomicLong unique = new AtomicLong(1); 

Atomiclong、AomicInteger等类是线程安全的,这样就保证了线程安全的自增操作,得到的实例化对象肯定唯一。
值得一提的是,FileSystem的另一个静态内部类 Statistics。用来记录FileSystem中完成的读写等操作的数据。
这里写图片描述
这样的弱引用,使得内存管理的更加合理。因为SattisticsData和Thread之间存在着依赖关系。

FileSystem兼容性

Hadoop会把已经Deprecated的参数也一起加载进行。而且低版本的HDFS的本地文件系统是通过“local”来访问的,现在通过“file”方法,这就设置到了一个fixname方法,解决兼容性问题。
1)fixname方法,当你使用低版本的命名格式(如,local的时候,会自动转换成版本匹配的字符)。

DistributedFileSystem类

DistributedFileSystem类继承自 FileSystem抽象类。
DistributedFileSystem是适配器模式的一个典型应用,它将DFSCl-ient提供的访问HDFS能力包装成FileSystem要求的界面。下面是从源代码上摘抄的成员变量。

  private Path workingDir;
  private URI uri;
  private String homeDirPrefix =
      DFSConfigKeys.DFS_USER_HOME_DIR_PREFIX_DEFAULT;
  DFSClient dfs; 
  private boolean verifyChecksum = true; 

其中成员变量dfs的类型是DFSClient,而其他四个成员变量(HDFS那本技术内幕的书上是三个,应该是版本更新后加了个成员变量),homeDirPrefix为主文件夹目录,默认为/user;workingDir保存了文件系统的当前工作;uri保存文件系统的URI模式和授权机构部分。
DistributedFileSystem.initialize()用于初始化对象,成员变量workingDir、uri和dfs都在这个方法被初始化。该方法需要一个Configuration对象,注意,类的static块会加载hdfs-default.xml和hdfs-site.xml两个配置文件,他们提供了访问Hadoop文件系统的一些默认配置。删除文件的delete()成员函数是典型的文件和目录相关事务方法,它的实现,就是简单地调用DFSClient的同名方法。DistributedFileSystem.open()用于打开HDFS文件,它返回一个FSDataInputStream对象,用于读取文件数据。方法open()实际返回一个DFSDataInputStream对象,它的FSDataInputStream的子类,也是为了兼容Hadoop文件系统界面而引入的包装器,它的大部分操作都委托给了通过DFSClient.open()创建的DFSInputStream对象。
DistributedFileSystem类提供了一系列对文件系统的操作,下面以mkdir和mkdirs两方法为例。
前者return mkdirsInternal(f, permission, false),后者return  mkdirsInternal(f, permission, ture),这意味着前者不创建父文件夹,而mkdirs方法可以。
这里面很多操作都是和 FileSystemLinkResolver这个抽象类有关系,都是实现了这个抽象类的docall和next方法,再调用resolve方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值