`
iwanna2008
  • 浏览: 4649 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
最近访客 更多访客>>
社区版块
存档分类
最新评论

Hadoop-0.1版本FSNamesystem类笔记

阅读更多

这个类维护了系统中多个重要的表:

 

 

 1.dir

     FSDirectory dir;

 文件的目录结构,也就是传说中的元数据,具体是由iNode组成,可以理解为文件到块的映射,保存在NameNode的本地内存和硬盘中。

 

 初始化:在FSNamesystem类的构造函数中,调用FSDirectory类构造函数,其参数dir是xml配置文件  中"dfs.name.dir"所对应的值,其默认值为"/tmp/hadoop/dfs/name"。

     this.dir = new FSDirectory(dir);

FSDirectory类构造函数:

 

     public FSDirectory(File dir) throws IOException {
        File fullimage = new File(dir, "image");
        if (! fullimage.exists()) {
          throw new IOException("NameNode not formatted: " + dir);
        }
        File edits = new File(dir, "edits");
        if (loadFSImage(fullimage, edits)) {
            saveFSImage(fullimage, edits);
        }

        synchronized (this) {
            this.ready = true;
            this.notifyAll();
            this.editlog = new DataOutputStream(new FileOutputStream(edits));
        }
    }

 

 FS_IMAGE是给内存中的FSDirectory类实例做备份的,image是FS_IMAGE所存储的路径,也就是说如果这个路径不存在,说明NameNode还没有格式化,换句话说在格式化的函数中一定能找到类似下面这样的代码

     File image = new File(dir, "image");
     image.mkdirs();

 

 接着FSDirectory类构造函数会读logEdit,目录的添加,删除,重命名,创建路径这四个操作会记录到logEdit,logEdit隔一段时间就会把这些修改作用到FS_IMAGE上,也就是说,对读到的FS_IMAGE做logEdit会得到最新的目录结构。至于从本地文件系统读FS_IMAGE和logEdit的过程,等讲到hdfs io时再说。也就是说,现在内存中的FSDirectory类实例已经是最新的了。至此FSDirectory类实例化结束。

 

 

 在下列情况下其值发生变化:

(1)在调用ClientProtocol接口中的create()函数时,文件需要覆盖时会调用delete()函数,同样对应于logEdit的删除。

(2)在调用ClientProtocol接口中的complete()函数时,要把完成的文件添加到FSDirectory类实例中去,包括所包含的块(从pendingCreates中该文件对应的Vecor中获取的)。对应于logEdit的添加。

(3)在调用ClientProtocol接口中的rename()函数时,对应于logEdit的重命名。

(4)在调用ClientProtocol接口中的delete()函数时,对应于logEdit的删除。

(5)在调用ClientProtocol接口中的mkdir()函数时,对应于logEdit的创建路径。

 

 

2.datanodeMap

     TreeMap datanodeMap = new TreeMap();

记录节点到块的映射,Key是UTF8类的实例(DataNode的Name),Value是DatanodeInfo类的实例。

DatanodeInfo类的成员变量有:

     private UTF8 name;
     private long capacityBytes, remainingBytes, lastUpdate;
     private volatile TreeSet blocks;

 

在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的sendHeartbeat()函数时,如果该节点未被datanodeMap所记录,则增加该节点信息。当然这里不包含该节点的块信息,也就是说其存储DatanodeInfo类的实例并没有其所对应块信息。 

(2)在调用DatanodeProtocol接口中的blockReport()函数时,如果Datanode所报告的块datanodeMap中没有,则添加,否则删除。这里增加了datanodeMap的块信息,也就是DatanodeInfo类的实例中所对应的块信息。

(3)在调用DatanodeProtocol接口中的blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,这里增加了datanodeMap的块信息,也就是DatanodeInfo类的实例中所对应的块信息。

(4)当心跳监视器监视到某个节点对应的心跳过期时,则把该心跳对应的节点从datanodeMap中删除。

 

3.heartbeats

    TreeSet heartbeats = new TreeSet(new Comparator() {
        public int compare(Object o1, Object o2) {
            DatanodeInfo d1 = (DatanodeInfo) o1;
            DatanodeInfo d2 = (DatanodeInfo) o2;            
            long lu1 = d1.lastUpdate();
            long lu2 = d2.lastUpdate();
            if (lu1 < lu2) {
                return -1;
            } else if (lu1 > lu2) {
                return 1;
            } else {
                return d1.getName().compareTo(d2.getName());
            }
        }
    });

 

 

记录当前活跃的节点,保存DatanodeInfo类的实例。与datanodeMap同步增删其对应的DatanodeInfo类的实例。

 

在下列情况下其值发生变化:

 

(1)在调用DatanodeProtocol接口中的sendHeartbeat()函数时,如果该节点未被heartbeats所记录,则增加该节点信息,当然这里不包含该节点的块信息,也就是说其存储DatanodeInfo类的实例并没有其所对应块信息。

(2)当心跳监视器监视到某个节点对应的心跳过期时,则把该节点对应的心跳从heartbeats中删除。

 

4.blocksMap

    TreeMap blocksMap = new TreeMap();

块到节点的映射,KEY是Block类实例,Value是DatanodeInfo类实例的TreeSet。可看作与datanodeMap记录相反的信息。与datanodeMap同步增删其对应的DatanodeInfo类实例中的块信息。

 

在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前记录过(通过和datanodeMap的对比),而报告中没有,则删除blocksMap中该块所对应的现在这个报告节点。如果以前没有记录过,而报告中有,则添加blocksMap中该块所对应的现在这个报告节点。

(2)在调用DatanodeProtocol接口中的 blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,添加映射到blocksMap中。

(3)当心跳监视器监视到某个节点对应的心跳过期时,从blocksMap中删除该节点所对应的块。

 

 5.recentInvalidateSets

     TreeMap recentInvalidateSets = new TreeMap();

 节点到需要删除的块的映射,通过Command形式发给DataNode节点以删除。Key是UTF8类的实例(DataNode)Value是block的类实例的Vector。

 

 在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前没有记录过,而报告中有,则添加blocksMap中该块所对应的现在这个报告节点。如果该块在FSDirectory类实例中依然存在并且该块没有在excessReplicateMap节点所对应得多余块中(我再并且)存有该快的节点数大于了系统设定的块最大复制数,则随机的选一个节点,加上该多余的块添加到excessReplicateMap中,再加到recentInvalidateSets中。

(2)在调用DatanodeProtocol接口中的 blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,添加映射到blocksMap中。如果该块在FSDirectory类实例中依然存在并且该块没有在excessReplicateMap节点所对应得多余块中(我再并且)存有该快的节点数大于了系统设定的块最大复制数,则随机的选一个节点,加上该多余的块添加到excessReplicateMap中,再加到recentInvalidateSets中。

(3)在调用DatanodeProtocol接口中的 getBlockwork()函数时,如果是删除命令,从recentInvalidateSets删除该节点所对应的块。

(4)在调用ClientProtocol接口中的create()函数时,文件需要覆盖时会调用delete()函数,添加信息到recentInvalidateSets。

 

 

6. neededReplications

     private TreeSet neededReplications = new TreeSet();

  没有达到需要的复制块的数量,就把该块加入到neededReplications中。neededReplications中存储的是Block类的实例。

 在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前记录过(通过和datanodeMap的对比),而报告中没有,则删除blocksMap中该块所对应的现在这个报告节点。同时如果该块在FSDirectory类实例中依然存在且现在块数小于需要复制的块数,说明该块不是通过ClientProtocol接口中的delete()函数删除的,所以导致该块没有被报告,是该DataNode节点本身的故障问题,所以需要另复制该块到其他节点,故添加该Block到neededReplications。

(2)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前没有记录过,而报告中有,则添加blocksMap中该块所对应的现在这个报告节点。同时,如果该块在FSDirectory类实例中依然存在且现在块数大于需要复制的块数,则从neededReplications删除该块。(可能失效的节点恢复了过来)否则,则添加该Block到neededReplications。

(3)在调用DatanodeProtocol接口中的 blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,添加映射到blocksMap中。同时,如果该块在FSDirectory类实例中依然存在且现在块数大于需要复制的块数,则从neededReplications删除该块。(可能失效的节点恢复了过来)否则,则添加该Block到neededReplications。

(4)在调用DatanodeProtocol接口中的 getBlockwork()函数时,在制定复制命令时,首先检查是否块在FSDirectory类实例中依然存在,如果不存在,从neededReplications中把块删除。如果该块在neededReplications中,则把该块从neededReplications中删除。

(5)在调用ClientProtocol接口中的complete()函数时,如果块所对应的节点数小于需要复制的块数时,添加该块到neededReplications中。这里还不太明白,再调用complete()前,dfsclient应该已经调用过reportWrittenBlock()了,所以datanodeMap已经被修改了,为什么还会出现这种情况呢?)

(6)当心跳监视器监视到某个节点对应的心跳过期时,则删除节点所对应的块。同时如果该块在FSDirectory类实例中依然存在且现在块数小于需要复制的块数,则添加该块到neededReplications。

 

7. pendingReplications

     private TreeSet pendingReplications = new TreeSet();

     pendingReplications中存储的是Block类的实例。

 在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前没有记录过,而报告中有,则添加blocksMap中该块所对应的现在这个报告节点。同时如果该块在FSDirectory类实例中依然存在且现在块数大于需要复制的块数,则从pendingReplications删除该块。

(2)在调用DatanodeProtocol接口中的 blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,添加映射到blocksMap中。同时如果该块在FSDirectory类实例中依然存在且现在块数大于需要复制的块数,则从pendingReplications删除该块。

(3)在调用DatanodeProtocol接口中的 getBlockwork()函数时,在制定复制命令时,首先检查是否块在FSDirectory类实例中依然存在,如果不存在,从neededReplications中把块删除。如果该块在neededReplications中,则把该块从neededReplications中删除,添加该块至pendingReplications。

 

 

8.excessReplicateMap(它的作用现在不是很清楚,和recentInvalidateSets有什么联系和区别呢?)

     TreeMap excessReplicateMap = new TreeMap();

Key是UTF8类的实例(DataNode的Name),Value是Block类实例的TreeSet. 

 

在下列情况下其值发生变化:

(1)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前记录过(通过和datanodeMap的对比),而报告中没有,则删除blocksMap中该块所对应的现在这个报告节点。因为报告中没有该块,说明该块已经不再该DataNode,所以也就谈不上该块在该节点是多余的了,故从excessReplicateMap中删除。

(2)在调用DatanodeProtocol接口中的 blockReport()函数时,如果该块以前没有记录过,而报告中有,则添加blocksMap中该块所对应的现在这个报告节点。如果该块在FSDirectory类实例中依然存在并且该块没有在excessReplicateMap节点所对应得多余块中(我再并且)存有该快的节点数大于了系统设定的块最大复制数,则随机的选一个节点,加上该多余的块添加到excessReplicateMap中。

(3)在调用DatanodeProtocol接口中的 blockReceived()函数时和ClientProtocol接口中的reportWrittenBlock()函数时,添加映射到blocksMap中。如果该块在FSDirectory类实例中依然存在并且该块没有在excessReplicateMap节点所对应得多余块中(我再并且)存有该快的节点数大于了系统设定的块最大复制数,则随机的选一个节点,加上该多余的块添加到excessReplicateMap中。

(4)当心跳监视器监视到某个节点对应的心跳过期时,则节点所对应的块。该块已经不再该DataNode,所以也就谈不上该块在该节点是多余的了,故从excessReplicateMap中删除。

 

9.pendingCreates

     TreeMap pendingCreates = new TreeMap();

 正在创建的文件,Key是UTF-8的实例(文件名),Value是该文件包含的块(Block类的实例的Vector)。

 在下列情况下其值发生变化:

(1)在调用ClientProtocol接口中的create()函数时,把文件加入到pendingCreates,创建空的Vector 。

(2)在调用ClientProtocol接口中的abandonBlock()函数时,把块从pendingCreates中的Vector中删除,文件不删除。

(3)在调用ClientProtocol接口中的addBlock()函数时,如果文件正在被创建,则增加一个块到Vector中。

(4)在调用ClientProtocol接口中abandonFileInProgress()函数时,把文件从pendingCreates中删除。

(5)在调用ClientProtocol接口中complete()函数时,NameNode通过节点或客户上报块的信息把块的长度这个字段在pendingCreates中的Vector中存的Block加上,然后在FSDirectory类的实例修改过后,把文件从从pendingCreates中删除。

(6)如果锁监视器监视到锁过期且持有锁的文件正在被创建,则把文件从pendingCreates中删除。

 

 

10.pendingCreateBlocks

     TreeSet pendingCreateBlocks = new TreeSet();

 正在创建的块,存储的是Block类的实例。

(1)在调用ClientProtocol接口中的create()函数时,把文件对应的块加入到pendingCreateBlocks。

(2)在调用ClientProtocol接口中的abandonBlock()函数时,把文件对应的块从pendingCreateBlocks中删除。

(3)在调用ClientProtocol接口中的addBlock()函数时,如果文件正在被创建,则增加一个块到pendingCreateBlocks中。

(4)在调用ClientProtocol接口中abandonFileInProgress()函数时,把该文件对应的所有块从pendingCreateBlocks 中删除。

(5)在调用ClientProtocol接口中complete()函数时,把该文件对应的块从pendingCreateBlocks中删除。

(6)如果锁监视器监视到锁过期且持有锁的文件正在被创建,则把文件对应的块从pendingCreateBlocks中删除。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics