hadoop源码解析——-INodeReference机制

  

本文主要介绍了hadoop源码中hdfs的INodeReference机制。


在hdfs2.6版本中,引入了许多新的功能,一些原有的源代码设计也有一定的改造。一个重要的更新就是引入了快照功能。但是当hdfs文件或者目录处于某个快照中,并且这个文件或者目录被重命名或者移动到其他路径时,该文件或者目录就会存在多条访问路径.INodeReference就是为了解决这个问题产生的。


<强>问题描述

/一个是hdfs中的一个普通目录,s0为/的一个快照,在/目录下有一个文件测试。根据快照的定义,我们可以通过//测试以及//s0/测试/快照访问测试文件。

但是当用户将//测试文件重命名成/x/test1时,通过快照路径//s0/测试/快照将无法访问测试文件,这种情况是不符合快照规范的。


<强>引入INodeReference

为了解决上述问题,hdfs引入了INodeReference类。图1 - 1给出了INodeReference的继承关系图。这里的WithName, WithCoount, DstReference都是INodeReference的子类,同时也是INodeReference的内部类.WithName对象用于替代重命名操作前源路径中的INode对象,DstReference对象则用于替代重命名操作后目标路径中的INode对象,WithName和DstReference共同指向了一个WithCount对象,WithCount对象则指向了文件系统目录树中真正的INode对象。

 hadoop源码解析——-INodeReference机制

图1

<强> INodeReference代码实现

INodeReference是一个抽象类,它拓展自索引节点类,所以INodeReference及其子类是可以添加到文件系统目录树中以替代原有的INodeFile节点的.INodeReference定义了称为字段,这个字段用于保存当前INodeReference类指向的INode节点,所以WithName和RstReference,称为字段就指向了WithCount对象,对于WithCount,称为指向了真正的INode对象.INodeReference还定义了getReferredINode()方法,在文件系统目录树的操作中,如果判断当前节点是一个引用节点,则会调用getReferredINode()方法获取INodeReference指向的INode对象。

public  abstract  class  INodeReference  extends  INode  {   ,,,private  INode 引用;//指向的INode节点   ,,,public  INodeReference (INode  INode 家长;称){   ,,,,,,,超级(父);   ,,,,,,,this.referred =,称为;   ,,,}   ,,,public  final  INode  getReferredINode(),{//才能获取指向的INode节点   ,,,,,,,return 提到;   ,,,}   ,,,public  final  void  setReferredINode (INode 提到),{   ,,,,,,,this.referred =,称为;   ,,,}   ,,,//?   }

然后,我们在来看看WithCount类的实现。

WithCount类定义了一个集合字段withNameList用于保存所有指向这个WithCount对象的WithName对象集合.WithCount类还定义了addReference()方法,任何指向WithCount对象的WithName对象以及DstReference对象都需要调用这个方法来添加指向关系。对于指向这个WithCount对象的DstReference对象,addReference()方法会将这个对象设置为自己的父INode节点;而对于WithName对象,addReference()方法则将这个对象放入withNameList集合中保存。

public  static  class  WithCount  extends  INodeReference  {   ,,,//保存所有指向这个WithCount对象的WithName对象的集合   ,,,private  final  List, withNameList =, new  ArrayList ();   ,,,,   ,,,public  WithCount (INode  INodeReference 家长;称),{   ,,,,,,,超级(父母,称为);,//调用父类的构造方法,指向文件系统目录树中的INode   ,,,,,,,Preconditions.checkArgument (! referred.isReference ());   ,,,,,,,refferred.setParentReferenct(这);,//设置真实INode的父节点为当前WithCount对象   ,,,}   ,,,,   ,,,public  void  addReferenct (INodeReference  ref) {   ,,,,,,,if  (, ref  instanceof  WithName),{,//如果是WithName对象,则加入withNameList   ,,,,,,,,,,,WithName  refWithName =, (WithName),裁判;   ,,,,,,,,,,,int 小姐:=,Collections.binarySearch (refWithName withNameList也WITHNAME_COMPARATOR);   ,,,,,,,,,,,Preconditions.checkState (i<0);   ,,,,,,,,,,,withNameList.add(我refWithName);   ,,,,,,,},else  if  (ref  instanceof  DstReference),{,//如果是DstReference对象,则设置为父节点   ,,,,,,,,,,,setParentReference (ref);   ,,,,,,,}   ,,,}   ,,,//?   }

看完WithCount后,在看看WithName和DstReference.WithName类定义了名字字段用于保存重命名前文件的名称,同事定义了lastSnapshotId字段用于保存WithName对象构造时源路径的快照版本号.DstReference类的实现就更简单了,只定义了一个dstSnapshotId字段用于保存重命名操作前目标路径的最新快照的版本号.WithName和DstReference在构造时都会调用父类的构造方法指向WithCount对象,同时还会调用WithCount.addReference()方法配置WithCount对象。

hadoop源码解析——-INodeReference机制