DatanodeDescriptor类记录了Datanode的使用情况,如capacity,used等统计信息,DatanodeDescriptor是Namenode内部的数据结构,并不是通过RPC通信从Datanode向Namenode通信时候使用。Namenode从DatanodeDescriptor中读取Datanode统计信息,并显示在jsp页面上,这就是在网页上面显示的统计信息的来源。
public class DatanodeDescriptor extends DatanodeInfo 首先来看一下DatanodeInfo
1. public class DatanodeInfo extends DatanodeID implements Node
1) 看一下DatanodeID类
public String name;
public String storageID;
protected int infoPort;
public int ipcPort;
有如上四个变量,name表示了名称,storageID是ID号唯一,infoPort是infoServer运行的端口,ipcPort是ipc运行的端口,剩下的就是getter和setter方法。
2) DatanodeInfo中的变量有
protected long capacity;
protected long dfsUsed;
protected long remaining;
protected long lastUpdate;
protected int xceiverCount;
protected String hostName = null;
这些变量是Datanode统计信息,要通过RPC通信在Namenode启动时将这些状态传递从Datanode传递给Namenode,剩下的方法也比较简单,基本上是getter和setter
public String getDatanodeReport() 方法,按照一定的格式输出Datanode统计信息。
同时,DatanodeInfo类中还有一个Node parent变量,这个变量是为了计算拓扑结构使用。
2. 解决了DatanodeInfo继续看DatanodeDescriptor,下面一个结构为BlockTargetPair
BlockTargetPair维护了一个Block和DatanodeDescriptor数组变量。为下面的变量提供了数据结构。
3. private static class BlockQueue 变量有
1) private final Queue<BlockTargetPair> blockq = new LinkedList<BlockTargetPair>();
2) synchronized boolean offer(Block block, DatanodeDescriptor[] targets) 入链表
3) synchronized List<BlockTargetPair> poll(int numBlocks) 出链表
4. private volatile BlockInfo blockList = null;
DatanodeDescriptor中维护了一个BlockInfo对象,是该Datanode对应的block的头结点,通过头结点可以遍历该Datanode上面的所有block。可以配合blocksMap理解这个结构。
5. 下面是三个重要变量
/** A queue of blocks to be replicated by this datanode */
private BlockQueue replicateBlocks = new BlockQueue();
        /** A queue of blocks to be recovered by this datanode */
private BlockQueue recoverBlocks = new BlockQueue();
        /** A set of blocks to be invalidated by this datanode */
private Set<Block> invalidateBlocks = new TreeSet<Block>();
这三个变量分别代表了需要复制的 block链表,需要recovery的block链表,以及无效的block表。
6. boolean addBlock(BlockInfo b)
向该Datanode添加block,具体方法是:
blockList = b.listInsert(blockList, this);
其中参数中的blockList是头结点,返回值是新的头结点,指向的是新添加的block对应的BlockInfo变量。
7. boolean removeBlock(BlockInfo b)
向该Datanode删除block,具体方法是:
blockList = b.listRemove(blockList, this);
从blockMap链表结构中删除该block,返回头结点,blockList仍然维护的是一个头结点。
8. void moveBlockToHead(BlockInfo b)
将某个BlockInfo对应的对象放在blocksMap结构的头结点,方法是先删除,在插入。
blockList = b.listRemove(blockList, this);
blockList = b.listInsert(blockList, this);
9. public int numBlocks()
根据头结点遍历所有block,获得该datanode上面所有block数量。
10. static private class BlockIterator implements Iterator<Block>
迭代器模式。
11. void addBlockToBeReplicated(Block block, DatanodeDescriptor[] targets)
void addBlockToBeRecovered(Block block, DatanodeDescriptor[] targets)
void addBlocksToBeInvalidated(List<Block> blocklist)
往相应的结构里面放,见5。
12. BlockCommand getReplicationCommand(int maxTransfers)
BlockCommand getLeaseRecoveryCommand(int maxTransfers)
BlockCommand getInvalidateBlocks(int maxblocks)
这些函数是要通过RPC传递给Datanode,datanode根据传递的信息进行相应操作,放到后面再说。
13. void reportDiff(BlocksMap blocksMap,
                 BlockListAsLongs newReport,
                 Collection<Block> toAdd,
                 Collection<Block> toRemove,
                 Collection<Block> toInvalidate)
这是DatanodeDescriptor中最重要的一个方法,从Datanode心跳汇报得到的块信
信息经过分类后传递给DatanodeDescriptor,进行统计分类。在想Namenode反馈
需要添加,需要移除以及无效的块集合。newReport是从datanode中通过RPC获
得的块信息。