HDFS源码学习纪录之-NameNode篇(一)

NameNode维护了HDFS命名空间的两层关系:

1) 文件与数据块之间的关系(INodeFile,INodeDirectory)

2) 数据块与DataNode之间的关系(BlockMap.BlockInfo)

首先,贴一张类图:

1. INode类:

INode模仿Linux文件系统中的索引节点inode。INode为一个抽象类,INode中保存了文件名,文件所有者,文件的访问权限,文件父目录(INodeDirectory引用,无论是INode的INodeFile子类还是INodeDirectory子类,都拥有父目录),修改时间,访问时间等。而INode中关键方法列举如下:

1) removeNode,将文件自己从父目录中删除。调用INodeDirectory的removeChild方法从父母中删除子文件。

  boolean removeNode() {
    if (parent == null) {
      return false;
    } else {

      parent.removeChild(this);
      parent = null;
      return true;
    }
  }

2) isUnderConstruction方法判断此INode所代表的文件是否在构建中(被写),默认情况下INode作为父类,返回的值都为false,而下文所讲的INodeUnderConstruction子类继承INode并重写了isUnderConstruction方法,返回true。

  /**
   * Is this inode being constructed?
   */
  boolean isUnderConstruction() {
    return false;
  }

2. INodeFile类

INodeFile为INode的子类,表示一个具体文件。INodeFile中保存的blocks表示构成文件的一系列数据块,其中BlockInfo类继承与Block类,其中不仅包含了该block对应的INode,而且包含了该块所处的DataNode(DataNodeDescriptor)。后文会再讲到BlockInfo类。INodeFile类中保存的long型属性header保存了block的副本数和建议的块大小。

  //Header mask 64-bit representation
  //Format: [16 bits for replication][48 bits for PreferredBlockSize]
  static final long HEADERMASK = 0xffffL << BLOCKBITS;

  protected long header;

  protected BlockInfo blocks[] = null;

collectSubtreeBlocksAndClear方法为INode抽象类中的抽象方法,INodeFile类与INodeDirectory类具体实现了该抽象方法。INodeFile类中的collectSubtreeBlocksAndClear方法实现简单,将INodeFile中的block数组设为空,同时将删除的blocks中的每个block加入collectSubtreeBlocksAndClear方法的参数。

  int collectSubtreeBlocksAndClear(List<Block> v) {
    parent = null;
    for (Block blk : blocks) {
      v.add(blk);
    }
    blocks = null;
    return 1;
  }

3.  INodeDirectory类

INodeDirectory中保存了Inode的列表,保存了目录下的每个子文件的INode。而INodeDirectory本身并不包含Block。

private List<INode> children;

INodeDirectory中的collectSubtreeBlocksAndClear方法如下:

  int collectSubtreeBlocksAndClear(List<Block> v) {
    int total = 1;
    if (children == null) {
      return total;
    }
    for (INode child : children) {
      total += child.collectSubtreeBlocksAndClear(v);
    }
    parent = null;
    children = null;
    return total;
  }

实现是通过遍历INodeDirectory的children(子目录/文件),并递归的调用INode.collectSubtreeBlocksAndClear方法,删除子目录,目录下的文件。并统计所有清除的子目录,子文件的数目,total变量返回。

4. INodeDirectoryWithQuota类

INodeDirectoryWithQuota类继承于INodeDirectory类,管理员可以配置目录的配额。既可以配置目录下的名字数量,也可以配置子目录下的所有文件的空间配额。

class INodeDirectoryWithQuota extends INodeDirectory {
  private long nsQuota; /// NameSpace quota命名空间配额,指代目录文件总数
  private long nsCount;
  private long dsQuota; /// disk space quota磁盘空间配额
  private long diskspace;  ···
}

5. INodeFileUnderConstruction类

INodeFileUnderConstruction类继承于INodeFile类,表示处于构建状态的INode,当客户端为写或追加打开文件时,该文件就变为构建状态,在HDFS的目录树中,该节点就为一个INodeFileUnderConstruction对象。

class INodeFileUnderConstruction extends INodeFile {
  String clientName;         // lease holder 租约持有者
  private final String clientMachine;//客户端所在主机
  private final DatanodeDescriptor clientNode; // if client is a cluster node too.如果客户端运行于集群中的机器,表示数据节点的信息

  private int primaryNodeIndex = -1; //the node working on lease recovery
  private DatanodeDescriptor[] targets = null;   //locations for last block最后一个块的数据流管道成员
  private long lastRecoveryTime = 0;//租约恢复的开始时间  ......
}

租约为客户端提供一定时间内的写操作的权限。相当于写锁。clientName表示发起写操作的客户端名称,即持有租约的客户端名称。clientMachine客户端所在主机。clientNode指,若客户端是运行于集群中的节点,则该变量表示该节点。targets表示最后一个数据块的数据流管道成员。primaryNodeIndex与lastRecoveryTime用于数据块恢复(租约恢复)。

INodeFileUnderConstruction调用isUnderConstruction来判断此文件是否正在被构建。

  /**
   * Is this inode being constructed?
   */
  @Override
  boolean isUnderConstruction() {
    return true;
  }
时间: 2024-10-13 03:15:52

HDFS源码学习纪录之-NameNode篇(一)的相关文章

BIND9源码学习笔记1---gdb调试篇

学习bind9源码之前,首先要知道如何用gdb来调试bind.BIND9的源码我是先看代码弄懂它的架构,像什么event-drive,epoll等, 再去看它的业务流程.看业务流程的时候要追踪它的数据流和处理过程,所以用gdb比较好,当然自己加日志再结合BIND9自有的日志也不是不 行,只是觉得这样更清晰. 编译bind的时候加的有-g和-O2选项,前者不用说了,后者很坑爹的,用gdb调试时会发现代码的实际执行顺序会有所改变,这是编译器的优化. 编译器的优化有三级,-O2就是二级优化的意思,扯远

jQuery源码学习1——整体架构篇

由于jQuery的源码比较复杂,所以我选择从jQuery1.0.0版本开始学习,逐步深入. 而且本系列文章包含大量的个人观点,纯属本人学习的记录 jQuery1.0.0只有1800行左右的代码,相对来讲看起来还是比较简单的 首先,想说一下我对jQuery的理解 jQuery其实就是一个很大的构造函数 它为我们提供了很多实例化方法 当然,由于在js中函数本身就是对象 因此jQuery也提供了很多的静态方法 个人认为,这些静态方法更为底层 今天把jQuery的架构梳理了一下 其实我们可以将其中的方法

jQuery源码学习3——工具方法篇

基本工具方法结构如下: jQuery.extend({ init:function(){}, each:function(){}, className:{ add:function(){}, remove:function(){}, has:function(){}, }, swap:function(){}, css:function(){}, curCSS:function(){}, clean:function(){}, expr:{}, token:[], find:function()

C++STL源码学习(之slist篇)

///stl_slist.h ///list为双向循环链表,slist为单向链表,某些操作效率更高 ///slist是SGI额外提供的单向链表,不属于C++标准 struct _Slist_node_base { _Slist_node_base* _M_next; }; ///将__new_node链在__prev_node后面 inline _Slist_node_base* __slist_make_link(_Slist_node_base* __prev_node, _Slist_no

C++ STL源码学习(之hash_table篇)

stl_hash_table.h 这不属于C++标准,是SGI STL标准的一部分,用于辅助实现hash_map和hash_set /// Hashtable class, used to implement the hashed associative containers /// hash_set, hash_map, hash_multiset, and hash_multimap. ///STL HashTable采用的是所谓的开链哈希法,依靠一个类似vector<list<T>

Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步看看几个对象的大至结构以及调用关系. 我们知道,三个结构(客户端,NameNode,DataNode)是能过网络调用的,走的是RPC.那在底层通讯时谁做服务器谁做客户端呢?我们先回顾一下这三者关系: 这样看,看不出,我们进入源码,看一下夹在中间的NameNode: 在这个initialize函数中,

JDK源码学习--String篇(二) 关于String采用final修饰的思考

JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JDK源码的时候,有粗略的思考过,今天下班后又把<Thinking in Java>中关于final的内容重新看了一遍,对此写下一些关于自己的理解和想法. String类中final关键字的使用 final关键字,用来描述一块数据不能被改变,两种可能理由:设计.效率 final使用的三种情况:数据.方

Vue.js 源码学习之Flag篇

The Progressive JavaScript Framework --vuejs.org 起因 第一次接触 Vue.js 是因为要做一个通讯录的外包项目,这个项目要有前台展示和中后台管理,从轮子做起肯定是不明智的选择,所以当时初步定下的是 Vue.js + Element UI 的技术栈. 项目过程很漫长,因为给的钱实在是可有可无,权当是学习了. 项目的接口是交给了同学. 整个项目采用的是钱后端分离的开发模式,我做我的页面,他做他的接口. 项目出了两个版本,做的时候,中间就强行的看文档.

Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何实现的. 提前申明,本人是一直搞.net的,对java略为生疏,所以在学习该作品时,会时不时插入对java的学习,到时也会摆一些上来,包括一下设计模式之类的.欢迎高手指正. 整个学习过程,我们主要通过eclipse来学习,之前已经讲过如何在eclipse中搭建调试环境,这里就不多述了. 在之前源码初