您好,登錄后才能下訂單哦!
本文主要介紹了hadoop源碼中hdfs的INodeReference機(jī)制。
在hdfs2.6版本中,引入了許多新的功能,一些原有的源代碼設(shè)計(jì)也有一定的改造。一個(gè)重要的更新就是引入了快照功能。但是當(dāng)HDFS文件或者目錄處于某個(gè)快照中,并且這個(gè)文件或者目錄被重命名或者移動(dòng)到其他路徑時(shí),該文件或者目錄就會(huì)存在多條訪問路徑。INodeReference就是為了解決這個(gè)問題產(chǎn)生的。
問題描述
/a是hdfs中的一個(gè)普通目錄,s0為/a的一個(gè)快照,在/a目錄下有一個(gè)文件test。根據(jù)快照的定義,我們可以通過/a/test以及/a/snapshot/s0/test訪問test文件。
但是當(dāng)用戶將/a/test文件重命名成/x/test1時(shí),通過快照路徑/a/snapshot/s0/test將無法訪問test文件,這種情況是不符合快照規(guī)范的。
引入INodeReference
為了解決上述問題,hdfs引入了INodeReference類。圖1-1給出了INodeReference的繼承關(guān)系圖。這里的WithName,WithCoount,DstReference都是INodeReference的子類,同時(shí)也是INodeReference的內(nèi)部類。WithName對(duì)象用于替代重命名操作前源路徑中的INode對(duì)象,DstReference對(duì)象則用于替代重命名操作后目標(biāo)路徑中的INode對(duì)象,WithName和DstReference共同指向了一個(gè)WithCount對(duì)象,WithCount對(duì)象則指向了文件系統(tǒng)目錄樹中真正的INode對(duì)象。
圖1
INodeReference代碼實(shí)現(xiàn)
INodeReference是一個(gè)抽象類,它拓展自INode類,所以INodeReference及其子類是可以添加到文件系統(tǒng)目錄樹中以替代原有的INodeFile節(jié)點(diǎn)的。INodeReference定義了referred字段,這個(gè)字段用于保存當(dāng)前INodeReference類指向的INode節(jié)點(diǎn),所以WithName和RstReference,referred字段就指向了WithCount對(duì)象,對(duì)于WithCount,referred指向了真正的INode對(duì)象。INodeReference還定義了getReferredINode()方法,在文件系統(tǒng)目錄樹的操作中,如果判斷當(dāng)前節(jié)點(diǎn)是一個(gè)引用節(jié)點(diǎn),則會(huì)調(diào)用getReferredINode()方法獲取INodeReference指向的INode對(duì)象。
public abstract class INodeReference extends INode { private INode referred;//指向的INode節(jié)點(diǎn) public INodeReference(INode parent,INode referred){ super(parent); this.referred = referred; } public final INode getReferredINode() { //獲取指向的INode節(jié)點(diǎn) return referred; } public final void setReferredINode(INode referred) { this.referred = referred; } //... }
然后,我們?cè)趤砜纯碬ithCount類的實(shí)現(xiàn)。
WithCount類定義了一個(gè)集合字段withNameList用于保存所有指向這個(gè)WithCount對(duì)象的WithName對(duì)象集合。WithCount類還定義了addReference()方法,任何指向WithCount對(duì)象的WithName對(duì)象以及DstReference對(duì)象都需要調(diào)用這個(gè)方法來添加指向關(guān)系。對(duì)于指向這個(gè)WithCount對(duì)象的DstReference對(duì)象,addReference()方法會(huì)將這個(gè)對(duì)象設(shè)置為自己的父INode節(jié)點(diǎn);而對(duì)于WithName對(duì)象,addReference()方法則將這個(gè)對(duì)象放入withNameList集合中保存。
public static class WithCount extends INodeReference { //保存所有指向這個(gè)WithCount對(duì)象的WithName對(duì)象的集合 private final List<WithName> withNameList = new ArrayList<WithName>(); public WithCount(INodeReference parent,INode referred) { super(parent,referred); //調(diào)用父類的構(gòu)造方法,指向文件系統(tǒng)目錄樹中的INode Preconditions.checkArgument(!referred.isReference()); refferred.setParentReferenct(this); //設(shè)置真實(shí)INode的父節(jié)點(diǎn)為當(dāng)前WithCount對(duì)象 } public void addReferenct(INodeReference ref){ if ( ref instanceof WithName) { //如果是WithName對(duì)象,則加入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對(duì)象,則設(shè)置為父節(jié)點(diǎn) setParentReference(ref); } } //... }
看完WithCount后,在看看WithName和DstReference。WithName類定義了name字段用于保存重命名前文件的名稱,同事定義了lastSnapshotId字段用于保存WithName對(duì)象構(gòu)造時(shí)源路徑的快照版本號(hào)。DstReference類的實(shí)現(xiàn)就更簡單了,只定義了一個(gè)dstSnapshotId字段用于保存重命名操作前目標(biāo)路徑的最新快照的版本號(hào)。WithName和DstReference在構(gòu)造時(shí)都會(huì)調(diào)用父類的構(gòu)造方法指向WithCount對(duì)象,同時(shí)還會(huì)調(diào)用WithCount.addReference()方法配置WithCount對(duì)象。
public static class WithName extend INodeReference { private final byte[] name;//重命名前的文件名 private final int lastSnapshotId; public WithName(INodeDirectory parent,WithCount referred,bytep[] name,int lastSnapshotId){ super(parent,referred); //調(diào)用父類構(gòu)造方法,指向WithCount節(jié)點(diǎn) this.name = name; this.lastSnapshotId = lastSnapshotId; referred.addReferenct(this); //調(diào)用WithCount.addReferenct() } //... } public static class DstReference extends INodeReference { private final int dstSnapshotId; public DstReference (INodeDirectory parent,WithCount referred,final int dstSnapshotId){ super(parent,referred); this.lastSnapshotId = lastSnapshotId; referred.addReferenct(this); //調(diào)用WithCount.addReferenct() } //.. }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。