UnderReplicatedBlocks还提供了一个数据块迭代器BlockIterator,用于遍历其中的数据块。它是UnderReplicatedBlocks的内部类,有三个成员变量,如下:

  1. // 当前迭代级别
  2. private int level;
  3. // 标志位:是否为特定复制优先级的迭代器
  4. private boolean isIteratorForLevel = false;
  5. // 数据块Block迭代器Iterator列表,存储各级别数据块迭代器
  6. private final List<Iterator<Block>> iterators = new ArrayList<Iterator<Block>>();

其中,level代表了迭代器当前处于的迭代级别,表示正在哪个块复制级别迭代数据块;isIteratorForLevel是一个标志位,是否为特定复制优先级的迭代器的标志位,也就意味着只在特定级别进行迭代;而iterators则是一个数据块Block迭代器Iterator列表,由前往后、由高到低的存储各级别数据块迭代器。
        BlockIterator提供了两个构造函数,一个是无参构造函数:生成所有级别的数据块迭代器,另外一个是有参构造函数:生成指定级别的数据块迭代器,代码分别如下:

  1. /**
  2. * Construct an iterator over all queues.
  3. * 无参构造函数:生成所有级别的数据块迭代器
  4. */
  5. private BlockIterator() {
  6. // 当前迭代级别level设置为0
  7. level=0;
  8. // iterators中添加全部级别的数据块迭代器
  9. for(int i=0; i<LEVEL; i++) {
  10. iterators.add(priorityQueues.get(i).iterator());
  11. }
  12. }
  13. /**
  14. * Constrict an iterator for a single queue level
  15. * 有参构造函数:生成指定级别的数据块迭代器
  16. * @param l the priority level to iterate over
  17. */
  18. private BlockIterator(int l) {
  19. // 当前迭代级别level设置为指定级别
  20. level = l;
  21. // 标志位:是否为特定复制优先级的迭代器设置为true
  22. isIteratorForLevel = true;
  23. // iterators中添加指定级别的数据块迭代器
  24. iterators.add(priorityQueues.get(level).iterator());
  25. }

注释很清晰,读者可自行阅读。另外,数据块是根据复制级别由高到低的顺序迭代的,当某一级别数据块迭代完毕,那么我们需要更新当前迭代级别,此时update()方法就完成这一个工作,代码如下:

  1. // 如果需要,更新当前迭代级别(由高往低迭代)
  2. private void update() {
  3. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回
  4. if (isIteratorForLevel) {
  5. return;
  6. }
  7. // 当前迭代级别小于LEVEL-1(也就是还没到最低级别),并且当前迭代级别已遍历所有数据块
  8. while(level< LEVEL-1 && !iterators.get(level).hasNext()) {
  9. // 当前迭代级别level加1
  10. level++;
  11. }
  12. }

它会先判断标志位isIteratorForLevel:是否为特定复制优先级的迭代器,为true的话,直接返回;否则当当前迭代级别小于LEVEL-1(也就是还没到最低级别),并且当前迭代级别已遍历所有数据块,当前迭代级别level加1。

既然是一个迭代器,那么我们看下它最重要的两个方法,hasNext()和next(),分别如下:

hasNext():判断是否还存在未迭代元素

  1. // 判断是否还有下一个元素
  2. @Override
  3. public boolean hasNext() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的判断下一个元素的结果
  5. if (isIteratorForLevel) {
  6. return iterators.get(0).hasNext();
  7. }
  8. // 如果需要,更新当前迭代级别(由高往低迭代)
  9. update();
  10. // 取当前级别的迭代器的判断是否存在下一个元素的结果
  11. return iterators.get(level).hasNext();
  12. }

hasNext()方法,也是先判断标志位isIteratorForLevel:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的判断下一个元素的结果,否则,如果需要,调用update()方法更新当前迭代级别(由高往低迭代),取当前级别的迭代器的判断是否存在下一个元素的结果。

next()方法:跌倒下一个元素

  1. // 取下一个元素
  2. @Override
  3. public Block next() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的下一个元素
  5. if (isIteratorForLevel) {
  6. return iterators.get(0).next();
  7. }
  8. // 如果需要,更新当前迭代级别(由高往低迭代)
  9. update();
  10. // 取当前级别的迭代器的下一个元素
  11. return iterators.get(level).next();
  12. }

处理逻辑与hasNext()方法一致,不再赘述。

BlockIterator还提供了从迭代器中移除元素remove()方法及获取当前迭代级别的getPriority()方法,代码分别如下:

  1. // 移除
  2. @Override
  3. public void remove() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的移除结果
  5. if (isIteratorForLevel) {
  6. iterators.get(0).remove();
  7. } else {
  8. // 取当前级别的迭代器的移除的结果
  9. iterators.get(level).remove();
  10. }
  11. }
  12. // 获取当前迭代级别
  13. int getPriority() {
  14. return level;
  15. }

UnderReplicatedBlocks还提供了按照优先级由高到低的顺序,获取指定数目的待复制数据块的chooseUnderReplicatedBlocks()方法,代码如下:

  1. /**
  2. * Get a list of block lists to be replicated. The index of block lists
  3. * represents its replication priority. Replication index will be tracked for
  4. * each priority list separately in priorityToReplIdx map. Iterates through
  5. * all priority lists and find the elements after replication index. Once the
  6. * last priority lists reaches to end, all replication indexes will be set to
  7. * 0 and start from 1st priority list to fulfill the blockToProces count.
  8. *
  9. * @param blocksToProcess - number of blocks to fetch from underReplicated blocks.
  10. * @return Return a list of block lists to be replicated. The block list index
  11. *         represents its replication priority.
  12. */
  13. public synchronized List<List<Block>> chooseUnderReplicatedBlocks(
  14. int blocksToProcess) {
  15. // initialize data structure for the return value
  16. // 初始化做为返回值的数据结构,LEVEL大小的一个块列表的列表
  17. List<List<Block>> blocksToReplicate = new ArrayList<List<Block>>(LEVEL);
  18. // 每种优先级都添加一个空的数据块ArrayList列表
  19. for (int i = 0; i < LEVEL; i++) {
  20. blocksToReplicate.add(new ArrayList<Block>());
  21. }
  22. // 如果不存在需要复制的数据块,直接返回空的列表blocksToReplicate
  23. if (size() == 0) { // There are no blocks to collect.
  24. return blocksToReplicate;
  25. }
  26. int blockCount = 0;
  27. // 按照优先级从高到低处理
  28. for (int priority = 0; priority < LEVEL; priority++) {
  29. // Go through all blocks that need replications with current priority.
  30. // 构造指定级别priority的数据块迭代器BlockIterator实例neededReplicationsIterator
  31. BlockIterator neededReplicationsIterator = iterator(priority);
  32. // 根据指定级别priority从priorityToReplIdx中取之前已经处理到的位置索引replIndex
  33. Integer replIndex = priorityToReplIdx.get(priority);
  34. // skip to the first unprocessed block, which is at replIndex
  35. // 利用replIndex,数据块迭代器跳过之前已处理的数据块,指向下一个该处理的正确位置
  36. for (int i = 0; i < replIndex && neededReplicationsIterator.hasNext(); i++) {
  37. neededReplicationsIterator.next();
  38. }
  39. // blocksToProcess的值不能超过所有待复制数据块总数
  40. blocksToProcess = Math.min(blocksToProcess, size());
  41. // 如果已获取到足够的数据块,即blockCount等于blocksToProcess,直接跳出循环
  42. if (blockCount == blocksToProcess) {
  43. break;  // break if already expected blocks are obtained
  44. }
  45. // Loop through all remaining blocks in the list.
  46. // 通过迭代器neededReplicationsIterator迭代数据块,添加入返回集合blocksToReplicate中,
  47. // 并累加索引位置replIndex
  48. // 判断条件为当前已取数据块blockCount还未达到要求的blocksToProcess,
  49. // 同时数据块迭代器neededReplicationsIterator还有下一个元素
  50. while (blockCount < blocksToProcess
  51. && neededReplicationsIterator.hasNext()) {
  52. // 通过数据块迭代器neededReplicationsIterator取下一个数据块
  53. Block block = neededReplicationsIterator.next();
  54. // 将数据块添加到优先级priority对应的列表
  55. blocksToReplicate.get(priority).add(block);
  56. // 累加索引位置replIndex
  57. replIndex++;
  58. // 累加已获取数据块数目blockCount
  59. blockCount++;
  60. }
  61. // 如果迭代器中已没有元素,且已处理到最高级别,重置位置索引priorityToReplIdx为0,跳出循环
  62. if (!neededReplicationsIterator.hasNext()
  63. && neededReplicationsIterator.getPriority() == LEVEL - 1) {
  64. // reset all priorities replication index to 0 because there is no
  65. // recently added blocks in any list.
  66. for (int i = 0; i < LEVEL; i++) {
  67. priorityToReplIdx.put(i, 0);
  68. }
  69. break;
  70. }
  71. // 记录索引位置replIndex
  72. priorityToReplIdx.put(priority, replIndex);
  73. }
  74. // 返回获取到的数据块列表
  75. return blocksToReplicate;
  76. }

其处理逻辑大体如下:

1、初始化做为返回值的数据结构,LEVEL大小的一个块列表的列表blocksToReplicate;

2、每种优先级都添加一个空的数据块ArrayList列表;

3、如果不存在需要复制的数据块,直接返回空的列表blocksToReplicate;

4、按照优先级从高到低处理:

4.1、构造指定级别priority的数据块迭代器BlockIterator实例neededReplicationsIterator;

4.2、根据指定级别priority从priorityToReplIdx中取之前已经处理到的位置索引replIndex;

4.3、利用replIndex,数据块迭代器跳过之前已处理的数据块,指向下一个该处理的正确位置;

4.4、blocksToProcess的值不能超过所有待复制数据块总数;

4.5、如果已获取到足够的数据块,即blockCount等于blocksToProcess,直接跳出循环;

4.6、通过迭代器neededReplicationsIterator迭代数据块,添加入返回集合blocksToReplicate中,并累加索引位置replIndex,判断条件为当前已取数据块blockCount还未达到要求的blocksToProcess,同时数据块迭代器neededReplicationsIterator还有下一个元素:

4.6.1、通过数据块迭代器neededReplicationsIterator取下一个数据块;

4.6.2、将数据块添加到优先级priority对应的列表;

4.6.3、累加索引位置replIndex;

4.6.4、累加已获取数据块数目blockCount;

4.7、如果迭代器中已没有元素,且已处理到最高级别,重置位置索引priorityToReplIdx为0,跳出循环;

4.8、priorityToReplIdx中记录优先级priority对应索引位置replIndex;

5、返回获取到的数据块列表。

未完待续,敬请期待《HDFS源码分析之UnderReplicatedBlocks(二)》

HDFS源码分析之UnderReplicatedBlocks(二)的更多相关文章

  1. HDFS源码分析之UnderReplicatedBlocks(一)

    http://blog.csdn.net/lipeng_bigdata/article/details/51160359 UnderReplicatedBlocks是HDFS中关于块复制的一个重要数据 ...

  2. HDFS源码分析数据块复制监控线程ReplicationMonitor(一)

    ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列.其定义及作为线程核心的run()方法如下: ...

  3. HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

    HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

  4. HDFS源码分析之数据块及副本状态BlockUCState、ReplicaState

    关于数据块.副本的介绍,请参考文章<HDFS源码分析之数据块Block.副本Replica>. 一.数据块状态BlockUCState 数据块状态用枚举类BlockUCState来表示,代 ...

  5. 手机自动化测试:appium源码分析之bootstrap二

    手机自动化测试:appium源码分析之bootstrap二   在bootstrap项目中的io.appium.android.bootstrap.handler包中的类都是对应的指令类, priva ...

  6. HDFS源码分析数据块校验之DataBlockScanner

    DataBlockScanner是运行在数据节点DataNode上的一个后台线程.它为所有的块池管理块扫描.针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独 ...

  7. HDFS源码分析之LightWeightGSet

    LightWeightGSet是名字节点NameNode在内存中存储全部数据块信息的类BlocksMap需要的一个重要数据结构,它是一个占用较低内存的集合的实现,它使用一个数组array存储元素,使用 ...

  8. HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()

    无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...

  9. HDFS源码分析EditLog之获取编辑日志输入流

    在<HDFS源码分析之EditLogTailer>一文中,我们详细了解了编辑日志跟踪器EditLogTailer的实现,介绍了其内部编辑日志追踪线程EditLogTailerThread的 ...

随机推荐

  1. 利用C#原有函数对数组进行降序排列

    原文发布时间为:2009-03-04 -- 来源于本人的百度文章 [由搬家工具导入] 利用 Array类的静态方法 Sort可以对数组进行升序排列。如下:       Array.Sort(数组名); ...

  2. Java下使用Swing来进行图形界面开发

    1. GUI从创建window开始,通常会使用JFrame.JFrame frame = new JFrame(); 2. 你可以这样加入按钮,文字字段等组件.frame.getContentPane ...

  3. 修改linux 的bash 为zsh

    针对centos1.  yum -y install zsh git   2. git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh- ...

  4. LeetCode OJ--Palindrome Number

    https://oj.leetcode.com/problems/palindrome-number/ 判断是否为回文数 取每一位存到vector中,再判断 负数不是回文数 class Solutio ...

  5. springBoot AOP环绕增强、自定义注解、log4j2、MDC

    (一)log4j2 maven配置 <dependency> <groupId>org.springframework.boot</groupId> <art ...

  6. ECNU 3480 没用的函数 (ST表预处理 + GCD性质)

    题目链接  ECNU 2018 JAN Problem E 这题卡了双$log$的做法 令$gcd(a_{i}, a_{i+1}, a_{i+2}, ..., a_{j}) = calc(i, j)$ ...

  7. js上传Excel文件

    一.问题 需要在项目里添加一个上传excel文件的功能,因为其他同样的后台里面有上传文件的功能,第一反应就是想着直接用.了解了一下发现它是利用bootstrap的fileinput实现的,但是我怎么都 ...

  8. COFF - 中间文件格式解析

    http://www.cnblogs.com/weikanzong/p/5296739.html

  9. DedeCMS使用channelartlist循环,不能获取外部链接的解决办法

    Dede在制作下拉菜单时,可以使用channelartlist循环调用顶级栏目和子栏目,但该标签不能获取外部链接, 下拉菜单时一段代码搞定多个顶级栏目和子级栏目的同时输出. <div>   ...

  10. 【Salvation】——项目进展&已取得的成果

    写在前面:这个项目为原创团体项目,其中美术设计与部分关卡功能为其他成员完成,我负责的部分以角色动画和登录注册为主. 一.游戏美术设计 游戏背景,道具,动物,人物帧动画制作全部完成. 1.人物 2.游戏 ...