1.1 Block
Block是HDFS中的最基本單位是對數據塊的抽象,它通過一個final long(blkid)來進行標識。一個Block擁有三個longs,它們分別是block-id 、block length和generation stamp。Block名的格式是”blk”+blkid。通過set和get等方法能夠得到關於Block的id、name、len等信息。
static final long GRANDFATHER_GENERATION_STAMP = 0; 產生一個塊的標記來預先說明要產生的STAMP。
GenerationStamp也是HDFS的一個基本元素,也是通過一個long來進行標識的。GenerationStamp作用的猜想:當兩個塊進行比較的時候,當它們的hashcode相同時,便用GenerationStamp進行比較。當然blkid是不可變的,而當Block的數據增長或者減少的時候,其GenerationStamp就會發生變化(加1??)。
一個Block對應着兩個文件,其中一個存數據,一個存放元數據信息。它的元數據信息文件的格式如下:”blk_”+blkid+”_”+version.meta
和Block相關的類如下所示:
1.2 BlockCommand
此類定義了一個對DataNode下的Block操作的一個指令集,它的主要作用是告訴DataNode所指定的一系列塊是不可用的或者把這這些塊複製到別的DataNode上去。
1.3 BlockListAsLongs
這個類提供了一個接口用來通過long[]來訪問塊的列表。
1.4 BlockMetadataHeader
此類用來管理DataNode數據塊的元數據。一個Block的元數據的最主要部分就是它的CRC數據效驗它佔了5個字節。而它的版本號佔了兩個字節。
1.5 BlockMetaDataInfo
這個類是Block的一個子類,保存了一個塊的元數據信息。
1.6 BlocksMap
這個類保存了從一個塊到它的元數據的映射,一個塊的元數據通常包括它的INode和保存這個塊的DataNode。
BlockInfo是BlocksMap中的一個內部類,它繼承了Block,所以完全就可以把BlockInfo看作成一個Block。BlockInfo類中有一個triplets數組,其中triplets[3*i]指向了它的DatanodeDescriptor,而triplets[3*i+1]和triplets[3*i+2]分別是前一個和後一個塊的引用。
this.triplets = new Object[3*replication]; //其中的replication一般由INode中的getReplication()方法得到,replication是這個Block的複製因子。
從源代碼private int ensureCapacity(int num)可以看出triplets的大小是可以改變的,同時從這段方法的註釋中可以看到,triplets的空間的增加僅僅發生在用戶手動的調整複製因子時發生。
對於triplets中的引用指向問題如添加、刪除等等,基本上和雙向鏈表的操作方法是相同的。當然添加和刪除操作的triplets的DatanodeDescriptor都是一個同一個Datanode。
BlockMap的另外一個內部類是NodeIterator,它實現了Blockinfo的一個遍歷器。不支持remove。
問題1:這些Block爲什麼要使用一種鏈式結構,它有什麼意義呢??
問題的解答,當NameNode向Datanode發出一個report時,它會產生一個分隔符,把有效的塊和無效的塊標記起來
一個DataNode上的Block鏈式結構如下所示:
1.7 BlocksWithLocations
這個類主要實現了一個BlockLocations的數組,它提供了有效的定製化的序列化和反序列化的方法,代替了由RPC提供的數組序列化方式。其中的getDatanodes()方法的返回值爲datanodeIDs,這就能表明這個Block所在的Datanode的位置。