您的位置:首页 > Web前端 > Node.js

hadoop源码解析---INodeReference机制

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

问题描述

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

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

引入INodeReference

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





图1

INodeReference代码实现

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public
abstract
class
INodeReference
extends
INode {

private
INode referred;
//指向的INode节点

public
INodeReference(INode parent,INode referred){

super
(parent);

this
.referred = referred;

}

public
final
INode getReferredINode() {
//获取指向的INode节点

return
referred;

}

public
final
void
setReferredINode(INode referred) {

this
.referred = referred;

}

//.
7fe0
..

}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public
static
class
WithCount
extends
INodeReference{

//保存所有指向这个WithCount对象的WithName对象的集合

private
final
List<WithName> withNameList =
new
ArrayList<WithName>();


public
WithCount(INodeReferenceparent,INode referred) {

super
(parent,referred);
//调用父类的构造方法,指向文件系统目录树中的INode

Preconditions.checkArgument(!referred.isReference());

refferred.setParentReferenct(
this
);
//设置真实INode的父节点为当前WithCount对象

}


public
void
addReferenct(INodeReferenceref){

if
( ref
instanceof
WithName) {
//如果是WithName对象,则加入withNameList

WithName refWithName = (WithName) ref;

int
i = Collections.binarySearch(withNameList, refWithName,WITHNAME_COMPARATOR);

Preconditions.checkState(i<
0
);

withNameList.add(-i-
1
,refWithName);

}
else
if
(ref
instanceof
DstReference) {
//如果是DstReference对象,则设置为父节点

setParentReference(ref);

}

}

//...

}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public
static
class
WithName extend INodeReference{

private
final
byte
[] name;
//重命名前的文件名

private
final
int
lastSnapshotId;

public
WithName(INodeDirectory parent,WithCountreferred,bytep[] name,
int
lastSnapshotId){

super
(parent,referred);
//调用父类构造方法,指向WithCount节点

this
.name = name;

this
.lastSnapshotId = lastSnapshotId;

referred.addReferenct(
this
);
//调用WithCount.addReferenct()

 
}

 
//...

}


public
static
class
DstReference
extends
INodeReference{

private
final
int
dstSnapshotId;

public
DstReference(INodeDirectory parent,WithCountreferred,
final
int
dstSnapshotId){

super
(parent,referred);

this
.lastSnapshotId = lastSnapshotId;

referred.addReferenct(
this
);
//调用WithCount.addReferenct()

}

//..

}


结束语:

免费学习更多精品课程,登录乐搏学院官网http://h.learnbo.cn/



原创:本文出自 “Xlows” 博客,请务必保留此出处http://xlows.blog.51cto.com/5380484/1811689
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: